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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
open Tsdl
open B_utils
module Theme = B_theme
module Draw = B_draw
type physicalpoint = Sdl.point
type logicalpoint = { x:float; y:float }
type boundary = float -> logicalpoint
type normal = float -> logicalpoint
type distance = logicalpoint -> float
type shape = {
boundary : boundary;
normal : normal;
distance : distance;
size : logicalpoint
}
let add p1 p2 =
{ x = p1.x +. p2.x; y = p1.y +. p2.y }
let mult s p =
{ x = p.x *. s; y = p.y *. s }
let dot p1 p2 =
p1.x *. p2.x +. p1.y *. p2.y
let norm_square p = dot p p
let norm p = sqrt (dot p p)
type colorfn = float -> float -> Draw.color
let getx = Sdl.Point.x
let gety = Sdl.Point.y
let logical_to_physical p =
Sdl.Point.create
~x:(Theme.scale_from_float p.x) ~y:(Theme.scale_from_float p.y)
let physical_to_logical p =
{ x = Theme.unscale_to_float (getx p);
y = Theme.unscale_to_float (gety p)}
let gaussian_float () =
let n = 10 in
let rec loop i x =
if i = 0 then x /. (float n)
else loop (i-1) (x +. Random.float 1.)
in
loop n 0.
let draw_pixel renderer ?(size=1.0) p =
let psize = Theme.scale_from_float size in
if psize = 1
then go (Sdl.render_draw_point renderer (getx p) (gety p))
else if psize > 1
then Draw.box renderer (getx p) (gety p) psize psize
let draw_random renderer ?(border_width = 10.) shape colorfn npoints =
for _ = 1 to npoints do
let t = Random.float 1. in
let s = 2. *. abs_float (gaussian_float () -. 0.5) in
let p = shape.boundary t in
let n = shape.normal t
|> mult (s *. border_width) |> add p |> logical_to_physical in
let r,g,b,a = colorfn t s in
go (Sdl.set_render_draw_color renderer r g b a);
print "POINT = %i,%i, COLOR = %i,%i,%i,%i" (getx n) (gety n) r g b a;
draw_pixel renderer n
done
let rectangle x0 y0 w h =
let t1 = w /. (2. *. ( w +. h))
and t2 = h /. (2. *. ( w +. h)) in
let boundary t =
let x, y = if t < t1 then t *. w /. t1, 0.
else if t < t1 +. t2 then w, (t -. t1) *. h /. t2
else if t < 2. *. t1 +. t2 then w -. (t -. t1 -. t2) *. w /. t1, h
else 0., (1. -. t) *. h /. t2 in
{ x = x0 +. x; y = y0 +. y} in
let normal t =
let x, y = if t < t1 then (0., -1.)
else if t < t1 +. t2 then (1., 0.)
else if t < 2. *. t1 +. t2 then (0., 1.)
else (-1., 0.) in
{ x; y} in
let distance _ = 0. in
{ boundary; normal; distance; size = { x = w; y = h}}
let ellipse center a b =
let pp = 2. *. pi in
{ boundary = (fun t ->
let t = pp *. t in
let x = center.x +. a *. (cos t) in
let y = center.y +. b *. (sin t) in
{x; y}
);
normal = (fun t ->
let t = pp *. t in
let x = (cos t) in
let y = (a /. b) *. (sin t) in
mult (1. /. (norm {x; y})) {x; y}
);
distance = (fun p ->
sqrt ( p.x *. p.x /. (a *. a) +. p.y *. p.y /. (b *. b)) -. 1.);
size = { x = 2. *. a; y = 2. *. b }
}
let essai renderer =
print_endline "ESSAI BORDER";
let bw = 10. in
let npoints = 1000 in
let shape = rectangle bw bw 100. 40. in
let colorfn _ s = let c = round ((1. -. s) *. 255.) in c,0,0,c in
draw_random renderer ~border_width:bw shape colorfn npoints