mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-04 03:45:58 -05:00
Handle intersection between linear curves without recursive subdivision.
Closes #207.
This commit is contained in:
parent
06ffd8089d
commit
c513a24f46
3 changed files with 29 additions and 20 deletions
|
@ -67,23 +67,23 @@ var Line = this.Line = Base.extend(/** @lends Line# */{
|
|||
|
||||
/**
|
||||
* @param {Line} line
|
||||
* @return {Point} the intersection point of the lines
|
||||
* @return {Point} the intersection point of the lines, {@code undefined}
|
||||
* if the two lines are colinear, or {@code null} if they don't intersect.
|
||||
*/
|
||||
intersect: function(line, excludeStart, excludeEnd) {
|
||||
intersect: function(line) {
|
||||
var cross = this.vector.cross(line.vector);
|
||||
// Avoid divisions by 0, and errors when getting too close to 0
|
||||
if (Numerical.isZero(cross))
|
||||
return null;
|
||||
return undefined;
|
||||
var v = line.point.subtract(this.point),
|
||||
t1 = v.cross(line.vector) / cross,
|
||||
t2 = v.cross(this.vector) / cross;
|
||||
// Check the ranges of t parameters if the line is not allowed to
|
||||
// extend beyond the definition points.
|
||||
return (this.infinite || (excludeStart ? 0 < t1 : 0 <= t1)
|
||||
&& (excludeEnd ? t1 < 1 : t1 <= 1))
|
||||
&& (line.infinite || (excludeStart ? 0 < t2 : 0 <= t2)
|
||||
&& (excludeEnd ? t2 < 1 : t2 <= 1))
|
||||
? this.point.add(this.vector.multiply(t1)) : null;
|
||||
return (this.infinite || 0 <= t1 && t1 <= 1)
|
||||
&& (line.infinite || 0 <= t2 && t2 <= 1)
|
||||
? this.point.add(this.vector.multiply(t1))
|
||||
: null;
|
||||
},
|
||||
|
||||
// DOCS: document Line#getSide(point)
|
||||
|
|
|
@ -685,7 +685,7 @@ var Point = this.Point = Base.extend(/** @lends Point# */{
|
|||
* another vector.
|
||||
*
|
||||
* @param {Point} point the vector to check against
|
||||
* @returns {Boolean} {@true it is parallel}
|
||||
* @returns {Boolean} {@true it is colinear}
|
||||
*/
|
||||
isColinear: function(point) {
|
||||
return this.cross(point) < /*#=*/ Numerical.TOLERANCE;
|
||||
|
|
|
@ -638,6 +638,10 @@ statics: {
|
|||
return v;
|
||||
},
|
||||
|
||||
isLinear: function(v) {
|
||||
return v[0] === v[2] && v[1] === v[3] && v[4] === v[6] && v[5] === v[7];
|
||||
},
|
||||
|
||||
isFlatEnough: function(v, tolerance) {
|
||||
// Thanks to Kaspar Fischer and Roger Willcocks for the following:
|
||||
// http://hcklbrrfnn.files.wordpress.com/2012/08/bez.pdf
|
||||
|
@ -728,8 +732,10 @@ statics: {
|
|||
});
|
||||
/*#*/ }
|
||||
if (bounds1.touches(bounds2)) {
|
||||
// See if both curves are flat enough to be treated as lines.
|
||||
if (this.isFlatEnough(v1, /*#=*/ Numerical.TOLERANCE)
|
||||
// See if both curves are flat enough to be treated as lines, either
|
||||
// because they have no control points at all, or are "flat enough"
|
||||
if (this.isLinear(v1) && this.isLinear(v2)
|
||||
|| this.isFlatEnough(v1, /*#=*/ Numerical.TOLERANCE)
|
||||
&& this.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE)) {
|
||||
/*#*/ if (options.debug) {
|
||||
new Path.Line({
|
||||
|
@ -747,15 +753,18 @@ statics: {
|
|||
/*#*/ }
|
||||
// See if the parametric equations of the lines interesct.
|
||||
var point = new Line(v1[0], v1[1], v1[6], v1[7], false)
|
||||
.intersect(new Line(v2[0], v2[1], v2[6], v2[7], false),
|
||||
// Filter out beginnings of the curves, to avoid
|
||||
// duplicate solutions where curves join.
|
||||
true, false);
|
||||
if (point)
|
||||
// Passing null for parameter leads to lazy determination of
|
||||
// parameter values in CurveLocation#getParameter() only
|
||||
// once they are requested.
|
||||
locations.push(new CurveLocation(curve, null, point));
|
||||
.intersect(new Line(v2[0], v2[1], v2[6], v2[7], false));
|
||||
if (point) {
|
||||
// Avoid duplicates when hitting segments (closed paths too)
|
||||
var first = locations[0],
|
||||
last = locations[locations.length - 1];
|
||||
if ((!first || !point.equals(first._point))
|
||||
&& (!last || !point.equals(last._point)))
|
||||
// Passing null for parameter leads to lazy determination
|
||||
// of parameter values in CurveLocation#getParameter()
|
||||
// only once they are requested.
|
||||
locations.push(new CurveLocation(curve, null, point));
|
||||
}
|
||||
} else {
|
||||
// Subdivide both curves, and see if they intersect.
|
||||
var v1s = this.subdivide(v1),
|
||||
|
|
Loading…
Reference in a new issue