diff options
| author | Johan B. C. Engelen <jbc.engelen@swissonline.ch> | 2008-07-16 21:36:19 +0000 |
|---|---|---|
| committer | johanengelen <johanengelen@users.sourceforge.net> | 2008-07-16 21:36:19 +0000 |
| commit | 680344945f84364fbbcbe4d4a353a52d4a724653 (patch) | |
| tree | 1e8f541be4d451eff0e58ec6d76e066dd3167086 /src/2geom/basic-intersection.cpp | |
| parent | improving SVG Fonts UI (diff) | |
| download | inkscape-680344945f84364fbbcbe4d4a353a52d4a724653.tar.gz inkscape-680344945f84364fbbcbe4d4a353a52d4a724653.zip | |
update to latest 2geom (rev1497)
(bzr r6332)
Diffstat (limited to 'src/2geom/basic-intersection.cpp')
| -rw-r--r-- | src/2geom/basic-intersection.cpp | 97 |
1 files changed, 95 insertions, 2 deletions
diff --git a/src/2geom/basic-intersection.cpp b/src/2geom/basic-intersection.cpp index 5375e5b58..48b990445 100644 --- a/src/2geom/basic-intersection.cpp +++ b/src/2geom/basic-intersection.cpp @@ -1,5 +1,8 @@ #include <2geom/basic-intersection.h> #include <2geom/exception.h> +#include <gsl/gsl_vector.h> +#include <gsl/gsl_multiroots.h> + unsigned intersect_steps = 0; @@ -12,6 +15,7 @@ public: OldBezier() { } void split(double t, OldBezier &a, OldBezier &b) const; + Point operator()(double t) const; ~OldBezier() {} @@ -152,7 +156,28 @@ void OldBezier::split(double t, OldBezier &left, OldBezier &right) const { right.p[j] = Vtemp[sz-1-j][j]; } - +/* + * split the curve at the midpoint, returning an array with the two parts + * Temporary storage is minimized by using part of the storage for the result + * to hold an intermediate value until it is no longer needed. + */ +Point OldBezier::operator()(double t) const { + const unsigned sz = p.size(); + Geom::Point Vtemp[sz][sz]; + + /* Copy control points */ + std::copy(p.begin(), p.end(), Vtemp[0]); + + /* Triangle computation */ + for (unsigned i = 1; i < sz; i++) { + for (unsigned j = 0; j < sz - i; j++) { + Vtemp[i][j] = lerp(t, Vtemp[i-1][j], Vtemp[i-1][j+1]); + } + } + return Vtemp[sz-1][0]; +} + + /* * Test the bounding boxes of two OldBezier curves for interference. * Several observations: @@ -324,7 +349,7 @@ double Lmax(Point p) { } unsigned wangs_theorem(OldBezier a) { - return 12; // seems a good approximation! + return 6; // seems a good approximation! double la1 = Lmax( ( a.p[2] - a.p[1] ) - (a.p[1] - a.p[0]) ); double la2 = Lmax( ( a.p[3] - a.p[2] ) - (a.p[2] - a.p[1]) ); double l0 = std::max(la1, la2); @@ -337,6 +362,71 @@ unsigned wangs_theorem(OldBezier a) { return ra; } +struct rparams +{ + OldBezier &A; + OldBezier &B; +}; + +static int +intersect_polish_f (const gsl_vector * x, void *params, + gsl_vector * f) +{ + const double x0 = gsl_vector_get (x, 0); + const double x1 = gsl_vector_get (x, 1); + + Geom::Point dx = ((struct rparams *) params)->A(x0) - + ((struct rparams *) params)->B(x1); + + gsl_vector_set (f, 0, dx[0]); + gsl_vector_set (f, 1, dx[1]); + + return GSL_SUCCESS; +} + +static void intersect_polish_root (OldBezier &A, double &s, + OldBezier &B, double &t) { + const gsl_multiroot_fsolver_type *T; + gsl_multiroot_fsolver *sol; + + int status; + size_t iter = 0; + + const size_t n = 2; + struct rparams p = {A, B}; + gsl_multiroot_function f = {&intersect_polish_f, n, &p}; + + double x_init[2] = {s, t}; + gsl_vector *x = gsl_vector_alloc (n); + + gsl_vector_set (x, 0, x_init[0]); + gsl_vector_set (x, 1, x_init[1]); + + T = gsl_multiroot_fsolver_hybrids; + sol = gsl_multiroot_fsolver_alloc (T, 2); + gsl_multiroot_fsolver_set (sol, &f, x); + + do + { + iter++; + status = gsl_multiroot_fsolver_iterate (sol); + + if (status) /* check if solver is stuck */ + break; + + status = + gsl_multiroot_test_residual (sol->f, 1e-12); + } + while (status == GSL_CONTINUE && iter < 1000); + + s = gsl_vector_get (sol->x, 0); + t = gsl_vector_get (sol->x, 1); + + gsl_multiroot_fsolver_free (sol); + gsl_vector_free (x); +} + + std::vector<std::pair<double, double> > find_intersections( OldBezier a, OldBezier b) { std::vector<std::pair<double, double> > parameters; @@ -346,6 +436,9 @@ std::vector<std::pair<double, double> > find_intersections( OldBezier a, OldBezi b, 0., 1., wangs_theorem(b), parameters); } + for(unsigned i = 0; i < parameters.size(); i++) + intersect_polish_root(a, parameters[i].first, + b, parameters[i].second); std::sort(parameters.begin(), parameters.end()); return parameters; } |
