mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-03 19:45:44 -05:00
Boolean: Improve handling of branching at crossings.
This commit is contained in:
parent
919c42af27
commit
86478b6873
1 changed files with 36 additions and 27 deletions
|
@ -765,6 +765,7 @@ PathItem.inject(new function() {
|
||||||
*/
|
*/
|
||||||
function tracePaths(segments, operator) {
|
function tracePaths(segments, operator) {
|
||||||
var paths = [],
|
var paths = [],
|
||||||
|
branches = [],
|
||||||
starts;
|
starts;
|
||||||
|
|
||||||
function isValid(seg) {
|
function isValid(seg) {
|
||||||
|
@ -800,10 +801,10 @@ PathItem.inject(new function() {
|
||||||
// If there are multiple possible intersections, find the ones that's
|
// If there are multiple possible intersections, find the ones that's
|
||||||
// either connecting back to start or are not visited yet, and will be
|
// either connecting back to start or are not visited yet, and will be
|
||||||
// part of the boolean result:
|
// part of the boolean result:
|
||||||
function getIntersections(segment, collectStarts) {
|
function getCrossingSegments(segment, collectStarts) {
|
||||||
var inter = segment._intersection,
|
var inter = segment._intersection,
|
||||||
start = inter,
|
start = inter,
|
||||||
inters = [];
|
crossings = [];
|
||||||
if (collectStarts)
|
if (collectStarts)
|
||||||
starts = [segment];
|
starts = [segment];
|
||||||
|
|
||||||
|
@ -821,7 +822,7 @@ PathItem.inject(new function() {
|
||||||
// If the next segment isn't valid, its intersection
|
// If the next segment isn't valid, its intersection
|
||||||
// to which we may switch might be, so check that.
|
// to which we may switch might be, so check that.
|
||||||
|| nextInter && isValid(nextInter._segment))))) {
|
|| nextInter && isValid(nextInter._segment))))) {
|
||||||
inters.push(inter);
|
crossings.push(other);
|
||||||
}
|
}
|
||||||
if (collectStarts)
|
if (collectStarts)
|
||||||
starts.push(other);
|
starts.push(other);
|
||||||
|
@ -837,7 +838,7 @@ PathItem.inject(new function() {
|
||||||
inter = inter._prev;
|
inter = inter._prev;
|
||||||
collect(inter, start);
|
collect(inter, start);
|
||||||
}
|
}
|
||||||
return inters;
|
return crossings;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort segments to give non-ambiguous segments the preference as
|
// Sort segments to give non-ambiguous segments the preference as
|
||||||
|
@ -873,7 +874,6 @@ PathItem.inject(new function() {
|
||||||
path = null,
|
path = null,
|
||||||
finished = false,
|
finished = false,
|
||||||
closed = true,
|
closed = true,
|
||||||
branches = [],
|
|
||||||
branch,
|
branch,
|
||||||
visited,
|
visited,
|
||||||
handleIn;
|
handleIn;
|
||||||
|
@ -897,12 +897,11 @@ PathItem.inject(new function() {
|
||||||
// visited, or that are not going to be part of the result).
|
// visited, or that are not going to be part of the result).
|
||||||
while (valid) {
|
while (valid) {
|
||||||
// For each segment we encounter, see if there are multiple
|
// For each segment we encounter, see if there are multiple
|
||||||
// intersections, and if so, pick the best one:
|
// crossings, and if so, pick the best one:
|
||||||
var first = !path,
|
var first = !path,
|
||||||
intersections = getIntersections(seg, first),
|
crossings = getCrossingSegments(seg, first),
|
||||||
inter = intersections.shift(),
|
// Get the other segment of the first found crossing.
|
||||||
// Get the other segment on the intersection.
|
other = crossings.shift(),
|
||||||
other = inter && inter._segment,
|
|
||||||
finished = !first && (isStart(seg) || isStart(other)),
|
finished = !first && (isStart(seg) || isStart(other)),
|
||||||
cross = !finished && other;
|
cross = !finished && other;
|
||||||
if (first) {
|
if (first) {
|
||||||
|
@ -926,10 +925,13 @@ PathItem.inject(new function() {
|
||||||
branch = null;
|
branch = null;
|
||||||
}
|
}
|
||||||
if (!branch) {
|
if (!branch) {
|
||||||
|
// Add the branch's root segment as the last segment to try,
|
||||||
|
// to see if we get to a solution without crossing.
|
||||||
|
if (cross)
|
||||||
|
crossings.push(seg);
|
||||||
branch = {
|
branch = {
|
||||||
start: path._segments.length,
|
start: path._segments.length,
|
||||||
segment: seg,
|
crossings: crossings,
|
||||||
intersections: intersections,
|
|
||||||
visited: visited = [],
|
visited: visited = [],
|
||||||
handleIn: handleIn
|
handleIn: handleIn
|
||||||
};
|
};
|
||||||
|
@ -946,21 +948,26 @@ PathItem.inject(new function() {
|
||||||
for (var j = 0, k = visited.length; j < k; j++) {
|
for (var j = 0, k = visited.length; j < k; j++) {
|
||||||
visited[j]._visited = false;
|
visited[j]._visited = false;
|
||||||
}
|
}
|
||||||
// Go back to the segment at which the crossing happened,
|
visited.length = 0;
|
||||||
// and try other crossings first.
|
// Go back to the branch's root segment at which the
|
||||||
if (inter = branch.intersections.shift()) {
|
// crossing happened, and try other crossings.
|
||||||
seg = inter._segment;
|
// NOTE: This also tries the root segment without crossing,
|
||||||
visited.length = 0;
|
// because it is added to the list of crossings when the
|
||||||
} else {
|
// branch is created above.
|
||||||
// If there are no crossings left, try not crossing:
|
do {
|
||||||
// Restore the previous branch and keep adding to it,
|
seg = branch && branch.crossings.shift();
|
||||||
// but stop once we run out of branches to try.
|
if (!seg) {
|
||||||
if (!(branch = branches.pop()) ||
|
// If there are no segments left, try previous
|
||||||
!isValid(seg = branch.segment))
|
// branches until we find one that works.
|
||||||
break;
|
branch = branches.pop();
|
||||||
visited = branch.visited;
|
if (branch) {
|
||||||
}
|
visited = branch.visited;
|
||||||
handleIn = branch.handleIn;
|
handleIn = branch.handleIn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (branch && !isValid(seg));
|
||||||
|
if (!seg)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// Add the segment to the path, and mark it as visited.
|
// Add the segment to the path, and mark it as visited.
|
||||||
// But first we need to look ahead. If we encounter the end of
|
// But first we need to look ahead. If we encounter the end of
|
||||||
|
@ -987,6 +994,8 @@ PathItem.inject(new function() {
|
||||||
if (path.getArea() !== 0) {
|
if (path.getArea() !== 0) {
|
||||||
paths.push(path);
|
paths.push(path);
|
||||||
}
|
}
|
||||||
|
// Clear branches.
|
||||||
|
branches = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return paths;
|
return paths;
|
||||||
|
|
Loading…
Reference in a new issue