Improve and clean up fat-line bug fix.

This commit is contained in:
Jürg Lehni 2013-06-13 15:53:28 -07:00
parent 38f31be6b2
commit 01e48b3322
5 changed files with 30 additions and 36 deletions

View file

@ -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()),

View file

@ -19,6 +19,6 @@ var options = {
browser: true,
stats: true,
svg: true,
fatline: false,
fatline: true,
debug: false
};

View file

@ -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],

View file

@ -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);
}

View file

@ -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,