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
|
open StdLabels
type t =
| Path of int
| Point of (int * Path.Point.t)
let threshold = 20.
let get_from_paths
: (float * float) -> Path.Fixed.t list -> float * (Gg.v2 * Path.Fixed.t * Path.Point.t * Path.Point.t) option
= fun position paths ->
let point = Gg.V2.of_tuple position in
(* If the user click on a curve, select it *)
List.fold_left paths
~init:(threshold, None)
~f:(fun (dist, selection) path ->
match Path.Fixed.distance point path with
| Some { closest_point ; distance; p0; p1 ; ratio} when distance < dist ->
ratio, Some (closest_point, path, p0, p1)
| _ -> dist, selection
)
let select_path
: Path.Fixed.t -> t
= fun path -> Path (Path.Fixed.id path)
let select_point
: Path.Fixed.t -> Gg.v2 -> t
= fun path v2_point ->
let point' = ref None in
let dist = ref threshold in
Path.Fixed.iter
path
~f:(fun p ->
let open Gg.V2 in
let new_dist = norm ((Path.Point.get_coord p) - v2_point) in
match (new_dist < !dist) with
| false -> ()
| true ->
dist:= new_dist;
point' := Some p
);
match !point' with
| Some point ->
Point (Path.Fixed.id path, point)
| None ->
Path (Path.Fixed.id path)
(*
(* If the point does not exists, find the exact point on the curve *)
let coord = Gg.V2.to_tuple v2_point in
begin match get_from_paths coord [path] with
| _, None -> Path (Path.Fixed.id path)
| f, Some (point, path, p0, p1) ->
let point' = Path.Point.mix f point p0 p1 in
Point (Path.Fixed.id path, point')
end
*)
|