-
Notifications
You must be signed in to change notification settings - Fork 0
/
Turtle.fsx
104 lines (77 loc) · 2.8 KB
/
Turtle.fsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#r "PresentationFramework.dll"
#r "PresentationCore.dll"
#r "WindowsBase.dll"
#r "System.Xaml.dll"
open System
open System.Windows
open System.Windows.Controls
open System.Windows.Media
open System.Windows.Shapes
let canvas = new Canvas(Background = Brushes.Black)
let w = new Window(Topmost = true, Content = canvas)
w.Show();
[<Measure>]
type deg
[<Measure>]
type rad
type Turtle = {Position:Point; Angle:float<rad>; Color: Brush; IsUp: bool}
let turtle = {
Position = new Point(canvas.ActualWidth/2.0, canvas.ActualHeight/2.0);
Angle = 0.0<rad>;
Color = Brushes.LightSteelBlue;
IsUp = false }
let degToRad (deg:float<deg>) = LanguagePrimitives.FloatWithMeasure<rad> ((float deg)/180.0*Math.PI)
let radToDeg (rad:float<rad>) = LanguagePrimitives.FloatWithMeasure<deg> ((float rad)*180.0/Math.PI)
let arrowTranslation = new TranslateTransform()
let arrowRotation = new RotateTransform()
let arrow =
let points =
[-10, 0; 10, 0; 0, 20]
|> Seq.map (fun (x, y) -> new Point (float x, float y))
let pointCollection = new PointCollection(points);
let arrowTransform = new TransformGroup()
arrowTransform.Children.Add arrowRotation
arrowTransform.Children.Add arrowTranslation
new Polygon(
Stroke = Brushes.White,
Points = pointCollection,
RenderTransform = arrowTransform
)
let updateArrowPosition turtle =
arrowTranslation.X <- turtle.Position.X
arrowTranslation.Y <- turtle.Position.Y
arrowRotation.Angle <- 180.0 + (radToDeg >> float) turtle.Angle
turtle
updateArrowPosition turtle
canvas.Children.Add arrow
let drawLine (destination:Point) turtle =
let line =
new Line(
Stroke = turtle.Color,
X1 = turtle.Position.X,
Y1 = turtle.Position.Y,
X2 = destination.X,
Y2 = destination.Y,
StrokeThickness = 2.0)
canvas.Children.Add line |> ignore
{ turtle with Position = destination }
let forward length turtle =
let up = -length * cos (float turtle.Angle)
let left = length * sin (float turtle.Angle)
let destination = new Point(turtle.Position.X + left, turtle.Position.Y + up)
if turtle.IsUp then updateArrowPosition { turtle with Position = destination }
else drawLine destination turtle |> updateArrowPosition
let fd = forward
let rotate (angle:float<deg>) turtle =
{ turtle with Angle = (turtle.Angle + degToRad angle) % (2.0<rad>*Math.PI) }
|> updateArrowPosition
let rt = rotate
let lt (angle:float<deg>) turtle = rotate (-angle) turtle
let repeat (n:int) (f:Turtle -> Turtle) turtle =
let rec loop n t =
if n < 1 then t
else loop (n-1) (f t)
loop n turtle
let square length turtle =
repeat 4 (forward length >> rotate 90.0<deg>) turtle
let clear () = canvas.Children.Clear()