Include _visited checks in isValid() calls.

This magically reduces the remaining glitches in @iconexperience's test-suite to half.

Relates to #784.
This commit is contained in:
Jürg Lehni 2015-10-06 22:23:43 +02:00
parent 896b068266
commit 8c56a1a110

View file

@ -567,6 +567,8 @@ PathItem.inject(new function() {
}[operation]; }[operation];
function isValid(seg, unadjusted) { function isValid(seg, unadjusted) {
if (seg._visited)
return false;
if (!operator) // For self-intersection, we're always valid! if (!operator) // For self-intersection, we're always valid!
return true; return true;
var winding = seg._winding, var winding = seg._winding,
@ -635,34 +637,35 @@ PathItem.inject(new function() {
// allowed as long as they are valid when not adjusted. // allowed as long as they are valid when not adjusted.
if (nextSeg === start || nextSeg === otherStart if (nextSeg === start || nextSeg === otherStart
|| !seg._visited && !nextSeg._visited || !seg._visited && !nextSeg._visited
// Self-intersections (!operator) don't need isValid() // Self-intersections (!operator) don't need isValid() calls
&& (!operator && (!operator
// We need to use the unadjusted winding here since // We need to use the unadjusted winding here since an
// an overlap crossing might have brought us here, // overlap crossing might have brought us here, in which
// in which case isValid(seg, false) might be false. // case isValid(seg, false) might be false.
|| (!strict || isValid(seg, true)) || (!strict || isValid(seg, true))
// Do not consider nextSeg in strict mode if it is // Do not consider nextSeg in strict mode if it is part
// part of an overlap, in order to prioritize non- // of an overlap, in order to give non-overlapping
// overlapping options that might follow. // options that might follow the priority over overlaps.
&& (!(strict && isOverlap(seg, nextSeg)) && (!(strict && isOverlap(seg, nextSeg))
&& isValid(nextSeg, true) && isValid(nextSeg, true)
// If next segment isn't valid, its intersection // If the next segment isn't valid, its intersection
// to which we may switch might be: // to which we may switch might be, so check that.
|| !strict && nextInter || !strict && nextInter
&& isValid(nextInter._segment, true)) && isValid(nextInter._segment, true))
)) ))
return inter; return inter;
// If it's no match, continue with the next linked intersection. // If it's no match, continue with the next linked intersection.
inter = inter._next; inter = inter._next;
} }
return null; return null;
} }
for (var i = 0, l = segments.length; i < l; i++) { for (var i = 0, l = segments.length; i < l; i++) {
var seg = segments[i], var seg = segments[i],
path = null; path = null;
// Do not start a chain with already visited segments, and segments // Do not start a chain with already visited segments, and segments
// that are not going to be part of the resulting operation. // that are not going to be part of the resulting operation.
if (seg._visited || !isValid(seg)) if (!isValid(seg))
continue; continue;
start = otherStart = null; start = otherStart = null;
while (true) { while (true) {
@ -728,7 +731,7 @@ PathItem.inject(new function() {
// switch at each crossing. // switch at each crossing.
drawSegment(seg, other, 'exclude-cross', i, 'green'); drawSegment(seg, other, 'exclude-cross', i, 'green');
seg = other; seg = other;
} else if (!other._visited && isValid(other)) { } else if (isValid(other)) {
// The other segment is part of the boolean result, and we // The other segment is part of the boolean result, and we
// are at crossing, switch over. // are at crossing, switch over.
drawSegment(seg, other, 'cross', i, 'green'); drawSegment(seg, other, 'cross', i, 'green');