Skip to content

Instantly share code, notes, and snippets.

@mastoj
Created November 6, 2015 00:19
Show Gist options
  • Save mastoj/2eb06a39bc3de503f7a3 to your computer and use it in GitHub Desktop.
Save mastoj/2eb06a39bc3de503f7a3 to your computer and use it in GitHub Desktop.
open System
open System.Drawing
open System.Windows.Forms
// Create a form to display the graphics
let width, height = 1000, 1000
let form = new Form(Width = width, Height = height)
let box = new PictureBox(BackColor = Color.White, Dock = DockStyle.Fill)
let image = new Bitmap(width, height)
let graphics = Graphics.FromImage(image)
//The following line produces higher quality images,
//at the expense of speed. Uncomment it if you want
//more beautiful images, even if it's slower.
//Thanks to https://twitter.com/AlexKozhemiakin for the tip!
graphics.SmoothingMode <- System.Drawing.Drawing2D.SmoothingMode.HighQuality
let brush = new SolidBrush(Color.FromArgb(0, 0, 0))
box.Image <- image
form.Controls.Add(box)
// Compute the endpoint of a line
// starting at x, y, going at a certain angle
// for a certain length.
let endpoint x y angle length =
x + length * cos angle,
y + length * sin angle
let flip x = (float)height - x
// Utility function: draw a line of given width,
// starting from x, y
// going at a certain angle, for a certain length.
let drawLine (target : Graphics) (brush : SolidBrush)
(x : float) (y : float)
(angle : float) (length : float) (width : float)
(color: Color) =
use brush2 = new SolidBrush(color)
let x_end, y_end = endpoint x y angle length
let origin = new PointF((single)x, (single)(y |> flip))
let destination = new PointF((single)x_end, (single)(y_end |> flip))
let pen = new Pen(brush2, (single)width)
target.DrawLine(pen, origin, destination)
let draw x y angle length width color =
drawLine graphics brush x y angle length width color
let pi = Math.PI
// Now... your turn to draw
// The trunk
//draw 250. 50. (pi*(0.5)) 100. 4.
//let x, y = endpoint 250. 50. (pi*(0.5)) 100.
//// first and second branches
//draw x y (pi*(0.5 + 0.3)) 50. 2.
//draw x y (pi*(0.5 - 0.4)) 50. 2.
let random = System.Random()
//let drawTree angle1Delta angle2Delta iterations =
let rec tree x y angle length width length1Div length2Div length3Div angle1Delta angle2Delta angle3Delta =
if length < 1.5 then ()
else
let r = (random.Next(200/int length))
let g = (random.Next(200/int length))
let b = (random.Next(200/int length))
let color = Color.FromArgb(r, g, b)
draw x y (pi*angle) length width color
let x', y' = endpoint x y (pi*angle) length
let chaosAngle1 = (random.NextDouble()*2. - 1.)/10.
let chaosAngle2 = (random.NextDouble()*2. - 1.)/10.
let chaosAngle3 = (random.NextDouble()*2. - 1.)/10.
tree x' y' (angle + (angle1Delta + chaosAngle1)) (length*length1Div) (width*length1Div) length1Div length2Div length3Div angle1Delta angle2Delta angle3Delta
tree x' y' (angle + (angle2Delta + chaosAngle2)) (length*length2Div) (width*length2Div) length1Div length2Div length3Div angle1Delta angle2Delta angle3Delta
tree x' y' (angle + (angle2Delta + chaosAngle3)) (length*length3Div) (width*length3Div) length1Div length2Div length3Div angle1Delta angle2Delta angle3Delta
//tree 250. 50. (pi*(0.5)) 100. 4. iterations
let rec forest numberOfTrees =
if numberOfTrees = 0 then ()
else
let startX, startY = (random.Next(width/2)+250, 200+random.Next(height/3))
let startLength = (random.Next(200) + 20)
let randDouble lower upper = random.NextDouble()*(upper-lower)+lower
let start1LengthDiv = randDouble 0.3 0.75
let start2LengthDiv = randDouble 0.3 0.55
let start3LengthDiv = randDouble 0.3 0.75
let chunk = 1. + random.NextDouble()*7.
tree (float startX) (float startY) (0.5) (float startLength) chunk start1LengthDiv start2LengthDiv start3LengthDiv 0.3 -0.2 0.1
forest (numberOfTrees-1)
forest 20
form.ShowDialog()
(* To do a nice fractal tree, using recursion is
probably a good idea. The following link might
come in handy if you have never used recursion in F#:
http://en.wikibooks.org/wiki/F_Sharp_Programming/Recursion
*)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment