mirror of
https://github.com/scratchfoundation/paper.js.git
synced 2025-01-06 04:42:15 -05:00
Boolean Subtraction added
This commit is contained in:
parent
27eeb24c4f
commit
aabec49446
3 changed files with 104 additions and 50 deletions
103
Boolean.js
103
Boolean.js
|
@ -57,6 +57,17 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
// path1 - path2
|
||||||
|
Subtraction: function( lnk, isInsidePath1, isInsidePath2 ){
|
||||||
|
var lnkid = lnk.id;
|
||||||
|
if( lnkid === 1 && isInsidePath2 ){
|
||||||
|
return false;
|
||||||
|
} else if( lnkid === 2 && !isInsidePath1 ){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,9 +92,9 @@
|
||||||
* @param {Point} _handleOut
|
* @param {Point} _handleOut
|
||||||
* @param {Any} _id
|
* @param {Any} _id
|
||||||
*/
|
*/
|
||||||
function Node( _point, _handleIn, _handleOut, _id, _childId ){
|
function Node( _point, _handleIn, _handleOut, _id, isBaseContour ){
|
||||||
this.id = _id;
|
this.id = _id;
|
||||||
this.childId = _childId;
|
this.isBaseContour = isBaseContour;
|
||||||
this.type = NORMAL_NODE;
|
this.type = NORMAL_NODE;
|
||||||
this.point = _point;
|
this.point = _point;
|
||||||
this.handleIn = _handleIn; // handleIn
|
this.handleIn = _handleIn; // handleIn
|
||||||
|
@ -95,6 +106,7 @@
|
||||||
// In case of an intersection this will be a merged node.
|
// In case of an intersection this will be a merged node.
|
||||||
// And we need space to save the "other Node's" parameters before merging.
|
// And we need space to save the "other Node's" parameters before merging.
|
||||||
this.idB = null;
|
this.idB = null;
|
||||||
|
this.isBaseContourB = false;
|
||||||
// this.pointB = this.point; // point should be the same
|
// this.pointB = this.point; // point should be the same
|
||||||
this.handleBIn = null;
|
this.handleBIn = null;
|
||||||
this.handleBOut = null;
|
this.handleBOut = null;
|
||||||
|
@ -120,6 +132,7 @@
|
||||||
this.linkOut.nodeIn = this; // linkOut.nodeStart
|
this.linkOut.nodeIn = this; // linkOut.nodeStart
|
||||||
this.handleIn = this.handleIn || this.handleBIn;
|
this.handleIn = this.handleIn || this.handleBIn;
|
||||||
this.handleOut = this.handleOut || this.handleBOut;
|
this.handleOut = this.handleOut || this.handleBOut;
|
||||||
|
this.isBaseContour = this.isBaseContour | this.isBaseContourB;
|
||||||
}
|
}
|
||||||
this._segment = this._segment || new Segment( this.point, this.handleIn, this.handleOut );
|
this._segment = this._segment || new Segment( this.point, this.handleIn, this.handleOut );
|
||||||
return this._segment;
|
return this._segment;
|
||||||
|
@ -132,9 +145,9 @@
|
||||||
* @param {Node} _nodeOut
|
* @param {Node} _nodeOut
|
||||||
* @param {Any} _id
|
* @param {Any} _id
|
||||||
*/
|
*/
|
||||||
function Link( _nodeIn, _nodeOut, _id, _childId ) {
|
function Link( _nodeIn, _nodeOut, _id, isBaseContour ) {
|
||||||
this.id = _id;
|
this.id = _id;
|
||||||
this.childId = _childId;
|
this.isBaseContour = isBaseContour;
|
||||||
this.nodeIn = _nodeIn; // nodeStart
|
this.nodeIn = _nodeIn; // nodeStart
|
||||||
this.nodeOut = _nodeOut; // nodeEnd
|
this.nodeOut = _nodeOut; // nodeEnd
|
||||||
this.nodeIn.linkOut = this; // nodeStart.linkOut
|
this.nodeIn.linkOut = this; // nodeStart.linkOut
|
||||||
|
@ -157,14 +170,14 @@
|
||||||
* @param {Integer} id
|
* @param {Integer} id
|
||||||
* @return {Array} Links
|
* @return {Array} Links
|
||||||
*/
|
*/
|
||||||
function makeGraph( path, id, childId ){
|
function makeGraph( path, id, isBaseContour ){
|
||||||
var graph = [];
|
var graph = [];
|
||||||
var segs = path.segments, prevNode = null, firstNode = null, nuLink, nuNode;
|
var segs = path.segments, prevNode = null, firstNode = null, nuLink, nuNode;
|
||||||
for( i = 0, l = segs.length; i < l; i++ ){
|
for( i = 0, l = segs.length; i < l; i++ ){
|
||||||
var nuSeg = segs[i].clone();
|
var nuSeg = segs[i].clone();
|
||||||
nuNode = new Node( nuSeg.point, nuSeg.handleIn, nuSeg.handleOut, id, childId );
|
nuNode = new Node( nuSeg.point, nuSeg.handleIn, nuSeg.handleOut, id, isBaseContour );
|
||||||
if( prevNode ) {
|
if( prevNode ) {
|
||||||
nuLink = new Link( prevNode, nuNode, id, childId );
|
nuLink = new Link( prevNode, nuNode, id, isBaseContour );
|
||||||
graph.push( nuLink );
|
graph.push( nuLink );
|
||||||
}
|
}
|
||||||
prevNode = nuNode;
|
prevNode = nuNode;
|
||||||
|
@ -173,12 +186,28 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// the path is closed
|
// the path is closed
|
||||||
nuLink = new Link( prevNode, firstNode, id, childId );
|
nuLink = new Link( prevNode, firstNode, id, isBaseContour );
|
||||||
graph.push( nuLink );
|
graph.push( nuLink );
|
||||||
return graph;
|
return graph;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* makes a graph for a pathItem
|
||||||
|
* @param {Path} path
|
||||||
|
* @param {Integer} id
|
||||||
|
* @return {Array} Links
|
||||||
|
*/
|
||||||
|
function makeGraph2( path, id ){
|
||||||
|
var graph = [];
|
||||||
|
var curves = path.getCurves(), firstChildCount , counter, isBaseContour = true, i, len;
|
||||||
|
firstChildCount = ( path instanceof CompoundPath )? path.children[0].curves.length : path.curves.length;
|
||||||
|
// Segments need an ID, so that we can compare them
|
||||||
|
for (i = 0, len = curves.length; i < len; i++, firstChildCount--) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the Union of two paths
|
* Calculates the Union of two paths
|
||||||
* Boolean API.
|
* Boolean API.
|
||||||
|
@ -186,7 +215,7 @@
|
||||||
* @param {Path} path2
|
* @param {Path} path2
|
||||||
* @return {CompoundPath} union of path1 & path2
|
* @return {CompoundPath} union of path1 & path2
|
||||||
*/
|
*/
|
||||||
function boolUnion( path1, path2 ){
|
function boolUnion( path1, path2 ){
|
||||||
return computeBoolean( path1, path2, BooleanOps.Union );
|
return computeBoolean( path1, path2, BooleanOps.Union );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,11 +227,23 @@
|
||||||
* @param {Path} path2
|
* @param {Path} path2
|
||||||
* @return {CompoundPath} Intersection of path1 & path2
|
* @return {CompoundPath} Intersection of path1 & path2
|
||||||
*/
|
*/
|
||||||
function boolIntersection( path1, path2 ){
|
function boolIntersection( path1, path2 ){
|
||||||
return computeBoolean( path1, path2, BooleanOps.Intersection );
|
return computeBoolean( path1, path2, BooleanOps.Intersection );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates path1—path2
|
||||||
|
* Boolean API.
|
||||||
|
* @param {Path} path1
|
||||||
|
* @param {Path} path2
|
||||||
|
* @return {CompoundPath} path1 <minus> path2
|
||||||
|
*/
|
||||||
|
function boolSubtract( path1, path2 ){
|
||||||
|
return computeBoolean( path1, path2, BooleanOps.Subtraction );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actual function that computes the boolean
|
* Actual function that computes the boolean
|
||||||
* @param {Path} _path1 (cannot be self-intersecting at the moment)
|
* @param {Path} _path1 (cannot be self-intersecting at the moment)
|
||||||
|
@ -210,7 +251,7 @@
|
||||||
* @param {BooleanOps type} operator
|
* @param {BooleanOps type} operator
|
||||||
* @return {CompoundPath} boolean result
|
* @return {CompoundPath} boolean result
|
||||||
*/
|
*/
|
||||||
function computeBoolean( _path1, _path2, operator ){
|
function computeBoolean( _path1, _path2, operator ){
|
||||||
IntersectionID = 1;
|
IntersectionID = 1;
|
||||||
UNIQUE_ID = 1;
|
UNIQUE_ID = 1;
|
||||||
|
|
||||||
|
@ -226,34 +267,36 @@
|
||||||
// full connectivity information. The order of links in a graph is not important
|
// full connectivity information. The order of links in a graph is not important
|
||||||
// That allows us to sort and merge graphs and 'splice' links with their splits easily.
|
// That allows us to sort and merge graphs and 'splice' links with their splits easily.
|
||||||
// Also, this is the place to resolve self-intersecting paths
|
// Also, this is the place to resolve self-intersecting paths
|
||||||
var graph = [], path1Children, path2Children;
|
var graph = [], path1Children, path2Children, base;
|
||||||
if( path1 instanceof CompoundPath ){
|
if( path1 instanceof CompoundPath ){
|
||||||
path1Children = path1.children;
|
path1Children = path1.children;
|
||||||
for (i = 0, l = path1Children.length; i < l; i++) {
|
for (i = 0, base = true, l = path1Children.length; i < l; i++, base = false) {
|
||||||
path1Children[i].closed = true;
|
path1Children[i].closed = true;
|
||||||
graph = graph.concat( makeGraph( path1Children[i], 1, i + 1 ) );
|
graph = graph.concat( makeGraph( path1Children[i], 1, base ) );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
path1.closed = true;
|
path1.closed = true;
|
||||||
path1.clockwise = true;
|
// path1.clockwise = true;
|
||||||
graph = graph.concat( makeGraph( path1, 1, 1 ) );
|
graph = graph.concat( makeGraph( path1, 1, 1, true ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: if operator === BooleanOps.subtract, then for path2, clockwise must be false
|
// if operator === BooleanOps.Subtraction, then reverse path2
|
||||||
|
// so that the nodes and links will link correctly
|
||||||
|
var reverse = ( operator === BooleanOps.Subtraction )? true: false;
|
||||||
if( path2 instanceof CompoundPath ){
|
if( path2 instanceof CompoundPath ){
|
||||||
path2Children = path2.children;
|
path2Children = path2.children;
|
||||||
for (i = 0, l = path2Children.length; i < l; i++) {
|
for (i = 0, base = true, l = path2Children.length; i < l; i++, base = false) {
|
||||||
path2Children[i].closed = true;
|
path2Children[i].closed = true;
|
||||||
graph = graph.concat( makeGraph( path2Children[i], 2, i + 1 ) );
|
if( reverse ){ path2Children[i].reverse(); }
|
||||||
|
graph = graph.concat( makeGraph( path2Children[i], 2, i + 1, base ) );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
path2.closed = true;
|
path2.closed = true;
|
||||||
path2.clockwise = true;
|
// path2.clockwise = true;
|
||||||
graph = graph.concat( makeGraph( path2, 2, 1 ) );
|
if( reverse ){ path2.reverse(); }
|
||||||
|
graph = graph.concat( makeGraph( path2, 2, 1, true ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
window.g = graph
|
|
||||||
|
|
||||||
// Sort function to sort intersections according to the 'parameter'(t) in a link (curve)
|
// Sort function to sort intersections according to the 'parameter'(t) in a link (curve)
|
||||||
function ixSort( a, b ){ return a._parameter - b._parameter; }
|
function ixSort( a, b ){ return a._parameter - b._parameter; }
|
||||||
|
|
||||||
|
@ -289,6 +332,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Pass 2:
|
* Pass 2:
|
||||||
* Walk the graph, sort the intersections on each individual link.
|
* Walk the graph, sort the intersections on each individual link.
|
||||||
|
@ -297,7 +341,8 @@
|
||||||
for ( i = graph.length - 1; i >= 0; i--) {
|
for ( i = graph.length - 1; i >= 0; i--) {
|
||||||
if( graph[i].intersections.length ){
|
if( graph[i].intersections.length ){
|
||||||
var ix = graph[i].intersections;
|
var ix = graph[i].intersections;
|
||||||
ix.sort( ixSort );
|
// Sort the intersections if there is more than one
|
||||||
|
if( graph[i].intersections.length > 1 ){ ix.sort( ixSort ); }
|
||||||
// Remove the graph link, this link has to be split and replaced with the splits
|
// Remove the graph link, this link has to be split and replaced with the splits
|
||||||
lnk = graph.splice( i, 1 )[0];
|
lnk = graph.splice( i, 1 )[0];
|
||||||
for (j =0, l=ix.length; j<l && lnk; j++) {
|
for (j =0, l=ix.length; j<l && lnk; j++) {
|
||||||
|
@ -328,7 +373,7 @@
|
||||||
// TODO: check if link is linear and set handles to null
|
// TODO: check if link is linear and set handles to null
|
||||||
var ixPoint = new Point( left[6], left[7] );
|
var ixPoint = new Point( left[6], left[7] );
|
||||||
nuNode = new Node( ixPoint, new Point(left[4] - ixPoint.x, left[5] - ixPoint.y),
|
nuNode = new Node( ixPoint, new Point(left[4] - ixPoint.x, left[5] - ixPoint.y),
|
||||||
new Point(right[2] - ixPoint.x, right[3] - ixPoint.y), lnk.id, lnk.childId );
|
new Point(right[2] - ixPoint.x, right[3] - ixPoint.y), lnk.id, lnk.isBaseContour );
|
||||||
nuNode.type = INTERSECTION_NODE;
|
nuNode.type = INTERSECTION_NODE;
|
||||||
nuNode._intersectionID = ix[j]._intersectionID;
|
nuNode._intersectionID = ix[j]._intersectionID;
|
||||||
// clear the cached Segment on original end nodes and Update their handles
|
// clear the cached Segment on original end nodes and Update their handles
|
||||||
|
@ -339,8 +384,8 @@
|
||||||
tmppnt = lnk.nodeOut.point;
|
tmppnt = lnk.nodeOut.point;
|
||||||
lnk.nodeOut.handleIn = new Point( right[4] - tmppnt.x, right[5] - tmppnt.y );
|
lnk.nodeOut.handleIn = new Point( right[4] - tmppnt.x, right[5] - tmppnt.y );
|
||||||
// Make new links after the split
|
// Make new links after the split
|
||||||
leftLink = new Link( lnk.nodeIn, nuNode, lnk.id, lnk.childId);
|
leftLink = new Link( lnk.nodeIn, nuNode, lnk.id, lnk.isBaseContour );
|
||||||
rightLink = new Link( nuNode, lnk.nodeOut, lnk.id, lnk.childId );
|
rightLink = new Link( nuNode, lnk.nodeOut, lnk.id, lnk.isBaseContour );
|
||||||
}
|
}
|
||||||
// Add the first split link back to the graph, since we sorted the intersections
|
// Add the first split link back to the graph, since we sorted the intersections
|
||||||
// already, this link should contain no more intersections to the left.
|
// already, this link should contain no more intersections to the left.
|
||||||
|
@ -427,6 +472,7 @@
|
||||||
} else {
|
} else {
|
||||||
// Merge the nodes together, by adding this node's information to the other node
|
// Merge the nodes together, by adding this node's information to the other node
|
||||||
otherNode.idB = node.id;
|
otherNode.idB = node.id;
|
||||||
|
otherNode.isBaseContourB = node.isBaseContour;
|
||||||
otherNode.handleBIn = node.handleIn;
|
otherNode.handleBIn = node.handleIn;
|
||||||
otherNode.handleBOut = node.handleOut;
|
otherNode.handleBOut = node.handleOut;
|
||||||
otherNode.linkBIn = node.linkIn;
|
otherNode.linkBIn = node.linkIn;
|
||||||
|
@ -441,6 +487,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Final step: Retrieve the resulting paths from the graph
|
// Final step: Retrieve the resulting paths from the graph
|
||||||
// TODO: start from a path where childId === 1
|
// TODO: start from a path where childId === 1
|
||||||
var boolResult = new CompoundPath();
|
var boolResult = new CompoundPath();
|
||||||
|
@ -450,7 +497,7 @@
|
||||||
len = graph.length;
|
len = graph.length;
|
||||||
while( len-- ){
|
while( len-- ){
|
||||||
if( !graph[len].INVALID && !graph[len].nodeIn.visited && !firstNode ){
|
if( !graph[len].INVALID && !graph[len].nodeIn.visited && !firstNode ){
|
||||||
if( !foundBasePath && graph[len].childId === 1 ){
|
if( !foundBasePath && graph[len].isBaseContour === 1 ){
|
||||||
firstNode = graph[len].nodeIn;
|
firstNode = graph[len].nodeIn;
|
||||||
foundBasePath = true;
|
foundBasePath = true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
<script type="text/javascript" src="booleanTests.js"></script>
|
<script type="text/javascript" src="booleanTests.js"></script>
|
||||||
<style>
|
<style>
|
||||||
body { height: 100%; overflow: auto; }
|
body { height: 100%; overflow: auto; }
|
||||||
#container { display: block; width: 800px; margin: 0 auto 50px; }
|
#container { display: block; width: 1000px; margin: 0 auto 50px; }
|
||||||
h1, h3 { font-family: 'Helvetica Neue'; font-weight: 300; margin: 50px 0 20px; }
|
h1, h3 { font-family: 'Helvetica Neue'; font-weight: 300; margin: 50px 0 20px; }
|
||||||
footer{display: block; width: 800px; height: 100px; margin: 30px auto; color: #999; }
|
footer{display: block; width: 1000px; height: 100px; margin: 30px auto; color: #999; }
|
||||||
footer p { font-family: 'Helvetica Neue'; font-style: italic; font-weight: 300; }
|
footer p { font-family: 'Helvetica Neue'; font-style: italic; font-weight: 300; }
|
||||||
canvas { cursor: crosshair; width: 100%; height: 220px; margin: 5px 0;}
|
canvas { cursor: crosshair; width: 100%; height: 220px; margin: 5px 0;}
|
||||||
.error { color: #a00; } .hide{ display: none; }
|
.error { color: #a00; } .hide{ display: none; }
|
||||||
|
|
|
@ -4,7 +4,7 @@ paper.install(window);
|
||||||
|
|
||||||
|
|
||||||
function runTests() {
|
function runTests() {
|
||||||
var caption, pathA, pathB;
|
var caption, pathA, pathB, group;
|
||||||
|
|
||||||
var container = document.getElementById( 'container' );
|
var container = document.getElementById( 'container' );
|
||||||
|
|
||||||
|
@ -49,10 +49,10 @@ function runTests() {
|
||||||
pathB = new Path.Star(new Point(110, 110), 6, 30, 100);
|
pathB = new Path.Star(new Point(110, 110), 6, 30, 100);
|
||||||
testBooleanStatic( pathA, pathB, caption );
|
testBooleanStatic( pathA, pathB, caption );
|
||||||
|
|
||||||
caption = prepareTest( 'Circles overlap exactly over each other', container );
|
// caption = prepareTest( 'Circles overlap exactly over each other', container );
|
||||||
pathA = new Path.Circle(new Point(110, 110), 100);
|
// pathA = new Path.Circle(new Point(110, 110), 100);
|
||||||
pathB = new Path.Circle(new Point(110, 110), 100 );
|
// pathB = new Path.Circle(new Point(110, 110), 100 );
|
||||||
testBooleanStatic( pathA, pathB, caption );
|
// testBooleanStatic( pathA, pathB, caption );
|
||||||
|
|
||||||
caption = prepareTest( 'Maximum possible intersections between 2 cubic bezier curve segments - 9', container );
|
caption = prepareTest( 'Maximum possible intersections between 2 cubic bezier curve segments - 9', container );
|
||||||
pathA = new Path();
|
pathA = new Path();
|
||||||
|
@ -62,34 +62,33 @@ function runTests() {
|
||||||
pathB = pathA.clone();
|
pathB = pathA.clone();
|
||||||
pathB.rotate( -90 );
|
pathB.rotate( -90 );
|
||||||
// FIXME: hangs when I move pathA, pathB apart by [-10,0] & [10,0] or [9...] etc.
|
// FIXME: hangs when I move pathA, pathB apart by [-10,0] & [10,0] or [9...] etc.
|
||||||
pathA.translate( [-11,0] );
|
pathA.translate( [-10,0] );
|
||||||
pathB.translate( [11,0] );
|
pathB.translate( [10,0] );
|
||||||
testBooleanStatic( pathA, pathB, caption );
|
testBooleanStatic( pathA, pathB, caption );
|
||||||
annotatePath( pathA, null, '#008' );
|
annotatePath( pathA, null, '#008' );
|
||||||
annotatePath( pathB, null, '#800' );
|
annotatePath( pathB, null, '#800' );
|
||||||
view.draw();
|
view.draw();
|
||||||
|
|
||||||
caption = prepareTest( 'Glyphs imported from SVG', container );
|
caption = prepareTest( 'Glyphs imported from SVG', container );
|
||||||
var group = paper.project.importSvg( document.getElementById( 'glyphsys' ) );
|
group = paper.project.importSvg( document.getElementById( 'glyphsys' ) );
|
||||||
pathA = group.children[0];
|
pathA = group.children[0];
|
||||||
pathB = group.children[1];
|
pathB = group.children[1];
|
||||||
testBooleanStatic( pathA, pathB, caption );
|
testBooleanStatic( pathA, pathB, caption );
|
||||||
|
|
||||||
caption = prepareTest( 'CompoundPaths 1', container );
|
caption = prepareTest( 'CompoundPaths 1', container );
|
||||||
var group = paper.project.importSvg( document.getElementById( 'glyphsacirc' ) );
|
group = paper.project.importSvg( document.getElementById( 'glyphsacirc' ) );
|
||||||
pathA = group.children[0];
|
pathA = group.children[0];
|
||||||
pathB = group.children[1];
|
pathB = group.children[1];
|
||||||
testBooleanStatic( pathA, pathB, caption );
|
testBooleanStatic( pathA, pathB, caption );
|
||||||
|
|
||||||
caption = prepareTest( 'CompoundPaths 2', container );
|
caption = prepareTest( 'CompoundPaths 2', container );
|
||||||
var group = paper.project.importSvg( document.getElementById( 'glyphsacirc' ) );
|
group = paper.project.importSvg( document.getElementById( 'glyphsacirc' ) );
|
||||||
pathA = group.children[0];
|
pathA = group.children[0];
|
||||||
pathB = new CompoundPath();
|
pathB = new CompoundPath();
|
||||||
|
group.children[1].clockwise = true;
|
||||||
pathB.addChild(group.children[1]);
|
pathB.addChild(group.children[1]);
|
||||||
var npath = new Path.Circle([110, 110], 30);
|
var npath = new Path.Circle([110, 110], 30);
|
||||||
console.log(npath.clockwise)
|
|
||||||
pathB.addChild( npath );
|
pathB.addChild( npath );
|
||||||
console.log(npath.clockwise)
|
|
||||||
testBooleanStatic( pathA, pathB, caption );
|
testBooleanStatic( pathA, pathB, caption );
|
||||||
|
|
||||||
window.p = pathB;
|
window.p = pathB;
|
||||||
|
@ -129,23 +128,30 @@ var pathStyleBoolean = {
|
||||||
// Better if path1 and path2 fit nicely inside a 200x200 pixels rect
|
// Better if path1 and path2 fit nicely inside a 200x200 pixels rect
|
||||||
function testBooleanStatic( path1, path2, caption ) {
|
function testBooleanStatic( path1, path2, caption ) {
|
||||||
try{
|
try{
|
||||||
var _p1U = path1.clone().translate( [280, 0] );
|
var _p1U = path1.clone().translate( [250, 0] );
|
||||||
var _p2U = path2.clone().translate( [280, 0] );
|
var _p2U = path2.clone().translate( [250, 0] );
|
||||||
|
_p1U.style = _p2U.style = pathStyleBoolean;
|
||||||
console.time( 'Union' );
|
console.time( 'Union' );
|
||||||
var boolPathU = boolUnion( _p1U, _p2U );
|
var boolPathU = boolUnion( _p1U, _p2U );
|
||||||
console.timeEnd( 'Union' );
|
console.timeEnd( 'Union' );
|
||||||
|
|
||||||
window.b = boolPathU
|
var _p1I = path1.clone().translate( [500, 0] );
|
||||||
|
var _p2I = path2.clone().translate( [500, 0] );
|
||||||
var _p1I = path1.clone().translate( [560, 0] );
|
_p1I.style = _p2I.style = pathStyleBoolean;
|
||||||
var _p2I = path2.clone().translate( [560, 0] );
|
|
||||||
console.time( 'Intersection' );
|
console.time( 'Intersection' );
|
||||||
var boolPathI = boolIntersection( _p1I, _p2I );
|
var boolPathI = boolIntersection( _p1I, _p2I );
|
||||||
console.timeEnd( 'Intersection' );
|
console.timeEnd( 'Intersection' );
|
||||||
|
|
||||||
|
var _p1S = path1.clone().translate( [750, 0] );
|
||||||
|
var _p2S = path2.clone().translate( [750, 0] );
|
||||||
|
_p1S.style = _p2S.style = pathStyleBoolean;
|
||||||
|
console.time( 'Subtraction' );
|
||||||
|
var boolPathS = boolSubtract( _p1S, _p2S );
|
||||||
|
console.timeEnd( 'Subtraction' );
|
||||||
|
|
||||||
path1.style = path2.style = pathStyleNormal;
|
path1.style = path2.style = pathStyleNormal;
|
||||||
_p1U.style = _p2U.style = _p1I.style = _p2I.style = pathStyleBoolean;
|
|
||||||
boolPathU.style = boolPathI.style = booleanStyle;
|
boolPathU.style = boolPathI.style = booleanStyle;
|
||||||
|
boolPathS.style = booleanStyle;
|
||||||
} catch( e ){
|
} catch( e ){
|
||||||
console.error( e.message );
|
console.error( e.message );
|
||||||
if( caption ) { caption.className += ' error'; }
|
if( caption ) { caption.className += ' error'; }
|
||||||
|
@ -153,6 +159,7 @@ function testBooleanStatic( path1, path2, caption ) {
|
||||||
} finally {
|
} finally {
|
||||||
console.timeEnd( 'Union' );
|
console.timeEnd( 'Union' );
|
||||||
console.timeEnd( 'Intersection' );
|
console.timeEnd( 'Intersection' );
|
||||||
|
console.timeEnd( 'Subtraction' );
|
||||||
view.draw();
|
view.draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue