From af88c8895bba85fe5340b34aafb3dce7650bd01f Mon Sep 17 00:00:00 2001 From: Sébastien Dailly Date: Fri, 1 Jan 2021 11:08:38 +0100 Subject: Use first type module instead of functors --- path/builder.ml | 203 +++++++++++++++++++++++++++----------------------------- 1 file changed, 98 insertions(+), 105 deletions(-) (limited to 'path/builder.ml') diff --git a/path/builder.ml b/path/builder.ml index bcad493..cb87fc5 100755 --- a/path/builder.ml +++ b/path/builder.ml @@ -15,20 +15,20 @@ end module type REPR = sig type t - type 'a repr + type repr (* Start a new path. *) val start - : t -> 'a repr -> 'a repr + : t -> repr -> repr val line_to - : t -> t -> 'a repr -> 'a repr + : t -> t -> repr -> repr val quadratic_to - : t -> Gg.v2 -> Gg.v2 -> t -> 'a repr -> 'a repr + : t -> Gg.v2 -> Gg.v2 -> t -> repr -> repr val stop - : 'a repr -> 'a repr + : repr -> repr end module Make(Point:P) = struct @@ -122,105 +122,98 @@ module Make(Point:P) = struct | [] -> None | hd::_ -> Some hd - (** Complete path **) - - module Draw(Repr:REPR with type t = Point.t) = struct - - (** Drawing path **) - - let draw - : t -> 'a Repr.repr -> 'a Repr.repr - = fun (points, beziers) path -> - - (* Represent the last points *) - let path = match points with - | [] -> - ( path ) - | p1::[] -> - ( Repr.start p1 path ) - | p1::p2::[] -> - let path = - Repr.start p1 path - |> Repr.line_to p1 p2 in - ( path ) - | p0::p1::p2::[] -> - let path = Repr.start p0 path in - - let b = Shapes.Bezier.quadratic_to_cubic - @@ Shapes.Bezier.three_points_quadratic - (Point.get_coord p0) - (Point.get_coord p1) - (Point.get_coord p2) - in - - let p0' = Point.copy p0 b.Shapes.Bezier.p0 - and p2' = Point.copy p1 b.Shapes.Bezier.p1 in - - ( Repr.quadratic_to - p0' - b.Shapes.Bezier.ctrl0 - b.Shapes.Bezier.ctrl1 - p2' - path ) - | (p0::_ as points) -> - - let (let*) v f = - match v with - | Ok beziers -> f beziers - | _ -> path in - - let points' = List.map ~f:Point.get_coord points in - let connexion = match beziers with - | [] -> None - | hd ::_ -> Some (Point.get_coord hd.p1) in - - let* beziers = Shapes.Bspline.to_bezier ?connexion1:connexion points' in - - (* Stdlib does not provide fold_left_i function and we need to map - each bezier point with the associated point in the curve. - - So I use references here for keeping each result element - - *) - let path = ref path in - let point = ref p0 in - - List.iteri - points - ~f:(fun i pt -> - - (* The first iteration is ignored, as we need both previous and - current point for the two point in the curve. - - Do not forget that there is always n-1 bezier curve for n - points *) - if i > 0 then ( - - let bezier = Array.get beziers (i - 1) in - - path := Repr.quadratic_to - !point - bezier.Shapes.Bezier.ctrl0 - bezier.Shapes.Bezier.ctrl1 - pt - (!path); - point := pt; - ) - ); - ( !path ) - in - - (* Now represent the already evaluated points. Much easer to do, just - iterate on them *) - Repr.stop @@ List.fold_left beziers - ~init:path - ~f:(fun path bezier -> - let p0' = bezier.p0 - and ctrl0 = bezier.ctrl0 - and ctrl1 = bezier.ctrl1 - and p1' = bezier.p1 in - Repr.quadratic_to p0' ctrl0 ctrl1 p1' path - ) - end + let repr + : t -> (module REPR with type t = Point.t and type repr = 's) -> 's -> 's + = fun (type s) (points, beziers) (module Repr : REPR with type t = Point.t and type repr = s) path -> + + (* Represent the last points *) + let path = match points with + | [] -> + ( path ) + | p1::[] -> + ( Repr.start p1 path ) + | p1::p2::[] -> + let path = + Repr.start p1 path + |> Repr.line_to p1 p2 in + ( path ) + | p0::p1::p2::[] -> + let path = Repr.start p0 path in + + let b = Shapes.Bezier.quadratic_to_cubic + @@ Shapes.Bezier.three_points_quadratic + (Point.get_coord p0) + (Point.get_coord p1) + (Point.get_coord p2) + in + + let p0' = Point.copy p0 b.Shapes.Bezier.p0 + and p2' = Point.copy p1 b.Shapes.Bezier.p1 in + + ( Repr.quadratic_to + p0' + b.Shapes.Bezier.ctrl0 + b.Shapes.Bezier.ctrl1 + p2' + path ) + | (p0::_ as points) -> + + let (let*) v f = + match v with + | Ok beziers -> f beziers + | _ -> path in + + let points' = List.map ~f:Point.get_coord points in + let connexion = match beziers with + | [] -> None + | hd ::_ -> Some (Point.get_coord hd.p1) in + + let* beziers = Shapes.Bspline.to_bezier ?connexion1:connexion points' in + + (* Stdlib does not provide fold_left_i function and we need to map + each bezier point with the associated point in the curve. + + So I use references here for keeping each result element + + *) + let path = ref path in + let point = ref p0 in + + List.iteri + points + ~f:(fun i pt -> + + (* The first iteration is ignored, as we need both previous and + current point for the two point in the curve. + + Do not forget that there is always n-1 bezier curve for n + points *) + if i > 0 then ( + + let bezier = Array.get beziers (i - 1) in + + path := Repr.quadratic_to + !point + bezier.Shapes.Bezier.ctrl0 + bezier.Shapes.Bezier.ctrl1 + pt + (!path); + point := pt; + ) + ); + ( !path ) + in + + (* Now represent the already evaluated points. Much easer to do, just + iterate on them *) + Repr.stop @@ List.fold_left beziers + ~init:path + ~f:(fun path bezier -> + let p0' = bezier.p0 + and ctrl0 = bezier.ctrl0 + and ctrl1 = bezier.ctrl1 + and p1' = bezier.p1 in + Repr.quadratic_to p0' ctrl0 ctrl1 p1' path + ) end -- cgit v1.2.3