Happy Haskmas!
At the last Melbourne Haskell Meetup we got into the spirit by making Christmas trees in Haskell.
However, I recently have access to a 3D printer, and I’ve long wanted an excuse to try and use ImplicitCAD, so I set about trying to make a 3D version of Lyndon’s logo.
So of course, I love stack I created a new simple
project with stack new
and got started.
It turns out that ImplicitCAD
has a pretty nice and reasonably intuitive interface (similar to the code that one would write into OpenSCAD).
I built the 3D version of the logo by moving around rectangles, and by extruding a hand-drawn shape.
The cool thing about generating this image in fully-feature programming language is that I can build a tree of any size I like!
Here’s the (pretty verbose) code that gets me a tree of arbitrary depth:
ntree :: Integer -> SymbolicObj3
= finalObj
ntree n where
= 0.8
dec = 0 : [dec^j | j <- [0..(n-2)]]
ratios -- build up logo structure
= foldl f ((0, 0, 0), []) (zip [0..(n-1)] ratios)
((lx, ly, lz), objs) -- position of logos
= (40, 4, 0)
(x,y,z) f :: ((ℝ, ℝ, ℝ), [SymbolicObj3]) -> (Integer, Float) -> ((ℝ, ℝ, ℝ), [SymbolicObj3])
=
f ((x', y', z'), xs) (j, r) let newPos = (x' + r*x, y' + r*y, z' + r*z)
= dec ^ j
s = if (even j) then R else L
loc = translate newPos $ scale (s, s, s) (logoBauble loc)
obj3 in (newPos, obj3 : xs)
-- star
= (40.5, 24.5, 0)
(a,b,c) = dec ** (fromIntegral (n-3))
starScale = dec ** (fromIntegral n)
posScale = translate (lx + (posScale * a), ly + (posScale * b), lz + (posScale * c))
starObj $ scale (starScale, starScale, starScale) star
= union (starObj : objs) finalObj
Running this with n = 5 gives result in the following render in OpenSCAD:
So there you have it! You can view the source code here: github.com/silky/haskmas or download a ready-to-print STL from Thingiverse.
Have a happy Haskmas! :)