-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathanimation.ml
70 lines (60 loc) · 1.64 KB
/
animation.ml
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
open Core_kernel
open! Import
(* https://rosettacode.org/wiki/Bitmap/Midpoint_circle_algorithm#OCaml *)
let raster_circle ~c:(x0, y0) ~r =
let new_tiles x y =
let open List in
cartesian_product [ 1; -1 ] [ 1; -1 ]
|> cartesian_product [ x, y; y, x ]
|> map ~f:T2.((*lol*) uncurry (map2 ~f:( * ) >+> map2 (x0, y0) ~f:( + )))
in
let rec loop x y m accum =
let y, m = if m > 0 then y - 1, m - (8 * y) else y, m in
let accum = new_tiles x y @ accum in
if x <= y
then (
let x = x + 1 in
let m = m + (8 * x) + 4 in
loop x y m accum)
else accum
in
loop 0 r (5 - (4 * r)) []
;;
module Circle = struct
module T = struct
type t =
{ centre : Coord.t
; radius : int
; duration : int
; elapsed : int
}
[@@deriving sexp, equal, compare, fields]
end
include T
include Comparable.Make (T)
let create ~centre =
{ centre; radius = Random.int_incl 5 15; duration = 60; elapsed = 0 }
;;
let step t =
match t.duration - t.elapsed with
| 0 -> `End
| _ -> `Cont { t with elapsed = t.elapsed + 1 }
;;
module PP = struct
module T = struct
type t = int * Coord.t [@@inline] [@@deriving sexp, equal, compare]
end
include T
include Comparable.Make (T)
end
let scaled_rad t = t.radius * t.elapsed / t.duration
let rasterise_preprocess t = scaled_rad t, t.centre
let rasterise (r, c) =
raster_circle ~c ~r |> List.map ~f:(fun a -> a, ()) |> Coord.Map.of_alist_multi
;;
let rasterise_map map_of_t =
let open Incr in
Map.mapi map_of_t ~f:(fun ~key ~data:_ -> rasterise_preprocess key)
|> Map.map ~f:rasterise
;;
end