From a9a0857ba41f2fac0253e62103c0a77528333cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Tue, 9 Apr 2013 20:27:55 -0700 Subject: [PATCH] Find a better strategy to avoid duplicate solutions in PathItem#getIntersections(). Closes #197. --- src/basic/Rectangle.js | 8 ++++++++ src/path/Curve.js | 26 +++++++++++--------------- src/path/PathItem.js | 2 +- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/basic/Rectangle.js b/src/basic/Rectangle.js index 0c55b058..c4448de3 100644 --- a/src/basic/Rectangle.js +++ b/src/basic/Rectangle.js @@ -596,6 +596,14 @@ var Rectangle = this.Rectangle = Base.extend(/** @lends Rectangle# */{ && rect.y < this.y + this.height; }, + touches: function(rect) { + rect = Rectangle.read(arguments); + return rect.x + rect.width >= this.x + && rect.y + rect.height >= this.y + && rect.x <= this.x + this.width + && rect.y <= this.y + this.height; + }, + /** * {@grouptitle Boolean Operations} * diff --git a/src/path/Curve.js b/src/path/Curve.js index 33959972..d5684640 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -650,15 +650,7 @@ statics: { strokeWidth: 0.1 }); /*#*/ } - // We are not using Rectangle#intersects() here, since in order to - // detect intersections that lie on curve bounds, we need to consider - // touching on one side of the tested rectangles as intersection as well - // If touch is condired at both sides, solutions lying on the border of - // bounds would turn up twice. - if (bounds1.x + bounds1.width >= bounds2.x - && bounds1.y + bounds1.height >= bounds2.y - && bounds1.x < bounds2.x + bounds2.width - && bounds1.y < bounds2.y + bounds2.height) { + if (bounds1.touches(bounds2)) { // See if both curves are flat enough to be treated as lines. if (Curve.isFlatEnough(v1, /*#=*/ Numerical.TOLERANCE) && Curve.isFlatEnough(v2, /*#=*/ Numerical.TOLERANCE)) { @@ -673,12 +665,16 @@ 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)); - // Passing null for parameter leads to lazy determination of - // parameter values in CurveLocation#getParameter() only once - // they are requested. - if (point) + var line1 = new Line(v1[0], v1[1], v1[6], v1[7], false), + line2 = new Line(v2[0], v2[1], v2[6], v2[7], false), + point = line1.intersect(line2); + // Filter out beginnings of the curves, to avoid duplicate + // solutions where curves join. + if (point && !point.equals(line1.point) + && !point.equals(line2.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. diff --git a/src/path/PathItem.js b/src/path/PathItem.js index 960b664f..72b40693 100644 --- a/src/path/PathItem.js +++ b/src/path/PathItem.js @@ -57,7 +57,7 @@ var PathItem = this.PathItem = Item.extend(/** @lends PathItem# */{ getIntersections: function(path) { // First check the bounds of the two paths. If they don't intersect, // we don't need to iterate through their curves. - if (!this.getBounds().intersects(path.getBounds())) + if (!this.getBounds().touches(path.getBounds())) return []; var locations = [], curves1 = this.getCurves(),