Fix orientation handling in new #resolveCrossings().

Closes #869
This commit is contained in:
Jürg Lehni 2015-12-28 01:54:49 +01:00
parent 9d4066da1c
commit b5a38ae5ec

View file

@ -797,28 +797,27 @@ PathItem.inject(new function() {
item; item;
if (length > 1) { if (length > 1) {
// First order the paths by the area of their bounding boxes. // First order the paths by the area of their bounding boxes.
// Make a clone of paths as it may still be the children array.
paths = paths.slice().sort(function (a, b) { paths = paths.slice().sort(function (a, b) {
return b.getBounds().getArea() - a.getBounds().getArea(); return b.getBounds().getArea() - a.getBounds().getArea();
}); });
var first = paths[0], var items = [],
clockwise = first.isClockwise(),
items = [first],
excluded = {}, excluded = {},
isNonZero = this.getFillRule() === 'nonzero', isNonZero = this.getFillRule() === 'nonzero',
windings = isNonZero && Base.each(paths, function(path) { windings = isNonZero && Base.each(paths, function(path) {
this.push(path.isClockwise() ? 1 : -1); this.push(path.isClockwise() ? 1 : -1);
}, []); }, []);
// Walk through paths, from largest to smallest. // Walk through paths, from largest to smallest.
// The first, largest path can be skipped. for (var i = 0; i < length; i++) {
for (var i = 1; i < length; i++) {
var path = paths[i], var path = paths[i],
point = path.getInteriorPoint(), point = path.getInteriorPoint(),
isOverlapping = false, isOverlapping = false,
exclude = false, exclude = false,
counter = 0; clockwise = path.isClockwise();
for (var j = i - 1; j >= 0; j--) { for (var j = i - 1; j >= 0; j--) {
if (paths[j].contains(point)) { if (paths[j].contains(point)) {
if (isNonZero && !isOverlapping) { if (isNonZero && !isOverlapping) {
isOverlapping = true;
windings[i] += windings[j]; windings[i] += windings[j];
// Remove path if rule is nonzero and winding // Remove path if rule is nonzero and winding
// of path and containing path is not zero. // of path and containing path is not zero.
@ -827,28 +826,21 @@ PathItem.inject(new function() {
break; break;
} }
} }
isOverlapping = true; if (!excluded[j]) {
// Increase counter for containing paths only if // Toggle orientation from the overlapping path.
// path will not be excluded. clockwise = !paths[j].isClockwise();
if (!excluded[j]) break;
counter++; }
} }
} }
if (!exclude) { if (!exclude) {
// Set correct orientation and add to final items. path.setClockwise(clockwise);
path.setClockwise((counter % 2 === 0) === clockwise);
items.push(path); items.push(path);
} }
} }
// Replace paths with the processed items list: // Replace paths with the processed items list:
paths = items; paths = items;
length = items.length; length = items.length;
} else if (length === 1) {
// TODO: Is this really required? We don't do the same for
// compound-paths:
// Paths that are not part of compound paths should never be
// counter- clockwise for boolean operations.
paths[0].setClockwise(true);
} }
// First try to recycle the current path / compound-path, if the // First try to recycle the current path / compound-path, if the
// amount of paths do not require a conversion. // amount of paths do not require a conversion.