Commits

Barry Schwartz  committed ea04862

A few new functions. Crossings module.

  • Participants
  • Parent commits 9003133

Comments (0)

Files changed (4)

File caml2geom.ml

   external corner : t -> int -> Point.t = "rect_corner_wrapper"
 end
 
+module Crossing =
+struct
+  type t = {
+    dir : bool;                (* True: along a, a becomes outside. *)
+    ta : float;                (* Time of crossing on a. *)
+    tb : float;                (* Time of crossing on b. *)
+    a : int;                   (* Storage of indices. *)
+    b : int;                   (* Storage of indices. *)
+  }
+  let get_other xing cur = if xing.a = cur then xing.b else xing.a
+  let get_time xing cur = if xing.a = cur then xing.ta else xing.tb
+  let get_other_time xing cur = if xing.a = cur then xing.tb else xing.ta
+  let on_ix xing ix = xing.a = ix || xing.b = ix
+end
+
 module Bezier =
 struct
   type t
   external reverse : t -> t = "curve_reverse_wrapper"
   external derivative : t -> t = "curve_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "curve_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "curve_roots_wrapper"
   external winding : t -> Point.t -> int = "curve_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "curve_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "curve_degrees_of_freedom_wrapper"
   external reverse : t -> t = "bezier_curve_reverse_wrapper"
   external derivative : t -> t = "bezier_curve_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "bezier_curve_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "bezier_curve_roots_wrapper"
   external winding : t -> Point.t -> int = "bezier_curve_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "bezier_curve_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "bezier_curve_degrees_of_freedom_wrapper"
   external reverse : t -> t = "line_segment_reverse_wrapper"
   external derivative : t -> t = "line_segment_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "line_segment_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "line_segment_roots_wrapper"
   external winding : t -> Point.t -> int = "line_segment_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "line_segment_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "line_segment_degrees_of_freedom_wrapper"
   external reverse : t -> t = "quadratic_bezier_reverse_wrapper"
   external derivative : t -> t = "quadratic_bezier_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "quadratic_bezier_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "quadratic_bezier_roots_wrapper"
   external winding : t -> Point.t -> int = "quadratic_bezier_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "quadratic_bezier_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "quadratic_bezier_degrees_of_freedom_wrapper"
   external reverse : t -> t = "cubic_bezier_reverse_wrapper"
   external derivative : t -> t = "cubic_bezier_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "cubic_bezier_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "cubic_bezier_roots_wrapper"
   external winding : t -> Point.t -> int = "cubic_bezier_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "cubic_bezier_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "cubic_bezier_degrees_of_freedom_wrapper"
   external make : Point.t -> t = "new_path_wrapper"
   external point_at : t -> float -> Point.t = "path_point_at_wrapper"
   external value_at : t -> float -> Coord.dim2 -> float = "path_value_at_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "path_roots_wrapper"
   external portion : t -> float -> float -> t = "path_portion_wrapper"
   external reverse : t -> t = "path_reverse_wrapper"
   external append_curve : ?stitch:stitching -> t -> Curve.t -> unit = "path_append_curve_wrapper"
   external to_cubic_beziers_open : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_open_wrapper"
   external to_cubic_beziers_closed : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_closed_wrapper"
   external to_cubic_beziers_default : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_default_wrapper"
+  external winding : t -> Point.t -> int = "path_winding_wrapper"
+  external direction : t -> bool = "path_direction_wrapper"
+  external contains : ?evenodd:bool -> t -> Point.t -> bool = "path_contains_wrapper"
 end
 
 module Path : Path_type =
   external make : Point.t -> t = "new_path_wrapper"
   external point_at : t -> float -> Point.t = "path_point_at_wrapper"
   external value_at : t -> float -> Coord.dim2 -> float = "path_value_at_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "path_roots_wrapper"
   external portion : t -> float -> float -> t = "path_portion_wrapper"
   external reverse : t -> t = "path_reverse_wrapper"
   external append_curve : ?stitch:stitching -> t -> Curve.t -> unit = "path_append_curve_wrapper"
   external to_cubic_beziers_open : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_open_wrapper"
   external to_cubic_beziers_closed : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_closed_wrapper"
   external to_cubic_beziers_default : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_default_wrapper"
+  external winding : t -> Point.t -> int = "path_winding_wrapper"
+  external direction : t -> bool = "path_direction_wrapper"
+  external contains : ?evenodd:bool -> t -> Point.t -> bool = "path_contains_wrapper"
 end

File caml2geom.mli

   external corner : t -> int -> Point.t = "rect_corner_wrapper"
 end
 
+module Crossing :
+sig
+  type t = {
+    dir : bool;                (* True: along a, a becomes outside. *)
+    ta : float;                (* Time of crossing on a. *)
+    tb : float;                (* Time of crossing on b. *)
+    a : int;                   (* Storage of indices. *)
+    b : int;                   (* Storage of indices. *)
+  }
+  val get_other : t -> int -> int
+  val get_time : t -> int -> float
+  val get_other_time : t -> int -> float
+  val on_ix : t -> int -> bool
+end
+
 module Bezier :
 sig
   type t
   external reverse : t -> t = "curve_reverse_wrapper"
   external derivative : t -> t = "curve_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "curve_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "curve_roots_wrapper"
   external winding : t -> Point.t -> int = "curve_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "curve_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "curve_degrees_of_freedom_wrapper"
   external reverse : t -> t = "bezier_curve_reverse_wrapper"
   external derivative : t -> t = "bezier_curve_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "bezier_curve_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "bezier_curve_roots_wrapper"
   external winding : t -> Point.t -> int = "bezier_curve_winding_wrapper"
   external unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t = "bezier_curve_unit_tangent_at_wrapper"
   external degrees_of_freedom : t -> int = "bezier_curve_degrees_of_freedom_wrapper"
   external reverse : t -> t = "line_segment_reverse_wrapper"
   external derivative : t -> t = "line_segment_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "line_segment_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "line_segment_roots_wrapper"
   external winding : t -> Point.t -> int = "line_segment_winding_wrapper"
   val unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t
   external degrees_of_freedom : t -> int = "line_segment_degrees_of_freedom_wrapper"
   external reverse : t -> t = "quadratic_bezier_reverse_wrapper"
   external derivative : t -> t = "quadratic_bezier_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "quadratic_bezier_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "quadratic_bezier_roots_wrapper"
   external winding : t -> Point.t -> int = "quadratic_bezier_winding_wrapper"
   val unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t
   external degrees_of_freedom : t -> int = "quadratic_bezier_degrees_of_freedom_wrapper"
   external reverse : t -> t = "cubic_bezier_reverse_wrapper"
   external derivative : t -> t = "cubic_bezier_derivative_wrapper"
   external length : t -> Coord.t -> Coord.t = "cubic_bezier_length_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "cubic_bezier_roots_wrapper"
   external winding : t -> Point.t -> int = "cubic_bezier_winding_wrapper"
   val unit_tangent_at : ?num_derivs:int -> t -> Coord.t -> Point.t
   external degrees_of_freedom : t -> int = "cubic_bezier_degrees_of_freedom_wrapper"
   external make : Point.t -> t = "new_path_wrapper"
   external point_at : t -> float -> Point.t = "path_point_at_wrapper"
   external value_at : t -> float -> Coord.dim2 -> float = "path_value_at_wrapper"
+  external roots : t -> Coord.t -> Coord.dim2 -> Coord.t array = "path_roots_wrapper"
   external portion : t -> float -> float -> t = "path_portion_wrapper"
   external reverse : t -> t = "path_reverse_wrapper"
   external append_curve : ?stitch:stitching -> t -> Curve.t -> unit = "path_append_curve_wrapper"
   external to_cubic_beziers_open : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_open_wrapper"
   external to_cubic_beziers_closed : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_closed_wrapper"
   external to_cubic_beziers_default : t -> float -> Bezier_curve.t list = "path_to_cubic_bezier_curves_default_wrapper"
+  external winding : t -> Point.t -> int = "path_winding_wrapper"
+  external direction : t -> bool = "path_direction_wrapper"
+  external contains : ?evenodd:bool -> t -> Point.t -> bool = "path_contains_wrapper"
 end
 
 module Path : Path_type

File caml2geom_stubs.c

 #include <2geom/exception.h>
 #include <2geom/interval.h>
 #include <2geom/path.h>
+#include <2geom/path-intersection.h>
 #include <2geom/point.h>
 #include <2geom/rect.h>
 #include <2geom/sbasis-to-bezier.h>
         CAMLparam1(_curve);                                             \
         t *curve = OPAQUE_P(t, _curve);                                 \
         CAMLreturn(Val_int(curve->degreesOfFreedom()));                 \
+    }                                                                   \
+                                                                        \
+    extern "C" CAMLprim value name##_roots_wrapper(value _curve, value _coord, value _dim2) \
+    {                                                                   \
+        CAMLparam3(_curve, _coord, _dim2);                              \
+        CAMLlocal1(_roots);                                             \
+        t *curve = OPAQUE_P(t, _curve);                                 \
+        std::vector<Geom::Coord> roots =                                \
+            curve->roots(Double_val(_coord), dim2[Int_val(_dim2)]);     \
+        size_t n = roots.size();                                        \
+        _roots = caml_alloc(n, 0);                                      \
+        for (int i; i < n; i++)                                         \
+            Store_field(_roots, i, caml_copy_double(roots[i]));         \
+        CAMLreturn(_roots);                                             \
     }
-
+    
 #define bezier_curve_wrappers(t, name)                                  \
                                                                         \
     curve_wrappers(t, name);                                            \
     CAMLreturn(caml_copy_double(val));
 }
 
+extern "C" CAMLprim value path_roots_wrapper(value _path, value _coord, value _dim2)
+{
+    CAMLparam3(_path, _coord, _dim2);
+    CAMLlocal1(_roots);
+    Geom::Path *path = OPAQUE_P(Geom::Path, _path);
+    std::vector<Geom::Coord> roots =
+        path->roots(Double_val(_coord), dim2[Int_val(_dim2)]);
+    size_t n = roots.size();
+    _roots = caml_alloc(n, 0);
+    for (int i; i < n; i++)
+        Store_field(_roots, i, caml_copy_double(roots[i]));
+    CAMLreturn(_roots);
+}
+
 extern "C" CAMLprim value path_portion_wrapper(value _path, value _a, value _b)
 {
     CAMLparam3(_path, _a, _b);
     return path_to_cubic_bezier_curves_wrapper(_path, _tol, 2);
 }
 
+extern "C" CAMLprim value path_winding_wrapper(value _path, value _point)
+{
+    CAMLparam2(_path, _point);
+    Geom::Path *path = OPAQUE_P(Geom::Path, _path);
+    Geom::Point *point = OPAQUE_P(Geom::Point, _point);
+    CAMLreturn(Val_int(Geom::winding(*path, *point)));
+}
+
+extern "C" CAMLprim value path_direction_wrapper(value _path)
+{
+    CAMLparam1(_path);
+    Geom::Path *path = OPAQUE_P(Geom::Path, _path);
+    CAMLreturn(Val_bool(Geom::path_direction(*path)));
+}
+
+extern "C" CAMLprim value path_contains_wrapper(value _evenodd, value _path, value _point)
+{
+    CAMLparam3(_evenodd, _path, _point);
+    Geom::Path *path = OPAQUE_P(Geom::Path, _path);
+    Geom::Point *point = OPAQUE_P(Geom::Point, _point);
+    bool does_contain;
+    if (_evenodd == Val_int(0))
+        does_contain = contains(*path, *point);
+    else
+        does_contain = contains(*path, *point, Bool_val(Field(_evenodd, 0)));
+    CAMLreturn(Val_bool(does_contain));
+}
+
 //-------------------------------------------------------------------------
     print_endline "|]")
 beziers ;;
 
+let bc = Bezier_curve.of_two_points (Point.make (1.) (-1.)) (Point.make 10. 20.) ;;
+let roots = Bezier_curve.roots bc 9. Coord.X ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Bezier_curve.roots bc (-0.5) Coord.Y ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+
+let path = Path.make (Point.make 1. (-1.)) ;;
+Path.append_curve path (Bezier_curve.to_curve bc) ;;
+let roots = Path.roots path 9. Coord.X ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path (-0.5) Coord.Y ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+
+let roots = Path.roots path5 10. Coord.X ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path5 10. Coord.Y ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path5 19.99 Coord.X ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path5 19.99 Coord.Y ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path5 0. Coord.X ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path5 0. Coord.Y ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+let roots = Path.roots path5 40. Coord.Y ;;
+Array.iter (fun r -> printf "%f " r) roots; print_newline () ;;
+
+let bc' = Bezier_curve.of_two_points (Point.make 10. 20.) (Point.make (15.) (-1.)) ;;
+Path.append_curve path (Bezier_curve.to_curve bc') ;;
+printf "winding: %d\n" (Path.winding path (Point.make 10. 5.)) ;;
+printf "winding: %d\n" (Path.winding path (Point.make 0. 500.)) ;;
+printf "direction: %b\n" (Path.direction path) ;;
+let path' = Path.reverse path ;;
+printf "direction: %b\n" (Path.direction path') ;;
+printf "winding: %d\n" (Path.winding path (Point.make 10. 5.)) ;;
+printf "winding: %d\n" (Path.winding path (Point.make 0. 500.)) ;;
+printf "contains: %b\n" (Path.contains path (Point.make 10. 5.)) ;;
+printf "contains: %b\n" (Path.contains path (Point.make 0. 500.)) ;;
+printf "contains: %b\n" (Path.contains ~evenodd:false path (Point.make 10. 5.)) ;;
+printf "contains: %b\n" (Path.contains ~evenodd:false path (Point.make 0. 500.)) ;;
+
 (*-----------------------------------------------------------------------*)