From a63662059215a26db627c4b76147a3c9338f5b74 Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Wed, 6 Jan 2021 22:09:53 +0100 Subject: Point suppression --- path/fixed.ml | 102 ++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 25 deletions(-) (limited to 'path/fixed.ml') 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} -- cgit v1.2.3