Properly solve issues with self-intersecting special case.

(e.g. shapes resembling the infinity sign)
This commit is contained in:
Jürg Lehni 2015-09-24 12:49:39 -04:00
parent fc0b5a8858
commit fd927cbe22
3 changed files with 27 additions and 23 deletions

View file

@ -1040,7 +1040,7 @@ statics: {
step /= 2;
}
var pt = Curve.getPoint(values, minT);
return new CurveLocation(this, minT, pt, point.getDistance(pt));
return new CurveLocation(this, minT, pt, null, point.getDistance(pt));
},
/**
@ -1357,11 +1357,10 @@ new function() { // Scope for intersection using bezier fat-line clipping
function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
overlap) {
var loc = null,
var startConnected = param.startConnected,
endConnected = param.endConnected,
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
tMax = 1 - tMin,
startConnected = param.startConnected,
endConnected = param.endConnected;
tMax = 1 - tMin;
if (t1 == null)
t1 = Curve.getParameterOf(v1, p1.x, p1.y);
// Check t1 and t2 against correct bounds, based on start-/endConnected:
@ -1372,11 +1371,11 @@ new function() { // Scope for intersection using bezier fat-line clipping
// a found overlap. The normal intersection will already be found at
// the beginning, and would be added twice otherwise.
if (t1 >= (startConnected ? tMin : 0) &&
t1 <= (endConnected || !overlap && c1.isLast() ? tMax : 1)) {
t1 <= (endConnected ? tMax : 1)) {
if (t2 == null)
t2 = Curve.getParameterOf(v2, p2.x, p2.y);
if (t2 >= (endConnected ? tMin : 0) &&
t2 <= (startConnected || !overlap && c2.isLast() ? tMax : 1)) {
t2 <= (startConnected ? tMax : 1)) {
// TODO: Don't we need to check the range of t2 as well? Does it
// also need startConnected / endConnected values?
var renormalize = param.renormalize;
@ -1385,13 +1384,25 @@ new function() { // Scope for intersection using bezier fat-line clipping
t1 = res[0];
t2 = res[1];
}
var include = param.include,
loc = new CurveLocation(c1, t1,
p1 || Curve.getPoint(v1, t1), null, overlap,
new CurveLocation(c2, t2,
p2 || Curve.getPoint(v2, t2), null, overlap));
if (!include || include(loc))
var loc1 = new CurveLocation(c1, t1,
p1 || Curve.getPoint(v1, t1), overlap),
loc2 = new CurveLocation(c2, t2,
p2 || Curve.getPoint(v2, t2), overlap),
// For self-intersections, detect the case where the second
// curve wrapped around, and flip them so they can get
// matched to a potentially already existing intersection.
flip = loc1.getPath() === loc2.getPath()
&& loc1.getIndex() > loc2.getIndex(),
loc = flip ? loc2 : loc1,
include = param.include;
// Link the two locations to each other.
loc1._intersection = loc2;
loc2._intersection = loc1;
// TODO: Remove this once debug logging is removed.
(flip ? loc1 : loc2)._other = true;
if (!include || include(loc)) {
CurveLocation.add(locations, loc, true);
}
}
}
}

View file

@ -42,7 +42,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
* @param {Point} [point]
*/
initialize: function CurveLocation(curve, parameter, point,
_distance, _overlap, _intersection) {
_overlap, _distance) {
// Merge intersections very close to the end of a curve to the
// beginning of the next curve.
if (parameter >= 1 - /*#=*/Numerical.CURVETIME_EPSILON) {
@ -60,15 +60,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
this._setCurve(curve);
this._parameter = parameter;
this._point = point || curve.getPointAt(parameter, true);
this._distance = _distance;
this._overlap = _overlap;
this._crossing = null;
this._intersection = _intersection;
if (_intersection) {
_intersection._intersection = this;
// TODO: Remove this once debug logging is removed.
_intersection._other = true;
}
this._distance = _distance;
this._intersection = null;
},
_setCurve: function(curve) {

View file

@ -639,7 +639,6 @@ PathItem.inject(new function() {
if (added && (seg === start || seg === otherStart)) {
// We've come back to the start, bail out as we're done.
drawSegment(seg, null, 'done', i, 'red');
seg._visited = true;
break;
} else if (seg._visited && (!other || other._visited)) {
// TODO: Do we still need to check other too?