mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-06 04:42:15 -05:00
More computeBoolean() optimizations and clean up.
This commit is contained in:
parent
1031f4ecfb
commit
4a9e3924c6
1 changed files with 60 additions and 69 deletions
|
@ -76,9 +76,8 @@ PathItem.inject(new function() {
|
||||||
* @param {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
|
* @param {CompoundPath} path - Input CompoundPath, Note: This path could be modified if need be.
|
||||||
* @return {boolean} the winding direction of the base contour(true if clockwise)
|
* @return {boolean} the winding direction of the base contour(true if clockwise)
|
||||||
*/
|
*/
|
||||||
function reorientCompoundPath(path) {
|
function reorientPath(path) {
|
||||||
if (!(path instanceof CompoundPath))
|
if (path instanceof CompoundPath) {
|
||||||
return path.isClockwise();
|
|
||||||
var children = path._children,
|
var children = path._children,
|
||||||
length = children.length,
|
length = children.length,
|
||||||
bounds = new Array(length),
|
bounds = new Array(length),
|
||||||
|
@ -100,20 +99,20 @@ PathItem.inject(new function() {
|
||||||
children[i].setClockwise(clockwise);
|
children[i].setClockwise(clockwise);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return clockwise;
|
}
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
function computeBoolean(path1, path2, operator, subtract, _cache) {
|
function computeBoolean(path1, path2, operator, subtract, _cache) {
|
||||||
var ixs, path1Id, path2Id;
|
|
||||||
// We do not modify the operands themselves
|
// We do not modify the operands themselves
|
||||||
// The result might not belong to the same type
|
// The result might not belong to the same type
|
||||||
// i.e. subtraction(A:Path, B:Path):CompoundPath etc.
|
// i.e. subtraction(A:Path, B:Path):CompoundPath etc.
|
||||||
var _path1 = path1.clone(),
|
var _path1 = reorientPath(path1.clone()),
|
||||||
_path2 = path2.clone(),
|
_path2 = reorientPath(path2.clone()),
|
||||||
|
path1Clockwise = _path1.isClockwise(),
|
||||||
|
path2Clockwise = _path2.isClockwise(),
|
||||||
path1Id = _path1.id,
|
path1Id = _path1.id,
|
||||||
path2Id = _path2.id,
|
path2Id = _path2.id,
|
||||||
path1Clockwise = reorientCompoundPath(_path1),
|
|
||||||
path2Clockwise = reorientCompoundPath(_path2),
|
|
||||||
// Calculate all the intersections
|
// Calculate all the intersections
|
||||||
intersections = _cache && _cache.intersections
|
intersections = _cache && _cache.intersections
|
||||||
|| _path1.getIntersections(_path2);
|
|| _path1.getIntersections(_path2);
|
||||||
|
@ -133,88 +132,80 @@ PathItem.inject(new function() {
|
||||||
path2Clockwise = !path2Clockwise;
|
path2Clockwise = !path2Clockwise;
|
||||||
}
|
}
|
||||||
|
|
||||||
var paths = [],
|
var paths = []
|
||||||
|
.concat(_path1._children || [_path1])
|
||||||
|
.concat(_path2._children || [_path2]),
|
||||||
nodes = [],
|
nodes = [],
|
||||||
result = new CompoundPath(),
|
result = new CompoundPath();
|
||||||
push = paths.push;
|
|
||||||
if (_path1 instanceof CompoundPath) {
|
|
||||||
push.apply(paths, _path1._children);
|
|
||||||
} else {
|
|
||||||
paths.push(_path1);
|
|
||||||
}
|
|
||||||
if (_path2 instanceof CompoundPath) {
|
|
||||||
push.apply(paths, _path2._children);
|
|
||||||
} else {
|
|
||||||
paths.push(_path2);
|
|
||||||
}
|
|
||||||
// Step 1: Discard invalid links according to the boolean operator
|
// Step 1: Discard invalid links according to the boolean operator
|
||||||
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],
|
||||||
insidePath1 = false,
|
parent = path._parent,
|
||||||
insidePath2 = false,
|
id = parent instanceof CompoundPath ? parent._id : path._id,
|
||||||
thisId = path.parent instanceof CompoundPath
|
|
||||||
? path.parent.id : path.id,
|
|
||||||
clockwise = path.isClockwise(),
|
clockwise = path.isClockwise(),
|
||||||
segments = path._segments;
|
segments = path._segments,
|
||||||
for (var j = 0, k = segments.length; j < k; j++) {
|
insidePath1 = false,
|
||||||
|
insidePath2 = false;
|
||||||
|
for (var j = segments.length - 1; j >= 0; j--) {
|
||||||
var segment = segments[j],
|
var segment = segments[j],
|
||||||
curve = segment.getCurve(),
|
midPoint = segment.getCurve().getPoint(0.5);
|
||||||
midPoint = curve.getPoint(0.5);
|
if (id !== path1Id) {
|
||||||
if (thisId !== path1Id) {
|
|
||||||
insidePath1 = _path1.contains(midPoint)
|
insidePath1 = _path1.contains(midPoint)
|
||||||
&& (clockwise === path1Clockwise || subtract
|
&& (clockwise === path1Clockwise || subtract
|
||||||
|| !testOnCurve(_path1, midPoint));
|
|| !testOnCurve(_path1, midPoint));
|
||||||
}
|
}
|
||||||
if (thisId !== path2Id) {
|
if (id !== path2Id) {
|
||||||
insidePath2 = _path2.contains(midPoint)
|
insidePath2 = _path2.contains(midPoint)
|
||||||
&& (clockwise === path2Clockwise
|
&& (clockwise === path2Clockwise
|
||||||
|| !testOnCurve(_path2, midPoint));
|
|| !testOnCurve(_path2, midPoint));
|
||||||
}
|
}
|
||||||
if (operator(thisId === path1Id, insidePath1, insidePath2)) {
|
if (operator(id === path1Id, insidePath1, insidePath2)) {
|
||||||
curve._INVALID = true;
|
segment._INVALID = true;
|
||||||
// markPoint(midPoint, '+');
|
// markPoint(midPoint, '+');
|
||||||
|
} else {
|
||||||
|
nodes.push(segment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
nodes = nodes.concat(path._segments);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2: Retrieve the resulting paths from the graph
|
// Step 2: Retrieve the resulting paths from the graph
|
||||||
for (var i = 0, l = nodes.length; i < l; i++) {
|
for (var i = 0, l = nodes.length; i < l; i++) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
if (node.curve._INVALID || node._visited) { continue; }
|
if (node._visited)
|
||||||
|
continue;
|
||||||
var path = node.path,
|
var path = node.path,
|
||||||
thisId = (path.parent instanceof CompoundPath)? path.parent.id : path.id,
|
|
||||||
nuPath = new Path(),
|
nuPath = new Path(),
|
||||||
firstNode = null,
|
firstNode = node,
|
||||||
firstNode_ix = null;
|
firstNode_ix = null;
|
||||||
if (node.previous.curve._INVALID) {
|
if (node.getPrevious()._INVALID) {
|
||||||
node.setHandleIn(node._ixPair
|
node.setHandleIn(node._ixPair
|
||||||
? node._ixPair.getIntersection().__segment._handleIn
|
? node._ixPair.getIntersection().__segment._handleIn
|
||||||
: Point.create(0, 0));
|
: Point.create(0, 0));
|
||||||
}
|
}
|
||||||
while (node && !node._visited && (node !== firstNode && node !== firstNode_ix)) {
|
while (node && !node._visited && node !== firstNode_ix) {
|
||||||
node._visited = true;
|
node._visited = true;
|
||||||
firstNode = firstNode || node;
|
firstNode_ix = firstNode_ix || firstNode._ixPair
|
||||||
firstNode_ix = !firstNode_ix && firstNode._ixPair
|
&& firstNode._ixPair.getIntersection().__segment;
|
||||||
? firstNode._ixPair.getIntersection().__segment
|
|
||||||
: firstNode_ix;
|
|
||||||
// node._ixPair is this node's intersection CurveLocation object
|
// node._ixPair is this node's intersection CurveLocation object
|
||||||
// node._ixPair.getIntersection() is the other CurveLocation object this node intersects with
|
// node._ixPair.getIntersection() is the other CurveLocation object this node intersects with
|
||||||
var nextNode = (node._ixPair && node.curve._INVALID)? node._ixPair.getIntersection().__segment : node;
|
var nextNode = node._ixPair && node._INVALID
|
||||||
|
? node._ixPair.getIntersection().__segment
|
||||||
|
: node;
|
||||||
if (node._ixPair) {
|
if (node._ixPair) {
|
||||||
nextNode._visited = true;
|
|
||||||
nuPath.add(new Segment(node._point, node._handleIn,
|
nuPath.add(new Segment(node._point, node._handleIn,
|
||||||
nextNode._handleOut));
|
nextNode._handleOut));
|
||||||
|
nextNode._visited = true;
|
||||||
node = nextNode;
|
node = nextNode;
|
||||||
} else {
|
} else {
|
||||||
nuPath.add(node);
|
nuPath.add(node);
|
||||||
}
|
}
|
||||||
node = node.next;
|
node = node.getNext();
|
||||||
}
|
}
|
||||||
// Avoid stray segments and incomplete paths
|
// Avoid stray segments and incomplete paths
|
||||||
if (nuPath.segments.length > 2 || !nuPath.curves[0].isLinear()) {
|
if (nuPath._segments.length > 2) {
|
||||||
nuPath.closed = true;
|
nuPath.setClosed(true);
|
||||||
result.addChild(nuPath, true);
|
result.addChild(nuPath, true);
|
||||||
|
} else {
|
||||||
|
nuPath.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Delete the proxies
|
// Delete the proxies
|
||||||
|
|
Loading…
Reference in a new issue