Merge pull request #938 from iconexperience/getWinding-simplification

Simplify getWindings() by using only the 'last' property to understand when a new loop starts.
This commit is contained in:
Jürg Lehni 2016-02-02 21:45:04 +01:00
commit 53269ab169

View file

@ -348,69 +348,65 @@ PathItem.inject(new function() {
} else { } else {
var xBefore = px - epsilon, var xBefore = px - epsilon,
xAfter = px + epsilon, xAfter = px + epsilon,
start, prevWinding,
end = 0; prevXEnd;
while (end < length) { for (var i = 0; i < length; i++) {
start = end; var curve = curves[i],
// The first curve of a loop holds information about its length winding = curve.winding,
// and the last curve with non-zero winding. values = curve.values,
yStart = values[1],
yEnd = values[7];
// The first curve of a loop holds the last curve with
// non-zero winding.
// Retrieve and use it here (See _getMonoCurve()). // Retrieve and use it here (See _getMonoCurve()).
var curve = curves[start], if (curve.last) {
last = curve.last,
// Get the values of to the end x coordinate and winding of // Get the values of to the end x coordinate and winding of
// the last non-horizontal curve, which will be the previous // the last non-horizontal curve, which will be the previous
// non-horizontal curve for the first curve of the loop. // non-horizontal curve for the first curve of the loop.
prevWinding = last.winding, prevWinding = curve.last.winding;
prevXEnd = last.values[6]; prevXEnd = curve.last.values[6];
end = start + curve.length; }
for (var i = start; i < end; i++) { // Since the curves are monotone in y direction, we can just
var curve = curves[i], // compare the endpoints of the curve to determine if the
winding = curve.winding, // ray from query point along +-x direction will intersect
values = curve.values, // the monotone curve.
yStart = values[1], // Horizontal curves with winding == 0 will be completely
yEnd = values[7]; // ignored.
// Since the curves are monotone in y direction, we can just if (winding && (py >= yStart && py <= yEnd
// compare the endpoints of the curve to determine if the || py >= yEnd && py <= yStart)) {
// ray from query point along +-x direction will intersect // Calculate the x value for the ray's intersection.
// the monotone curve. var x = py === yStart ? values[0]
// Horizontal curves with winding == 0 will be completely : py === yEnd ? values[6]
// ignored. : Curve.solveCubic(values, 1, py, roots, 0, 1) === 1
if (winding && (py >= yStart && py <= yEnd ? Curve.getPoint(values, roots[0]).x
|| py >= yEnd && py <= yStart)) { : null;
// Calculate the x value for the ray's intersection. if (x != null) {
var x = py === yStart ? values[0] // Count the intersection of the ray with the
: py === yEnd ? values[6] // monotonic curve if:
: Curve.solveCubic(values, 1, py, roots, 0, 1) === 1 // - the crossing is not at the start of the curve
? Curve.getPoint(values, roots[0]).x // - or the windings are opposite (intersect at a
: null; // vertical extremum)
if (x != null) { // - or the start of the current curve and the end
// Count the intersection of the ray with the // of the prev curve are on opposite sides of px
// monotonic curve if: var isWindingChange = winding === -prevWinding;
// - the crossing is not at the start of the curve if (py !== yStart || isWindingChange
// - or the windings are opposite (intersect at a || (x - px) * (prevXEnd - px) < 0) {
// vertical extremum) if (x < xBefore) {
// - or the start of the current curve and the end windLeft += winding;
// of the prev curve are on opposite sides of px } else if (x > xAfter) {
var isWindingChange = winding === -prevWinding; windRight += winding;
if (py !== yStart || isWindingChange } else if (py === yStart && isWindingChange) {
|| (x - px) * (prevXEnd - px) < 0) { // The point is a vertical extremum of the
if (x < xBefore) { // path.
windLeft += winding; ++windLeft;
} else if (x > xAfter) { ++windRight;
windRight += winding;
} else if (py === yStart && isWindingChange) {
// The point is a vertical extremum of the
// path.
++windLeft;
++windRight;
}
} }
} }
// Update previous winding and end coordinate whenever
// the ray intersects a non-horizontal curve.
prevWinding = winding;
prevXEnd = values[6];
} }
// Update previous winding and end coordinate whenever
// the ray intersects a non-horizontal curve.
prevWinding = winding;
prevXEnd = values[6];
} }
} }
} }
@ -976,11 +972,9 @@ Path.inject(/** @lends Path# */{
handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]); handleCurve([p1x, p1y, p1x, p1y, p2x, p2y, p2x, p2y]);
} }
if (monoCurves.length > 0) { if (monoCurves.length > 0) {
// Add information about the loop length and the last curve with // Add information about the last curve with non-zero winding,
// non-zero winding, as required in getWinding(). // as required in getWinding().
var first = monoCurves[0]; monoCurves[0].last = last;
first.length = monoCurves.length;
first.last = last;
} }
} }
return monoCurves; return monoCurves;