Shades of Gray
Last year I drew some things, and today I recreated one of them using Haskell with the Diagrams library. It features a circular Gray code with five bits, giving 32 possible combinations. A Gray code has the property that neighbouring combinations change only in one position, which is useful for detecting errors in rotary encoders.
Here is the source code:
{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-} import Diagrams.Prelude hiding (size) import Diagrams.Backend.SVG.CmdLine (B, defaultMain) main :: IO () main = defaultMain diagram diagram :: Diagram B diagram = bg white . frame 0.125 . centerXY . mconcat $ [ ring 6 2 1 , ring 5 4 2 , ring 4 8 4 , ring 3 16 8 , ring 2 16 0 , txt ] ring :: Double -> Int -> Int -> Diagram B ring inr count offset = mconcat . zipWith (cell inr) [0..31] . drop offset . cycle $ ( replicate count False ++ replicate count True ) cell :: Double -> Double -> Bool -> Diagram B cell inr angle flag = rotate (angle / 32 @@ turn) . fc (if flag then dark else light) . lc white . translate (r2 (i, 0)) . strokeT . closeTrail $ mconcat [ p2 (i, 0) ~~ p2 (o, 0) , arc' o h t , rotate t $ p2 (o, 0) ~~ p2 (i, 0) , arc' i (rotate t h) t' ] where t = 1 / 32 @@ turn t' = -1 / 32 @@ turn i = size inr o = size (inr + 1) h = direction (r2 (1, 0)) light, dark :: Colour Double light = sRGB 0.7 0.7 0.7 dark = sRGB 0.3 0.3 0.3 size :: Double -> Double size r = exp ((r - 7) / 5) txt :: Diagram B txt = scale 0.125 . centerXY . vcat $ centerXY . atop (translateY 0.4 $ strutY 0.8) . font "LMSans10" . italic . fontSizeL 1 . text <$> words "32 Shades of Gray"
I had some frustrations until I realized that fontSizeL was what I needed to make the text change size when rendering at different sizes.