Winding: First attempt at specially handling overlaps in getWinding()

Relates to #1116
This commit is contained in:
Jürg Lehni 2016-07-23 13:32:18 +02:00
parent 31732917c0
commit 83148a2c72

View file

@ -382,6 +382,7 @@ PathItem.inject(new function() {
onPath = false, onPath = false,
onPathWinding = 0, onPathWinding = 0,
onPathCount = 0, onPathCount = 0,
onCurves = [],
roots = [], roots = [],
vPrev, vPrev,
vClose; vClose;
@ -426,13 +427,15 @@ PathItem.inject(new function() {
winding = o0 > o3 ? 1 : -1, winding = o0 > o3 ? 1 : -1,
windingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1, windingPrev = vPrev[io] > vPrev[io + 6] ? 1 : -1,
a3Prev = vPrev[ia + 6], a3Prev = vPrev[ia + 6],
curveWindingL = 0,
curveWindingR = 0,
onCurve = false; onCurve = false;
if (po !== o0) { if (po !== o0) {
// Standard case, curve is not crossed at its starting point. // Standard case, curve is not crossed at its starting point.
if (a < paL) { if (a < paL) {
pathWindingL += winding; curveWindingL = winding;
} else if (a > paR) { } else if (a > paR) {
pathWindingR += winding; curveWindingR = winding;
} else { } else {
onCurve = true; onCurve = true;
pathWindingL += winding; pathWindingL += winding;
@ -442,10 +445,10 @@ PathItem.inject(new function() {
// Curve is crossed at starting point and winding changes from // Curve is crossed at starting point and winding changes from
// previous curve. Cancel the winding from previous curve. // previous curve. Cancel the winding from previous curve.
if (a3Prev < paR) { if (a3Prev < paR) {
pathWindingL += winding; curveWindingL = winding;
} }
if (a3Prev > paL) { if (a3Prev > paL) {
pathWindingR += winding; curveWindingR = winding;
} }
} else if (a3Prev < paL && a > paL || a3Prev > paR && a < paR) { } else if (a3Prev < paL && a > paL || a3Prev > paR && a < paR) {
// Point is on a horizontal curve between the previous non- // Point is on a horizontal curve between the previous non-
@ -453,15 +456,24 @@ PathItem.inject(new function() {
onCurve = true; onCurve = true;
if (a3Prev < paL) { if (a3Prev < paL) {
// left winding was added before, now add right winding. // left winding was added before, now add right winding.
pathWindingR += winding; curveWindingR = winding;
} else if (a3Prev > paR) { } else if (a3Prev > paR) {
// right winding was added before, not add left winding. // right winding was added before, not add left winding.
pathWindingL += winding; curveWindingL = winding;
} }
} }
vPrev = v; vPrev = v;
if (onCurve) if (onCurve) {
onCurves.push({
curve: v,
winding: winding,
windingL: curveWindingL,
windingR: curveWindingR,
});
onPath = true; onPath = true;
}
pathWindingL += curveWindingL;
pathWindingR += curveWindingR;
// If we're on the curve, look at the tangent to decide whether to // If we're on the curve, look at the tangent to decide whether to
// flip direction to determine a reliable winding number: // flip direction to determine a reliable winding number:
// If the tangent is parallel to the direction, call getWinding() // If the tangent is parallel to the direction, call getWinding()
@ -573,6 +585,20 @@ PathItem.inject(new function() {
vClose = null; vClose = null;
} }
} }
for (var i = 0; i < onCurves.length - 1; i++) {
var entry1 = onCurves[i],
hasOverlaps = false;
for (var j = i + 1; !hasOverlaps && j < onCurves.length; j++) {
var entry2 = onCurves[j];
hasOverlaps = !!Curve.getOverlaps(entry1.curve, entry2.curve);
}
if (!hasOverlaps) {
windingL -= entry1.windingL;
windingR -= entry1.windingR;
}
}
if (!windingL && !windingR) { if (!windingL && !windingR) {
windingL = windingR = onPathWinding; windingL = windingR = onPathWinding;
} }