9#include <gsl/gsl_vector.h>
10#include <gsl/gsl_multiroots.h>
26 if(p.
empty())
return false;
66 a.insert(a.end(), b.begin(), b.end());
77 double &tA,
double &tB,
double &
det) {
87 if (both_lines_non_zero) {
89 det_rel /= Bd.length();
92 if( fabs(det_rel) < 1e-12 ) {
94 if (both_lines_non_zero) {
103 double detinv = 1.0 /
det;
104 tA =
cross(d, Bd) * detinv;
105 tB =
cross(d, Ad) * detinv;
106 return (tA >= 0.) && (tA <= 1.) && (tB >= 0.) && (tB <= 1.);
123 return s.d64 - value;
126 return s.d64 - value;
128 return value - s.d64;
142 const double x0 = gsl_vector_get (x, 0);
143 const double x1 = gsl_vector_get (x, 1);
145 Geom::Point dx = ((
struct rparams *) params)->A(x0) -
146 ((
struct rparams *) params)->B(x1);
148 gsl_vector_set (f, 0, dx[0]);
149 gsl_vector_set (f, 1, dx[1]);
158 std::vector<Point> as,
bs;
162 double best =
dot(F, F);
164 for(
int i = 0; i < 4; i++) {
176 Affine jack(as[1][0], as[1][1],
177 -
bs[1][0], -
bs[1][1],
180 double ns = s - soln[0];
181 double nt = t - soln[1];
191 double trial =
dot(F, F);
192 if (trial > best*0.1)
205 struct rparams p = {A, B};
208 double x_init[2] = {s, t};
209 gsl_vector *x = gsl_vector_alloc (n);
211 gsl_vector_set (x, 0, x_init[0]);
212 gsl_vector_set (x, 1, x_init[1]);
214 const gsl_multiroot_fsolver_type *T = gsl_multiroot_fsolver_hybrids;
215 gsl_multiroot_fsolver *sol = gsl_multiroot_fsolver_alloc (T, 2);
216 gsl_multiroot_fsolver_set (sol, &f, x);
221 status = gsl_multiroot_fsolver_iterate (sol);
227 gsl_multiroot_test_residual (sol->f, 1e-12);
229 while (status == GSL_CONTINUE && iter < 1000);
231 s = gsl_vector_get (sol->x, 0);
232 t = gsl_vector_get (sol->x, 1);
234 gsl_multiroot_fsolver_free (sol);
246 Curve const & B,
double Bl,
double Bh,
264 tA = tA * (Ah - Al) + Al;
265 tB = tB * (Bh - Bl) + Bl;
275 if(depth > 12)
return;
276 double mid = (Bl + Bh)/2;
302 Curve const &B,
double Bl,
double Bh,
303 Crossings &ret,
double tol = 0.1,
unsigned depth = 0) {
304 if( Al >= Ah || Bl >= Bh)
return;
311 if(!Ar.
intersects(Br) || A0 == A1 || B0 == B1)
return;
318 tA = tA * (Ah - Al) + Al;
319 tB = tB * (Bh - Bl) + Bl;
329 if(depth > 12)
return;
330 double mid = (Bl + Bh)/2;
353 Path const &B,
double Bl,
double Bh,
354 Crossings &ret,
double ,
unsigned depth = 0) {
355 if( Al >= Ah || Bl >= Bh)
return;
356 std::cout <<
" " << depth <<
"[" << Al <<
", " << Ah <<
"]" <<
"[" << Bl <<
", " << Bh <<
"]";
362 if(!Ar.
intersects(Br) || A0 == A1 || B0 == B1)
return;
368 tA = tA * (Ah - Al) + Al;
369 tB = tB * (Bh - Bl) + Bl;
377 if(depth > 12)
return;
378 double mid = (Bl + Bh)/2;
390 std::vector<double>
rs = deriv->
roots(0,
X);
393 std::sort(
rs.begin(),
rs.end());
399 std::vector<double> ret;
401 ret.push_back(i + offs);
411 std::vector<double> ret;
412 if(p.
empty())
return ret;
414 int pdx = 2, pdy = 2;
415 for(
unsigned i = 0; i < p.
size(); i++) {
420 if(dx != pdx || dy != pdy) {
434 std::vector<std::vector<double> > ret;
435 for(
const auto & p : ps)
446 std::vector<std::vector<Rect> > ret;
447 for(
unsigned i = 0; i < p.
size(); i++) {
448 std::vector<Rect> res;
449 for(
unsigned j = 1; j < splits[i].size(); j++)
450 res.emplace_back(p[i].
pointAt(splits[i][j-1]), p[i].
pointAt(splits[i][j]));
468 if(a.
empty())
return results;
473 std::vector<Rect> bounds_a_union, bounds_b_union;
474 for(
auto & i : bounds_a) bounds_a_union.push_back(
union_list(i));
475 for(
auto & i : bounds_b) bounds_b_union.push_back(
union_list(i));
477 std::vector<std::vector<unsigned> > cull =
sweep_bounds(bounds_a_union, bounds_b_union);
479 for(
unsigned i = 0; i < cull.size(); i++) {
480 for(
unsigned jx = 0; jx < cull[i].size(); jx++) {
481 unsigned j = cull[i][jx];
482 unsigned jc = j + a.
size();
486 std::vector<std::vector<unsigned> > cull2 =
sweep_bounds(bounds_a[i], bounds_b[j]);
487 for(
unsigned k = 0; k < cull2.size(); k++) {
488 for(
unsigned lx = 0; lx < cull2[k].size(); lx++) {
489 unsigned l = cull2[k][lx];
490 mono_pair(a[i], splits_a[i][k-1], splits_a[i][k],
491 b[j], splits_b[j][l-1], splits_b[j][l],
496 for(
auto & re : res) { re.a = i; re.b = jc; }
552 std::vector<double> spl;
556 for(
unsigned i = 1; i < spl.size(); i++)
557 for(
unsigned j = i+1; j < spl.size(); j++)
662 for(
unsigned i = 0; i < cull.size(); i++) {
666 for(
unsigned jx = 0; jx < cull[i].size(); jx++) {
667 unsigned j = cull[i][jx];
673 for(
auto & re : res) {
674 if(re.ta != 0 && re.ta != 1 && re.tb != 0 && re.tb != 1) {
689 cr =
Crossing(cr.tb, cr.ta, cr.b, cr.a, !cr.dir);
694 if(p.
empty())
return results;
699 for(
unsigned i = 0; i < cull.size(); i++) {
701 for(
auto & re : res) { re.a = re.b = i; }
705 for(
unsigned jx = 0; jx < cull[i].size(); jx++) {
706 unsigned j = cull[i][jx];
709 for(
auto & re : res) { re.a = i; re.b = j; }
3x3 matrix representing an affine transformation.
Affine inverse() const
Compute the inverse matrix.
Abstract continuous curve on a plane defined on [0,1].
virtual std::vector< Coord > roots(Coord v, Dim2 d) const =0
Computes time values at which the curve intersects an axis-aligned line.
virtual Curve * derivative() const =0
Create a derivative of this curve.
virtual std::vector< Point > pointAndDerivatives(Coord t, unsigned n) const =0
Evaluate the curve and its derivatives.
virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const =0
virtual Point pointAt(Coord t) const
Evaluate the curve at a specified time value.
bool intersects(CRect const &r) const
Check whether the rectangles have any common points.
bool intersects(GenericRect< C > const &r) const
Check whether the rectangles have any common points.
C maxExtent() const
Get the larger extent (width or height) of the rectangle.
Range of real numbers that is never empty.
Axis-aligned rectangle that can be empty.
size_type size() const
Get the number of paths in the vector.
Point pointAt(Coord t) const
bool empty() const
Check whether the vector contains any paths.
Sequence of contiguous curves, aka spline.
Point finalPoint() const
Get the last point in the path.
bool empty() const
Check whether path is empty.
Piecewise< D2< SBasis > > toPwSb() const
Point pointAt(Coord t) const
Get the point at the specified time value.
int winding(Point const &p) const
Determine the winding number at the specified point.
Point initialPoint() const
Get the first point in the path.
size_type size() const
Natural size of the path.
Coord valueAt(Coord t, Dim2 d) const
Get one coordinate (X or Y) at the specified time value.
Function defined as discrete pieces.
Two-dimensional point that doubles as a vector.
Coord length() const
Compute the distance from origin.
Axis aligned, non-empty rectangle.
vector< vpsc::Rectangle * > rs
Various utility functions.
int winding(Path const &path, Point const &p)
Compute winding number of the path at the specified point.
void flip_crossings(Crossings &crs)
Crossings pair_intersect(Curve const &A, Interval const &Ad, Curve const &B, Interval const &Bd)
std::vector< double > path_mono_splits(Path const &p)
Finds all the monotonic splits for a path.
void offset_crossings(Crossings &cr, double a, double b)
bool path_direction(Path const &p)
This function should only be applied to simple paths (regions), as otherwise a boolean winding direct...
void merge_crossings(Crossings &a, Crossings &b, unsigned i)
std::vector< double > curve_mono_splits(Curve const &d)
This returns the times when the x or y derivative is 0 in the curve.
void append(T &a, T const &b)
A little sugar for appending a list to another.
static int intersect_polish_f(const gsl_vector *x, void *params, gsl_vector *f)
int centroid(std::vector< Geom::Point > const &p, Geom::Point ¢roid, double &area)
polyCentroid: Calculates the centroid (xCentroid, yCentroid) and area of a polygon,...
static double area(Geom::Point a, Geom::Point b, Geom::Point c)
CrossingSet crossings_among(PathVector const &p)
std::vector< std::vector< double > > paths_mono_splits(PathVector const &ps)
Applies path_mono_splits to multiple paths, and returns the results such that time-set i corresponds ...
std::vector< Crossing > Crossings
static double EpsilonOf(double value)
static void intersect_polish_root(D2< SBasis > const &A, double &s, D2< SBasis > const &B, double &t)
std::vector< double > offset_doubles(std::vector< double > const &x, double offs)
Convenience function to add a value to each entry in a vector of doubles.
std::vector< std::vector< unsigned > > sweep_bounds(std::vector< Rect >, Dim2 dim=X)
Make a list of pairs of self intersections in a list of Rects.
std::vector< Crossings > CrossingSet
Crossings curve_self_crossings(Curve const &a)
std::vector< std::vector< Rect > > split_bounds(PathVector const &p, std::vector< std::vector< double > > splits)
Processes the bounds for a list of paths and a list of splits on them, yielding a list of rects for e...
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
void mono_pair(Path const &A, double Al, double Ah, Path const &B, double Bl, double Bh, Crossings &ret, double, unsigned depth=0)
Takes two paths and time ranges on them, with the invariant that the paths are monotonic on the range...
Rect union_list(std::vector< Rect > const &r)
Union a list of rectangles.
bool linear_intersect(Point const &A0, Point const &A1, Point const &B0, Point const &B1, double &tA, double &tB, double &det)
Finds the intersection between the lines defined by A0 & A1, and B0 & B1.
T dot(D2< T > const &a, D2< T > const &b)
static double det(Point a, Point b)
Crossings mono_intersect(Curve const &A, Interval const &Ad, Curve const &B, Interval const &Bd)
Crossings self_crossings(Path const &a)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
two-dimensional geometric operators.
Crossings crossings(Path const &a, Path const &b) override
Crossings crossings(Curve const &a, Curve const &b)
A simple wrapper around pair_intersect.