Boolean: Improve handling of open paths.

Relates to #1089
This commit is contained in:
Jürg Lehni 2016-07-14 10:49:12 +02:00
parent c2df96c440
commit acfe6cddeb
2 changed files with 14 additions and 10 deletions

View file

@ -47,10 +47,12 @@ PathItem.inject(new function() {
* remove empty curves, #resolveCrossings() to resolve self-intersection * remove empty curves, #resolveCrossings() to resolve self-intersection
* make sure all paths have correct winding direction. * make sure all paths have correct winding direction.
*/ */
function preparePath(path, resolve) { function preparePath(path, closed) {
var res = path.clone(false).reduce({ simplify: true }) var res = path.clone(false).reduce({ simplify: true })
.transform(null, true, true); .transform(null, true, true);
return resolve ? res.resolveCrossings() : res; if (closed)
res.setClosed(true);
return closed ? res.resolveCrossings() : res;
} }
function createResult(ctor, paths, reduce, path1, path2) { function createResult(ctor, paths, reduce, path1, path2) {
@ -74,8 +76,10 @@ PathItem.inject(new function() {
// Add a simple boolean property to check for a given operation, // Add a simple boolean property to check for a given operation,
// e.g. `if (operator.unite)` // e.g. `if (operator.unite)`
operator[operation] = true; operator[operation] = true;
// If path1 is open, delegate to computeOpenBoolean() // If path1 is open, delegate to computeOpenBoolean().
if (!path1._children && !path1._closed) // NOTE: Do not access private _closed property here, since path1 may
// be a CompoundPath.
if (!path1.isClosed())
return computeOpenBoolean(path1, path2, operator); return computeOpenBoolean(path1, path2, operator);
// We do not modify the operands themselves, but create copies instead, // We do not modify the operands themselves, but create copies instead,
// fas produced by the calls to preparePath(). // fas produced by the calls to preparePath().
@ -144,11 +148,11 @@ PathItem.inject(new function() {
function computeOpenBoolean(path1, path2, operator) { function computeOpenBoolean(path1, path2, operator) {
// Only support subtract and intersect operations between an open // Only support subtract and intersect operations between an open
// and a closed path. Assume that compound-paths are closed. // and a closed path.
// TODO: Should we complain about not supported operations? if (!path2 || !operator.subtract && !operator.intersect) {
if (!path2 || !path2._children && !path2._closed throw new Error('Boolean operations on open paths only support ' +
|| !operator.subtract && !operator.intersect) 'subtraction and intersection with another path.');
return null; }
var _path1 = preparePath(path1, false), var _path1 = preparePath(path1, false),
_path2 = preparePath(path2, false), _path2 = preparePath(path2, false),
crossings = _path1.getCrossings(_path2), crossings = _path1.getCrossings(_path2),

View file

@ -188,7 +188,7 @@ var PathItem = Item.extend(/** @lends PathItem# */{
_contains: function(point) { _contains: function(point) {
// NOTE: point is reverse transformed by _matrix, so we don't need to // NOTE: point is reverse transformed by _matrix, so we don't need to
// apply here. // apply the matrix here.
/*#*/ if (__options.nativeContains || !__options.booleanOperations) { /*#*/ if (__options.nativeContains || !__options.booleanOperations) {
// To compare with native canvas approach: // To compare with native canvas approach:
var ctx = CanvasProvider.getContext(1, 1); var ctx = CanvasProvider.getContext(1, 1);