Barry Schwartz avatar Barry Schwartz committed fb1a43f

Intersection finders and such.

Comments (0)

Files changed (5)

 	$(MLMKLIB) -o $(CAML2GEOM) $< $(LDFLAGS)
 
 test1: test1.ml $(CAML2GEOM).cmi $(CAML2GEOM).cma dll$(CAML2GEOM).so
-	$(OCAMLC) -o $@ -dllib dll$(CAML2GEOM) $(CAML2GEOM).cma $<
+	$(OCAMLC) -o $@ -syntax camlp4o -package batteries,batteries.syntax -linkpkg -thread \
+		-dllib dll$(CAML2GEOM) $(CAML2GEOM).cma $<
 
 install-data-local: all
 	-$(MLFIND) remove $(CAML2GEOM)
   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 crossings : t -> t -> Crossing.t array = "curve_crossings_wrapper"
 end
 
 module Bezier_curve =
   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 crossings : t -> t -> Crossing.t array = "bezier_curve_crossings_wrapper"
 
   let of_array points = 
     match points with
   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 crossings : t -> t -> Crossing.t array = "line_segment_crossings_wrapper"
 
   let of_array points = 
     match points with
   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 crossings : t -> t -> Crossing.t array = "quadratic_bezier_crossings_wrapper"
 
   let of_array points = 
     match points with
   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 crossings : t -> t -> Crossing.t array = "cubic_bezier_crossings_wrapper"
 
   let of_array points = 
     match points with
   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"
+  external mono_splits : t -> float array = "path_mono_splits_wrapper"
+  external crossings_among : t array -> Crossing.t array array = "path_crossings_among_wrapper"
+  external self_crossings : t -> Crossing.t array = "path_self_crossings_wrapper"
+  external crossings : t -> t -> Crossing.t array = "path_crossings_wrapper"
+  external crossings_between : t array -> t array -> Crossing.t array array = "path_crossings_between_wrapper"
 end
 
 module Path : Path_type =
   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"
+  external mono_splits : t -> float array = "path_mono_splits_wrapper"
+  external crossings_among : t array -> Crossing.t array array = "path_crossings_among_wrapper"
+  external self_crossings : t -> Crossing.t array = "path_self_crossings_wrapper"
+  external crossings : t -> t -> Crossing.t array = "path_crossings_wrapper"
+  external crossings_between : t array -> t array -> Crossing.t array array = "path_crossings_between_wrapper"
 end
   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 crossings : t -> t -> Crossing.t array = "curve_crossings_wrapper"
 end
 
 module Bezier_curve :
   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 crossings : t -> t -> Crossing.t array = "bezier_curve_crossings_wrapper"
 
   val of_array : Point.t array -> t
   external to_array : t -> Point.t array = "bezier_curve_points_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 crossings : t -> t -> Crossing.t array = "line_segment_crossings_wrapper"
 
   val of_array : Point.t array -> t
   external to_array : t -> Point.t array = "line_segment_points_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 crossings : t -> t -> Crossing.t array = "quadratic_bezier_crossings_wrapper"
 
   val of_array : Point.t array -> t
   external to_array : t -> Point.t array = "quadratic_bezier_points_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 crossings : t -> t -> Crossing.t array = "cubic_bezier_crossings_wrapper"
 
   val of_array : Point.t array -> t
   external to_array : t -> Point.t array = "cubic_bezier_points_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"
+  external mono_splits : t -> float array = "path_mono_splits_wrapper"
+  external crossings_among : t array -> Crossing.t array array = "path_crossings_among_wrapper"
+  external self_crossings : t -> Crossing.t array = "path_self_crossings_wrapper"
+  external crossings : t -> t -> Crossing.t array = "path_crossings_wrapper"
+  external crossings_between : t array -> t array -> Crossing.t array array = "path_crossings_between_wrapper"
 end
 
 module Path : Path_type

caml2geom_stubs.c

 #include <2geom/bezier.h>
 #include <2geom/bezier-curve.h>
 #include <2geom/coord.h>
+#include <2geom/crossing.h>
 #include <2geom/exception.h>
 #include <2geom/interval.h>
 #include <2geom/path.h>
         for (int i; i < n; i++)                                         \
             Store_field(_roots, i, caml_copy_double(roots[i]));         \
         CAMLreturn(_roots);                                             \
+    }                                                                   \
+                                                                        \
+    extern "C" CAMLprim value name##_crossings_wrapper(value _curve1, value _curve2) \
+    {                                                                   \
+    CAMLparam2(_curve1, _curve2);                                       \
+    CAMLlocal2(_crossing, _crossings);                                  \
+    t *curve1 = OPAQUE_P(t, _curve1);                                   \
+    t *curve2 = OPAQUE_P(t, _curve2);                                   \
+    Geom::Crossings xings = crossings(*curve1, *curve2);                \
+    _crossings = caml_alloc(xings.size(), 0);                           \
+    for (size_t i = 0; i < xings.size(); i++) {                         \
+        Geom::Crossing x = xings[i];                                    \
+        _crossing = caml_alloc(5, 0);                                   \
+        Store_field(_crossing, 0, Val_bool(x.dir));                     \
+        Store_field(_crossing, 1, caml_copy_double(x.ta));              \
+        Store_field(_crossing, 2, caml_copy_double(x.tb));              \
+        Store_field(_crossing, 3, Val_int(x.a));                        \
+        Store_field(_crossing, 4, Val_int(x.b));                        \
+        Store_field(_crossings, i, _crossing);                          \
+    }                                                                   \
+    CAMLreturn(_crossings);                                             \
     }
+
     
 #define bezier_curve_wrappers(t, name)                                  \
                                                                         \
     CAMLreturn(Val_bool(does_contain));
 }
 
+extern "C" CAMLprim value path_mono_splits_wrapper(value _path)
+{
+    CAMLparam1(_path);
+    CAMLlocal1(_splits);
+    Geom::Path *path = OPAQUE_P(Geom::Path, _path);
+    std::vector<double> splits = Geom::path_mono_splits(*path);
+    size_t n = splits.size();
+    _splits = caml_alloc(n, 0);
+    for (size_t i = 0; i < n; i++)
+        Store_field(_splits, i, caml_copy_double(splits[i]));
+    CAMLreturn(_splits);
+}
+
+extern "C" CAMLprim value path_crossings_among_wrapper(value _path_array)
+{
+    CAMLparam1(_path_array);
+    CAMLlocal3(_crossing, _crossings, _crossingset);
+    size_t path_count = Wosize_val(_path_array);
+    std::vector<Geom::Path> paths;
+    for (size_t i = 0; i < path_count; i++) {
+        Geom::Path p = *OPAQUE_P(Geom::Path, Field(_path_array, i));
+        paths.push_back(p);
+    }
+    Geom::CrossingSet xingset = Geom::crossings_among(paths);
+    _crossingset = caml_alloc(xingset.size(), 0);
+    for (size_t i = 0; i < xingset.size(); i++) {
+        Geom::Crossings xings = xingset[i];
+        _crossings = caml_alloc(xings.size(), 0);
+        for (size_t j = 0; j < xings.size(); j++) {
+            Geom::Crossing x = xings[j];
+            _crossing = caml_alloc(5, 0);
+            Store_field(_crossing, 0, Val_bool(x.dir));
+            Store_field(_crossing, 1, caml_copy_double(x.ta));
+            Store_field(_crossing, 2, caml_copy_double(x.tb));
+            Store_field(_crossing, 3, Val_int(x.a));
+            Store_field(_crossing, 4, Val_int(x.b));
+            Store_field(_crossings, j, _crossing);
+        }
+        Store_field(_crossingset, i, _crossings);
+    }
+    CAMLreturn(_crossingset);
+}
+
+extern "C" CAMLprim value path_self_crossings_wrapper(value _path)
+{
+    CAMLparam1(_path);
+    CAMLlocal2(_crossing, _crossings);
+    Geom::Path *path = OPAQUE_P(Geom::Path, _path);
+    Geom::Crossings xings = self_crossings(*path);
+    _crossings = caml_alloc(xings.size(), 0);
+    for (size_t i = 0; i < xings.size(); i++) {
+        Geom::Crossing x = xings[i];
+        _crossing = caml_alloc(5, 0);
+        Store_field(_crossing, 0, Val_bool(x.dir));
+        Store_field(_crossing, 1, caml_copy_double(x.ta));
+        Store_field(_crossing, 2, caml_copy_double(x.tb));
+        Store_field(_crossing, 3, Val_int(x.a));
+        Store_field(_crossing, 4, Val_int(x.b));
+        Store_field(_crossings, i, _crossing);
+    }
+    CAMLreturn(_crossings);
+}
+
+extern "C" CAMLprim value path_crossings_wrapper(value _path1, value _path2)
+{
+    CAMLparam2(_path1, _path2);
+    CAMLlocal2(_crossing, _crossings);
+    Geom::Path *path1 = OPAQUE_P(Geom::Path, _path1);
+    Geom::Path *path2 = OPAQUE_P(Geom::Path, _path2);
+    Geom::Crossings xings = crossings(*path1, *path2);
+    _crossings = caml_alloc(xings.size(), 0);
+    for (size_t i = 0; i < xings.size(); i++) {
+        Geom::Crossing x = xings[i];
+        _crossing = caml_alloc(5, 0);
+        Store_field(_crossing, 0, Val_bool(x.dir));
+        Store_field(_crossing, 1, caml_copy_double(x.ta));
+        Store_field(_crossing, 2, caml_copy_double(x.tb));
+        Store_field(_crossing, 3, Val_int(x.a));
+        Store_field(_crossing, 4, Val_int(x.b));
+        Store_field(_crossings, i, _crossing);
+    }
+    CAMLreturn(_crossings);
+}
+
+extern "C" CAMLprim value path_crossings_between_wrapper(value _path_array1, value _path_array2)
+{
+    CAMLparam2(_path_array1, _path_array2);
+    CAMLlocal3(_crossing, _crossings, _crossingset);
+    size_t path_count1 = Wosize_val(_path_array1);
+    size_t path_count2 = Wosize_val(_path_array2);
+    std::vector<Geom::Path> paths1;
+    std::vector<Geom::Path> paths2;
+    for (size_t i = 0; i < path_count1; i++) {
+        Geom::Path p = *OPAQUE_P(Geom::Path, Field(_path_array1, i));
+        paths1.push_back(p);
+    }
+    for (size_t i = 0; i < path_count2; i++) {
+        Geom::Path p = *OPAQUE_P(Geom::Path, Field(_path_array2, i));
+        paths2.push_back(p);
+    }
+    Geom::CrossingSet xingset = Geom::crossings(paths1, paths2);
+    _crossingset = caml_alloc(xingset.size(), 0);
+    for (size_t i = 0; i < xingset.size(); i++) {
+        Geom::Crossings xings = xingset[i];
+        _crossings = caml_alloc(xings.size(), 0);
+        for (size_t j = 0; j < xings.size(); j++) {
+            Geom::Crossing x = xings[j];
+            _crossing = caml_alloc(5, 0);
+            Store_field(_crossing, 0, Val_bool(x.dir));
+            Store_field(_crossing, 1, caml_copy_double(x.ta));
+            Store_field(_crossing, 2, caml_copy_double(x.tb));
+            Store_field(_crossing, 3, Val_int(x.a));
+            Store_field(_crossing, 4, Val_int(x.b));
+            Store_field(_crossings, j, _crossing);
+        }
+        Store_field(_crossingset, i, _crossings);
+    }
+    CAMLreturn(_crossingset);
+}
+
 //-------------------------------------------------------------------------
+open Batteries
 open Caml2geom
 open Printf
 
 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.)) ;;
 
+let splits = Path.mono_splits path ;;
+Array.iter (fun r -> printf "%f " r) splits; print_newline () ;;
+
+let bc2 = Bezier_curve.of_four_points (Point.make (1.) (1.)) (Point.make 10. 10.) (Point.make 15. 15.) (Point.make 20. 20.) ;;
+let path2 = Path.make (Point.make 1. 1.) ;;
+Path.append_curve path2 (Bezier_curve.to_curve bc2) ;;
+let splits = Path.mono_splits path2 ;;
+Array.iter (fun r -> printf "%f " r) splits; print_newline () ;;
+
+let bc2 = Bezier_curve.of_four_points (Point.make (1.) (1.)) (Point.make 10. 10.) (Point.make 15. 10.) (Point.make 5. (-10.)) ;;
+let path2 = Path.make (Point.make 1. 1.) ;;
+Path.append_curve path2 (Bezier_curve.to_curve bc2) ;;
+let splits = Path.mono_splits path2 ;;
+Array.iter (fun r -> printf "%f " r) splits; print_newline () ;;
+
+let crossingset = Path.crossings_among [| path; path2; path3 |] ;;
+print_guess stdout crossingset; print_newline () ;;
+
+let crossings = Path.self_crossings path ;;
+print_guess stdout crossings; print_newline () ;;
+let path = Path.make (Point.make (-10.) (-10.)) ;;
+Path.append_curve path (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make (-10.) (-10.)) (Point.make 10. 10.)));;
+Path.append_curve path (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make 10. 10.) (Point.make 10. (-10.)))) ;;
+Path.append_curve path (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make 10. (-10.)) (Point.make (-10.) 10.)));;
+let crossings = Path.self_crossings path ;;
+print_guess stdout crossings; print_newline () ;;
+
+let crossings = Curve.crossings
+  (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make (-10.) (-10.)) (Point.make 10. 10.)))
+  (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make 10. (-10.)) (Point.make (-10.) 10.))) ;;
+print_guess stdout crossings; print_newline () ;;
+
+let path = Path.make (Point.make (-10.) (-10.)) ;;
+Path.append_curve path (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make (-10.) (-10.)) (Point.make 10. 10.)));;
+let path' = Path.make (Point.make (-10.) 10.) ;;
+Path.append_curve path' (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make 5. (-5.)) (Point.make (-10.) 10.)));;
+let crossings = Path.crossings path path' ;;
+print_guess stdout crossings; print_newline () ;;
+
+let path = Path.make (Point.make (-10.) (-10.)) ;;
+Path.append_curve path (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make (-10.) (-10.)) (Point.make 10. 10.)));;
+let path' = Path.make (Point.make (-10.) 10.) ;;
+Path.append_curve path' (Bezier_curve.to_curve (Bezier_curve.of_two_points (Point.make 5. (-5.)) (Point.make (-10.) 10.)));;
+let crossings = Path.crossings_between [|path|] [|path'|] ;;
+print_guess stdout crossings; print_newline () ;;
+
 (*-----------------------------------------------------------------------*)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.