From 01e48b3322dd0da97556a998615c794b68ceec16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrg=20Lehni?= Date: Thu, 13 Jun 2013 15:53:28 -0700 Subject: [PATCH] Improve and clean up fat-line bug fix. --- fatline/intersectTests.js | 2 +- src/options.js | 2 +- src/path/Curve.js | 37 ++++++++++++++++++------------------- src/path/CurveLocation.js | 24 ++++++++++-------------- src/util/Numerical.js | 1 - 5 files changed, 30 insertions(+), 36 deletions(-) diff --git a/fatline/intersectTests.js b/fatline/intersectTests.js index 749fdd65..1b019e36 100644 --- a/fatline/intersectTests.js +++ b/fatline/intersectTests.js @@ -485,7 +485,7 @@ function testIntersections(path1, path2, caption, testname, testdata, nomark) { fatTime: t2, success: success }); - console.log(found); + console.log(ixsPaper.length, found); if (!success) { var ser = new XMLSerializer(); console.log('failcase:', ser.serializeToString(path1.exportSVG()), diff --git a/src/options.js b/src/options.js index 20d1e802..30c88de4 100644 --- a/src/options.js +++ b/src/options.js @@ -19,6 +19,6 @@ var options = { browser: true, stats: true, svg: true, - fatline: false, + fatline: true, debug: false }; diff --git a/src/path/Curve.js b/src/path/Curve.js index de88490d..4875da57 100644 --- a/src/path/Curve.js +++ b/src/path/Curve.js @@ -869,7 +869,7 @@ statics: { step /= 2; } var pt = Curve.evaluate(values, minT, true, 0); - return new CurveLocation(this, minT, pt, null, null, + return new CurveLocation(this, minT, pt, null, null, null, point.getDistance(pt)); }, @@ -966,7 +966,7 @@ new function() { // Scope for methods that require numerical integration a = 0; if (b === undefined) b = 1; - // if (p1 == c1 && p2 == c2): + // See if the curve is linear by checking p1 == c1 and p2 == c2 if (v[0] == v[2] && v[1] == v[3] && v[6] == v[4] && v[7] == v[5]) { // Straight line var dx = v[6] - v[0], // p2x - p1x @@ -1030,13 +1030,14 @@ new function() { // Scope for methods that require numerical integration } }; }, new function() { // Scope for intersection using bezier fat-line clipping - function addLocation(locations, curve1, t1, point, curve2, t2) { + function addLocation(locations, curve1, t1, point1, curve2, t2, point2) { // 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))) - locations.push(new CurveLocation(curve1, t1, point, curve2, t2)); + if ((!first || !point1.equals(first._point)) + && (!last || !point1.equals(last._point))) + locations.push( + new CurveLocation(curve1, t1, point1, curve2, t2, point2)); } function addCurveIntersections(v1, v2, curve1, curve2, locations, @@ -1065,9 +1066,7 @@ new function() { // Scope for methods that require numerical integration // degenerate case seperately, where fat-line clipping can become // numerically unstable when one of the curves has converged to a point // and the other hasn't. - while (iteration++ < 20 - && (Math.abs(range1[1] - range1[0]) > /*#=*/ Numerical.TOLERANCE - || Math.abs(range2[1] - range2[0]) > /*#=*/ Numerical.TOLERANCE)) { + while (iteration++ < 20) { // First we clip v2 with v1's fat-line var range, intersects1 = clipFatLine(part1, part2, range = range2.slice()), @@ -1119,14 +1118,15 @@ new function() { // Scope for methods that require numerical integration } } // We need to bailout of clipping and try a numerically stable - // method if both of the parameter ranges have converged reasonably well - // (according to Numerical.TOLERANCE). - if (Math.abs(range1[1] - range1[0]) < /*#=*/ Numerical.TOLERANCE && - Math.abs(range2[1] - range2[0]) < /*#=*/ Numerical.TOLERANCE) { + // method if both of the parameter ranges have converged reasonably + // well (according to Numerical.TOLERANCE). + if (Math.abs(range1[1] - range1[0]) <= /*#=*/ Numerical.TOLERANCE && + Math.abs(range2[1] - range2[0]) <= /*#=*/ Numerical.TOLERANCE) { var t1 = (range1[0] + range1[1]) / 2, t2 = (range2[0] + range2[1]) / 2; - addLocation(locations, curve1, t1, - Curve.evaluate(v1, t1, true, 0), curve2, t2); + addLocation(locations, + curve1, t1, Curve.evaluate(v1, t1, true, 0), + curve2, t2, Curve.evaluate(v2, t2, true, 0)); break; } } @@ -1330,10 +1330,9 @@ new function() { // Scope for methods that require numerical integration * 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, flip) { - if (flip === undefined) - flip = Curve.isLinear(v1); - var vc = flip ? v2 : v1, + function addCurveLineIntersections(v1, v2, curve1, curve2, locations) { + var flip = Curve.isLinear(v1), + vc = flip ? v2 : v1, vl = flip ? v1 : v2, l1x = vl[0], l1y = vl[1], l2x = vl[6], l2y = vl[7], diff --git a/src/path/CurveLocation.js b/src/path/CurveLocation.js index 67bfe74c..c93290c2 100644 --- a/src/path/CurveLocation.js +++ b/src/path/CurveLocation.js @@ -36,8 +36,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ * @param {Number} parameter * @param {Point} point */ - initialize: function CurveLocation(curve, parameter, point, _otherCurve, - _otherParameter, _distance) { + initialize: function CurveLocation(curve, parameter, point, _curve2, + _parameter2, _point2, _distance) { // Define this CurveLocation's unique id. this._id = CurveLocation._id = (CurveLocation._id || 0) + 1; this._curve = curve; @@ -48,8 +48,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ this._segment2 = curve._segment2; this._parameter = parameter; this._point = point; - this._otherCurve = _otherCurve; - this._otherParameter = _otherParameter; + this._curve2 = _curve2; + this._parameter2 = _parameter2; + this._point2 = _point2; this._distance = _distance; }, @@ -110,17 +111,12 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ */ getIntersection: function() { var intersection = this._intersection; - if (!intersection && this._otherCurve) { - var param = this._otherParameter; + if (!intersection && this._curve2) { + var param = this._parameter2; // If we have the parameter on the other curve use that for // intersection rather than the point. this._intersection = intersection = new CurveLocation( - this._otherCurve, param, param ? null : this._point, this); - // Force calculate the other point from the parameter. - // DEBUG: @jlehni - Not sure why we have to do this? Shouldn't - // it auto-calculate upon first access?! - if (param) - intersection.getPoint(); + this._curve2, param, this._point2 || this._point, this); intersection._intersection = this; } return intersection; @@ -197,8 +193,8 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{ * @type Point * @bean */ - getPoint: function() { - if (!this._point && this._parameter != null) { + getPoint: function(/* uncached */) { + if ((!this._point || arguments[0]) && this._parameter != null) { var curve = this.getCurve(); this._point = curve && curve.getPointAt(this._parameter, true); } diff --git a/src/util/Numerical.js b/src/util/Numerical.js index db04302a..11e25a36 100644 --- a/src/util/Numerical.js +++ b/src/util/Numerical.js @@ -61,7 +61,6 @@ var Numerical = new function() { return { TOLERANCE: 10e-6, // Precision when comparing against 0 - // TODO: Find a good value EPSILON: 10e-12, // Kappa, see: http://www.whizkidtech.redprince.net/bezier/circle/kappa/ KAPPA: 4 * (sqrt(2) - 1) / 3,