41#include <gsl/gsl_vector.h>
42#include <gsl/gsl_multiroots.h>
70namespace detail{
namespace bezier_clipping {
72void derivative(std::vector<Point> &
D, std::vector<Point>
const &B);
88 vector<Point> BezA, BezB;
96 std::vector<Point>
const& A,
97 std::vector<Point>
const& B,
111void split(vector<Point>
const &p,
double t,
112 vector<Point> &left, vector<Point> &right) {
113 const unsigned sz = p.size();
115 vector<vector<Point> > Vtemp(sz);
116 for (
size_t i = 0; i < sz; ++i )
117 Vtemp[i].reserve(sz);
120 std::copy(p.begin(), p.end(), Vtemp[0].begin());
123 for (
unsigned i = 1; i < sz; i++) {
124 for (
unsigned j = 0; j < sz - i; j++) {
125 Vtemp[i][j] =
lerp(t, Vtemp[i-1][j], Vtemp[i-1][j+1]);
131 for (
unsigned j = 0; j < sz; j++)
132 left[j] = Vtemp[j][0];
133 for (
unsigned j = 0; j < sz; j++)
134 right[j] = Vtemp[sz-1-j][j];
146 dr.insert(dr.begin(), dyr.begin(), dyr.end());
151 std::sort(dr.begin(), dr.end());
152 std::vector<double>::iterator new_end = std::unique(dr.begin(), dr.end());
153 dr.resize( new_end - dr.begin() );
155 std::vector< D2<Bezier> > pieces;
156 for (
unsigned i = 0; i < dr.size() - 1; ++i) {
157 pieces.push_back(
portion(A, dr[i], dr[i+1]));
168 for(
unsigned i = 0; i < dr.size()-1; i++) {
169 for(
unsigned j = i+1; j < dr.size()-1; j++) {
170 std::vector<std::pair<double, double> > section;
173 for(
auto & k : section) {
179 if( ( l > precision ) && (r < precision) )
181 xs.emplace_back((1-l)*dr[i] + l*dr[i+1],
182 (1-r)*dr[j] + r*dr[j+1]);
204 std::vector< std::pair<double, double> >
const &xs,
214 std::pair<double, double> prev = std::make_pair(0., 0.);
215 for (
const auto & x : xs) {
216 av.push_back(
portion(a, prev.first, x.first));
217 bv.push_back(
portion(b, prev.second, x.second));
218 av.back()[
X].at0() = bv.back()[
X].at0() =
lerp(0.5, av.back()[
X].at0(), bv.back()[
X].at0());
219 av.back()[
X].at1() = bv.back()[
X].at1() =
lerp(0.5, av.back()[
X].at1(), bv.back()[
X].at1());
220 av.back()[
Y].at0() = bv.back()[
Y].at0() =
lerp(0.5, av.back()[
Y].at0(), bv.back()[
Y].at0());
221 av.back()[
Y].at1() = bv.back()[
Y].at1() =
lerp(0.5, av.back()[
Y].at1(), bv.back()[
Y].at1());
224 av.push_back(
portion(a, prev.first, 1));
225 bv.push_back(
portion(b, prev.second, 1));
226 av.back()[
X].at0() = bv.back()[
X].at0() =
lerp(0.5, av.back()[
X].at0(), bv.back()[
X].at0());
227 av.back()[
X].at1() = bv.back()[
X].at1() =
lerp(0.5, av.back()[
X].at1(), bv.back()[
X].at1());
228 av.back()[
Y].at0() = bv.back()[
Y].at0() =
lerp(0.5, av.back()[
Y].at0(), bv.back()[
Y].at0());
229 av.back()[
Y].at1() = bv.back()[
Y].at1() =
lerp(0.5, av.back()[
Y].at1(), bv.back()[
Y].at1());
233#include <gsl/gsl_multiroots.h>
245 const double x0 = gsl_vector_get (x, 0);
246 const double x1 = gsl_vector_get (x, 1);
248 Geom::Point dx = ((
struct rparams *) params)->A(x0) -
249 ((
struct rparams *) params)->B(x1);
251 gsl_vector_set (f, 0, dx[0]);
252 gsl_vector_set (f, 1, dx[1]);
275 const gsl_multiroot_fsolver_type *T;
276 gsl_multiroot_fsolver *sol;
281 std::vector<Point> as,
bs;
285 double best =
dot(F, F);
287 for(
int i = 0; i < 4; i++) {
299 Affine jack(as[1][0], as[1][1],
300 -
bs[1][0], -
bs[1][1],
303 double ns = s - soln[0];
304 double nt = t - soln[1];
309 double trial =
dot(F, F);
310 if (trial > best*0.1) {
321 struct rparams p = {A, B};
324 double x_init[2] = {s, t};
325 gsl_vector *x = gsl_vector_alloc (n);
327 gsl_vector_set (x, 0, x_init[0]);
328 gsl_vector_set (x, 1, x_init[1]);
330 T = gsl_multiroot_fsolver_hybrids;
331 sol = gsl_multiroot_fsolver_alloc (T, 2);
332 gsl_multiroot_fsolver_set (sol, &f, x);
337 status = gsl_multiroot_fsolver_iterate (sol);
343 gsl_multiroot_test_residual (sol->f, 1e-12);
345 while (status == GSL_CONTINUE && iter < 1000);
347 s = gsl_vector_get (sol->x, 0);
348 t = gsl_vector_get (sol->x, 1);
350 gsl_multiroot_fsolver_free (sol);
356 double best_v =
L1(A(s) - B(t));
361 double trial_v = best_v;
362 for(
int nsi = -1; nsi < 2; nsi++) {
363 for(
int nti = -1; nti < 2; nti++) {
366 double c =
L1(A(n[0]) - B(n[1]));
403 double *a_t,
double* b_t) {
404 std::vector< std::pair<double, double> > xs;
405 std::vector<Point> Az, Bz;
409 double h_dist = 0, h_a_t = 0, h_b_t = 0;
429 Point At = A(x.first);
430 Point Bu = B(x.second);
435 if (dist >= distAtBu-.1 && distAtBu > h_dist) {
442 if(a_t) *a_t = h_a_t;
443 if(b_t) *b_t = h_b_t;
453 double *a_t,
double* b_t) {
454 double h_dist =
hausdorfl(A, B, m_precision, a_t, b_t);
Defines the different types of exceptions that 2geom can throw.
Basic intersection routines.
3x3 matrix representing an affine transformation.
Affine inverse() const
Compute the inverse matrix.
std::vector< Coord > roots() const
Adaptor that creates 2D functions from 1D ones.
std::vector< Point > valueAndDerivatives(double t, unsigned n) const
Range of real numbers that is never empty.
Two-dimensional point that doubles as a vector.
constexpr Coord lerp(Coord t, Coord a, Coord b)
Numerically stable linear interpolation.
void portion(std::vector< Point > &B, Interval const &I)
void derivative(std::vector< Point > &D, std::vector< Point > const &B)
Various utility functions.
double hausdorf(D2< SBasis > &A, D2< SBasis > const &B, double m_precision, double *a_t=NULL, double *b_t=NULL)
Compute the symmetric Hausdorf distance.
std::vector< Point > bezier_points(const D2< Bezier > &a)
void find_intersections_bezier_clipping(std::vector< std::pair< double, double > > &xs, std::vector< Point > const &A, std::vector< Point > const &B, double precision=EPSILON)
Coord nearest_time(Point const &p, Curve const &c)
Angle distance(Angle const &a, Angle const &b)
void find_collinear_normal(std::vector< std::pair< double, double > > &xs, std::vector< Point > const &A, std::vector< Point > const &B, double precision=EPSILON)
static double EpsilonBy(double value, int eps)
static int intersect_polish_f(const gsl_vector *x, void *params, gsl_vector *f)
bool non_collinear_segments_intersect(const Point &A, const Point &B, const Point &C, const Point &D)
Check if two line segments intersect.
void polish_intersections(std::vector< std::pair< double, double > > &xs, D2< SBasis > const &A, D2< SBasis > const &B)
static void intersect_polish_root(D2< SBasis > const &A, double &s, D2< SBasis > const &B, double &t)
void subdivide(D2< Bezier > const &a, D2< Bezier > const &b, std::vector< std::pair< double, double > > const &xs, std::vector< D2< Bezier > > &av, std::vector< D2< Bezier > > &bv)
void find_intersections(std::vector< std::pair< double, double > > &xs, D2< Bezier > const &A, D2< Bezier > const &B, double precision=EPSILON)
void split(vector< Point > const &p, double t, vector< Point > &left, vector< Point > &right)
void sbasis_to_bezier(Bezier &bz, SBasis const &sb, size_t sz=0)
Changes the basis of p to be bernstein.
Bezier portion(const Bezier &a, double from, double to)
Bezier derivative(Bezier const &a)
Piecewise< SBasis > cross(Piecewise< D2< SBasis > > const &a, Piecewise< D2< SBasis > > const &b)
T dot(D2< T > const &a, D2< T > const &b)
double hausdorfl(D2< SBasis > &A, D2< SBasis > const &B, double m_precision, double *a_t=NULL, double *b_t=NULL)
Compute the Hausdorf distance from A to B only.
void find_self_intersections(std::vector< std::pair< double, double > > &xs, D2< SBasis > const &A, double precision=EPSILON)
Conversion between SBasis and Bezier basis polynomials.