packages feed

implicit (empty) → 0.0.0

raw patch · 13 files changed

+1821/−0 lines, 13 filesdep +basedep +containersdep +hashmapsetup-changed

Dependencies added: base, containers, hashmap, parallel, parsec

Files

+ Graphics/Implicit.hs view
@@ -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+
+ Graphics/Implicit/Definitions.hs view
@@ -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 -> ℝ)+++
+ Graphics/Implicit/Export.hs view
@@ -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+
+ Graphics/Implicit/ExtOpenScad.hs view
@@ -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+
+ Graphics/Implicit/MathUtil.hs view
@@ -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)+
+ Graphics/Implicit/Operations.hs view
@@ -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) +
+ Graphics/Implicit/Primitives.hs view
@@ -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++
+ Graphics/Implicit/SaneOperators.hs view
@@ -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+++
+ Graphics/Implicit/Tracing.hs view
@@ -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-}+
+ Graphics/Implicit/Tracing/GetTriangles.hs view
@@ -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)]+++++		_ -> []+
+ LICENSE view
@@ -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.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ implicit.cabal view
@@ -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+