diff --git a/Graphics/OpenSCAD.hs b/Graphics/OpenSCAD.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/OpenSCAD.hs
@@ -0,0 +1,429 @@
+{- |
+Module      : Graphics.OpenSCAD
+Description : Type-checked wrappers for the OpenSCAD primitives.
+Copyright   : &#xa9; Mike Meyer, 2014
+License     : BSD4
+Maintainer  : mwm@mired.org
+Stability   : experimental
+
+The Graphics.OpenSCAD module provides abstract data types for creating
+OpenSCAD model definitions calls, along with a function to render it
+as a string, and some utilities. The primary goal is that the output
+should always be valid OpenSCAD. If you manage to generate OpenSCAD
+source that causes OpenSCAD to complain, please open an issue.
+
+Standard usage is to have a @main@ function that looks like:
+
+@
+main = draw $ /Solid/
+@
+
+and then set your IDE's compile command to use @runhaskell@ or
+equivalent to run your code and send the output to a .scad file. Open
+that file in OpenSCAD, and set it to automatically reload if the file
+changes. Recompiling your program will cause the model to be loaded
+and displayed by OpenSCAD.
+
+The type constructors are generally not exported, with functions being
+exported in their stead.  This allows extra checking to be done on
+those that need it.  It also provides consistency, as otherwise you'd
+have to remember whether 'box' is a constructor or a convenience
+function, etc.
+
+Because of this, the constructors are not documented, the exported
+functions are. The documentation is generally just the corresponding
+OpenSCAD function name, along with the names of the arguments from the
+OpenSCAD documentation. If no OpenSCAD function name is given, then
+it's the same as the 'Graphics.OpenSCAD' function. You should check
+the OpenSCAD documentation for usage information.
+
+-}
+
+module Graphics.OpenSCAD (
+  -- * Basic data types
+  Solid,
+  Shape,
+  Facet,
+  -- * Type aliases to save typing
+  Vector, Point,
+  -- * Rendering functions
+  render, draw,
+  -- * Constructors
+  -- ** 'Solid's
+  sphere, box, cube, cylinder, obCylinder, rectangle3d, square3d, circle3d,
+  import3d, linearExtrude, rotateExtrude,
+  -- ** 'Shape's
+  rectangle, square, circle, import2d, projection,
+ -- * Combinations of 'Solid's
+  union, intersection, difference, minkowski, hull,
+  -- * Transformations
+  -- ** 'Solid's
+  scale, resize, rotate, translate, mirror, multMatrix, color, transparent, up,
+  projection3d, 
+  -- ** 'Shape's
+  scale2d, resize2d, rotate2d, translate2d, mirror2d,
+  -- ** General convenience functions
+  diam,
+  -- * Convenience functions for 'Facet's.
+  var, fn, fs, fa, def,
+  module Colours)
+
+where
+
+import Data.Colour (Colour, AlphaColour, alphaChannel, darken, over, black)
+import Data.Colour.SRGB (channelRed, channelBlue, channelGreen, toSRGB)
+import System.FilePath (FilePath)
+import qualified Data.Colour.Names as Colours
+
+-- | 'Vector' is used where OpenSCAD expects an OpenSCAD @vector@ of length 3.
+type Vector = (Float, Float, Float)
+
+-- | 'Point' is used where OpenSCAD expects an OpenSCAD @vector@ of length 3.
+type Point = (Float, Float)
+
+-- | These are for @Poly*s@, which don't work yet.
+type Path = [Int]
+type Face = (Int, Int, Int)
+
+type Transform = ((Float, Float, Float, Float), (Float, Float, Float, Float),
+                  (Float, Float, Float, Float), (Float, Float, Float, Float))
+
+
+-- While it's tempting to add more options to Solid, don't do it. Instead,
+-- add functions that add that functionality, like cube vs. box.
+--
+-- Missing at this time: Poly*s, some special features.
+-- There's also no way to set $f? vars globally, due to an OpenSCAD quirk.
+
+-- | A 'Facet' is used to set one of the special variables that
+-- control the mesh used during generation of circular objects. They
+-- appear as arguments to various constructors, as well as in the
+-- 'var' function to set them for the argument objects.
+data Facet = Fa Float | Fs Float | Fn Int | Def deriving Show
+
+-- | A 'Shape' is a two-dimensional object. They are a separate type
+-- so that Haskell can type check that we aren't using a 2d operation
+-- on a 3d shape, or vice versa. Unfortunately, this means the
+-- dynamically typed functions that accept either - and possibly
+-- generate either - need to have two versions of those functions.  I
+-- believe the 2d creation functions are more common for 2d objects,
+-- but the 3d transformation functions are more common. Hence the 2d
+-- creation functions (which have the names of 2d objects like circle,
+-- square, etc.) that create 'Solid's have @3d@ appended, but the 3d
+-- version of transformations that have both 2d and 3d versions have
+-- @3d@ appended.
+data Shape =
+             Rectangle Float Float
+           | Circle Float Facet
+           -- add | Polygon [Point] [Path] Int
+           | Import2d FilePath
+           | Projection Bool Solid
+           -- 2d versions of the transformations
+           | Scale2d Point Shape
+           | Resize2d Point Shape
+           | Rotate2d Point Shape
+           | Translate2d Point Shape
+           | Mirror2d Point Shape
+           deriving Show
+
+-- | A 'Solid' is a solid object in OpenSCAD. Since we don't have
+-- optional or named objects, some constructors appear twice to allow
+-- two different variants to be used. And of course, they all have all
+-- their arguments.
+data Solid =
+             Sphere Float Facet
+           | Box Float Float Float
+           | Cylinder Float Float Facet
+           | ObCylinder Float Float Float Facet
+           -- add | Polyhedron [Vector] [Face] Int
+           | Import3d FilePath
+           | Shape Shape
+           -- Combinations
+           | Union [Solid]
+           | Intersection [Solid]
+           | Difference Solid Solid
+           | Minkowski [Solid]
+           | Hull [Solid]
+           -- Transformations
+           | Scale Vector Solid
+           | Resize Vector Solid
+           | Rotate Vector Solid
+           | Translate Vector Solid
+           | Mirror Vector Solid
+           | MultMatrix Transform Solid
+           | Color (Colour Float) Solid
+           | Transparent (AlphaColour Float) Solid
+           | LinearExtrude Float Float Point Int Int Facet Shape
+           | RotateExtrude Int Facet Shape
+           -- Mesh control
+           | Var Facet [Solid]
+           deriving Show
+
+-- | 'render' does all the real work. It will walk the AST for a 'Solid',
+-- returning an OpenSCAD program in a 'String'.
+render :: Solid -> String
+render (Sphere x f) = "sphere(" ++ show x ++ rFacet f ++ ");\n\n"
+render (Box x y z) =
+  "cube([" ++ show x ++ "," ++ show y ++ "," ++ show z ++ "]);\n"
+render (Cylinder r h f) =
+  "cylinder(r=" ++ show r ++ ",h=" ++ show h ++ rFacet f ++ ");\n\n"
+render (ObCylinder r1 h r2 f) =
+    "cylinder(r1=" ++ show r1 ++ ",h=" ++ show h ++ ",r2=" ++ show r2 ++ rFacet f
+    ++ ");\n\n"
+render (Import3d f) = "import(" ++ f ++");\n\n"
+render (Shape s) = rShape s
+render (Union ss) = rList "union()" ss
+render (Intersection ss) = rList "intersection()" ss
+render (Difference s1 s2) = "difference(){" ++ render s1 ++ render s2 ++ "}\n\n"
+render (Minkowski ss) = rList "minkowski()" ss
+render (Hull ss) = rList "hull()" ss
+render (Scale v s) = rVecSolid "scale" v s
+render (Resize v s) = rVecSolid "resize" v s
+render (Translate v s) = rVecSolid "translate" v s
+render (Rotate v s) = "rotate(a=" ++ rVector v ++ ")" ++ render s
+render (Mirror v s) = rVecSolid "mirror" v s
+render (MultMatrix (a, b, c, d) s) =
+    "multmatrix([" ++ rQuad a ++ "," ++ rQuad b ++ "," ++ rQuad c ++ ","
+    ++ rQuad d ++"])\n" ++ render s
+render (Color c s) = let r = toSRGB c in
+    "color(" ++ rVector (channelRed r, channelGreen r, channelBlue r) ++ ")\n"
+    ++ render s
+render (Transparent c s) =
+    "color(" ++ rQuad (channelRed r, channelGreen r, channelBlue r, a) ++ ")"
+    ++ render s
+    where r = toSRGB $ toPure c
+          a = alphaChannel c
+          toPure ac = if a > 0 then darken (recip a) (ac `over` black) else black
+render (LinearExtrude h t sc sl c f sh) =
+    "linear_extrude(height=" ++ show h ++ ",twist=" ++ show t ++ ",scale="
+    ++ rPoint sc ++ ",slices=" ++ show sl ++ ",convexity=" ++ show c ++ rFacet f
+    ++ ")" ++ rShape sh
+render (RotateExtrude c f sh) =
+  "rotate_extrude(convexity=" ++ show c ++ rFacet f ++ ")" ++ rShape sh
+render (Var (Fa f) ss) = rList ("assign($fa=" ++ show f ++ ")") ss
+render (Var (Fs f) ss) = rList ("assign($fs=" ++ show f ++ ")") ss
+render (Var (Fn n) ss) = rList ("assign($fn=" ++ show n ++ ")") ss
+
+-- | 'draw' is a convenience function to write the rendered 'Solid' to
+-- standard output.
+draw = putStrLn . render
+
+
+-- utilities for rendering Shapes.
+rShape (Rectangle r f) = "square([" ++ show r ++ "," ++ show f ++ "]);\n\n"
+rShape (Circle r f) = "circle(" ++ show r ++ rFacet f ++ ");\n\n"
+rShape (Import2d f) = "import(" ++ f ++ ");\n\n"
+rShape (Projection c s) =
+  "projection(cut=" ++ (if c then "true)" else "false)") ++ render s
+rShape (Scale2d p s) = "scale(" ++ rPoint p ++ ")" ++ rShape s
+rShape (Resize2d p s) = "resize(" ++ rPoint p ++ ")" ++ rShape s
+rShape (Rotate2d p s) = "rotate(" ++ rPoint p ++ ")" ++ rShape s
+rShape (Translate2d p s) = "translate(" ++ rPoint p ++ ")" ++ rShape s
+rShape (Mirror2d p s) = "mirror(" ++ rPoint p ++ ")" ++ rShape s
+
+-- And some misc. rendering utilities.
+rList n ss = n ++ "{\n" ++  concatMap render ss ++ "}"
+rSolid n s = n ++ "()\n" ++ render s
+rVector (a, b, c) = "[" ++ show a ++ "," ++ show b ++ "," ++ show c ++ "]"
+rVecSolid n v s = n ++ "(" ++ rVector v ++ ")\n" ++ render s
+rQuad (w, x, y, z) =
+  "[" ++ show w ++ "," ++ show x ++ "," ++ show y ++ "," ++ show z ++ "]"
+rFacet Def = ""
+rFacet f = "," ++ showFacet f
+rPoint (x, y)  = "[" ++ show x ++ "," ++ show y ++ "]"
+
+-- render a facet setting.
+showFacet :: Facet -> String
+showFacet (Fa f) = "$fa=" ++ show f
+showFacet (Fs f) = "$fs=" ++ show f
+showFacet (Fn n) = "$fn=" ++ show n
+showFacet Def    = ""
+
+-- | Create a sphere with @sphere /radius 'Facet'/@.
+sphere :: Float -> Facet -> Solid
+sphere = Sphere
+
+-- | Create a box with @cube /x-size y-size z-size/@
+box :: Float -> Float -> Float -> Solid
+box = Box
+
+-- | A convenience function for creating a cube as a 'box' with all
+-- sides the same length.
+cube :: Float -> Solid
+cube x = Box x x x
+
+-- | Create a cylinder with @cylinder /radius height 'Facet'/@.
+cylinder :: Float -> Float -> Facet -> Solid
+cylinder = Cylinder
+
+-- | Create an oblique cylinder with @cylinder /radius1 height radius2
+-- 'Facet'/@
+obCylinder :: Float -> Float -> Float -> Facet -> Solid
+obCylinder = ObCylinder
+
+-- | __UNTESTED__ 'import3d' is @import /filename/@, where /filename/
+-- is an stl file.  It's /3d/ because import is a key word.
+import3d :: FilePath -> Solid
+import3d = Import3d
+
+-- | __UNTESTED__ 'import2d' is @import /filename/@, where /filename/
+-- is an image or other 2d object.
+import2d :: FilePath -> Shape
+import2d = Import2d
+
+-- | Create the union of a list of 'Solid's.
+union :: [Solid] -> Solid
+union = Union
+
+-- | Create the intersection of a list of 'Solid's.
+intersection :: [Solid] -> Solid
+intersection = Intersection
+
+-- | The difference between two 'Solid's.
+difference :: Solid -> Solid -> Solid
+difference = Difference
+
+-- | The Minkowski sum of a list of 'Solid's.
+minkowski :: [Solid] -> Solid
+minkowski = Minkowski
+
+-- | The convex hull of a list of 'Solid's.
+hull :: [Solid] -> Solid
+hull = Hull
+
+-- | Scale a 'Solid', specifying the scale factor for each axis.
+scale :: Vector -> Solid -> Solid
+scale = Scale
+
+-- | __UNTESTED__ Resize a 'Solid' to occupy the given dimensions.
+resize :: Vector -> Solid -> Solid
+resize = Resize
+
+-- | Rotate a 'Solid' by different amounts around each of the three axis.
+rotate :: Vector -> Solid -> Solid
+rotate = Rotate
+
+-- | Translate a 'Solid' along a 'Vector'.
+translate :: Vector -> Solid -> Solid
+translate = Translate
+
+-- | Mirror a 'Solid' across a plane intersecting the origin.
+mirror :: Vector -> Solid -> Solid
+mirror = Mirror
+
+-- | Transform a 'Solid' with a 'Transform' matrix.
+multMatrix :: Transform -> Solid -> Solid
+multMatrix = MultMatrix
+
+-- | A 'translate' that just goes up, since those seem to be common.
+up :: Float -> Solid -> Solid
+up f = Translate (0, 0, f)
+
+
+-- | Render a 'Solid' in a specific color. This doesn't us the
+-- OpenSCAD color model, but instead uses the 'Data.Colour' model. The
+-- 'Graphics.OpenSCAD' module rexports 'Data.Colour.Names' so you can
+-- conveniently say @'color' 'red' /'Solid'/@.
+color :: Colour Float -> Solid -> Solid
+color = Color
+
+-- | Render a 'Solid' in a transparent color. This uses the
+-- 'Data.Coulor.AphaColour' color model.
+transparent :: AlphaColour Float -> Solid -> Solid
+transparent = Transparent
+
+-- | Extrude a 'Shape' along a line with @linear_extrude@.
+linearExtrude :: Float         -- ^ height
+              -> Float         -- ^ twist
+              -> Point         -- ^ scale
+              -> Int           -- ^ slices
+              -> Int           -- ^ convexity
+              -> Facet
+              -> Shape         -- ^ to extrude
+              -> Solid
+linearExtrude = LinearExtrude
+
+-- | Rotate a 'Shape' around the origin with @rotate_extrude
+-- /convexity 'Facet' 'Shape'/@
+rotateExtrude ::  Int -> Facet -> Shape -> Solid
+rotateExtrude = RotateExtrude
+
+-- | Use 'diam' to turn a diameter into a radius for circles, spheres, etc.
+diam :: Float -> Float
+diam = (/ 2)
+
+-- | Create a rectangular 'Shape' with @rectangle /x-size y-size/@.
+rectangle :: Float -> Float -> Shape
+rectangle = Rectangle
+
+-- | Create a rectangular 'Solid' with @rectangle /x-size y-size/@.
+rectangle3d :: Float -> Float -> Solid
+rectangle3d w d = Shape $ Rectangle w d
+
+-- | 'square' is a 'rectangle' with both sides the same size.
+square :: Float -> Shape
+square s = rectangle s s
+
+-- | 'square3d' is a 'rectangle3d' with both sides the same size.
+square3d :: Float -> Solid
+square3d s = rectangle3d s s
+
+-- | Create a circular 'Shape' with @circle /radius/ 'Facet'@.
+circle :: Float -> Facet -> Shape
+circle = Circle
+
+-- | Create a circular 'Solid' with @circle /radius/ 'Facet'@.
+circle3d :: Float -> Facet -> Solid
+circle3d r f = Shape $ Circle r f
+
+-- | Project a 'Solid' into a 'Shape' with @projection /cut 'Solid'/@.
+projection :: Bool -> Solid -> Shape
+projection = Projection
+
+-- | Project a 'Solid' to a thin 'Solid' with @projection /cut 'Solid'/@.
+projection3d :: Bool -> Solid -> Solid
+projection3d c s = Shape $ Projection c s
+
+-- | 'scale2d' is 'scale' for 'Shape's.
+scale2d :: Point -> Shape -> Shape
+scale2d = Scale2d
+
+-- | 'resize2d' is 'resize' for 'Shape's.
+resize2d :: Point -> Shape -> Shape
+resize2d = Resize2d
+
+-- | 'rotate2d' is 'rotate' for 'Shape's.
+rotate2d :: Point -> Shape -> Shape
+rotate2d = Rotate2d
+
+-- | 'translate2d' is 'translate' for 'Shape's.
+translate2d :: Point -> Shape -> Shape
+translate2d = Translate2d
+
+-- | 'mirror2d' is 'mirror' for 'Shape's.
+mirror2d :: Point -> Shape -> Shape
+mirror2d = Mirror2d
+
+-- Convenience functions for Facets.
+
+-- Maybe this should have type [Facet] -> [Solid] -> [Solid]
+-- | 'var' uses @assign@ to set a special variable for the 'Solid's.
+var :: Facet -> [Solid] -> Solid
+var = Var
+
+-- | 'fa' is used to set the @$fa@ variable in a 'Facet' or 'var'.
+fa :: Float -> Facet
+fa = Fa
+
+-- | 'fs' is used to set the @$fs@ variable in a 'Facet' or 'var'.
+fs :: Float -> Facet
+fs = Fs
+
+-- | 'fn' is used to set the @$fn@ variable in a 'Facet' or 'var'.
+fn :: Int -> Facet
+fn = Fn
+
+-- | 'def' is used where a 'Facet' is needed but we don't want to change
+-- any of the values.
+def :: Facet
+def = Def
diff --git a/Graphics/OpenSCAD/Unicode.hs b/Graphics/OpenSCAD/Unicode.hs
new file mode 100644
--- /dev/null
+++ b/Graphics/OpenSCAD/Unicode.hs
@@ -0,0 +1,44 @@
+{-# LANGUAGE UnicodeSyntax #-}
+
+{-
+Module      : Graphics.OpenSCAD.Unicode
+Description : Unicode operators so you can write @Solid@ expressions.
+Copyright   : &#xa9; Mike Meyer, 2014
+License     : BSD4
+Maintainer  : mwm@mired.org
+Stability   : experimental
+-}
+
+module Graphics.OpenSCAD.Unicode where
+
+import Graphics.OpenSCAD
+
+infixl 6 ∪
+infixr 6 ∩
+infixl 9 ∖
+infixl 9 ∆
+
+-- | (&#x222A;) = 'union'
+--
+-- U+222A, UNION
+(∪) :: Solid -> Solid -> Solid
+a ∪ b = union [a, b]
+
+-- | (&#x2229;) = 'intersection'
+--
+-- U+2229, INTERSECTION
+(∩) :: Solid -> Solid -> Solid
+a ∩ b = intersection [a, b]
+
+-- | (&#x2216;) = 'difference'
+--
+-- U+2216, SET MINUS
+(∖):: Solid -> Solid -> Solid
+(∖) = difference
+
+-- | (&#x2206;) = Symmetric difference
+--
+-- U+2206, INCREMENT
+(∆) :: Solid -> Solid -> Solid
+a ∆ b = (a ∖ b) ∪ (b ∖ a)
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, Mike Meyer
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the name of Mike Meyer nor the names of other
+      contributors may be used to endorse or promote products derived
+      from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/OpenSCAD.cabal b/OpenSCAD.cabal
new file mode 100644
--- /dev/null
+++ b/OpenSCAD.cabal
@@ -0,0 +1,42 @@
+-- Initial OpenSCAD.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                OpenSCAD
+version:             0.1.0.0
+synopsis:            ADT wrapper and renderer for OpenSCAD models.
+description:         An algebraic data type for describing OpenSCAD models,
+                     functions to make building such models easier, and
+                     functions for rendering an ADT into an OpenSCAD program.
+homepage:            https://graphics-openscad.googlecode.com/
+license:             BSD3
+license-file:        LICENSE
+author:              Mike Meyer
+maintainer:          mwm@mired.org
+-- copyright:           
+category:            Graphics
+build-type:          Simple
+extra-source-files:
+cabal-version:       >=1.10
+
+library
+  exposed-modules:     Graphics.OpenSCAD, Graphics.OpenSCAD.Unicode
+  -- other-modules:       
+  other-extensions:    UnicodeSyntax
+  build-depends:       base >=4.6 && <4.8, colour >=2.3 && <2.4, filepath >=1.3 && <1.4
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
+
+Test-Suite Units
+  type:        exitcode-stdio-1.0
+  main-is:     UnitTest.hs
+  build-depends: base >=4.6 && <4.8, colour >=2.3 && <2.4, filepath >=1.3 && <1.4, HUnit >=1.2 && <1.4, Cabal >= 1.18 && < 1.21, test-framework-hunit >=0.3 && < 0.5, test-framework >=0.8 && <1.0
+  default-language:    Haskell2010
+
+source-repository head
+  type:           hg
+  location:       https://code.google.com/p/graphics-openscad/
+
+source-repository this
+  type:           hg
+  location:       https://code.google.com/p/graphics-openscad/
+  tag:            0.1
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/UnitTest.hs b/UnitTest.hs
new file mode 100644
--- /dev/null
+++ b/UnitTest.hs
@@ -0,0 +1,101 @@
+module Main where
+
+import Data.Monoid
+import Test.HUnit
+import Test.Framework
+import Test.Framework.Providers.HUnit
+
+import Graphics.OpenSCAD
+import Data.Colour.Names
+import Data.Colour (withOpacity)
+
+sw = concat . words
+st n e a = testCase n $ (sw e) @=?(sw $ render a)
+
+main = defaultMainWithOpts [
+  st "sphere 1"     "sphere(1.0);"                    (sphere 1 def),
+  st "sphere 2"     "sphere(2.0,$fn=100);"            (sphere 2 $ fn 100),
+  st "sphere 3"     "sphere(2.0,$fa=5.0);"            (sphere 2 $ fa 5),
+  st "sphere 4"     "sphere(2.0,$fs=0.1);"            (sphere 2 $ fs 0.1),
+  st "box"          "cube([1.0,2.0,3.0]);"            (box 1 2 3),
+  st "cube"         "cube([2.0,2.0,2.0]);"            (cube 2),
+  st "cylinder 1"   "cylinder(r=1.0,h=2.0);"          (cylinder 1 2 def),
+  st "cylinder 2"   "cylinder(r=1.0,h=2.0,$fs=0.6);"  (cylinder 1 2 $ fs 0.6),
+  st "cylinder 3"   "cylinder(r=1.0,h=2.0,$fn=10);"   (cylinder 1 2 $ fn 10),
+  st "cylinder 4"   "cylinder(r=1.0,h=2.0,$fa=30.0);" (cylinder 1 2 $ fa 30),
+  st "obCylinder 1" "cylinder(r1=1.0,h=2.0,r2=2.0);"  (obCylinder 1 2 2 def),
+  st "obCylinder 2" "cylinder(r1=1.0,h=2.0,r2=2.0,$fs=0.6);"
+     (obCylinder 1 2 2 $ fs 0.6),
+  st "obCylinder 3" "cylinder(r1=1.0,h=2.0,r2=2.0,$fn=10);"
+     (obCylinder 1 2 2 $ fn 10),
+  st "obCylinder 4" "cylinder(r1=1.0,h=2.0,r2=2.0,$fa=30.0);"
+     (obCylinder 1 2  2 $ fa 30),
+  -- polyhedron & import3D goes here
+  st "rectangle"    "square([2.0,3.0]);"              (rectangle3d 2 3),
+  st "square"       "square([2.0,2.0]);"              (square3d 2),
+  st "circle 1"     "circle(1.0);"                    (circle3d 1 def),
+  st "circle 2"     "circle(2.0,$fn=100);"            (circle3d 2 $ fn 100),
+  st "circle 3"     "circle(2.0,$fa=5.0);"            (circle3d 2 $ fa 5),
+  st "circle 4"     "circle(2.0,$fs=0.1);"            (circle3d 2 $ fs 0.1),
+  -- polygon & import2D goes here
+  st "projection"   "projection(cut=false)scale([10.0,10.0,10.0])difference(){translate([0.0,0.0,1.0])cube([1.0,1.0,1.0]);translate([0.25,0.25,0.0])cube([0.5,0.5,3.0]);}"
+     (projection3d False $ scale (10, 10, 10) $ difference (up 1 (cube 1)) $ translate (0.25, 0.25, 0) (box 0.5 0.5 3)),
+  -- Transformations
+  st "scale"        "scale([0.5,1.0,2.0])cube([1.0,1.0,1.0]);"
+     (scale(0.5, 1, 2) $ cube 1),
+  -- resize goes here
+  st "rotate 1" "rotate(a=[180.0,0.0,0.0])cube([2.0,2.0,2.0]);"
+     (rotate (180, 0, 0) $ cube 2),
+  st "rotate 2" "rotate(a=[0.0,180.0,0.0])cube([2.0,2.0,2.0]);"
+     (rotate (0, 180, 0) $ cube 2),
+  st "rotate 3" "rotate(a=[0.0,180.0,180.0])cube([2.0,2.0,2.0]);"
+     (rotate (0, 180, 180) $ cube 2),
+  st "mirror 1" "mirror([1.0,0.0,0.0])cube([2.0,2.0,2.0]);"
+     (mirror (1, 0, 0) $ cube 2),
+  st "mirror 2" "mirror([0.0,1.0,0.0])cube([2.0,2.0,2.0]);"
+     (mirror (0, 1, 0) $ cube 2),
+  st "mirror 3" "rotate(a=[0.0,1.0,1.0])cube([2.0,2.0,2.0]);"
+     (rotate (0, 1, 1) $ cube 2),
+  st "multmatrix" "multmatrix([[1.0,0.0,0.0,10.0],[0.0,1.0,0.0,20.0],[0.0,0.0,1.0,30.0],[0.0,0.0,0.0,1.0]])cylinder(r=2.0,h=3.0);"
+     (multMatrix ( (1, 0, 0, 10),
+                   (0, 1, 0, 20),
+                   (0, 0, 1, 30),
+                   (0, 0, 0,  1) ) $ cylinder 2 3 def),
+  st "color" "color([1.0,0.0,0.0])cube([1.0,1.0,1.0]);" (color red $ cube 1),
+  st "transparent" "color([1.0,0.0,0.0,0.7])cube([1.0,1.0,1.0]);"
+     (transparent (red `withOpacity` 0.7) $ cube 1),
+  st "linearExtrude 1"
+     "linear_extrude(height=10.0,twist=0.0,scale=[1.0,1.0],slices=10,convexity=10)circle(1.0);"
+     (linearExtrude 10 0 (1, 1) 10 10 def $ circle 1 def),
+  st "linearExtrude 2"
+     "linear_extrude(height=10.0,twist=100.0,scale=[1.0,1.0],slices=10,convexity=10)translate([2.0,0.0])circle(1.0);"
+     (linearExtrude 10 100 (1, 1) 10 10 def $ translate2d (2, 0) $ circle 1 def),
+  st "linearExtrude 3"
+     "linear_extrude(height=10.0,twist=500.0,scale=[1.0,1.0],slices=10,convexity=10)translate([2.0,0.0])circle(1.0);"
+     (linearExtrude 10 500 (1, 1) 10 10 def $ translate2d (2, 0) $ circle 1 def),
+  st "linearExtrude 4"
+     "linear_extrude(height=10.0,twist=360.0,scale=[1.0,1.0],slices=100,convexity=10)translate([2.0,0.0])circle(1.0);"
+     (linearExtrude 10 360 (1, 1) 100 10 def $ translate2d (2, 0) $ circle 1 def),
+  st "linearExtrude 5"
+     "linear_extrude(height=10.0,twist=360.0,scale=[1.0,1.0],slices=100,convexity=10,$fn=100)translate([2.0,0.0])circle(1.0);"
+     (linearExtrude 10 360 (1, 1) 100 10 (fn 100) $ translate2d (2, 0) $ circle 1 def),
+  st "linearExtrude 6"
+     "linear_extrude(height=10.0,twist=0.0,scale=[3.0,3.0],slices=100,convexity=10)translate([2.0,0.0])circle(1.0);"
+     (linearExtrude 10 0 (3, 3) 100 10 def $ translate2d (2, 0) $ circle 1 def),
+  st "linearExtrude 7"
+     "linear_extrude(height=10.0,twist=0.0,scale=[1.0,5.0],slices=100,convexity=10,$fn=100)translate([2.0,0.0])circle(1.0);"
+     (linearExtrude 10 0 (1, 5) 100 10 (fn 100) $ translate2d (2, 0)
+      $ circle 1 def),
+  st "rotate_extrude 1"
+     "rotate_extrude(convexity=10)translate([2.0,0.0])circle(1.0);"
+     (rotateExtrude 10 def $ translate2d (2, 0) $ circle 1 def),
+  st "rotate_extrude 2"
+     "rotate_extrude(convexity=10,$fn=100)translate([2.0,0.0])circle(1.0,$fn=100);"
+     (rotateExtrude 10 (fn 100) $ translate2d (2, 0) $ circle 1 $ fn 100),
+  st "facet 1" "assign($fn=100){sphere(2.0,$fn=100);}"
+     (var (fn 100) [sphere 2 $ fn 100]),
+  st "facet 2" "assign($fa=5.0){sphere(2.0,$fa=5.0);}"
+     (var (fa 5) [sphere 2 $ fa 5]),
+  st "facet 3" "assign($fs=0.1){sphere(2.0,$fs=0.1);}"
+     (var (fs 0.1) [sphere 2 $ fs 0.1])
+  ] mempty
