From 7f8237adc89adfd8496cac7de75922d35c59d008 Mon Sep 17 00:00:00 2001 From: hkrish Date: Mon, 18 Mar 2013 17:04:46 +0100 Subject: [PATCH] Rudimentary Boolean (Union) code working. Only Polygons for now. Need to add handles appropriately --- boolean1.js | 89 ++++++++++++++++++++++ boolean2.js | 186 ++++++++++++++++++++++++++++++++++++++++++++++ booleanStudy.html | 13 ++++ 3 files changed, 288 insertions(+) create mode 100644 boolean1.js create mode 100644 boolean2.js create mode 100644 booleanStudy.html diff --git a/boolean1.js b/boolean1.js new file mode 100644 index 00000000..a6e99ddd --- /dev/null +++ b/boolean1.js @@ -0,0 +1,89 @@ + +project.currentStyle.fillColor = 'black'; + +var path11 = new Path.Rectangle([100, 100], [100, 100]); +var path21 = new Path.Rectangle([50, 30], [100, 100]); +var newPath = new Path(); +path11.style.fillColor = 'rgb( 71, 91, 98 )' +path21.style.fillColor = 'rgb( 129, 144, 144 )' + + +// onFrame = function( event ) { + path21.rotate( 148 ); + + var path1 = path11.clone(); + var path2 = path21.clone(); + + newPath.removeSegments(); + +// Intersections of path1 with path2 +var ixs = path1.getIntersections( path2 ); + +// TODO for both paths, first sort ixs according to curveOffset, +// so that, insert order is correct + +ixs.forEach( function( item, index ){ + // T + console.log( item.curveOffset ) + var newSeg1 = new Segment( item.point ); + var newSeg2 = new Segment( item.point ); + newSeg1._ixOtherSeg = newSeg2; + newSeg2._ixOtherSeg = newSeg1; + path1.insertSegment( item.curve.segment1.index + 1, newSeg1 ); + path2.insertSegment( item._ixCurve.segment1.index + 1, newSeg2 ); +}); + +// console.log( path2.segments ) + +var startSeg = path1.firstSegment; +// TODO Make sure, if path1 is not completely inside path2 +while( path2.contains( startSeg.point ) ) { + startSeg = startSeg.next; +} + +// path2.firstSegment.selected = path2.firstSegment.next.selected = true; +// path1.firstSegment.selected = path1.firstSegment.next.selected = true; + +console.log( path1.isClockwise() ) +console.log( path2.isClockwise() ) + +// path2.reverse() +// startSeg.selected = true; + +var curSeg; +var count = 1; +var ixswitch = true; +while( curSeg !== startSeg ) { + if( !curSeg ) { + curSeg = startSeg; + } + if( curSeg._ixOtherSeg ){ + curSeg = curSeg._ixOtherSeg; + ixswitch = !ixswitch + } + newPath.addSegment( new Segment( curSeg ) ); + + var text = new PointText( curSeg.point - [ 5, 5 ] ); + text.justification = 'center'; + if( ixswitch ) { + text.fillColor = 'black'; + }else{ + text.fillColor = 'blue'; + } + text.content = count.toString(); + count++; + + curSeg = curSeg.next; +} + +newPath.translate( [200, 0] ); +newPath.style.fillColor = 'rgb( 209, 28, 36 )'; +newPath.selected = true; + +// path1.remove(); +// path2.remove(); +// } + +// path1.selected = true; +// path1.selected = true; + diff --git a/boolean2.js b/boolean2.js new file mode 100644 index 00000000..15947f9f --- /dev/null +++ b/boolean2.js @@ -0,0 +1,186 @@ + +project.currentStyle.fillColor = 'black'; + +var path11 = new Path.Circle([100, 100], 50); +// var path11 = new Path.Rectangle([100, 100], [100, 100]); +var path21 = new Path.Rectangle([100, 100], [100, 100]); +// var path21 = new Path.Polygon +var newPath = new Path(); +path11.style.fillColor = 'rgb( 71, 91, 98 )' +path21.style.fillColor = 'rgb( 129, 144, 144 )' + + +// onFrame = function( event ) { + path21.rotate( 1 ); + + newPath.removeSegments(); + + var path1 = path11.clone(); + var path2 = path21.clone(); + +// console.log(path1.isClockwise()) +// console.log(path2.isClockwise()) + + // Intersections of path1 with path2 + var ixs = path1.getIntersections( path2 ); + + // TODO for both paths, first sort ixs according to curveOffset, + // so that, insert order is correct + + if( ixs.length > 0 ) { + ixs.forEach( function( item, index ){ + + var newSeg1 = new Segment( item.point ); + var newSeg2 = new Segment( item.point ); + newSeg1._ixCurveOffset = item.curveOffset; + newSeg2._ixCurveOffset = item._ixLocation.curveOffset; + newSeg1._ixOtherSeg = newSeg2; + newSeg2._ixOtherSeg = newSeg1; + + if( item.curve.segment1._ixPoints === undefined ){ + item.curve.segment1._ixPoints = [ newSeg1 ]; + } else { + item.curve.segment1._ixPoints.push( newSeg1 ); + } + if( item._ixLocation.curve.segment1._ixPoints === undefined ){ + item._ixLocation.curve.segment1._ixPoints = [ newSeg2 ]; + } else { + item._ixLocation.curve.segment1._ixPoints.push( newSeg2 ); + } + }); + + + // path1.segments.forEach( function( item, index ){ + // if( item._ixPoints ) { + // if( item._ixPoints.length > 1 ) { + // item._ixPoints.sort( compare_ixPoints ); + // } + // path1.insertSegments( item.index + 1, item._ixPoints ); + // item._ixPoints = undefined; + // } + // }); + // path2.segments.forEach( function( item, index ){ + // console.log(item._ixPoints) + // if( item._ixPoints ) { + // if( item._ixPoints.length > 1 ) { + // item._ixPoints.sort( compare_ixPoints ); + // } + // path2.insertSegments( item.index + 1, item._ixPoints ); + // item._ixPoints = undefined; + // } + // }); + + // TODO make sure path is closed + + // Walk the segments in path1, backwards (counter-clockwise) + var pathSeg = path1.lastSegment; + do{ + if( pathSeg._ixPoints ) { + if( pathSeg._ixPoints.length > 1 ) { + pathSeg._ixPoints.sort( compare_ixPoints ); + } + path1.insertSegments( pathSeg.index + 1, pathSeg._ixPoints ); + pathSeg._ixPoints = undefined; + } + pathSeg = pathSeg.previous; + } while ( pathSeg !== path1.lastSegment ); + + // Walk the segments in path2, backwards (counter-clockwise) + var pathSeg = path2.lastSegment; + do { + if( pathSeg._ixPoints ) { + if( pathSeg._ixPoints.length > 1 ) { + pathSeg._ixPoints.sort( compare_ixPoints ); + } + path2.insertSegments( pathSeg.index + 1, pathSeg._ixPoints ); + pathSeg._ixPoints = undefined; + } + pathSeg = pathSeg.previous; + } while ( pathSeg !== path2.lastSegment ); + + + // TODO Make sure, if path1 is not completely inside path2. + // TODO. This part will differ for different boolean ops. + // For Union + var startSeg = path1.firstSegment; + while( path2.contains( startSeg.point ) || startSeg._ixOtherSeg ) { + startSeg = startSeg.next; + } + + // path11.segments[startSeg.index].selected = true; + + // startSeg.selected = true; + + var curSeg; + var count = 1; + var ixswitch = true; + do { + if( !curSeg ) { + curSeg = startSeg; + } + if( curSeg._ixOtherSeg ){ + curSeg = curSeg._ixOtherSeg; + ixswitch = !ixswitch + } + newPath.addSegment( new Segment( curSeg ) ); + + // var text = new PointText( curSeg.point - [ 5, 5 ] ); + // text.justification = 'center'; + // if( ixswitch ) { + // text.fillColor = 'black'; + // }else{ + // text.fillColor = 'blue'; + // } + // text.content = count.toString(); + + count++; + + curSeg = curSeg.next; + } while( curSeg !== startSeg && count < 50); + + // console.log(count); + + + // annotateSegments( path1, 5, '#f00' ) + // annotateSegments( path2, -5, '#000' ) + + newPath.closePath() + newPath.translate( [200, 0] ); + newPath.style.fillColor = 'rgb( 209, 28, 36 )'; + newPath.fullySelected = true; + } + +// path1.remove(); +// path2.remove(); +// } + +// path1.selected = true; +// path2.selected = true; + + +// Sort new intersection points according to their +// distance along the curve, so that when we +// insert them in to the respective paths, the orientation +// of the path is maintained ( in out case clockwise ) +function compare_ixPoints( a, b ) { + if( a._ixCurveOffset < b._ixCurveOffset ) { + return -1 + } else if( a._ixCurveOffset > b._ixCurveOffset ){ + return 1; + } else { + // This shouldn't happen?! + return 0; + } +} + +// For debugging: Show a number next to each segment ina path +function annotateSegments( p, d, c ) { + var count = 0; + p.segments.forEach( function( item, index ){ + var text = new PointText( item.point - [ d, d ] ); + text.style.fillColor = c; + text.justification = 'center'; + text.content = count.toString(); + count++; + }); +} diff --git a/booleanStudy.html b/booleanStudy.html new file mode 100644 index 00000000..a15fa84a --- /dev/null +++ b/booleanStudy.html @@ -0,0 +1,13 @@ + + + + + Boolean Study + + + + + + + +