Merge branch 'refs/heads/intersect-fix'

Conflicts:
	src/path/Curve.js
This commit is contained in:
Jürg Lehni 2013-10-29 15:15:59 +01:00
commit 979428b6dc

View file

@ -1420,8 +1420,10 @@ new function() { // Scope for methods that require numerical integration
/*#*/ } // options.fatline
/**
* Intersections between curve and line based on the algebraic method
* described at http://www.particleincell.com/blog/2013/cubic-line-intersection/
* Intersections between curve and line becomes rather simple here mostly
* because of Numerical class. We can rotate the curve and line so that the
* line is on the X axis, and solve the implicit equations for the X axis
* and the curve.
*/
function addCurveLineIntersections(v1, v2, curve1, curve2, locations) {
var flip = Curve.isLinear(v1),
@ -1429,58 +1431,43 @@ new function() { // Scope for methods that require numerical integration
vl = flip ? v1 : v2,
l1x = vl[0], l1y = vl[1],
l2x = vl[6], l2y = vl[7],
vc0 = vc[0], vc1 = vc[1],
vc2 = vc[2], vc3 = vc[3],
vc4 = vc[4], vc5 = vc[5],
// Equation of the line Ax + By + C = 0
// A = y2 - y1
// B = x1 - x2
// C = x1 * (y1 - y2) + y1 * (x2 - x1)
A = l2y - l1y,
B = l1x - l2x,
C = l1x * (l1y - l2y) + l1y * (l2x - l1x),
// Bernstein coefficients for the curve
bx0 = -vc0 + 3 * vc2 + -3 * vc4 + vc[6],
bx1 = 3 * vc0 - 6 * vc2 + 3 * vc4,
bx2 = -3 * vc0 + 3 * vc2,
bx3 = vc0,
by0 = -vc1 + 3 * vc3 + -3 * vc5 + vc[7],
by1 = 3 * vc1 - 6 * vc3 + 3 * vc5,
by2 = -3 * vc1 + 3 * vc3,
by3 = vc1,
// Form the cubic equation
// a * t^3 + b*t^2 + c*t + d = 0
a = A * bx0 + B * by0, // t^3
b = A * bx1 + B * by1, // t^2
c = A * bx2 + B * by2, // t
d = A * bx3 + B * by3 + C, // t1
roots = [],
// Solve the cubic equation, interested only in results in [0 .. 1]
count = Numerical.solveCubic(a, b, c, d, roots, 0, 1);
// Rotate both curve and line around l1 so that line is on x axis
lvx = l2x - l1x,
lvy = l2y - l1y,
// Angle with x axis (1, 0)
angle = Math.atan2(-lvy, lvx),
sin = Math.sin(angle),
cos = Math.cos(angle),
// (rl1x, rl1y) = (0, 0)
rl2x = lvx * cos - lvy * sin,
vcr = [];
for(var i = 0; i < 8; i += 2) {
var x = vc[i] - l1x,
y = vc[i + 1] - l1y;
vcr.push(
x * cos - y * sin,
y * cos + x * sin);
}
var roots = [],
count = Curve.solveCubic(vcr, 1, 0, roots);
// NOTE: count could be -1 for inifnite solutions, but that should only
// happen with lines, in which case we should not be here.
for (var i = 0; i < count; i++) {
var t = roots[i],
tt = t * t,
ttt = tt * t,
x = bx0 * ttt + bx1 * tt + bx2 * t + bx3,
y = by0 * ttt + by1 * tt + by2 * t + by3;
// tl is the parameter of the intersection point in line segment.
// Special case to override the tight tolerence in
// Curve.solveQuadratic when line is horizontal
if (l2y === l1y)
y = l1y;
var tl = Curve.getParameterOf(vl, x, y),
t2;
// We do have a point on the infinite line. Check if it falls on
// the line *segment*.
if (tl >= 0 && tl <= 1) {
// Interpolate the parameter for the intersection on line.
t1 = flip ? tl : t;
t2 = flip ? t : tl;
addLocation(locations,
curve1, t1, Curve.evaluate(v1, t1, 0),
curve2, t2, Curve.evaluate(v2, t2, 0));
var t = roots[i];
if (t >= 0 && t <= 1) {
var point = Curve.evaluate(vcr, t, 0);
// We do have a point on the infinite line. Check if it falls on
// the line *segment*.
if (point.x >= 0 && point.x <= rl2x){
var tl = Curve.getParameterOf(vl, point.x, point.y);
// Interpolate the parameter for the intersection on line.
var t1 = flip ? tl : t,
t2 = flip ? t : tl;
addLocation(locations,
curve1, t1, Curve.evaluate(v1, t1, 0),
curve2, t2, Curve.evaluate(v2, t2, 0));
}
}
}
}