mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-07 13:22:07 -05:00
Properly solve issues with self-intersecting special case.
(e.g. shapes resembling the infinity sign)
This commit is contained in:
parent
fc0b5a8858
commit
fd927cbe22
3 changed files with 27 additions and 23 deletions
|
@ -1040,7 +1040,7 @@ statics: {
|
||||||
step /= 2;
|
step /= 2;
|
||||||
}
|
}
|
||||||
var pt = Curve.getPoint(values, minT);
|
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,
|
function addLocation(locations, param, v1, c1, t1, p1, v2, c2, t2, p2,
|
||||||
overlap) {
|
overlap) {
|
||||||
var loc = null,
|
var startConnected = param.startConnected,
|
||||||
|
endConnected = param.endConnected,
|
||||||
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
tMin = /*#=*/Numerical.CURVETIME_EPSILON,
|
||||||
tMax = 1 - tMin,
|
tMax = 1 - tMin;
|
||||||
startConnected = param.startConnected,
|
|
||||||
endConnected = param.endConnected;
|
|
||||||
if (t1 == null)
|
if (t1 == null)
|
||||||
t1 = Curve.getParameterOf(v1, p1.x, p1.y);
|
t1 = Curve.getParameterOf(v1, p1.x, p1.y);
|
||||||
// Check t1 and t2 against correct bounds, based on start-/endConnected:
|
// 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
|
// a found overlap. The normal intersection will already be found at
|
||||||
// the beginning, and would be added twice otherwise.
|
// the beginning, and would be added twice otherwise.
|
||||||
if (t1 >= (startConnected ? tMin : 0) &&
|
if (t1 >= (startConnected ? tMin : 0) &&
|
||||||
t1 <= (endConnected || !overlap && c1.isLast() ? tMax : 1)) {
|
t1 <= (endConnected ? tMax : 1)) {
|
||||||
if (t2 == null)
|
if (t2 == null)
|
||||||
t2 = Curve.getParameterOf(v2, p2.x, p2.y);
|
t2 = Curve.getParameterOf(v2, p2.x, p2.y);
|
||||||
if (t2 >= (endConnected ? tMin : 0) &&
|
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
|
// TODO: Don't we need to check the range of t2 as well? Does it
|
||||||
// also need startConnected / endConnected values?
|
// also need startConnected / endConnected values?
|
||||||
var renormalize = param.renormalize;
|
var renormalize = param.renormalize;
|
||||||
|
@ -1385,13 +1384,25 @@ new function() { // Scope for intersection using bezier fat-line clipping
|
||||||
t1 = res[0];
|
t1 = res[0];
|
||||||
t2 = res[1];
|
t2 = res[1];
|
||||||
}
|
}
|
||||||
var include = param.include,
|
var loc1 = new CurveLocation(c1, t1,
|
||||||
loc = new CurveLocation(c1, t1,
|
p1 || Curve.getPoint(v1, t1), overlap),
|
||||||
p1 || Curve.getPoint(v1, t1), null, overlap,
|
loc2 = new CurveLocation(c2, t2,
|
||||||
new CurveLocation(c2, t2,
|
p2 || Curve.getPoint(v2, t2), overlap),
|
||||||
p2 || Curve.getPoint(v2, t2), null, overlap));
|
// For self-intersections, detect the case where the second
|
||||||
if (!include || include(loc))
|
// 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);
|
CurveLocation.add(locations, loc, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
* @param {Point} [point]
|
* @param {Point} [point]
|
||||||
*/
|
*/
|
||||||
initialize: function CurveLocation(curve, parameter, point,
|
initialize: function CurveLocation(curve, parameter, point,
|
||||||
_distance, _overlap, _intersection) {
|
_overlap, _distance) {
|
||||||
// Merge intersections very close to the end of a curve to the
|
// Merge intersections very close to the end of a curve to the
|
||||||
// beginning of the next curve.
|
// beginning of the next curve.
|
||||||
if (parameter >= 1 - /*#=*/Numerical.CURVETIME_EPSILON) {
|
if (parameter >= 1 - /*#=*/Numerical.CURVETIME_EPSILON) {
|
||||||
|
@ -60,15 +60,9 @@ var CurveLocation = Base.extend(/** @lends CurveLocation# */{
|
||||||
this._setCurve(curve);
|
this._setCurve(curve);
|
||||||
this._parameter = parameter;
|
this._parameter = parameter;
|
||||||
this._point = point || curve.getPointAt(parameter, true);
|
this._point = point || curve.getPointAt(parameter, true);
|
||||||
this._distance = _distance;
|
|
||||||
this._overlap = _overlap;
|
this._overlap = _overlap;
|
||||||
this._crossing = null;
|
this._distance = _distance;
|
||||||
this._intersection = _intersection;
|
this._intersection = null;
|
||||||
if (_intersection) {
|
|
||||||
_intersection._intersection = this;
|
|
||||||
// TODO: Remove this once debug logging is removed.
|
|
||||||
_intersection._other = true;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_setCurve: function(curve) {
|
_setCurve: function(curve) {
|
||||||
|
|
|
@ -639,7 +639,6 @@ PathItem.inject(new function() {
|
||||||
if (added && (seg === start || seg === otherStart)) {
|
if (added && (seg === start || seg === otherStart)) {
|
||||||
// We've come back to the start, bail out as we're done.
|
// We've come back to the start, bail out as we're done.
|
||||||
drawSegment(seg, null, 'done', i, 'red');
|
drawSegment(seg, null, 'done', i, 'red');
|
||||||
seg._visited = true;
|
|
||||||
break;
|
break;
|
||||||
} else if (seg._visited && (!other || other._visited)) {
|
} else if (seg._visited && (!other || other._visited)) {
|
||||||
// TODO: Do we still need to check other too?
|
// TODO: Do we still need to check other too?
|
||||||
|
|
Loading…
Reference in a new issue