packages feed

OpenSCAD (empty) → 0.1.0.0

raw patch · 6 files changed

+648/−0 lines, 6 filesdep +Cabaldep +HUnitdep +basesetup-changed

Dependencies added: Cabal, HUnit, base, colour, filepath, test-framework, test-framework-hunit

Files

+ Graphics/OpenSCAD.hs view
@@ -0,0 +1,429 @@+{- |+Module      : Graphics.OpenSCAD+Description : Type-checked wrappers for the OpenSCAD primitives.+Copyright   : © 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
+ Graphics/OpenSCAD/Unicode.hs view
@@ -0,0 +1,44 @@+{-# LANGUAGE UnicodeSyntax #-}++{-+Module      : Graphics.OpenSCAD.Unicode+Description : Unicode operators so you can write @Solid@ expressions.+Copyright   : © 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 ∆++-- | (∪) = 'union'+--+-- U+222A, UNION+(∪) :: Solid -> Solid -> Solid+a ∪ b = union [a, b]++-- | (∩) = 'intersection'+--+-- U+2229, INTERSECTION+(∩) :: Solid -> Solid -> Solid+a ∩ b = intersection [a, b]++-- | (∖) = 'difference'+--+-- U+2216, SET MINUS+(∖):: Solid -> Solid -> Solid+(∖) = difference++-- | (∆) = Symmetric difference+--+-- U+2206, INCREMENT+(∆) :: Solid -> Solid -> Solid+a ∆ b = (a ∖ b) ∪ (b ∖ a)+
+ LICENSE view
@@ -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.
+ OpenSCAD.cabal view
@@ -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
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ UnitTest.hs view
@@ -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