diff options
Diffstat (limited to 'path')
-rwxr-xr-x | path/fixed.ml | 102 | ||||
-rwxr-xr-x | path/fixed.mli | 6 |
2 files changed, 83 insertions, 25 deletions
diff --git a/path/fixed.ml b/path/fixed.ml index 7ee0705..95a42d5 100755 --- a/path/fixed.ml +++ b/path/fixed.ml @@ -129,15 +129,6 @@ module Make(Point:P) = struct ) in Repr.stop repr - let box - : bezier -> Gg.box2 - = fun bezier -> - Gg.Box2.of_pts - (Point.get_coord bezier.p0) - (Point.get_coord bezier.p1) - |> (fun b -> Gg.Box2.add_pt b bezier.ctrl0) - |> (fun b -> Gg.Box2.add_pt b bezier.ctrl1) - (** Return the distance between a given point and the curve. May return None if the point is out of the curve *) let distance @@ -157,23 +148,20 @@ module Make(Point:P) = struct res end | Curve bezier -> - begin match Gg.Box2.mem point (box bezier) with - | false -> res - | true -> - let bezier' = Shapes.Bezier.( - - { p0 = Point.get_coord bezier.p0 - ; p1 = Point.get_coord bezier.p1 - ; ctrl0 = bezier.ctrl0 - ; ctrl1 = bezier.ctrl1 } - ) in - let _, point' = Shapes.Bezier.get_closest_point point bezier' in - let distance = Gg.V2.( norm (point - point') ) in - match res with - | None -> Some (point', distance, bezier.p0, bezier.p1) - | Some (_, d, _, _) -> if d < distance then res else (Some (point', distance, bezier.p0, bezier.p1)) - end + let bezier' = Shapes.Bezier.( + + { p0 = Point.get_coord bezier.p0 + ; p1 = Point.get_coord bezier.p1 + ; ctrl0 = bezier.ctrl0 + ; ctrl1 = bezier.ctrl1 } + ) in + let _, point' = Shapes.Bezier.get_closest_point point bezier' in + let distance = Gg.V2.( norm (point - point') ) in + match res with + | None -> Some (point', distance, bezier.p0, bezier.p1) + | Some (_, d, _, _) when d < distance -> res + | _ -> (Some (point', distance, bezier.p0, bezier.p1)) ) let map_point @@ -187,6 +175,70 @@ module Make(Point:P) = struct ) in {id; path} + let iter + : t -> f:(Point.t -> unit) -> unit + = fun {path; _} ~f -> + Array.iter path + ~f:(function + | Empty -> () + | Line (p1, p2) -> f p1; f p2 + | Curve bezier -> f bezier.p0 ; f bezier.p1 + ) + + + let remove_point + : t -> Point.t -> t + = fun {id; path} point -> + + (* First search the element to remove *) + let idx = ref None + and counter = ref 0 in + + let _ = Array.exists + path + ~f:(fun element -> + + let res = match element with + | Empty -> false + | Line (p0, p1) + | Curve {p0;p1;_} -> + if p0 = point then ( + idx := Some (!counter) ; + true + ) else if p1 = point then ( + idx := Some (!counter +1) ; + true + ) else + false + in + incr counter; + res) in + + match !idx with + | None -> {id; path} + | Some 0 -> + (* Remove the first point *) + let path' = Array.init + ((Array.length path) -1) + ~f:( fun i -> Array.get path (i + 1)) in + {id; path=path'} + | Some n when n = (Array.length path) -> + (* Remove the last point *) + let path' = Array.init + ((Array.length path) -1) + ~f:( fun i -> Array.get path i) in + {id; path=path'} + | Some n -> + let path' = Array.init + ((Array.length path) -1) + ~f:(fun i -> + if i < (n -1) then + Array.get path (i) + else + Array.get path (i +1) + ) in + {id; path=path'} + let update : t -> path array -> t = fun {id; _} path -> {id; path} diff --git a/path/fixed.mli b/path/fixed.mli index c6af84d..32f6012 100755 --- a/path/fixed.mli +++ b/path/fixed.mli @@ -40,9 +40,15 @@ module Make(Point:P) : sig val distance : Gg.v2 -> t -> (Gg.v2 * float * Point.t * Point.t) option + val iter + : t -> f:(Point.t -> unit) -> unit + val map_point : t -> (Point.t -> Point.t) -> t + val remove_point + : t -> Point.t -> t + type bezier = { p0:Point.t (* The starting point *) ; p1:Point.t (* The end point *) |