More simplifications related to reorientPaths()

This commit is contained in:
Jürg Lehni 2017-01-22 12:08:54 -05:00
parent f77621f67d
commit 8bbbe149ea

View file

@ -38,10 +38,12 @@ PathItem.inject(new function() {
// contribution contributes to the final result or not. They are applied // contribution contributes to the final result or not. They are applied
// to for each segment after the paths are split at crossings. // to for each segment after the paths are split at crossings.
operators = { operators = {
unite: { 1: true, 2: true }, unite: { '1': true, '2': true },
intersect: { 2: true }, intersect: { '2': true },
subtract: { 1: true }, subtract: { '1': true },
exclude: { 1: true } // exclude only needs -1 to support reorientPaths() when there are
// no crossings.
exclude: { '1': true, '-1': true }
}; };
/* /*
@ -109,20 +111,6 @@ PathItem.inject(new function() {
curves = [], curves = [],
paths; paths;
// When there are no crossings, the result can be known ahead of tracePaths(),
// largely simplifying the processing required:
if (!crossings.length) {
if (paths2 && operator.exclude) {
for (var i = 0; i < paths2.length; i++) {
paths2[i].reverse();
}
}
paths = reorientPaths(paths2 ? paths1.concat(paths2) : paths1,
function(w) {
return !!operator[w];
});
}
function collect(paths) { function collect(paths) {
for (var i = 0, l = paths.length; i < l; i++) { for (var i = 0, l = paths.length; i < l; i++) {
var path = paths[i]; var path = paths[i];
@ -134,7 +122,7 @@ PathItem.inject(new function() {
} }
} }
if (!paths) { if (crossings.length) {
// Collect all segments and curves of both involved operands. // Collect all segments and curves of both involved operands.
collect(paths1); collect(paths1);
if (paths2) if (paths2)
@ -158,6 +146,13 @@ PathItem.inject(new function() {
segment._path._overlapsOnly = false; segment._path._overlapsOnly = false;
} }
paths = tracePaths(segments, operator); paths = tracePaths(segments, operator);
} else {
// When there are no crossings, the result can be determined through
// a much faster call to reorientPaths():
paths = reorientPaths(paths2 ? paths1.concat(paths2) : paths1,
function(w) {
return !!operator[w];
});
} }
return createResult(CompoundPath, paths, true, path1, path2, options); return createResult(CompoundPath, paths, true, path1, path2, options);
@ -265,7 +260,7 @@ PathItem.inject(new function() {
first = sorted[0]; first = sorted[0];
if (clockwise == null) if (clockwise == null)
clockwise = first.isClockwise(); clockwise = first.isClockwise();
// determine winding for each path // Now determine the winding for each path, from large to small.
for (var i = 0; i < length; i++) { for (var i = 0; i < length; i++) {
var path1 = sorted[i], var path1 = sorted[i],
entry1 = lookup[path1._id], entry1 = lookup[path1._id],
@ -273,14 +268,12 @@ PathItem.inject(new function() {
containerWinding = 0; containerWinding = 0;
for (var j = i - 1; j >= 0; j--) { for (var j = i - 1; j >= 0; j--) {
var path2 = sorted[j]; var path2 = sorted[j];
// We run through the paths from largest to smallest, // As we run through the paths from largest to smallest, for
// meaning that for any current path, all potentially // any current path, all potentially containing paths have
// containing paths have already been processed and their // already been processed and their orientation fixed.
// orientation has been fixed. Since we want to achieve // To achieve correct orientation of contained paths based
// alternating orientation of contained paths, all we have // on winding, we have to find one containing path with
// to do is to find one include path that contains the // different "insideness" and set opposite orientation.
// current path, and then set the orientation to the
// opposite of the containing path.
if (path2.contains(point)) { if (path2.contains(point)) {
var entry2 = lookup[path2._id]; var entry2 = lookup[path2._id];
entry1.container = entry2.exclude ? entry2.container entry1.container = entry2.exclude ? entry2.container
@ -289,10 +282,10 @@ PathItem.inject(new function() {
break; break;
} }
} }
// only keep paths if the insideness changes when crossing the // Only keep paths if the "insideness" changes when crossing the
// path, e.g. the inside of the path is filled and the outside // path, e.g. the inside of the path is filled and the outside
// not filled (or vice versa). // is not, or vice versa.
if (isInside(entry1.winding) == isInside(containerWinding)) { if (isInside(entry1.winding) === isInside(containerWinding)) {
entry1.exclude = true; entry1.exclude = true;
// No need to delete excluded entries. Setting to null is // No need to delete excluded entries. Setting to null is
// enough, as #setChildren() can handle arrays with gaps. // enough, as #setChildren() can handle arrays with gaps.