Phillip Trelford's Array

POKE 36879,255

Snowflakes

Welcome to day 2 of the F# Advent Calendar in English, and don’t miss Scott Wlaschin’s introduction to property-based testing from yesterday.

In A Christmas Carol Charles Dickens wrote of cold winters with snow as a matter of course. White Christmases were common during the Little Ice Age that lasted from the 1550s to the 1850s. Nowadays the chances of a snowfall on Christmas day are much lower, but the imagery of a white Christmas persists.

In this post we’ll generate our snowflakes instead.

Koch Snowflake

The Koch snowflake is a mathematical curve constructed from an equilateral triangle where each line segment is recursively altered:

Koch

The picture above was generated in the F# REPL, using WinForms to display a bitmap:

let snowflake (graphics:Graphics) length =
   use pen = new Pen(Color.White)
   let angle = ref 0.0
   let x = ref ((float width/2.0) - length/2.0)
   let y = ref ((float height/2.0) - length/3.0)
   let rec segment n depth =
      if depth = 0 then
         line n
      else
         segment (n/3.0) (depth-1)
         rotate -60.0
         segment (n/3.0) (depth-1)
         rotate 120.0
         segment (n/3.0) (depth-1)
         rotate -60.0
         segment (n/3.0) (depth-1)
   and line n =
      let r = !angle * Math.PI / 180.0
      let x2 = !x + cos(r) * n
      let y2 = !y + sin(r) * n
      graphics.DrawLine(pen, float32 !x,float32 !y, float32 x2, float32 y2)
      x := x2
      y := y2
   and rotate a =
      angle := !angle + a
   let depth = 5
   segment length depth
   rotate 120.0  
   segment length depth  
   rotate 120.0
   segment length depth

The full snippet is available on F# Snippets: http://fssnip.net/oA

Paper and Scissors

Snowflakes can be created by folding paper and cutting holes with scissors. We can get a similar effect using transparent polygons and rotational symmetry:

Paper

Here the polygons are selected randomly and like snowflakes each one is different:

let paperSnowflake () =   
   let image = new Bitmap(int width, int height)
   use graphics = Graphics.FromImage(image)  
   use brush = new SolidBrush(Color.Black)
   graphics.FillRectangle(brush, 0, 0, int width, int height)
   graphics.TranslateTransform(float32 (width/2.0),float32 (height/2.0))
   let color = Color.FromArgb(128,0,128,255)
   use brush = new SolidBrush(color)
   let rand = Random()
   let polys =
      [for i in 1..12 ->
         let w = rand.Next(20)+1 // width
         let h = rand.Next(20)+1 // height
         let m = rand.Next(h)    // midpoint
         let s = rand.Next(30)   // start
         [|0,s; -w,s+m; 0,s+h; w,s+m|]
      ]
   for i in 0.0..60.0..300.0 do
      graphics.RotateTransform(float32 60.0)
      let poly points =
         let points = [|for (x,y) in points -> Point(x*5,y*5)|]
         graphics.FillPolygon(brush,points)
      polys |> List.iter poly 
   image

 

The full snippet is on F# Snippets: http://fssnip.net/oB

Another interesting method of generating snowflakes is cellular automata, but I’ll leave that as an exercise for the reader.

Happy holidays!

Pingbacks and trackbacks (2)+

Comments are closed