aboutsummaryrefslogtreecommitdiff
path: root/path/builder.ml
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@chimrod.com>2020-12-20 06:38:04 +0100
committerSébastien Dailly <sebastien@chimrod.com>2020-12-20 06:38:04 +0100
commit986a36b3728eba40789d6063997dafda67b519ec (patch)
treef0c26704df237b5ccad380596c49a3b13eeac14f /path/builder.ml
parent01c0f5faf98b78d44aaae7f70e0cf4229ad8ed91 (diff)
Update
Diffstat (limited to 'path/builder.ml')
-rwxr-xr-xpath/builder.ml188
1 files changed, 103 insertions, 85 deletions
diff --git a/path/builder.ml b/path/builder.ml
index 01dfb35..2774cae 100755
--- a/path/builder.ml
+++ b/path/builder.ml
@@ -10,6 +10,11 @@ module type P = sig
val copy : t -> Gg.v2 -> t
+end
+
+module type REPR = sig
+ type t
+
type 'a repr
val create_path
@@ -23,7 +28,7 @@ module type P = sig
: t -> 'a repr -> 'a repr
val quadratic_to
- : t -> t -> t -> t -> 'a repr -> 'a repr
+ : t -> Gg.v2 -> Gg.v2 -> t -> 'a repr -> 'a repr
val stop
: 'a repr -> 'a repr
@@ -34,8 +39,8 @@ module Make(Point:P) = struct
(** Point creation **)
type bezier =
- { p0:Point.t (* The starting point *)
- ; p1:Point.t (* The end point *)
+ { p0:Point.t (* The starting point *)
+ ; p1:Point.t (* The end point *)
; ctrl0:Gg.v2 (* The control point *)
; ctrl1:Gg.v2 } (* The control point *)
@@ -169,91 +174,104 @@ module Make(Point:P) = struct
curves
- (** Drawing path **)
-
- let draw
- : t -> 'a Point.repr
- = fun (points, beziers) ->
-
- let path = Point.create_path () in
- let path = match points with
- | [] ->
- ( path )
- | p1::[] ->
- ( Point.start p1 path )
- | p1::p2::[] ->
- let path =
- Point.start p1 path
- |> Point.line_to p2 in
- ( path )
- | p0::p1::p2::[] ->
- let path = Point.start p0 path in
-
- let b = Shapes.Bezier.three_points_quadratic
- (Point.get_coord p0)
- (Point.get_coord p1)
- (Point.get_coord p2)
- |> Shapes.Bezier.quadratic_to_cubic in
-
- let p0' = Point.copy p0 b.Shapes.Bezier.p0
- and ctrl0 = Point.copy p0 b.Shapes.Bezier.ctrl0
- and ctrl1 = Point.copy p1 b.Shapes.Bezier.ctrl1
- and p2' = Point.copy p1 b.Shapes.Bezier.p1 in
-
- ( Point.quadratic_to p0' ctrl0 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 *)
- if i > 0 then (
-
- let bezier = Array.get beziers (i - 1) in
- let p0' = !point
- and ctrl0 = Point.copy (!point) bezier.Shapes.Bezier.ctrl0
- and ctrl1 = Point.copy pt bezier.Shapes.Bezier.ctrl1
- and p1' = pt in
-
- path := Point.quadratic_to p0' ctrl0 ctrl1 p1' (!path);
-
- point := pt;
- )
- );
- ( !path )
- in
-
- let path = List.fold_left beziers
+ module Draw(Repr:REPR with type t = Point.t) = struct
+
+ (** Drawing path **)
+
+ let draw
+ : t -> 'a Repr.repr
+ = fun (points, beziers) ->
+
+ let path = Repr.create_path () in
+
+ (* 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 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 = Point.copy bezier.p0 bezier.ctrl0
- and ctrl1 = Point.copy bezier.p1 bezier.ctrl1
+ and ctrl0 = bezier.ctrl0
+ and ctrl1 = bezier.ctrl1
and p1' = bezier.p1 in
- Point.quadratic_to p0' ctrl0 ctrl1 p1' path
+ Repr.quadratic_to p0' ctrl0 ctrl1 p1' path
)
- in Point.stop path
+ end
end