fix erase with holes in it, but it still doesn't work if you erase crazy path with crazy path

This commit is contained in:
DD 2017-10-26 18:27:39 -04:00
parent 2be90c1633
commit 819215786f
2 changed files with 66 additions and 41 deletions

View file

@ -157,7 +157,7 @@ class PaperCanvas extends React.Component {
PaperCanvas.propTypes = { PaperCanvas.propTypes = {
canvasRef: PropTypes.func, canvasRef: PropTypes.func,
clearUndo: PropTypes.func.isRequired, clearUndo: PropTypes.func.isRequired,
mode: PropTypes.instanceOf(Modes), mode: PropTypes.oneOf(Object.values(Modes)),
onUpdateSvg: PropTypes.func.isRequired, onUpdateSvg: PropTypes.func.isRequired,
rotationCenterX: PropTypes.number, rotationCenterX: PropTypes.number,
rotationCenterY: PropTypes.number, rotationCenterY: PropTypes.number,

View file

@ -248,7 +248,8 @@ class Blobbiness {
let items = getItems({ let items = getItems({
match: function (item) { match: function (item) {
return item.selected && blob.isMergeable(lastPath, item) && blob.touches(lastPath, item); return item.selected && blob.isMergeable(lastPath, item) && blob.touches(lastPath, item);
} },
class: paper.PathItem
}); });
// Eraser didn't hit anything selected, so assume they meant to erase from all instead of from subset // Eraser didn't hit anything selected, so assume they meant to erase from all instead of from subset
// and deselect the selection // and deselect the selection
@ -257,7 +258,8 @@ class Blobbiness {
items = getItems({ items = getItems({
match: function (item) { match: function (item) {
return blob.isMergeable(lastPath, item) && blob.touches(lastPath, item); return blob.isMergeable(lastPath, item) && blob.touches(lastPath, item);
} },
class: paper.PathItem
}); });
} }
@ -317,42 +319,8 @@ class Blobbiness {
} }
} }
// Divide topologically separate shapes into their own compound paths, instead of
// everything being stuck together.
// Assume that result of erase operation returns clockwise paths for positive shapes
const clockwiseChildren = [];
const ccwChildren = [];
if (newPath.children) { if (newPath.children) {
for (let j = newPath.children.length - 1; j >= 0; j--) { this.separateCompoundPath(newPath);
const child = newPath.children[j];
if (child.isClockwise()) {
clockwiseChildren.push(child);
} else {
ccwChildren.push(child);
}
}
for (let j = 0; j < clockwiseChildren.length; j++) {
const cw = clockwiseChildren[j];
cw.copyAttributes(newPath);
cw.fillColor = newPath.fillColor;
cw.strokeColor = newPath.strokeColor;
cw.strokeWidth = newPath.strokeWidth;
cw.insertAbove(items[i]);
// Go backward since we are deleting elements
let newCw = cw;
for (let k = ccwChildren.length - 1; k >= 0; k--) {
const ccw = ccwChildren[k];
if (this.firstEnclosesSecond(ccw, cw) || this.firstEnclosesSecond(cw, ccw)) {
const temp = newCw.subtract(ccw);
temp.insertAbove(newCw);
newCw.remove();
newCw = temp;
ccw.remove();
ccwChildren.splice(k, 1);
}
}
}
newPath.remove(); newPath.remove();
} }
items[i].remove(); items[i].remove();
@ -360,6 +328,44 @@ class Blobbiness {
lastPath.remove(); lastPath.remove();
} }
separateCompoundPath (compoundPath) {
// Divide topologically separate shapes into their own compound paths, instead of
// everything being stuck together.
// Assume that result of erase operation returns clockwise paths for positive shapes
const clockwiseChildren = [];
const ccwChildren = [];
for (let j = compoundPath.children.length - 1; j >= 0; j--) {
const child = compoundPath.children[j];
if (child.isClockwise()) {
clockwiseChildren.push(child);
} else {
ccwChildren.push(child);
}
}
for (let j = 0; j < clockwiseChildren.length; j++) {
const cw = clockwiseChildren[j];
cw.copyAttributes(compoundPath);
cw.fillColor = compoundPath.fillColor;
cw.strokeColor = compoundPath.strokeColor;
cw.strokeWidth = compoundPath.strokeWidth;
cw.insertAbove(compoundPath);
// Go backward since we are deleting elements
let newCw = cw;
for (let k = ccwChildren.length - 1; k >= 0; k--) {
const ccw = ccwChildren[k];
if (this.firstEnclosesSecond(cw, ccw)) {
const temp = newCw.subtract(ccw);
temp.insertAbove(compoundPath);
newCw.remove();
newCw = temp;
ccw.remove();
ccwChildren.splice(k, 1);
}
}
}
}
colorMatch (existingPath, addedPath) { colorMatch (existingPath, addedPath) {
// Note: transparent fill colors do notdetect as touching // Note: transparent fill colors do notdetect as touching
return existingPath.getFillColor().equals(addedPath.getFillColor()) && return existingPath.getFillColor().equals(addedPath.getFillColor()) &&
@ -388,10 +394,29 @@ class Blobbiness {
return false; return false;
} }
matchesAnyChild (group, path) {
for (const child of group.children) {
if (child.children && this.matchesAnyChild(path, child)) {
return true;
}
if (path === child) {
return true;
}
}
return false;
}
isMergeable (newPath, existingPath) { isMergeable (newPath, existingPath) {
return existingPath instanceof paper.PathItem && // path or compound path // Path or compound path
existingPath !== this.cursorPreview && // don't merge with the mouse preview if (!(existingPath instanceof paper.PathItem)) {
existingPath !== newPath; // don't merge with self return;
}
if (newPath.children) {
if (this.matchesAnyChild(newPath, existingPath)) { // Don't merge with children of self
return false;
}
}
return existingPath !== newPath; // don't merge with self
} }
deactivateTool () { deactivateTool () {