diff --git a/Graphics/Implicit.hs b/Graphics/Implicit.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit.hs
@@ -0,0 +1,39 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+{- The sole purpose of this file it to pass on the 
+   functionality we want to be accessible to the end user. -}
+
+module Graphics.Implicit(
+	-- Operations
+	translate, 
+	scale,
+	complement,
+	union,  intersect,  difference,
+	unionR, intersectR, differenceR,
+	shell,
+	slice,
+	bubble,
+	extrude,
+	extrudeR,
+	extrudeOnEdgeOf,
+	-- Primitives
+	sphere,
+	cube,
+	circle,
+	cylinder,
+	square,
+	regularPolygon,
+	zsurface,
+	polygon,
+	--ellipse,
+	-- Export
+	writeSVG,
+	writeSTL
+) where
+
+import Graphics.Implicit.Definitions
+import Graphics.Implicit.Primitives
+import Graphics.Implicit.Operations
+import Graphics.Implicit.Export
+
diff --git a/Graphics/Implicit/Definitions.hs b/Graphics/Implicit/Definitions.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/Definitions.hs
@@ -0,0 +1,30 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+module Graphics.Implicit.Definitions where
+
+-- Let's make things a bit nicer. 
+-- Following math notation ℝ, ℝ², ℝ³...
+type ℝ = Float
+type ℝ2 = (ℝ,ℝ)
+type ℝ3 = (ℝ,ℝ,ℝ)
+
+type ℕ = Int
+
+-- | A chain of line segments, as in SVG
+-- eg. [(0,0), (0.5,1), (1,0)] ---> /\
+type Polyline = [ℝ2]
+
+-- $ In Implicit CAD, we consider objects as functions
+-- of `outwardness'. The boundary is 0, negative is the
+-- interior and positive the exterior. The magnitude is
+-- how far out or in.
+
+-- | A 2D object
+type Obj2 = (ℝ2 -> ℝ)
+
+-- | A 3D object
+type Obj3 = (ℝ3 -> ℝ)
+
+
+
diff --git a/Graphics/Implicit/Export.hs b/Graphics/Implicit/Export.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/Export.hs
@@ -0,0 +1,178 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+module Graphics.Implicit.Export where
+
+import Graphics.Implicit.Definitions
+import Graphics.Implicit.Tracing
+import System.IO
+
+
+renderRaw :: ℝ3 -> ℝ3 -> ℝ -> String -> Obj3 -> IO()
+renderRaw (x1, y1, z1) (x2, y2, z2) res name obj = 
+	-- A hacky way to encode to chars, but it will do
+	let convert n = if n > 1 then 'a' else if n > 0.5 then 'b' else  if n > 0.1 then 'c' else  if n == 0 then 'd' else if n > -0.5 then 'e' else 'd' in
+		do
+			putStrLn $ show $ length $ [ obj (x,y,z) | x <- [x1, x1+res.. x2], y <- [y1, y1+res.. y2], z <- [z1, z1+res.. z2] ]
+			out <- openFile name WriteMode
+			mapM_ ( (hPutChar out) . convert) $ 
+				[ obj (x,y,z) | x <- [x1, x1+res.. x2], y <- [y1, y1+res.. y2], z <- [z1, z1+res.. z2] ]
+			hClose out
+
+renderRaw2D :: ℝ2 -> ℝ2 -> ℝ -> String -> Obj2 -> IO()
+renderRaw2D (x1, y1) (x2, y2) res name obj = 
+	-- A hacky way to encode to chars, but it will do
+	let convert n = if n > 1 then 'a' else if n > 0.5 then 'b' else  if n > 0.1 then 'c' else  if n == 0 then 'd' else if n > -0.5 then 'e' else 'd' in
+		do
+			putStrLn $ show $ length $ [x1, x1+res.. x2]
+			putStrLn $ show $ length $ [ obj (x,y) | x <- [x1, x1+res.. x2], y <- [y1, y1+res.. y2] ]
+			out <- openFile name WriteMode
+			mapM_ (mapM_ ( (hPutChar out) . convert)) $ 
+				[[ obj (x,y) | x <- [x1, x1+res.. x2] ] | y <- [y1, y1+res.. y2] ]
+			hClose out
+
+-- | Write an SVG of a 2D object
+writeSVG :: 
+	ℝ2         -- ^ lower corner of bounding box
+	-> ℝ2      -- ^ upper corner of bounding box
+	-> ℝ       -- ^ resolution of rendering
+	-> String  -- ^ Filename to write SVG to
+	-> Obj2    -- ^ 2D object to render as SVG
+	-> IO ()   -- ^ Resulting IO action that will write SVG
+
+writeSVG (x1,y1) (x2,y2) d name obj = 
+	let 
+		-- Note that 0,0 is the upper right hand corner and that positive is down
+		grid = [(obj (x,-y), obj (x+d,-y), obj (x+d,-(y+d)), obj (x,-(y+d)), obj (x+d/2,-(y+d/2)) , (x-x1,y-y1), d ) | x <- [x1, x1+d.. x2], y <- [y1, y1 +d.. y2] ]
+		multilines = (filter polylineNotNull) $ (map reducePolyline) $ orderLines $ concat $ map getLineSeg grid
+		svglines = concat $ map (\line -> 
+				"  <polyline points=\"" 
+				++ concat (map (\(x,y) -> " " ++ show x ++ "," ++ show y) line)
+				++ "\" style=\"stroke:rgb(0,0,255);stroke-width:1;fill:none;\"/> \n" ) 
+				multilines	
+		text = "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"> \n" 
+			++ svglines			
+			++ "</svg> "
+	in do 
+		writeFile name text
+
+-- | Write an SVG of a 2D object (uses parallel algorithms)
+writeSVG2 :: 
+	ℝ2         -- ^ lower corner of bounding box
+	-> ℝ2      -- ^ upper corner of bounding box
+	-> ℝ       -- ^ resolution of rendering
+	-> String  -- ^ Filename to write SVG to
+	-> Obj2    -- ^ 2D object to render as SVG
+	-> IO ()   -- ^ Resulting IO action that will write SVG
+
+writeSVG2 (x1,y1) (x2,y2) d name obj = 
+	let 
+		grid = [[getLineSeg (obj (x,-y), obj (x+d,-y), obj (x+d,-(y+d)), obj (x,-(y+d)), obj (x+d/2,-(y+d/2)) , (x-x1,y-y1), d ) | x <- [x1, x1+d.. x2]] | y <- [y1, y1 +d.. y2] ]
+		multilines = (filter polylineNotNull) $ (map reducePolyline) $ orderLinesP grid
+		svglines = concat $ map (\line -> 
+				"  <polyline points=\"" 
+				++ concat (map (\(x,y) -> " " ++ show x ++ "," ++ show y) line)
+				++ "\" style=\"stroke:rgb(0,0,255);stroke-width:1;fill:none;\"/> \n" ) 
+				multilines	
+		text = "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\"> \n" 
+			++ svglines			
+			++ "</svg> "
+	in do 
+		writeFile name text
+
+
+
+writeGCode :: 
+	ℝ2          -- ^ lower corner of bounding box
+	-> ℝ2       -- ^ upper corner of bounding box
+	-> ℝ        -- ^ resolution of rendering
+	-> FilePath -- ^ Filename to write gcode to
+	-> Obj2     -- ^ 2D object to make gcode for
+	-> IO ()    -- ^ Resulting IO action that will write gcode
+
+writeGCode (x1,y1) (x2,y2) d name obj = 
+	let 
+		multilines = (filter polylineNotNull) $ (map reducePolyline) $ orderLines $ concat $ map getLineSeg [(obj (x,y), obj (x+d,y), obj (x+d,y+d), obj (x,y+d), obj (x+d/2,y+d/2) , (x,y), d ) | x <- [x1, x1+d.. x2], y <- [y1, y1 +d.. y2] ]
+		gcodeHeader = "(generated by ImplicitCAD)\nM3\nG21 (units=mm)\nG00 Z5.0 (tool is off)\n\n"
+		gcodeFooter = "\n%\n"
+		gcodeXY :: ℝ2 -> [Char]
+		gcodeXY (x,y) = "X"++ show x ++" Y"++ show y 
+		interpretPolyline (start:next:others) = 
+			"G00 "++ gcodeXY start ++ "\n"
+			++ "G01 Z-1.0 F100.0\n"
+			++ "G01 " ++ gcodeXY next ++ " Z-1.0 F400.0\n"
+			++ concat (map (\p -> "G01 " ++ (gcodeXY p) ++ " Z-1.0\n") others)
+			++ "G00 Z5.0\n\n"
+		text = gcodeHeader
+			++ (concat $ map interpretPolyline multilines)
+			++ gcodeFooter
+	in do 
+		writeFile name text
+
+writeGCodeHacklabLaser :: 
+	ℝ2          -- ^ lower corner of bounding box
+	-> ℝ2       -- ^ upper corner of bounding box
+	-> ℝ        -- ^ resolution of rendering
+	-> FilePath -- ^ Filename to write gcode to
+	-> Obj2     -- ^ 2D object to make gcode for
+	-> IO ()    -- ^ Resulting IO action that will write gcode
+
+writeGCodeHacklabLaser (x1,y1) (x2,y2) d name obj = 
+	let 
+		multilines = (filter polylineNotNull) $ (map reducePolyline) $ orderLines $ concat $ map getLineSeg [(obj (x,y), obj (x+d,y), obj (x+d,y+d), obj (x,y+d), obj (x+d/2,y+d/2) , (x,y), d ) | x <- [x1, x1+d.. x2], y <- [y1, y1 +d.. y2] ]
+		gcodeHeader = 
+			"(generated by ImplicitCAD, based of hacklab wiki example)\n"
+			++"M63 P0 (laser off)\n"
+			++"G0 Z0.002 (laser off)\n"
+			++"G21 (units=mm)\n"
+			++"F400 (set feedrate)\n"
+			++"M3 S1 (enable laser)\n"
+			++"\n"
+		gcodeFooter = 
+			"M5 (disable laser)\n"
+			++"G00 X0.0 Y0.0 (move to 0)\n"
+			++"M2 (end)"
+		gcodeXY :: ℝ2 -> [Char]
+		gcodeXY (x,y) = "X"++ show x ++" Y"++ show y 
+		interpretPolyline (start:others) = 
+			"G00 "++ gcodeXY start ++ "\n"
+			++ "M62 P0 (laser on)\n"
+			++ concat (map (\p -> "G01 " ++ (gcodeXY p) ++ "\n") others)
+			++ "M63 P0 (laser off)\n\n"
+		text = gcodeHeader
+			++ (concat $ map interpretPolyline multilines)
+			++ gcodeFooter
+	in do 
+		writeFile name text
+
+
+writeSTL :: 
+	ℝ3           -- ^ Lower corner of (3D) bounding box
+	-> ℝ3        -- ^ Upper corner of bounding box
+	-> ℝ         -- ^ resolution of rendering
+	-> FilePath  -- ^ Name of file to write STL to
+	-> Obj3      -- ^ 3D object to make STL for
+	-> IO()      -- ^ Resulting IO action that will write STL
+writeSTL (x1,y1,z1) (x2,y2,z2) d name obj =
+	let
+		grid3d = [((obj(x,y,z), obj(x+d,y,z), obj(x,y+d,z), obj(x+d,y+d,z), obj(x,y,z+d), obj(x+d,y,z+d), obj(x,y+d,z+d), obj(x+d,y+d,z+d)), (x,y,z), d )| x <- [x1, x1+d.. x2], y <- [y1, y1 +d.. y2], z <- [z1, z1+d.. z2] ]
+		triangles = concat $ map getTriangles grid3d
+		stlHeader = "solid ImplictCADExport\n"
+		stlFooter = "endsolid ImplictCADExport\n"
+		vertex :: ℝ3 -> String
+		vertex (x,y,z) = "vertex " ++ show x ++ " " ++ show y ++ " " ++ show z
+		stlTriangle :: (ℝ3, ℝ3, ℝ3) -> String
+		stlTriangle (a,b,c) =
+			"facet normal 0 0 0\n"
+			++ "outer loop\n"
+			++ vertex a ++ "\n"
+			++ vertex b ++ "\n"
+			++ vertex c ++ "\n"
+			++ "endloop\n"
+			++ "endfacet\n"
+		text = stlHeader
+			++ (concat $ map stlTriangle triangles)
+			++ stlFooter
+	in do 
+		writeFile name text
+
diff --git a/Graphics/Implicit/ExtOpenScad.hs b/Graphics/Implicit/ExtOpenScad.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/ExtOpenScad.hs
@@ -0,0 +1,193 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+-- We'd like to parse openscad code, with some improvements, for backwards compatability.
+
+module Graphics.Implicit.ExtOpenScad where
+
+import Prelude hiding (lookup)
+import Graphics.Implicit.Definitions
+import Data.Map hiding (map)
+import Text.ParserCombinators.Parsec 
+import Text.ParserCombinators.Parsec.Expr
+import Control.Monad (liftM)
+
+type VariableLookup = Map String OpenscadObj
+
+data OpenscadObj = OUndefined 
+		 | OBool Bool 
+		 | ONum ℝ
+		 | OList [OpenscadObj]
+		 | OString String
+		 | OFunc ( OpenscadObj -> OpenscadObj ) 
+
+instance Show OpenscadObj where
+	show OUndefined = "Undefined"
+	show (OBool b) = show b
+	show (ONum n) = show n
+	show (OList l) = show l
+	show (OString s) = show s
+	show (OFunc f) = "<function>"
+
+numericOFunc f = OFunc $ \oObj -> case oObj of
+	ONum n -> ONum $ f n
+	_ -> OUndefined
+
+data Computation = 
+	ControlStructure ( VariableLookup -> [Computation] -> ([Obj2], [Obj3], VariableLookup) ) [Computation]
+	| Assignment (VariableLookup -> VariableLookup)
+	| Object2 (VariableLookup -> Obj2)
+	| Object3 (VariableLookup -> Obj3)
+	| Include String
+
+variableSymb = many1 (noneOf " ,|[]{}()*&^%$#@!~`'\"\\/;:.,<>?") <?> "variable"
+
+variable :: GenParser Char st (VariableLookup -> OpenscadObj)
+variable = liftM (\varstr -> \varlookup -> case lookup varstr varlookup of
+			Nothing -> OUndefined
+			Just a -> a )
+		variableSymb
+	
+			
+
+literal :: GenParser Char st (VariableLookup -> OpenscadObj)
+literal = 
+	try ( (string "true" >> return (\map -> OBool True) )
+		<|> (string "false" >> return (\map -> OBool False) )
+		<?> "boolean" )
+	<|> try ( try (do
+			a <- (many1 digit);
+			char '.';
+			b <- (many digit);
+			return ( \map -> ONum ( read (a ++ "." ++ b) :: ℝ) );
+		) <|>  (do
+			a <- (many1 digit);
+			return ( \map -> ONum ( read a :: ℝ) );
+		) <?> "number" )
+	<|> try ( ( do
+		string "\"";
+		strlit <- many $ noneOf "\"\n";
+		string "\"";
+		return $ \map -> OString $ strlit;
+	) <?> "string" )
+	<?> "literal"
+
+-- space = oneOf " \t\n"
+
+-- We represent the priority or 'fixity' of different types of expressions
+-- by the Int argument
+
+expression :: Int -> GenParser Char st (VariableLookup -> OpenscadObj)
+expression 10 = (try literal) <|> (try variable )
+	<|> ((do
+		string "(";
+		many space;
+		expr <- expression 0;
+		many space;
+		string ")";
+		return expr;
+	) <?> "bracketed expression" )
+	<|> ( ( do
+		string "[";
+		many space;
+		exprs <- sepBy (expression 0) (many space >> char ',' >> many space);
+		many space;
+		string "]";
+		return $ \varlookup -> OList (map ($varlookup) exprs )
+	) <?> "vector/list" )
+expression 9 = ( try( do 
+		f <- expression 10;
+		string "(";
+		many space;
+		arg <- expression 0;
+		many space;
+		string ")";
+		return $ \varlookup ->
+			case f varlookup of
+				OFunc actual_func -> actual_func (arg varlookup)
+				_ -> OUndefined
+	) <?> "function appliation" )
+	<|> try (expression 10)
+expression n@8 = try (( do 
+		a <- expression (n+1);
+		string "^";
+		b <- expression n;
+		return $ \varlookup -> case (a varlookup, b varlookup) of
+			(ONum na, ONum nb) -> ONum (na ** nb)
+			_ -> OUndefined
+	) <?> "exponentiation")
+	<|> try (expression $ n+1)
+expression n@7 =  try (expression $ n+1)
+expression n@6 = 
+	let 
+		mult (ONum a) (ONum b) = ONum (a*b)
+		mult (ONum a) (OList b) = OList (map (mult (ONum a)) b)
+		mult (OList a) (ONum b) = OList (map (mult (ONum b)) a)
+		mult _ _ = OUndefined
+
+		div  (ONum a) (ONum b) = ONum (a/b)
+		div (OList a) (ONum b) = OList (map (\x -> div x (ONum b)) a)
+		div _ _ = OUndefined
+	in try (( do 
+		exprs <- sepBy1 (sepBy (expression $ n+1) (char '/')) (char '*')
+		return $ \varlookup -> foldl1 mult $ map ( (foldl1 div) . (map ($varlookup) ) ) exprs;
+	) <?> "multiplication/division")
+	<|>try (expression $ n+1)
+expression n@5 =
+	let 
+		append (OList a) (OList b) = OList $ a++b
+		append (OString a) (OString b) = OString $ a++b
+		append _ _ = OUndefined
+	in try (( do 
+		exprs <- sepBy1 (expression $ n+1) (string "++")
+		return $ \varlookup -> foldl1 append $ map ($varlookup) exprs;
+	) <?> "append") 
+	<|>try (expression $ n+1)
+
+expression n@4 =
+	let 
+		add (ONum a) (ONum b) = ONum (a+b)
+		add (OList a) (OList b) = OList $ zipWith add a b
+		add _ _ = OUndefined
+
+		sub (ONum a) (ONum b) = ONum (a-b)
+		sub (OList a) (OList b) = OList $ zipWith sub a b
+		sub _ _ = OUndefined
+	in try (( do 
+		exprs <- sepBy1 (sepBy (expression $ n+1) (char '-')) (char '+')
+		return $ \varlookup -> foldl1 add $ map ( (foldl1 sub) . (map ($varlookup) ) ) exprs;
+	) <?> "addition/subtraction")
+	<|>try (expression $ n+1)
+expression n@3 = try (expression $ n+1)
+expression n@2 = try (expression $ n+1)
+expression n@1 = try (expression $ n+1)
+expression n@0 = try (expression $ n+1)
+
+
+
+testParse str = case parse (expression 0) ""  str of
+		Right res -> show $ res 
+			(fromList [("sin", numericOFunc sin)] )
+		Left  err -> show err
+
+
+assigmentStatement = do
+	var <- variableSymb
+	many space
+	char '='
+	many space
+	val <- expression 0
+	return $ Assignment (\varlookup -> insert var (val varlookup) varlookup)
+
+{-ifStatement = do
+	string "if"
+	many space
+	char '('
+	condition <- expression 0
+	char ')'
+	many space
+	trueCase <- computationStatement-}
+	
+
+computationStatement = assigmentStatement
+
diff --git a/Graphics/Implicit/MathUtil.hs b/Graphics/Implicit/MathUtil.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/MathUtil.hs
@@ -0,0 +1,61 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+module Graphics.Implicit.MathUtil (rmax, rmin, rmaximum, rminimum) where
+
+import Data.List
+import Graphics.Implicit.Definitions
+
+-- | Rounded Maximum
+-- Consider  max(x,y) = 0, the generated curve 
+-- has a square-like corner. We replace it with a 
+-- quarter of a circle
+rmax :: 
+	ℝ     -- ^ radius
+	-> ℝ  -- ^ first number to round maximum
+	-> ℝ  -- ^ second number to round maximum
+	-> ℝ  -- ^ resulting number
+rmax r x y =  if abs (x-y) < r 
+	then y - r*sin(pi/4-asin((x-y)/r/sqrt 2)) + r
+	else max x y
+
+-- | Rounded minimum
+rmin :: 
+	ℝ     -- ^ radius
+	-> ℝ  -- ^ first number to round minimum
+	-> ℝ  -- ^ second number to round minimum
+	-> ℝ  -- ^ resulting number
+rmin r x y = if abs (x-y) < r 
+	then y + r*sin(pi/4+asin((x-y)/r/sqrt 2)) - r
+	else min x y
+
+-- | Like rmax, but on a list instead of two.
+-- Just as maximum is.
+-- The implementation is to take the maximum two
+-- and rmax those.
+
+rmaximum ::
+	ℝ      -- ^ radius
+	-> [ℝ] -- ^ numbers to take round maximum
+	-> ℝ   -- ^ resulting number
+rmaximum _ (a:[]) = a
+rmaximum r (a:b:[]) = rmax r a b
+rmaximum r l = 
+	let
+		tops = reverse $ sort l
+	in
+		rmax r (tops !! 0) (tops !! 1)
+
+-- | Like rmin but on a list.
+rminimum ::
+	ℝ      -- ^ radius
+	-> [ℝ] -- ^ numbers to take round minimum
+	-> ℝ   -- ^ resulting number
+rminimum r (a:[]) = a
+rminimum r (a:b:[]) = rmin r a b
+rminimum r l = 
+	let
+		tops = sort l
+	in
+		rmin r (tops !! 0) (tops !! 1)
+
diff --git a/Graphics/Implicit/Operations.hs b/Graphics/Implicit/Operations.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/Operations.hs
@@ -0,0 +1,130 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}
+
+module Graphics.Implicit.Operations (
+	translate, 
+	scale,
+	complement,
+	union,  intersect,  difference,
+	unionR, intersectR, differenceR,
+	shell,
+	slice,
+	bubble,
+	extrude,
+	extrudeR,
+	extrudeOnEdgeOf
+) where
+
+import Prelude hiding ((+),(-),(*),(/))
+import Graphics.Implicit.Definitions
+import Graphics.Implicit.MathUtil
+import Graphics.Implicit.SaneOperators
+
+
+-- | Translate an object by a vector of appropriate dimension. 
+translate :: 
+	(Additive a a a, AdditiveInvertable a)
+	=> a             -- ^ Vector to translate by (Also: a is a vector, blah, blah)
+	-> (a -> ℝ)   -- ^ Object to translate
+	-> (a -> ℝ)   -- ^ Resulting object
+translate p obj = \q -> obj (q-p)
+
+-- | Scale an object
+scale :: (Multiplicative a ℝ a) => 
+	ℝ            -- ^ Amount to scale by
+	-> (a -> ℝ)  -- ^ Object to scale
+	-> (a -> ℝ)  -- ^ Resulting scaled object
+scale s obj = \p -> s * obj (p/s)
+
+complement :: 
+	(a -> ℝ)     -- ^ Object to complement
+	-> (a -> ℝ)  -- ^ Result
+complement obj = \p -> - obj p
+
+shell :: 
+	ℝ             -- ^ width of shell
+	-> (a -> ℝ)   -- ^ object to take shell of
+	-> (a -> ℝ)   -- ^ resulting shell
+shell w a = \p -> abs (a p) - w/(2.0::ℝ)
+
+-- | Rounded union
+unionR :: 
+	ℝ           -- ^ The radius of rounding
+	-> [a -> ℝ] -- ^ objects to union
+	-> (a -> ℝ) -- ^ Resulting object
+unionR r objs = \p -> rminimum r $ map ($p) objs
+
+-- | Rounded minimum
+intersectR :: 
+	ℝ           -- ^ The radius of rounding
+	-> [a -> ℝ] -- ^ Objects to intersect
+	-> (a -> ℝ) -- ^ Resulting object
+intersectR r objs = \p -> rmaximum r $ map ($p) objs
+
+-- | Rounded difference
+differenceR :: 
+	ℝ           -- ^ The radius of rounding
+	-> [a -> ℝ] -- ^ Objects to difference 
+	-> (a -> ℝ) -- ^ Resulting object
+differenceR r (x:xs) = \p -> rmaximum r $ (x p) :(map (negate . ($p)) xs)
+
+
+-- | Union a list of objects
+union :: 
+	[a -> ℝ] -- ^ List of objects to union
+	-> (a -> ℝ) -- ^ The object resulting from the union
+union objs = \p -> minimum $ map ($p) objs
+
+-- | Intersect a list of objects
+intersect :: 
+	[a -> ℝ] -- ^ List of objects to intersect
+	-> (a -> ℝ) -- ^ The object resulting from the intersection
+intersect objs = \p -> maximum $ map ($p) objs
+
+-- | Difference a list of objects
+difference :: 
+	[a -> ℝ] -- ^ List of objects to difference
+	-> (a -> ℝ) -- ^ The object resulting from the difference
+difference (obj:objs) = \p -> maximum $ map ($p) $ obj:(map complement objs)
+
+-- | Slice a 3D objects at a given z value to make a 2D object.
+slice :: 
+	ℝ         -- ^ z-level to cut at
+	-> Obj3   -- ^ 3D object to slice from
+	-> Obj2   -- ^ Resulting 2D object
+slice z obj = \(a,b) -> obj (a,b,z)
+
+-- | Bubble out a 2D object into a 3D one.
+bubble :: ℝ -> Obj2 -> Obj3
+bubble s obj = 
+	let
+		spsqrt n = signum n * sqrt (abs n)
+		spsq n = signum n * n ** 2
+	in
+		\(x,y,z) -> spsqrt ( z ** 2 + s * obj (x,y) )
+
+-- | Extrude a 2D object. (The extrusion goes into the z-plane)
+extrude :: 
+	ℝ          -- ^ Length to extrude
+	-> Obj2    -- ^ 2D object to extrude
+	-> Obj3    -- ^ Resulting 3D object
+extrude h obj = \(x,y,z) -> max (obj (x,y)) (abs (z + h/(2.0 :: ℝ )) - h)
+
+-- | Rounded extrude. Instead of the extrude having a flat top or bottom, it is bevelled.
+extrudeR ::
+	ℝ          -- ^ Radius of rounding
+	-> ℝ       -- ^ Length to extrude
+	-> Obj2    -- ^ 2D object to extrude
+	-> Obj3    -- ^ Resulting 3D object
+extrudeR r h obj = \(x,y,z) -> rmax r (obj (x,y)) (abs (z + h/(2.0 :: ℝ)) - h)
+
+-- | Create a 3D object by extruding a 2D object along the edge of another 2D object.
+-- For example, extruding a circle on the edge of another circle would make a torus.
+extrudeOnEdgeOf :: 
+	Obj2     -- ^ Object to extrude
+	-> Obj2  -- ^ Object to extrude along the edge of
+	-> Obj3  -- ^ Resulting 3D object
+extrudeOnEdgeOf a b = \(x,y,z) -> a (b (x,y), z) 
+
diff --git a/Graphics/Implicit/Primitives.hs b/Graphics/Implicit/Primitives.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/Primitives.hs
@@ -0,0 +1,102 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+module Graphics.Implicit.Primitives (
+	sphere,
+	cube,
+	circle,
+	cylinder,
+	square,
+	regularPolygon,
+	polygon,
+	zsurface--,
+	--ellipse
+) where
+
+import Graphics.Implicit.Definitions
+import qualified Graphics.Implicit.SaneOperators as S
+
+sphere :: 
+	ℝ         -- ^ Radius of the sphere
+	-> Obj3   -- ^ Resulting sphere
+sphere r = \(x,y,z) -> sqrt (x**2 + y**2 + z**2) - r
+
+cube :: 
+	ℝ          -- ^ Width of the cube
+	 -> Obj3   -- ^ Resuting cube
+cube l = \(x,y,z) -> (maximum $ map abs [x,y,z]) - l/2.0
+
+cylinder :: 
+	ℝ         -- ^ Radius of the cylinder
+	-> ℝ      -- ^ Height of the cylinder
+	-> Obj3   -- ^ Resulting cylinder
+cylinder r h = \(x,y,z) -> max (sqrt(x^2+y^2) - r) (abs(z) - h)
+
+circle :: 
+	ℝ        -- ^ radius of the circle
+	-> Obj2  -- ^ resulting circle
+circle r = \(x,y) -> sqrt (x**2 + y**2) - r
+
+torus :: 
+	ℝ       -- ^ radius of the rotated circle of a torus
+	-> ℝ    -- ^ radius of the circle rotationaly extruded on of a torus
+	-> Obj3 -- ^ resulting torus
+torus r_main r_second = \(x,y,z) -> sqrt( ( sqrt (x^2 + y^2) - r_main )^2 + z^2 ) - r_second
+
+--ellipse :: ℝ -> ℝ -> Obj2
+--ellipse a b = \(x,y) ->
+--	if a > b 
+--	then ellipse b a (y,x)
+--	else sqrt ((b/a*x)*	*2 + y**2) - a
+
+square :: 
+	ℝ        -- ^ Width of the square
+	-> Obj2  -- ^ Resulting square
+square l = \(x,y) -> (maximum $ map abs [x,y]) - l/2.0
+
+polygon :: 
+	[ℝ2]      -- ^ Verticies of the polygon
+	 -> Obj2  -- ^ Resulting polygon
+polygon points = 
+	let
+		pairs = 
+		   [ (points !! n, points !! (mod (n+1) (length points) ) ) | n <- [0 .. (length points) - 1] ]
+		isIn p@(p1,p2) = 
+			let 
+				crossing_points = 
+					[x1 + (x2-x1)*y2/(y2-y1) |
+					((x1,y1), (x2,y2)) <- 
+						map (\((a1,a2),(b1,b2)) -> ((a1-p1,a2-p2), (b1-p1,b2-p2)) ) pairs,
+					( (y2 < 0) && (y1 > 0) ) || ( (y2 > 0) && (y1 < 0) ) ]
+			in 
+				if odd $ length $ filter (>0) crossing_points then -1 else 1
+		dist a@(a1,a2) b@(b1,b2) p@(p1,p2) =
+			let
+				ab = b S.- a
+				nab = (1 / S.norm ab) S.* ab
+				ap = p S.- a
+				d  = nab S.⋅ ap
+				closest 
+					| d < 0 = a
+					| d > S.norm ab = b
+					| otherwise = a S.+ d S.* nab
+			in
+				S.norm (closest S.- p)
+		dists = \ p -> map (\(a,b) ->  dist a b p) pairs
+	in 
+		\ p -> isIn p * minimum (dists p)
+
+regularPolygon :: 
+	ℕ       -- ^ number of sides
+	-> ℝ    -- ^ radius
+	-> Obj2 -- ^ resulting regular polygon
+regularPolygon sides r = let sidesr = fromIntegral sides in
+	\(x,y) -> maximum [ x*cos(2*pi*m/sidesr) + y*sin(2*pi*m/sidesr) | m <- [0.. sidesr -1]] - r 
+
+
+zsurface :: 
+	(ℝ2 -> ℝ) -- ^ Description of the height of the surface
+	-> Obj3   -- ^ Resulting 3D object
+zsurface f = \(x,y,z) -> f (x,y) - z
+
+
diff --git a/Graphics/Implicit/SaneOperators.hs b/Graphics/Implicit/SaneOperators.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/SaneOperators.hs
@@ -0,0 +1,160 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, TypeSynonymInstances, UndecidableInstances  #-}
+
+-- We're going to be working with vectors, etc, a lot.
+-- I'd rather not have to break every stupid vector into
+-- its components to add them or scale them...
+
+module Graphics.Implicit.SaneOperators where
+
+import qualified Prelude as P
+import Prelude hiding ((+),(-),(*),(/))
+
+import Graphics.Implicit.Definitions
+
+-- * Num is too big a class and doesn't make sense for, say, vectors.
+
+class Additive a b c | a b -> c where
+	(+) :: a -> b -> c
+	infixl 6 +
+
+class Multiplicative a b c | a b -> c where
+	(*) :: a -> b -> c
+	infixl 7 *
+
+class AdditiveInvertable a where
+	additiveInverse :: a -> a
+
+class MultiplicativeInvertable a where
+	multiplicativeInverse :: a -> a
+
+class Normable a where
+	norm :: a -> ℝ
+
+class InnerProductSpace a where
+	(⋅) :: a -> a -> ℝ
+
+-- * I should be able to create instances for all Num instances,
+-- but Haskell's type checker doesn't seem to play nice with them.
+
+
+{-instance Num a => Additive a a a where
+	a + b = a P.+ b
+
+instance Num a => Multiplicative a a a where
+	a * b = a P.* b
+
+instance Num a => AdditiveInvertable a where
+	additiveInverse a = negate a
+
+instance Fractional a => MultiplicativeInvertable a where
+	multiplicativeInverse a = 1 P./ a-}
+
+-- So, we do this instead. :(
+
+instance Additive ℝ ℝ ℝ where
+	a + b = a P.+ b
+
+instance Multiplicative ℝ ℝ ℝ where
+	a * b = a P.* b
+
+instance AdditiveInvertable ℝ where
+	additiveInverse a = negate a
+
+instance MultiplicativeInvertable ℝ where
+	multiplicativeInverse a = 1 P./ a
+
+instance Additive ℕ ℕ ℕ where
+	a + b = a P.+ b
+
+instance Multiplicative ℕ ℕ ℕ where
+	a * b = a P.* b
+
+instance AdditiveInvertable ℕ where
+	additiveInverse a = negate a
+
+
+instance Additive ℝ ℕ ℝ where
+	a + b = a P.+ (fromIntegral b)
+
+instance Multiplicative ℝ ℕ ℝ where
+	a * b = a P.* (fromIntegral b)
+
+instance Additive ℕ ℝ ℝ where
+	a + b = (fromIntegral a) P.+ b
+
+instance Multiplicative ℕ ℝ ℝ where
+	a * b = (fromIntegral a) P.* b
+
+
+(-) :: (Additive a b c) => (AdditiveInvertable b) => a -> b -> c
+x - y = x + (additiveInverse y)
+infixl 6 -
+
+(/) :: (Multiplicative a b c) => (MultiplicativeInvertable b) => a -> b -> c
+x / y = x * (multiplicativeInverse y)
+infixl 7 /
+
+
+
+instance Additive ℝ2 ℝ2 ℝ2 where
+	(x1, y1) + (x2, y2) = (x1+x2, y1+y2)
+
+instance Additive ℝ3 ℝ3 ℝ3 where
+	(x1, y1, z1) + (x2, y2, z2) = (x1+x2, y1+y2, z1+z2)
+
+{-instance (Additive a b c, Additive d e f) => Additive (a,d) (b,e) (c,f) where
+	(x1, y1) + (x2, y2) = (x1+x2, y1+y2)
+
+instance (Additive a b c, Additive d e f, Additive  g h i) => Additive (a,d,g) (b,e,h) (c,f,i) where
+	(x1, y1, z1) + (x2, y2, z2) = (x1+x2, y1+y2, z1+z2)-}
+
+instance Multiplicative ℝ ℝ2 ℝ2 where
+	s * (x,y) = (s*x, s*y)
+
+instance Multiplicative ℝ ℝ3 ℝ3 where
+	s * (x,y,z) = (s*x, s*y, s*z)
+
+instance AdditiveInvertable ℝ2 where
+	additiveInverse (x, y) = (additiveInverse x, additiveInverse y)
+
+instance AdditiveInvertable ℝ3 where
+	additiveInverse (x, y, z) = (additiveInverse x, additiveInverse y, additiveInverse z)
+
+{-instance (AdditiveInvertable a, AdditiveInvertable b) =>  AdditiveInvertable (a,b) where
+	additiveInverse (x, y) = (additiveInverse x, additiveInverse y)
+
+instance (AdditiveInvertable a, AdditiveInvertable b, AdditiveInvertable c) => AdditiveInvertable (a,b,c) where
+	additiveInverse (x, y, z) = (additiveInverse x, additiveInverse y, additiveInverse z)-}
+
+
+
+instance (Additive a b c) => Additive (d -> a) (d -> b) (d -> c) where
+	f + g = \p -> f p + g p
+
+instance (Multiplicative a b c) => Multiplicative (d -> a) (d -> b) (d -> c) where
+	f * g = \p -> f p * g p
+
+
+instance Normable ℝ where
+	norm a = abs a
+
+instance Normable ℝ2 where
+	norm (a, b) = sqrt ((a**2) + (b**2))
+
+instance Normable ℝ3 where
+	norm (a, b, c) = sqrt ((a**2) + (b**2) + (c**2))
+
+instance InnerProductSpace ℝ where
+	x ⋅ y = x*y
+
+instance InnerProductSpace ℝ2 where
+	(a1, a2) ⋅ (b1, b2) = a1*b1 + a2*b2
+
+instance InnerProductSpace ℝ3 where
+	(a1, a2, a3) ⋅ (b1, b2, b3) = a1*b1 + a2*b2+a3*b3
+
+
+
diff --git a/Graphics/Implicit/Tracing.hs b/Graphics/Implicit/Tracing.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/Tracing.hs
@@ -0,0 +1,137 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+module Graphics.Implicit.Tracing (
+	getTriangles,
+	getLineSeg,
+	orderLines,
+	orderLinesDC,
+	orderLinesP,
+	reducePolyline,
+	polylineNotNull
+) where
+
+import Graphics.Implicit.Definitions
+import Graphics.Implicit.Tracing.GetTriangles (getTriangles)
+
+import Control.Parallel (par, pseq)
+
+getLineSeg :: (ℝ,ℝ,ℝ,ℝ,ℝ,ℝ2,ℝ) -> [Polyline]
+getLineSeg (x1y1,x2y1,x2y2,x1y2,c,(x,y),s) = 
+	let 
+		x1 = (x, y+s*x1y1/(x1y1-x1y2))
+		x2 = (x+s, y+s*x2y1/(x2y1-x2y2))
+		y1 = (x+s*x1y1/(x1y1-x2y1), y )
+		y2 = (x+s*x1y2/(x1y2-x2y2), y+s)
+		notPointLine (p1:p2:[]) = p1 /= p2
+	in filter (notPointLine) $ case (x1y2 <= 0, x2y2 <= 0,
+	         x1y1 <= 0, x2y1 <= 0) of
+		(True,  True, 
+		 True,  True)  -> []
+		(False, False,
+		 False, False) -> []
+		(True,  True, 
+		 False, False) -> [[x1, x2]]
+		(False, False,
+		 True,  True)  -> [[x1, x2]]
+		(False, True, 
+		 False, True)  -> [[y1, y2]]
+		(True,  False,
+		 True,  False) -> [[y1, y2]]
+		(True,  False,
+		 False, False) -> [[x1, y2]]
+		(False, True, 
+		 True,  True)  -> [[x1, y2]]
+		(True,  True, 
+		 False, True)  -> [[x1, y1]]
+		(False, False,
+		 True,  False) -> [[x1, y1]]
+		(True,  True, 
+		 True,  False) -> [[x2, y1]]
+		(False, False,
+		 False, True)  -> [[x2, y1]]
+		(True,  False,
+		 True,  True)  -> [[x2, y2]]
+		(False, True, 
+		 False, False) -> [[x2, y2]]
+		(True,  False,
+		 False, True)  -> if c > 0
+			then [[x1, y2], [x2, y1]]
+			else [[x1, y1], [x2, y2]]
+		(False, True, 
+		 True,  False) -> if c <= 0
+			then [[x1, y2], [x2, y1]]
+			else [[x1, y1], [x2, y2]]
+
+
+
+
+orderLines :: [Polyline] -> [Polyline]
+orderLines [] = []
+orderLines (present:remaining) =
+	let
+		findNext ((p3:ps):segs) = if p3 == last present then (Just (p3:ps), segs) else
+			if last ps == last present then (Just (reverse $ p3:ps), segs) else
+			case findNext segs of (res1,res2) -> (res1,(p3:ps):res2)
+		findNext [] = (Nothing, [])
+	in
+		case findNext remaining of
+			(Nothing, _) -> present:(orderLines remaining)
+			(Just match, others) -> orderLines $ (present ++ tail match): others
+
+reducePolyline ((x1,y1):(x2,y2):(x3,y3):others) = 
+	if (x1,y1) == (x2,y2) then reducePolyline ((x2,y2):(x3,y3):others) else
+	if abs ( (y2-y1)/(x2-x1) - (y3-y1)/(x3-x1) ) < 0.0001 
+	   || ( (x2-x1) == 0 && (x3-x1) == 0 && (y2-y1)*(y3-y1) > 0)
+	then reducePolyline ((x1,y1):(x3,y3):others)
+	else (x1,y1) : reducePolyline ((x2,y2):(x3,y3):others)
+reducePolyline ((x1,y1):(x2,y2):others) = 
+	if (x1,y1) == (x2,y2) then reducePolyline ((x2,y2):others) else (x1,y1):(x2,y2):others
+reducePolyline l = l
+
+orderLinesDC :: [[[Polyline]]] -> [Polyline]
+orderLinesDC segs =
+	let
+		halve l = splitAt (div (length l) 2) l
+		splitOrder segs = case (\(x,y) -> (halve x, halve y)) $ unzip $ map (halve) segs of
+			((a,b),(c,d)) -> orderLinesDC a ++ orderLinesDC b ++ orderLinesDC c ++ orderLinesDC d
+	in
+		if (length segs < 5 || length (head segs) < 5 ) then concat $ concat segs else
+		case (\(x,y) -> (halve x, halve y)) $ unzip $ map (halve) segs of
+			((a,b),(c,d)) ->orderLines $ 
+				orderLinesDC a ++ orderLinesDC b ++ orderLinesDC c ++ orderLinesDC d
+
+orderLinesP :: [[[Polyline]]] -> [Polyline]
+orderLinesP segs =
+	let
+		halve l = splitAt (div (length l) 2) l
+		splitOrder segs = case (\(x,y) -> (halve x, halve y)) $ unzip $ map (halve) segs of
+			((a,b),(c,d)) -> orderLinesDC a ++ orderLinesDC b ++ orderLinesDC c ++ orderLinesDC d
+		-- force is frome real world haskell
+		force xs = go xs `pseq` ()
+		    where go (_:xs) = go xs
+		          go [] = 1
+	in
+		if (length segs < 5 || length (head segs) < 5 ) then concat $ concat segs else
+		case (\(x,y) -> (halve x, halve y)) $ unzip $ map (halve) segs of
+			((a,b),(c,d)) -> orderLines $ 
+				let
+					a' = orderLinesP a
+					b' = orderLinesP b
+					c' = orderLinesP c
+					d' = orderLinesP d
+				in (force a' `par` force b' `par` force c' `par` force d') `pseq` 
+					(a' ++ b' ++ c' ++ d')
+
+
+polylineNotNull (a:l) = not (null l)
+polylineNotNull [] = False
+
+
+
+{-getMesh (a1, a2, a3) (b1, b2, b3) d obj = 
+	if abs (obj ( (a1 + b1)/2, (a2 + b2)/2, (a3 + b3)/2 )) > 2*d 
+	then []
+	else if maximum [ abs $ b1 - a1, abs $ b2 - a2, abs $ b3 - a3 ] < d 
+	then getTriangles-}
+
diff --git a/Graphics/Implicit/Tracing/GetTriangles.hs b/Graphics/Implicit/Tracing/GetTriangles.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/Implicit/Tracing/GetTriangles.hs
@@ -0,0 +1,416 @@
+-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
+-- Released under the GNU GPL, see LICENSE
+
+module Graphics.Implicit.Tracing.GetTriangles (getTriangles) where
+
+import Graphics.Implicit.Definitions
+
+
+-- This monstrosity of a function gives triangles to divde negative interior
+-- regions and positive exterior ones inside a cube, based on its vertices.
+
+-- It is based on the linearly-interpolated marching cubes algorithm.
+
+getTriangles :: ((ℝ,ℝ,ℝ,ℝ,ℝ,ℝ,ℝ,ℝ),ℝ3,ℝ) -> [(ℝ3,ℝ3,ℝ3)]
+getTriangles ((x1y1z1,x2y1z1,x1y2z1,x2y2z1,x1y1z2,x2y1z2,x1y2z2,x2y2z2), (x,y,z), d) =
+	let
+		--{- Linearly interpolated
+		x1y1 = (x,   y,   z+d*x1y1z1/(x1y1z1-x1y1z2))
+		x1y2 = (x,   y+d, z+d*x1y2z1/(x1y2z1-x1y2z2))
+		x2y1 = (x+d, y,   z+d*x2y1z1/(x2y1z1-x2y1z2))
+		x2y2 = (x+d, y+d, z+d*x2y2z1/(x2y2z1-x2y2z2))
+
+		x1z1 = (x,   y+d*x1y1z1/(x1y1z1-x1y2z1), z)
+		x1z2 = (x,   y+d*x1y1z2/(x1y1z2-x1y2z2), z+d)
+		x2z1 = (x+d, y+d*x2y1z1/(x2y1z1-x2y2z1), z)
+		x2z2 = (x+d, y+d*x2y1z2/(x2y1z2-x2y2z2), z+d)
+
+		y1z1 = (x+d*x1y1z1/(x1y1z1-x2y1z1), y,   z)
+		y1z2 = (x+d*x1y1z2/(x1y1z2-x2y1z2), y,   z+d)
+		y2z1 = (x+d*x1y2z1/(x1y2z1-x2y2z1), y+d, z)
+		y2z2 = (x+d*x1y2z2/(x1y2z2-x2y2z2), y+d, z+d)
+		--}
+
+
+		{- Non-linearly interpolated
+		x1y1 = (x,   y,   z+d/2)
+		x1y2 = (x,   y+d, z+d/2)
+		x2y1 = (x+d, y,   z+d/2)
+		x2y2 = (x+d, y+d, z+d/2)
+
+		x1z1 = (x,   y+d/2, z)
+		x1z2 = (x,   y+d/2, z+d)
+		x2z1 = (x+d, y+d/2, z)
+		x2z2 = (x+d, y+d/2, z+d)
+
+		y1z1 = (x+d/2, y,  z)
+		y1z2 = (x+d/2, y,  z+d)
+		y2z1 = (x+d/2, y+d,z)
+		y2z2 = (x+d/2, y+d,z+d)
+		--}
+
+		-- Convenience function
+		square a b c d = [(a,b,c),(d,a,c)]
+	in case 
+		-- whether the vertices are "in" or "out" form the topological 
+		-- basis of our triangles constructions. We must consider every 
+		-- possible case.
+
+		-- We arrange the vertices in a human readable way
+
+		-- BOTTOM LAYER             TOP LAYER
+		(x1y2z1<=0, x2y2z1<=0,    x1y2z2<=0, x2y2z2<=0,
+		 x1y1z1<=0, x2y1z1<=0,    x1y1z2<=0, x2y1z2<=0)
+	of
+
+		-- There are 256 cases to implement.
+		-- Only about half are, but they're the most common ones.
+		-- In practice, this has no issues redering reasonable objects.
+
+		-- Uniform cases = empty
+		(False,False,    False,False,
+		 False,False,    False,False) -> []
+
+		(True, True,     True, True,
+		 True, True,     True, True ) -> []
+
+		-- 2 uniform layers
+
+		(True, True,     False,False,
+		 True, True,     False,False) -> square x1y1 x2y1 x2y2 x1y2
+
+		(False,False,    True, True,
+		 False,False,    True, True ) -> square x1y1 x2y1 x2y2 x1y2
+
+		(True, True,     True, True,
+		 False,False,    False,False) -> square x1z1 x2z1 x2z2 x1z2
+
+		(False,False,    False,False,
+		 True, True,     True, True ) -> square x1z1 x2z1 x2z2 x1z2
+
+		(False,True,     False,True,
+		 False,True,     False,True ) -> square y1z1 y2z1 y2z2 y1z2
+
+		(True, False,    True, False,
+		 True, False,    True, False) -> square y1z1 y2z1 y2z2 y1z2
+
+
+		-- z single column
+
+		(True, False,    True, False,
+		 False,False,    False,False) -> square x1z1 y2z1 y2z2 x1z2
+
+		(False,True,     False,True,
+		 False,False,    False,False) -> square x2z1 y2z1 y2z2 x2z2
+
+		(False,False,    False,False,
+		 True, False,    True, False) -> square x1z1 y1z1 y1z2 x1z2
+
+		(False,False,    False,False,
+		 False,True,     False,True ) -> square y1z1 x2z1 x2z2 y1z2
+
+		(False,True,     False,True, 
+		 True, True,     True, True ) -> square x1z1 y2z1 y2z2 x1z2
+
+		(True, False,    True, False,
+		 True, True,     True, True ) -> square x2z1 y2z1 y2z2 x2z2
+
+		(True, True,     True, True, 
+		 False,True,     False,True ) -> square x1z1 y1z1 y1z2 x1z2
+
+		(True, True,     True, True, 
+		 True, False,    True, False) -> square y1z1 x2z1 x2z2 y1z2
+
+		-- single y column
+
+		(True, False,    False,False,
+		 True, False,    False,False) -> square x1y1 y1z1 y2z1 x1y2
+
+		(False,True,     False,False,
+		 False,True,     False,False) -> square x2y1 y1z1 y2z1 x2y2
+
+		(False,False,    True, False,
+		 False,False,    True, False) -> square x1y1 y1z2 y2z2 x1y2
+
+		(False,False,    False,True, 
+		 False,False,    False,True ) -> square x2y1 y1z2 y2z2 x2y2
+
+		(False,True,     True, True,
+		 False,True,     True, True) -> square x1y1 y1z1 y2z1 x1y2
+
+		(True, False,    True, True,
+		 True, False,    True, True) -> square x2y1 y1z1 y2z1 x2y2
+
+		(True, True,     False, True,
+		 True, True,     False, True) -> square x1y1 y1z2 y2z2 x1y2
+
+		(True, True,     True, False, 
+		 True, True,     True, False) -> square x2y1 y1z2 y2z2 x2y2
+
+		-- since x column
+
+		(True, True,     False,False,
+		 False,False,    False,False) -> square x1y2 x1z1 x2z1 x2y2
+
+		(False,False,    False,False,
+		 True, True,     False,False) -> square x1y1 x1z1 x2z1 x2y1
+
+		(False,False,    True, True,
+		 False,False,    False,False) -> square x1y2 x1z2 x2z2 x2y2
+
+		(False,False,    False,False,
+		 False,False,    True, True ) -> square x1y1 x1z2 x2z2 x2y1
+
+		(False,False,    True, True, 
+		 True, True,     True, True ) -> square x1y2 x1z1 x2z1 x2y2
+
+		(True, True,     True, True, 
+		 False,False,    True, True ) -> square x1y1 x1z1 x2z1 x2y1
+
+		(True, True,     False,False,
+		 True, True,     True, True ) -> square x1y2 x1z2 x2z2 x2y2
+
+		(True, True,     True, True, 
+		 True, True,     False,False) -> square x1y1 x1z2 x2z2 x2y1
+
+		-- lone points
+
+		(True, False,    False,False,
+		 False,False,    False,False) -> [(x1z1, y2z1, x1y2)]
+
+		(False,True,     False,False,
+		 False,False,    False,False) -> [(x2z1, y2z1, x2y2)]
+
+		(False,False,    False,False,
+		 True, False,    False,False) -> [(x1z1, y1z1, x1y1)]
+
+		(False,False,    False,False,
+		 False,True,     False,False) -> [(x2z1, y1z1, x2y1)]
+
+		(False,False,    True, False,
+		 False,False,    False,False) -> [(x1z2, y2z2, x1y2)]
+
+		(False,False,    False,True,
+		 False,False,    False,False) -> [(x2z2, y2z2, x2y2)]
+
+		(False,False,    False,False,
+		 False,False,    True, False) -> [(x1z2, y1z2, x1y1)]
+
+		(False,False,    False,False,
+		 False,False,    False,True ) -> [(x2z2, y1z2, x2y1)]
+
+		(False,True,     True, True, 
+		 True, True,     True, True ) -> [(x1z1, y2z1, x1y2)]
+
+		(True, False,    True, True, 
+		 True, True,     True, True ) -> [(x2z1, y2z1, x2y2)]
+
+		(True, True,     True, True, 
+		 False,True,     True, True ) -> [(x1z1, y1z1, x1y1)]
+
+		(True, True,     True, True, 
+		 True, False,    True, True ) -> [(x2z1, y1z1, x2y1)]
+
+		(True, True,     False,True, 
+		 True, True,     True, True ) -> [(x1z2, y2z2, x1y2)]
+
+		(True, True,     True, False,
+		 True, True,     True, True ) -> [(x2z2, y2z2, x2y2)]
+
+		(True, True,     True, True, 
+		 True, True,     False,True ) -> [(x1z2, y1z2, x1y1)]
+
+		(True, True,     True, True, 
+		 True, True,     True, False) -> [(x2z2, y1z2, x2y1)]
+
+		-- z flat + 1
+
+		(False,False,    True, False,
+		 False,False,    True, True) -> [(x1y1,x2y1,x2z2), (x1y1,x2z2,y2z2), (x1y1,y2z2,x1y2)]
+
+		(True, True,    False,True,
+		 True, True,    False,False) -> [(x1y1,x2y1,x2z2), (x1y1,x2z2,y2z2), (x1y1,y2z2,x1y2)]
+
+		(False,False,    False,True,
+		 False,False,    True, True) -> [(x2y1,x1y1,x1z2), (x2y1,x1z2,y2z2), (x2y1,y2z2,x2y2)]
+
+		(True, True,    True, False,
+		 True, True,    False,False) -> [(x2y1,x1y1,x1z2), (x2y1,x1z2,y2z2), (x2y1,y2z2,x2y2)]
+
+		(False,False,    True, True,
+		 False,False,    True, False) -> [(x1y2,x2y2,x2z2), (x1y2,x2z2,y1z2), (x1y2,y1z2,x1y1)]
+
+		(True, True,    False,False,
+		 True, True,    False,True ) -> [(x1y2,x2y2,x2z2), (x1y2,x2z2,y1z2), (x1y2,y1z2,x1y1)]
+
+		(False,False,    True, True,
+		 False,False,    False,True) -> [(x2y2,x1y2,x1z2), (x2y2,x1z2,y1z2), (x2y2,y1z2,x2y1)]
+
+		(True, True,    False,False,
+		 True, True,    True, False) -> [(x2y2,x1y2,x1z2), (x2y2,x1z2,y1z2), (x2y2,y1z2,x2y1)]
+
+
+
+		(True, False,    False,False,
+		 True, True,     False,False) -> [(x1y1,x2y1,x2z1), (x1y1,x2z1,y2z1), (x1y1,y2z1,x1y2)]
+
+		(False,True,     True, True,
+		 False,False,     True, True) -> [(x1y1,x2y1,x2z1), (x1y1,x2z1,y2z1), (x1y1,y2z1,x1y2)]
+
+		(False,True,    False,False,
+		 True, True,    False,False) -> [(x2y1,x1y1,x1z1), (x2y1,x1z1,y2z1), (x2y1,y2z1,x2y2)]
+
+		(True, False,     True, True,
+		 False,False,     True, True) -> [(x2y1,x1y1,x1z1), (x2y1,x1z1,y2z1), (x2y1,y2z1,x2y2)]
+
+		(True, True,    False,False,
+		 True, False,    False,False) -> [(x1y2,x2y2,x2z1), (x1y2,x2z1,y1z1), (x1y2,y1z1,x1y1)]
+
+		(False,False,     True, True,
+		 False,True,     True, True) -> [(x1y2,x2y2,x2z1), (x1y2,x2z1,y1z1), (x1y2,y1z1,x1y1)]
+
+		(True, True,    False,False,
+		 False,True,    False,False) -> [(x2y2,x1y2,x1z1), (x2y2,x1z1,y1z1), (x2y2,y1z1,x2y1)]
+
+		(False,False,     True, True,
+		 True, False,     True, True) -> [(x2y2,x1y2,x1z1), (x2y2,x1z1,y1z1), (x2y2,y1z1,x2y1)]
+
+		-- y flat + 1
+
+		(True, False,    True, True,
+		 True, False,    True, False) -> [(y2z1,x2y2,x2z2),(y2z1,x2z2,y1z1),(y1z1,x2z2,y1z2)]
+
+		(False,True,     False,False,
+		 False,True,     False,True ) -> [(y2z1,x2y2,x2z2),(y2z1,x2z2,y1z1),(y1z1,x2z2,y1z2)]
+
+		(True, False,    True, False,
+		 True, False,    True, True ) -> [(y1z1,x2y1,x2z2),(y1z1,x2z2,y2z1),(y2z1,x2z2,y2z2)]
+
+		(False,True,     False,True,
+		 False,True,     False,False) -> [(y1z1,x2y1,x2z2),(y1z1,x2z2,y2z1),(y2z1,x2z2,y2z2)]
+
+		(False,True,     True, True,
+		 False,True,     False,True ) -> [(y2z1,x1y2,x1z2),(y2z1,x1z2,y1z1),(y1z1,x1z2,y1z2)]
+
+		(True, False,    False,False,
+		 True, False,    True, False) -> [(y2z1,x1y2,x1z2),(y2z1,x1z2,y1z1),(y1z1,x1z2,y1z2)]
+
+		(False,True,     False,True,
+		 False,True,     True, True ) -> [(y1z1,x1y1,x1z2),(y1z1,x1z2,y2z1),(y2z1,x1z2,y2z2)]
+
+		(True, False,    True, False,
+		 True, False,    False,False) -> [(y1z1,x1y1,x1z2),(y1z1,x1z2,y2z1),(y2z1,x1z2,y2z2)]
+
+
+
+		(True, True,    True, False,
+		 True, False,    True, False) -> [(y2z2,x2y2,x2z1),(y2z2,x2z1,y1z2),(y1z2,x2z1,y1z1)]
+
+		(False,False,    False,True,
+		 False,True,     False,True ) -> [(y2z2,x2y2,x2z1),(y2z2,x2z1,y1z2),(y1z2,x2z1,y1z1)]
+
+		(True, False,    True, False,
+		 True, True,     True, False) -> [(y1z2,x2y1,x2z1),(y1z2,x2z1,y2z2),(y2z2,x2z1,y2z1)]
+
+		(False,True,     False,True,
+		 False,False,    False,True) -> [(y1z2,x2y1,x2z1),(y1z2,x2z1,y2z2),(y2z2,x2z1,y2z1)]
+
+		(True, True,     False,True,
+		 False,True,     False,True) -> [(y2z2,x1y2,x1z1),(y2z2,x1z1,y1z2),(y1z2,x1z1,y1z1)]
+
+		(False,False,    True, False,
+		 True, False,    True, False) -> [(y2z2,x1y2,x1z1),(y2z2,x1z1,y1z2),(y1z2,x1z1,y1z1)]
+
+		(False,True,     False,True,
+		 True, True,     False,True) -> [(y1z2,x1y1,x1z1),(y1z2,x1z1,y2z2),(y2z2,x1z1,y2z1)]
+
+		(True, False,    True, False,
+		 False,False,    True, False) -> [(y1z2,x1y1,x1z1),(y1z2,x1z1,y2z2),(y2z2,x1z1,y2z1)]
+
+
+
+		-- x flat +1
+
+		(True, True,     True, True,
+		 False,False,    True, False) -> [(x1z1,x2z1,x1y1),(x1y1,x2z1,x2z2),(x1y1,x2z2,y1z2)]
+
+		(False,False,    False,False,
+		 True, True,     False,True ) -> [(x1z1,x2z1,x1y1),(x1y1,x2z1,x2z2),(x1y1,x2z2,y1z2)]
+
+		(False,False,    True, False,
+		 True, True,     True, True) -> [(x1z1,x2z1,x1y2),(x1y2,x2z1,x2z2),(x1y2,x2z2,y2z2)]
+
+		(True, True,     False,True,
+		 False,False,    False,False) -> [(x1z1,x2z1,x1y2),(x1y2,x2z1,x2z2),(x1y2,x2z2,y2z2)]
+
+		(True, True,     True, True,
+		 False,False,    False,True) -> [(x2z1,x1z1,x2y1),(x2y1,x1z1,x1z2),(x2y1,x1z2,y1z2)]
+
+		(False,False,    False,False,
+		 True, True,     True, False) -> [(x2z1,x1z1,x2y1),(x2y1,x1z1,x1z2),(x2y1,x1z2,y1z2)]
+
+		(False,False,    False,True,
+		 True, True,     True, True) -> [(x2z1,x1z1,x2y2),(x2y2,x1z1,x1z2),(x2y2,x1z2,y2z2)]
+
+		(True, True,     True, False,
+		 False,False,    False,False) -> [(x2z1,x1z1,x2y2),(x2y2,x1z1,x1z2),(x2y2,x1z2,y2z2)]
+
+
+		(True, True,     True, True,
+		 True, False,    False,False) -> [(x1z2,x2z2,x1y1),(x1y1,x2z2,x2z1),(x1y1,x2z1,y1z1)]
+
+		(False,False,    False,False,
+		 False,True,     True, True ) -> [(x1z2,x2z2,x1y1),(x1y1,x2z2,x2z1),(x1y1,x2z1,y1z1)]
+
+		(True, False,    False,False,
+		 True, True,     True, True ) -> [(x1z2,x2z2,x1y2),(x1y2,x2z2,x2z1),(x1y2,x2z1,y2z1)]
+
+		(False,True,     True, True,
+		 False,False,    False,False) -> [(x1z2,x2z2,x1y2),(x1y2,x2z2,x2z1),(x1y2,x2z1,y2z1)]
+
+		(True, True,     True, True,
+		 False,True,     False,False) -> [(x2z2,x1z2,x2y1),(x2y1,x1z2,x1z1),(x2y1,x1z1,y1z1)]
+
+		(False,False,    False,False,
+		 True, False,    True, True) -> [(x2z2,x1z2,x2y1),(x2y1,x1z2,x1z1),(x2y1,x1z1,y1z1)]
+
+		(False,True,     False,False,
+		 True, True,     True, True) -> [(x2z2,x1z2,x2y2),(x2y2,x1z2,x1z1),(x2y2,x1z1,y2z1)]
+
+		(True, False,    True, True,
+		 False,False,    False,False) -> [(x2z2,x1z2,x2y2),(x2y2,x1z2,x1z1),(x2y2,x1z1,y2z1)]
+
+
+
+		(True, True,     True, False,
+		 True, False,    False,False) -> [(x1y1,x1z2,y1z1),(y1z1,x1z2,y2z2),(y1z1,y2z2,x2z1),(x2z1,y2z2,x2y2)]
+
+		(False,False,    False,True,
+		 False,True,     True, True ) -> [(x1y1,x1z2,y1z1),(y1z1,x1z2,y2z2),(y1z1,y2z2,x2z1),(x2z1,y2z2,x2y2)]
+
+		(True, True,     False,True,
+		 False,True,     False,False) -> [(x2y1,x2z2,y1z1),(y1z1,x2z2,y2z2),(y1z1,y2z2,x1z1),(x1z1,y2z2,x1y2)]
+
+		(False,False,    True, False,
+		 True, False,    True, True ) -> [(x2y1,x2z2,y1z1),(y1z1,x2z2,y2z2),(y1z1,y2z2,x1z1),(x1z1,y2z2,x1y2)]
+
+
+
+
+		(True, False,    False,False,
+		 True, True,     True, False) -> [(x1y2,x1z2,y2z1),(y2z1,x1z2,y1z2),(y2z1,y1z2,x2z1),(x2z1,y1z2,x2y1)]
+
+		(False,True,     True, True,
+		 False,False,    False,True ) -> [(x1y2,x1z2,y2z1),(y2z1,x1z2,y1z2),(y2z1,y1z2,x2z1),(x2z1,y1z2,x2y1)]
+
+		(False,True,     False,False,
+		 True, True,     False,True ) -> [(x2y2,x2z2,y2z1),(y2z1,x2z2,y1z2),(y2z1,y1z2,x1z1),(x1z1,y1z2,x1y1)]
+
+		(True, False,    True, True,
+		 False,False,    True, False) -> [(x2y2,x2z2,y2z1),(y2z1,x2z2,y1z2),(y2z1,y1z2,x1z1),(x1z1,y1z2,x1y1)]
+
+
+
+
+		_ -> []
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/implicit.cabal b/implicit.cabal
new file mode 100644
--- /dev/null
+++ b/implicit.cabal
@@ -0,0 +1,34 @@
+Name:                implicit
+Version:             0.0.0
+cabal-version:       >= 1.6
+Synopsis:            Math-inspired programmatic 2&3D CAD: CSG, bevels, and shells; gcode export..
+Description:         A math-inspired programmatic CAD library in haskell.
+                     Build objects with constructive solid geometry, bevels,
+                     shells and more in 2D & 3D. Then export to SVGs, STLs, 
+                     or produce gcode directly!
+License:             GPL
+License-file:        LICENSE
+Author:              Christopher Olah
+Maintainer:          Christopher Olah <chris@colah.ca>
+Homepage:            https://github.com/colah/ImplicitCAD
+build-type:          Simple
+Category:            Graphics
+
+Library
+    Build-Depends:       base >= 3 && < 5, parsec, hashmap, parallel, containers
+    Exposed-Modules:   
+        Graphics.Implicit
+        Graphics.Implicit.Definitions
+        Graphics.Implicit.Export
+        Graphics.Implicit.ExtOpenScad
+        Graphics.Implicit.MathUtil
+        Graphics.Implicit.Operations
+        Graphics.Implicit.Primitives
+        Graphics.Implicit.SaneOperators
+        Graphics.Implicit.Tracing
+        Graphics.Implicit.Tracing.GetTriangles
+
+source-repository head
+    type:            git
+    location:        https://github.com/colah/ImplicitCAD.git
+
