From 262331673a804c998663d192b4e09435a6a8dfa4 Mon Sep 17 00:00:00 2001 From: hkrish Date: Sun, 12 May 2013 15:59:24 +0200 Subject: [PATCH] Tests for curve-line intersection --- fatline/intersectTests.js | 322 ++++++++++++++++++++++++-------------- 1 file changed, 205 insertions(+), 117 deletions(-) diff --git a/fatline/intersectTests.js b/fatline/intersectTests.js index 2d075128..07188398 100644 --- a/fatline/intersectTests.js +++ b/fatline/intersectTests.js @@ -8,45 +8,191 @@ function runTests() { var container = document.getElementById( 'container' ); - caption = prepareTest( 'Find Curve Intersections - 10,000 times.', container ); + // caption = prepareTest( 'Overlapping circles', container ); + // pathA = new Path.Circle(new Point(80, 110), 50); + // pathB = new Path.Circle(new Point(150, 110), 70); + // testIntersections( pathA, pathB, caption ); - // pathA = new Path.Circle(new Point(70, 110), 50); + // caption = prepareTest( 'Polygon and square', container ); + // pathA = new Path.RegularPolygon(new Point(80, 110), 12, 80); + // pathB = new Path.Rectangle(new Point(100, 80), [80, 80] ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Circle and square (overlaps exactly on existing segments)', container ); + // pathA = new Path.Circle(new Point(110, 110), 80); + // pathB = new Path.Rectangle(new Point(110, 110), [80, 80] ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Circle and square (existing segments overlaps on curves)', container ); + // pathA = new Path.Circle(new Point(110, 110), 80); + // pathB = new Path.Rectangle(new Point(110, 110), [100, 100] ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Square and square (one segment overlaps on a line)', container ); + // pathA = new Path.Rectangle(new Point(80, 125), [50, 50] ); // pathA.rotate( 45 ); - // pathB = new Path.Circle(new Point(160, 110), 50); - // pathB.rotate( 45 ); - // // pathB.segments[3].point = pathB.segments[3].point.add( [10, -120] ); - // // pathB.translate( [ -20, -30 ] ); - // // pathB.segments[0].handleIn = pathB.segments[0].handleIn.add( [-100, 30] ); - // // pathB.translate( [ 20, -30 ] ); - // // testIntersection( pathA, pathB, caption ); + // pathB = new Path.Rectangle(new Point(pathA.segments[2].point.x, 110), [80, 80] ); + // testIntersections( pathA, pathB, caption ); - pathA = new Path(); - pathA.add( new Segment( [47, 93], [-89, 100], [240, -239] ) ); - pathA.add( new Segment( [173, 44], [-281, 268], [-86, 152] ) ); - pathA.closed = true; - pathB = pathA.clone(); - pathB.rotate( -90 ); - pathA.translate( [-10,0] ); - pathB.translate( [10,0] ); + // caption = prepareTest( 'Rectangle and rectangle (overlaps exactly on existing curves)', container ); + // pathA = new Path.Rectangle(new Point(30.5, 50.5), [100, 150]); + // pathB = new Path.Rectangle(new Point(130.5, 60.5), [100, 150]); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Circle and banana (multiple intersections within same curve segment)', container ); + // pathA = new Path.Circle(new Point(80, 110), 80); + // pathB = new Path.Circle(new Point(130, 110), 80 ); + // pathB.segments[3].point = pathB.segments[3].point.add( [ 0, -120 ] ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Overlapping stars 1', container ); + // pathA = new Path.Star(new Point(80, 110), 10, 20, 80); + // pathB = new Path.Star(new Point(120, 110), 10, 30, 100); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Overlapping stars 2', container ); + // pathA = new Path.Star(new Point(110, 110), 20, 20, 80); + // pathB = new Path.Star(new Point(110, 110), 6, 30, 100); + // testIntersections( pathA, pathB, caption ); + + // // caption = prepareTest( 'Circles overlap exactly over each other', container ); + // // pathA = new Path.Circle(new Point(110, 110), 100); + // // pathB = new Path.Circle(new Point(110, 110), 100 ); + // // // pathB.translate([0.5,0]) + // // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Maximum possible intersections between 2 cubic bezier curve segments - 9', container ); + // pathA = new Path(); + // pathA.add( new Segment( [173, 44], [-281, 268], [-86, 152] ) ); + // pathA.add( new Segment( [47, 93], [-89, 100], [240, -239] ) ); + // pathA.closed = true; + // pathB = pathA.clone(); + // pathB.rotate( -90 ); + // pathA.translate( [-10,0] ); + // pathB.translate( [10,0] ); + // testIntersections( pathA, pathB, caption ); + // // annotatePath( pathA, null, '#008' ); + // // annotatePath( pathB, null, '#800' ); + // view.draw(); + + // caption = prepareTest( 'SVG gears', container ); + // group = paper.project.importSVG( document.getElementById( 'svggears' ) ); + // pathA = group.children[0]; + // pathB = group.children[1]; + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'Glyphs imported from SVG', container ); + // group = paper.project.importSVG( document.getElementById( 'glyphsys' ) ); + // pathA = group.children[0]; + // pathB = group.children[1]; + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 1', container ); + // group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + // pathA = group.children[0]; + // pathB = group.children[1]; + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 2 - holes', container ); + // group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + // pathA = group.children[0]; + // pathB = new CompoundPath(); + // group.children[1].clockwise = true; + // pathB.addChild(group.children[1]); + // var npath = new Path.Circle([110, 110], 30); + // pathB.addChild( npath ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 3 !', container ); + // group = paper.project.importSVG( document.getElementById( 'svggreenland' ) ); + // pathA = group.children[0]; + // pathB = group.children[1]; + // pathB.scale( 0.5, 1 ).translate( [25.5, 0] ); + // // pathA.scale( 2 ); + // // pathB.scale( 2 ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 4 - holes and islands 1', container ); + // group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + // pathA = group.children[0]; + // pathB = new CompoundPath(); + // group.children[1].clockwise = true; + // pathB.addChild(group.children[1]); + // var npath = new Path.Circle([40, 80], 20); + // pathB.addChild( npath ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 5 - holes and islands 2', container ); + // group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + // pathA = group.children[0]; + // pathB = new CompoundPath(); + // group.children[1].clockwise = true; + // pathB.addChild(group.children[1]); + // var npath = new Path.Circle([40, 80], 20); + // pathB.addChild( npath ); + // npath = new Path.Circle([120, 110], 30); + // pathB.addChild( npath ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 6 - holes and islands 3', container ); + // group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + // pathA = group.children[0]; + // pathB = new CompoundPath(); + // var npath = new Path.Circle([110, 110], 100); + // pathB.addChild( npath ); + // npath = new Path.Circle([110, 110], 60); + // pathB.addChild( npath ); + // npath = new Path.Circle([110, 110], 30); + // pathB.addChild( npath ); + // testIntersections( pathA, pathB, caption ); + + // caption = prepareTest( 'CompoundPaths 6 - holes and islands 4 (curves overlap exactly on existing curves)', container ); + // pathA = new Path.Rectangle(new Point(50.5, 50.5), [100, 120]); + // pathB = new CompoundPath(); + // pathB.addChild( new Path.Rectangle(new Point(140.5, 30.5), [100, 150]) ); + // pathB.addChild( new Path.Rectangle(new Point(150.5, 65.5), [50, 100]) ); + // // pathB = new Path.Rectangle(new Point(150.5, 80.5), [80, 80] ); + // testIntersections( pathA, pathB, caption ); + + // var tool = new Tool(); + // tool.onMouseMove = function( e ){ + // var hi = project.hitTest( e.point ); + // if( hi ){ + // var item = hi.item; + // if( item instanceof PathItem ){ + // var txt = new PointText( e.point.add([0, -10]) ); + // txt.justification = 'center'; + // txt.content = item.id; + // txt.fillColor = '#000'; + // txt.removeOnMove(); + // } + // } + // }; window.a = pathA; window.b = pathB; + prepareTest( 'none', container ); + + // var pa = new Path( new Segment([100, 100], null, [70, 0]), new Segment([200, 200], [0, -70], null) ); + var pa = new Path( new Segment([100, 100], null, [150, 0]), new Segment([230, 180], [-150, -20], null) ); + var pb = new Path.Line( [120, 80], [ 210, 200 ] ); + // pb.reverse(); + // pb.scale(0.6); + pa.style = pb.style = pathStyleBoolean; + + var vc = pa.curves[0].getValues(); + var vl = pb.curves[0].getValues(); + + var loc = []; + // _getCurveLineIntersection( vc, vl, pa.curves[0], pb.curves[0], loc ); + _getCurveLineIntersection( vl, vc, pb.curves[0], pa.curves[0], loc ); + + console.log( loc ) + markIntersections( loc ) + view.draw(); - window.setTimeout( function(){doTest( pathA, pathB, 1000 )}, 10 ); - - // var v1 = [84.625,79.375,51,130.5,22.5,178,163,44]; - // var v2 = [91.81412502271213,92.91643774058434,142.93912502271212,126.54143774058434,190.43912502271212,155.04143774058434,56.43912502271214,14.541437740584342] - // var c1 = new Curve( 84.625,79.375,51,130.5,22.5,178,163,44 ); - // var c2 = new Curve( 91.81412502271213,92.91643774058434,142.93912502271212,126.54143774058434,190.43912502271212,155.04143774058434,56.43912502271214,14.541437740584342); - // var p1 = new Path( c1.segment1, c1.segment2 ); - // var p2 = new Path( c2.segment1, c2.segment2 ); - // p1.style = p2.style = pathStyleBoolean; - // var loc = []; - // Curve.getIntersections2( v1, v2, c1, c2, loc ); - // console.log( loc ) - function prepareTest( testName, parentNode ){ console.log( '\n' + testName ); var caption = document.createElement('h3'); @@ -77,95 +223,41 @@ var pathStyleBoolean = { }; -function doTest( pathA, pathB, count ){ - var _p1U = new Path( pathA.segments[0], pathA.segments[1] ); - // var _p1U = new Path( pathA.segments[1], pathA.segments[2] ); - // _p1U.reverse(); - var _p2U = new Path( pathB.segments[0], pathB.segments[1] ); - // var _p2U = new Path( pathB.segments[3], pathB.segments[0] ); - _p1U.style = _p2U.style = pathStyleBoolean; - // for (var i = 0; i < crvs.length; i++) { - // drawFatline( _p1U.curves[0].getValues() ); - // drawFatline( _p2U.curves[0].getValues() ); - // } - - var maxCount = count || 1, count = maxCount, loc, loc2; - var v1 = _p1U.curves[0].getValues(), v2 = _p2U.curves[0].getValues(); - console.time('fatline'); - while( count-- ){ - loc = []; - Curve.getIntersections2( v1, v2, _p1U.curves[0], _p2U.curves[0], loc ); - // Curve.getIntersections2( v2, v1, _p2U.curves[0], _p1U.curves[0], loc ); - // var ret = _clipFatLine( v1, v2, 0, 1, 0, 1, true, crvs[0], _p1U.curves[0], loc ); - } - console.timeEnd('fatline'); - - count = maxCount; - console.time('paperjs'); - while( count-- ){ - loc2 = []; - Curve.getIntersections( v1, v2, _p1U.curves[0], _p2U.curves[0], loc2 ); - } - console.timeEnd('paperjs'); - - console.log( ' ' ); - for( i =0; i < loc2.length; i++){ - markPoint( loc2[i].point, ' ', '#00f' ); - // markPoint( loc2[i].point, loc2[i].parameter, '#00f' ); - console.log( 'paperjs t = ' + loc2[i].parameter + ' , u = ' + loc2[i].getIntersection().parameter ); - } - for( i =0; i < loc.length; i++){ - // console.log( loc[i].point ) - markPoint( loc[i].point, ' ', '#f00' ); - // markPoint( loc[i].point, loc[i].parameter, '#f00' ); - console.log( 'fatline t = ' + loc[i].parameter + ' , u = ' + loc[i].getIntersection().parameter ); - } - view.draw(); -} - // Better if path1 and path2 fit nicely inside a 200x200 pixels rect -function testIntersection( path1, path2, caption ) { - try{ +function testIntersections( path1, path2, caption ) { + // try{ path1.style = path2.style = pathStyleNormal; + var maxCount = 1, count = maxCount; + console.time('paperjs'); + while(count--){ + var ixsPaper = path1.getIntersections( path2 ); + } + console.timeEnd('paperjs'); - var _p1U = path1.clone().translate( [250, 0] ); - var _p2U = path2.clone().translate( [250, 0] ); - _p1U.style = _p2U.style = pathStyleBoolean; - console.time( 'New' ); - var ixs = getIntersections2( _p1U, _p2U ); - console.timeEnd( 'New' ); - markIntersections(ixs); + count = maxCount; + console.time('fatline'); + while(count--){ + var ixsFatline = getIntersections2( path1, path2 ); + } + console.timeEnd('fatline'); - - var _p1I = path1.clone().translate( [500, 0] ); - // _p1I.reverse(); - var _p2I = path2.clone().translate( [500, 0] ); - _p1I.style = _p2I.style = pathStyleBoolean; - console.time( 'Paperjs' ); - ixs = _p1I.getIntersections( _p2I ); - console.timeEnd( 'Paperjs' ); - // markIntersections(ixs); - - var vals = ixs[0].curve.getValues(); - var section = Curve.getPart( vals, ixs[1].parameter, ixs[0].parameter ); - console.log(section) - - markPoint( new Point(section[0], section[1]), ixs[0].parameter ); - markPoint( new Point(section[6], section[7]), ixs[1].parameter ); - } catch( e ){ - console.error( e.name + ": " + e.message ); - if( caption ) { caption.className += ' error'; } - // paper.project.view.element.className += ' hide'; - } finally { - console.timeEnd( 'New' ); - console.timeEnd( 'Paperjs' ); + markIntersections( ixsPaper, '#00f' ); + markIntersections( ixsFatline, '#f00' ); view.draw(); - } + // } catch(e){ + // console.error( e.name + ": " + e.message ); + // if( caption ) { caption.className += ' error'; } + // }finally{ + // console.timeEnd(caption + ' paperjs'); + // console.timeEnd(caption + ' fatline'); + // view.draw(); + // } } -function markIntersections( ixs ){ +function markIntersections( ixs, c ){ for (i = 0, len = ixs.length; i < len; i++) { - markPoint( ixs[i].point, ixs[i].parameter ); + // markPoint( ixs[i].point, ixs[i].parameter ); + markPoint( ixs[i].point, ' ', c ); } } @@ -202,6 +294,7 @@ function markCurve( crv, c, flag) { new Segment( [crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null ) ); window.__p1.style.strokeColor = c; + // window.__p1.fullySelected = true; } else { if( window.__p2 ) window.__p2.remove(); window.__p2 = new Path( @@ -209,16 +302,11 @@ function markCurve( crv, c, flag) { new Segment( [crv[6], crv[7]], [crv[4] - crv[6], crv[5] - crv[7]], null ) ); window.__p2.style.strokeColor = c; + // window.__p2.fullySelected = true; } view.draw(); } -function waitFor( time ){ - var st = new Date(); - while( new Date() - st < time ){} -} - - function annotatePath( path, t, c, tc, remove ) { if( !path ) return; var crvs = path.curves;