diff --git a/fatline/intersectTests.js b/fatline/intersectTests.js index 97fda453..2dfc2632 100644 --- a/fatline/intersectTests.js +++ b/fatline/intersectTests.js @@ -20,7 +20,7 @@ if (window.performance && window.performance.now) { function runTests() { var caption, pathA, pathB, group, testdata = [], randomtestdata = [], testQueued = 0, testExecuted = 0; - var container = document.getElementById( 'container' ); + var container = document.getElementById('container'); function runTest(testName, handler) { var caption = document.createElement('h3'); @@ -34,12 +34,12 @@ function runTests() { paper.setup(canvas); var paths = handler(); var success = testIntersections(paths[0], paths[1], caption, testName, testdata); - if( !success ){ + if (!success) { window.p1 = paths[0].exportSVG(); window.p2 = paths[1].exportSVG(); } testExecuted++; - if( testExecuted === testQueued ){ + if (testExecuted === testQueued) { plotData(); } }, 0); @@ -50,276 +50,276 @@ function runTests() { caption.appendChild(document.createTextNode("Randomised tests (may take a while...)")); container.appendChild(caption); var canvas = document.createElement('CANVAS'); - container.appendChild( canvas ); - paper.setup( canvas ); - doRandomTests( randomtestdata ); + container.appendChild(canvas); + paper.setup(canvas); + doRandomTests(randomtestdata); window.d = randomtestdata; - container.removeChild( canvas ); + container.removeChild(canvas); - runTest('random', function(){ + runTest('random', function() { pathA = getRandomPath(20); pathB = getRandomPath(20); return [pathA, pathB]; }); - runTest('failcase 1', function(){ - group = paper.project.importSVG( document.getElementById( 'svgrandom1' ) ); + runTest('failcase 1', function() { + group = paper.project.importSVG(document.getElementById('svgrandom1')); pathA = group.children[0]; pathB = group.children[1]; pathA.style = pathB.style = null; return [pathA, pathB]; }); - runTest('Overlapping circles', function(){ + runTest('Overlapping circles', function() { pathA = new Path.Circle(new Point(80, 110), 50); pathB = new Path.Circle(new Point(150, 110), 70); return [pathA, pathB]; }); - runTest('Polygon and square', function(){ + runTest('Polygon and square', function() { pathA = new Path.RegularPolygon(new Point(80, 110), 12, 80); - pathB = new Path.Rectangle(new Point(100, 80), [80, 80] ); + pathB = new Path.Rectangle(new Point(100, 80), [80, 80]); return [pathA, pathB]; }); - runTest('Circle and square (overlaps exactly on existing segments)', function(){ + runTest('Circle and square (overlaps exactly on existing segments)', function() { pathA = new Path.Circle(new Point(110, 110), 80); - pathB = new Path.Rectangle(new Point(110, 110), [80, 80] ); + pathB = new Path.Rectangle(new Point(110, 110), [80, 80]); return [pathA, pathB]; }); - runTest('Circle and square (existing segments overlaps on curves)', function(){ + runTest('Circle and square (existing segments overlaps on curves)', function() { pathA = new Path.Circle(new Point(110, 110), 80); - pathB = new Path.Rectangle(new Point(110, 110), [100, 100] ); + pathB = new Path.Rectangle(new Point(110, 110), [100, 100]); return [pathA, pathB]; }); - runTest('Square and square (one segment overlaps on a line)', function(){ - pathA = new Path.Rectangle(new Point(80, 125), [50, 50] ); - pathA.rotate( 45 ); - pathB = new Path.Rectangle(new Point(pathA.segments[2].point.x, 110), [80, 80] ); + runTest('Square and square (one segment overlaps on a line)', function() { + pathA = new Path.Rectangle(new Point(80, 125), [50, 50]); + pathA.rotate(45); + pathB = new Path.Rectangle(new Point(pathA.segments[2].point.x, 110), [80, 80]); return [pathA, pathB]; }); - runTest('Rectangle and rectangle (overlaps exactly on existing curves)', function(){ + runTest('Rectangle and rectangle (overlaps exactly on existing curves)', function() { pathA = new Path.Rectangle(new Point(30.5, 50.5), [100, 150]); pathB = new Path.Rectangle(new Point(130.5, 60.5), [100, 150]); return [pathA, pathB]; }); - runTest('Overlapping stars 1', function(){ + runTest('Overlapping stars 1', function() { pathA = new Path.Star(new Point(80, 110), 10, 20, 80); pathB = new Path.Star(new Point(120, 110), 10, 30, 100); return [pathA, pathB]; }); - runTest('Overlapping stars 2', function(){ + runTest('Overlapping stars 2', function() { pathA = new Path.Star(new Point(110, 110), 20, 20, 80); pathB = new Path.Star(new Point(110, 110), 6, 30, 100); return [pathA, pathB]; }); - runTest('Circle and banana (multiple intersections within same curve segment)', function(){ + runTest('Circle and banana (multiple intersections within same curve segment)', function() { 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 ] ); + pathB = new Path.Circle(new Point(130, 110), 80); + pathB.segments[3].point = pathB.segments[3].point.add([ 0, -120 ]); return [pathA, pathB]; }); - runTest('Maximum possible intersections between 2 cubic bezier curve segments - 9', function(){ + runTest('Maximum possible intersections between 2 cubic bezier curve segments - 9', function() { pathA = new Path(); - pathA.add( new Segment( [173, 44], [-281, 268], [-86, 152] ) ); - pathA.add( new Segment( [47, 93], [-89, 100], [240, -239] ) ); + 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] ); + pathB.rotate(-90); + pathA.translate([-10,0]); + pathB.translate([10,0]); return [pathA, pathB]; }); - runTest('SVG gears', function(){ - group = paper.project.importSVG( document.getElementById( 'svggears' ) ); - pathA = group.children[0]; - pathB = group.children[1]; - return [pathA, pathB]; - }); - - runTest('Glyphs imported from SVG', function(){ - group = paper.project.importSVG( document.getElementById( 'glyphsys' ) ); + runTest('SVG gears', function() { + group = paper.project.importSVG(document.getElementById('svggears')); pathA = group.children[0]; pathB = group.children[1]; return [pathA, pathB]; }); - runTest('CompoundPaths 1', function(){ - group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + runTest('Glyphs imported from SVG', function() { + group = paper.project.importSVG(document.getElementById('glyphsys')); pathA = group.children[0]; pathB = group.children[1]; return [pathA, pathB]; }); - runTest('CompoundPaths 2 - holes', function(){ - group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + runTest('CompoundPaths 1', function() { + group = paper.project.importSVG(document.getElementById('glyphsacirc')); + pathA = group.children[0]; + pathB = group.children[1]; + return [pathA, pathB]; + }); + + runTest('CompoundPaths 2 - holes', function() { + 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 ); + pathB.addChild(npath); return [pathA, pathB]; }); - runTest('CompoundPaths 3 !', function(){ - group = paper.project.importSVG( document.getElementById( 'svggreenland' ) ); + runTest('CompoundPaths 3 !', function() { + 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 ); + pathB.scale(0.5, 1).translate([25.5, 0]); + // pathA.scale(2); + // pathB.scale(2); return [pathA, pathB]; }); - runTest('CompoundPaths 4 - holes and islands 1', function(){ - group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + runTest('CompoundPaths 4 - holes and islands 1', function() { + 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 ); + pathB.addChild(npath); return [pathA, pathB]; }); - runTest('CompoundPaths 5 - holes and islands 2', function(){ - group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + runTest('CompoundPaths 5 - holes and islands 2', function() { + 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 ); + pathB.addChild(npath); npath = new Path.Circle([120, 110], 30); - pathB.addChild( npath ); + pathB.addChild(npath); return [pathA, pathB]; }); - runTest('CompoundPaths 6 - holes and islands 3', function(){ - group = paper.project.importSVG( document.getElementById( 'glyphsacirc' ) ); + runTest('CompoundPaths 6 - holes and islands 3', function() { + 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 ); + pathB.addChild(npath); npath = new Path.Circle([110, 110], 60); - pathB.addChild( npath ); + pathB.addChild(npath); npath = new Path.Circle([110, 110], 30); - pathB.addChild( npath ); + pathB.addChild(npath); return [pathA, pathB]; }); - runTest('CompoundPaths 6 - holes and islands 4 (curves overlap exactly on existing curves)', function(){ + runTest('CompoundPaths 6 - holes and islands 4 (curves overlap exactly on existing curves)', function() { 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] ); + 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]); return [pathA, pathB]; }); // Plot the run times - function plotData(){ - prepareTest( 'Results - Random tests ( Intersections/Curve vs Time)', container, 'big2' ); - plotDataRandom( randomtestdata ); + function plotData() { + prepareTest('Results - Random tests (Intersections/Curve vs Time)', container, 'big2'); + plotDataRandom(randomtestdata); - prepareTest( 'Results - Boolean tests ( Time taken per test )', container, 'big' ); + prepareTest('Results - Boolean tests (Time taken per test)', container, 'big'); var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny, yy = y + height, xx = x + width; var ppaperfill = new Path(), pfatfill = new Path(); var ppaper = new Path(), pfat = new Path(); - var max = testdata.reduce(function( a, b ){ return Math.max( a, b.paperTime + b.fatTime ); }, 0) + 20; + var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime + b.fatTime); }, 0) + 20; var vscale = height / max, hscale = width / testdata.length; var caxes = '#999', ctxt = '#222', ctxt2 = '#555', cpaper = '#268BD2', cpaperfill ='#B5E1FF', cfat = '#D33682', cfatfill = '#FFADD4'; - new Path.Line( x, yy, xx, yy ).style.strokeColor = caxes; - new Path.Line( x, yy, x, y ).style.strokeColor = caxes; - for( i = 0; i < 10 ; i++ ){ + new Path.Line(x, yy, xx, yy).style.strokeColor = caxes; + new Path.Line(x, yy, x, y).style.strokeColor = caxes; + for (i = 0; i < 10 ; i++) { ny = yy - vscale * max * i / 10; - new Path.Line( x, ny, x-5, ny ).style.strokeColor = caxes; - txt = new PointText( [x-10, ny] ); + new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes; + txt = new PointText([x-10, ny]); txt.justification = 'right'; txt.fillColor = (i%2)? ctxt: ctxt2; txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : ''); } - ppaperfill.add( new Segment( x, yy ) ); - pfatfill.add( new Segment( x, yy ) ); + ppaperfill.add(new Segment(x, yy)); + pfatfill.add(new Segment(x, yy)); var vx = x, clr = ctxt; var coords = [], avgPaper = 0, avgFat = 0, maxSpeedup = -Infinity, minSpeedup = Infinity, avgSpeedup = 0; - testdata.map(function(data){ + testdata.map(function(data) { avgPaper += data.paperTime; ny = yy - (data.paperTime + data.fatTime) * vscale; - ppaper.add( new Segment([vx, ny]) ); - ppaperfill.add( new Segment([vx, ny]) ); - var np = new Point( vx, ny ); + ppaper.add(new Segment([vx, ny])); + ppaperfill.add(new Segment([vx, ny])); + var np = new Point(vx, ny); np._data = data; np._datatype = 'paper'; - coords.push( np ); + coords.push(np); avgFat += data.fatTime; ny = yy - (data.fatTime) * vscale; - pfat.add( new Segment([vx, ny]) ); - pfatfill.add( new Segment([vx, ny]) ); - np = new Point( vx, ny ); + pfat.add(new Segment([vx, ny])); + pfatfill.add(new Segment([vx, ny])); + np = new Point(vx, ny); np._data = data; np._datatype = 'fat'; - coords.push( np ); + coords.push(np); var speedup = data.paperTime / data.fatTime; - if( speedup > maxSpeedup ) maxSpeedup = speedup; - if( speedup < minSpeedup ) minSpeedup = speedup; + if (speedup > maxSpeedup) maxSpeedup = speedup; + if (speedup < minSpeedup) minSpeedup = speedup; avgSpeedup += speedup; - new Path.Line( vx, yy, vx, yy + 5 ).style.strokeColor = caxes; - txt = new PointText( [vx, yy+18] ); + new Path.Line(vx, yy, vx, yy + 5).style.strokeColor = caxes; + txt = new PointText([vx, yy+18]); txt.justification = 'left'; txt.fillColor = clr; txt.content = data.name; - txt.rotate( 30, new Point(vx, yy+10) ); + txt.rotate(30, new Point(vx, yy+10)); - if( !data.success ){ - var p = new Path.Line( vx, y, vx, yy ); + if (!data.success) { + var p = new Path.Line(vx, y, vx, yy); p.style.strokeWidth = 5; p.style.strokeColor = '#f00'; } - clr = ( clr === ctxt )? ctxt2 : ctxt; + clr = (clr === ctxt)? ctxt2 : ctxt; vx += hscale; }); ppaper.style.strokeWidth = 2; ppaper.style.strokeColor = cpaper; - ppaperfill.add( new Segment( vx-hscale, yy ) ); + ppaperfill.add(new Segment(vx-hscale, yy)); ppaperfill.closed = true; ppaperfill.style.fillColor = cpaperfill; pfat.style.strokeWidth = 2; pfat.style.strokeColor = cfat; - pfatfill.add( new Segment( vx-hscale, yy ) ); + pfatfill.add(new Segment(vx-hscale, yy)); pfatfill.closed = true; pfatfill.style.fillColor = cfatfill; avgPaper/= testdata.length; avgFat/= testdata.length; avgSpeedup = Math.round(avgSpeedup / testdata.length); - maxSpeedup = Math.round( maxSpeedup ); - minSpeedup = Math.round( minSpeedup ); + maxSpeedup = Math.round(maxSpeedup); + minSpeedup = Math.round(minSpeedup); ny = Math.round(yy - avgPaper * vscale) + 0.5; new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper; - txt = new PointText( [xx, ny] ); + txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cpaper; txt.content = avgPaper.toFixed(1); ny = Math.round(yy - avgFat * vscale) + 0.5; new Path.Line(x, ny, xx, ny).style.strokeColor = cfat; - txt = new PointText( [xx, ny] ); + txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cfat; txt.content = avgFat.toFixed(1); @@ -328,9 +328,9 @@ function runTests() { txt.justification = 'center'; txt.fillColor = '#000'; txt.content = 'fatline vs subdiv'; - new Path.Rectangle( [600, 90], [20, 100] ).style = { fillColor: '#ccc', strokeColor: '#000' }; + new Path.Rectangle([600, 90], [20, 100]).style = { fillColor: '#ccc', strokeColor: '#000' }; ny = 190 - (avgSpeedup - minSpeedup) * 100.0 / (maxSpeedup - minSpeedup); - new Path.Line( [600, ny], [620, ny] ).style = { strokeWidth: 2, strokeColor: '#000' }; + new Path.Line([600, ny], [620, ny]).style = { strokeWidth: 2, strokeColor: '#000' }; txt = new PointText([630, 95]); txt.fillColor = '#000'; txt.content = maxSpeedup; @@ -343,31 +343,31 @@ function runTests() { view.draw(); var tool = new Tool(); - tool.onMouseMove = function( e ){ + tool.onMouseMove = function(e) { var len = coords.length; var data = null, dist = Infinity, dst, pnt = null, type = 'paper'; - while( len-- ){ - dst = e.point.getDistance( coords[len], true ); - if( dst < dist ){ + while (len--) { + dst = e.point.getDistance(coords[len], true); + if (dst < dist) { pnt = coords[len]; data = coords[len]._data; type = coords[len]._datatype; dist = dst; } } - if( dist > 500 ){ return; } - if( pnt && data ){ - var p = new Path.Line( pnt.x+0.5, y, pnt.x+0.5, yy ); + if (dist > 500) { return; } + if (pnt && data) { + var p = new Path.Line(pnt.x+0.5, y, pnt.x+0.5, yy); p.style.strokeColor = '#000'; p.removeOnMove(); - p = new Path.Circle( pnt, 3 ); + p = new Path.Circle(pnt, 3); p.style.fillColor = (type === 'fat')? '#D33682' :'#268BD2'; p.removeOnMove(); - var txt = new PointText( [ 500, 20 ] ); + var txt = new PointText([ 500, 20 ]); txt.content = 'subdiv : ' + data.paperTime.toFixed(1) + ' ms'; txt.fillColor = '#222'; txt.removeOnMove(); - txt = new PointText( [ 500, 36 ] ); + txt = new PointText([ 500, 36 ]); txt.content = 'fatline : ' + data.fatTime.toFixed(1) + ' ms'; txt.fillColor = '#222'; txt.removeOnMove(); @@ -376,69 +376,69 @@ function runTests() { } - function prepareTest( testName, parentNode, _big ){ - console.log( '\n' + testName ); + function prepareTest(testName, parentNode, _big) { + console.log('\n' + testName); var caption = document.createElement('h3'); - caption.appendChild( document.createTextNode( testName ) ); + caption.appendChild(document.createTextNode(testName)); var canvas = document.createElement('CANVAS'); canvas.className += ' ' + _big; - parentNode.appendChild( caption ); - parentNode.appendChild( canvas ); - paper.setup( canvas ); + parentNode.appendChild(caption); + parentNode.appendChild(canvas); + paper.setup(canvas); return caption; } } var pathStyleIx = { - fillColor: new Color( 0.8, 0, 0 ), - strokeColor: new Color( 0, 0, 0 ) + fillColor: new Color(0.8, 0, 0), + strokeColor: new Color(0, 0, 0) }; var pathStyleNormal = { - strokeColor: new Color( 0, 0, 0 ), - // fillColor: new Color( 0, 0, 0, 0.1 ), + strokeColor: new Color(0, 0, 0), + // fillColor: new Color(0, 0, 0, 0.1), strokeWidth: 1 }; var pathStyleBoolean = { - strokeColor: new Color( 0,0,0,0.4 ), - fillColor: new Color( 0, 0, 0, 0.0 ), + strokeColor: new Color(0,0,0,0.4), + fillColor: new Color(0, 0, 0, 0.0), strokeWidth: 1 }; // Better if path1 and path2 fit nicely inside a 200x200 pixels rect -function testIntersections( path1, path2, caption, testname, testdata, nomark) { +function testIntersections(path1, path2, caption, testname, testdata, nomark) { var i, l, maxCount = 10, count = maxCount, st, t1, t2, ixsPaper, ixsFatline, success = false, maxdiff = -Infinity; - try{ + try { path1.style = path2.style = pathStyleNormal; - if( !nomark ) console.time('paperjs x ' + maxCount); + if (!nomark) console.time('paperjs x ' + maxCount); st = getTimestamp(); - while(count--){ - ixsPaper = path1.getIntersections( path2 ); + while (count--) { + ixsPaper = path1.getIntersections(path2); } t1 = (getTimestamp() - st) / maxCount; - if( !nomark ) console.timeEnd('paperjs x ' + maxCount); + if (!nomark) console.timeEnd('paperjs x ' + maxCount); count = maxCount; - if( !nomark ) console.time('fatline x ' + maxCount); + if (!nomark) console.time('fatline x ' + maxCount); st = getTimestamp(); - while(count--){ - ixsFatline = path1.getIntersections2( path2 ); + while (count--) { + ixsFatline = path1.getIntersections2(path2); } t2 = (getTimestamp() - st) / maxCount; - if( !nomark ) console.timeEnd('fatline x ' + maxCount); + if (!nomark) console.timeEnd('fatline x ' + maxCount); var found = 0, tol = 0.1; - if( ixsFatline.length === ixsPaper.length ){ - for(i=0, l=ixsFatline.length; i= 0; i--) { - annotateCurve( crvs[i], t, c, tc, remove ); + annotateCurve(crvs[i], t, c, tc, remove); } var segs = path.segments; for (i = segs.length - 1; i >= 0; i--) { - annotateSegment( segs[i], t, c, tc, remove, true ); + annotateSegment(segs[i], t, c, tc, remove, true); } } -function annotateSegment( s, t, c, tc, remove, skipCurves ) { - if( !s ) return; +function annotateSegment(s, t, c, tc, remove, skipCurves) { + if (!s) return; c = c || '#000'; tc = tc || '#ccc'; t = t || s.index; - if( remove === undefined ){ remove = true; } + if (remove === undefined) { remove = true; } var crv = s.curve; - var t1 = crv.getNormal( 0 ).normalize( 10 ); - var p = s.point.clone().add( t1 ); - var cir = new Path.Circle( s.point, 2 ); + var t1 = crv.getNormal(0).normalize(10); + var p = s.point.clone().add(t1); + var cir = new Path.Circle(s.point, 2); cir.style.fillColor = c; cir.style.strokeColor = tc; - var text = new PointText( p ); + var text = new PointText(p); text.justification = 'center'; text.fillColor = c; text.content = t; - if( remove ) { + if (remove) { cir.removeOnMove(); text.removeOnMove(); } - if( !skipCurves ) { - annotateCurve( s.curveIn, null, c, tc, remove ); - annotateCurve( s.curveOut, null, c, tc, remove ); + if (!skipCurves) { + annotateCurve(s.curveIn, null, c, tc, remove); + annotateCurve(s.curveOut, null, c, tc, remove); } } -function annotateCurve( crv, t, c, tc, remove ) { - if( !crv ) return; +function annotateCurve(crv, t, c, tc, remove) { + if (!crv) return; c = c || '#000'; tc = tc || '#ccc'; t = t || crv.index; - if( remove === undefined ){ remove = true; } - var p = crv.getPoint( 0.57 ); - var t1 = crv.getTangent( 0.57 ).normalize( -10 ); - var p2 = p.clone().add( t1 ); - var l = new Path.Line( p, p2 ).rotate( 30, p ); - var l2 = new Path.Line( p, p2 ).rotate( -30, p ); - p = crv.getPoint( 0.43 ); - var cir = new Path.Circle( p, 8 ); - var text = new PointText( p.subtract( [0, -4] ) ); + if (remove === undefined) { remove = true; } + var p = crv.getPoint(0.57); + var t1 = crv.getTangent(0.57).normalize(-10); + var p2 = p.clone().add(t1); + var l = new Path.Line(p, p2).rotate(30, p); + var l2 = new Path.Line(p, p2).rotate(-30, p); + p = crv.getPoint(0.43); + var cir = new Path.Circle(p, 8); + var text = new PointText(p.subtract([0, -4])); text.justification = 'center'; text.fillColor = tc; text.content = t; l.style.strokeColor = l2.style.strokeColor = c; cir.style.fillColor = c; - if( remove ) { + if (remove) { l.removeOnMove(); l2.removeOnMove(); cir.removeOnMove(); @@ -669,20 +669,20 @@ function annotateCurve( crv, t, c, tc, remove ) { // Plot the run times -function plotDataRandom( testdata ){ +function plotDataRandom(testdata) { var x = 80.5, y = 15.5, width = 500, height = 190, i, txt, ny, yy = y + height, xx = x + width; var ppaper = new Path(), pfat = new Path(); - var max = testdata.reduce(function( a, b ){ return Math.max( a, b.paperTime, b.fatTime ); }, 0) + 20; - testdata.sort( function(a,b){ return a.ratio - b.ratio; } ); + var max = testdata.reduce(function(a, b) { return Math.max(a, b.paperTime, b.fatTime); }, 0) + 20; + testdata.sort(function(a,b) { return a.ratio - b.ratio; }); var vscale = height / max, hscale = width / testdata.length; var caxes = '#999', ctxt = '#222', cpaper = '#268BD2', cfat = '#D33682'; - new Path.Line( x, yy, xx, yy ).style.strokeColor = caxes; - new Path.Line( x, yy, x, y ).style.strokeColor = caxes; - for( i = 0; i < 10 ; i++ ){ + new Path.Line(x, yy, xx, yy).style.strokeColor = caxes; + new Path.Line(x, yy, x, y).style.strokeColor = caxes; + for (i = 0; i < 10 ; i++) { ny = yy - vscale * max * i / 10; - new Path.Line( x, ny, x-5, ny ).style.strokeColor = caxes; - txt = new PointText( [x-10, ny] ); + new Path.Line(x, ny, x-5, ny).style.strokeColor = caxes; + txt = new PointText([x-10, ny]); txt.justification = 'right'; txt.fillColor = ctxt; txt.content = (max * i / 10).toFixed(1) + ((!i)? ' ms' : ''); @@ -694,30 +694,30 @@ function plotDataRandom( testdata ){ txt = new PointText([xx + 20, yy + 40]); txt.justification = 'left'; txt.fillColor = '#999'; - txt.content = '( Total Curves )'; + txt.content = '(Total Curves)'; var vx = x, step = 15, count = 0; var avgPaper = 0, avgFat = 0; - testdata.map(function(data){ + testdata.map(function(data) { avgPaper += data.paperTime; ny = yy - (data.paperTime + data.fatTime) * vscale; - ppaper.add( new Segment([vx, ny]) ); + ppaper.add(new Segment([vx, ny])); avgFat += data.fatTime; ny = yy - (data.fatTime) * vscale; - pfat.add( new Segment([vx, ny]) ); + pfat.add(new Segment([vx, ny])); - new Path.Line( vx, yy, vx, yy + 5 + ((count%2)? step:0) ).style.strokeColor = caxes; - txt = new PointText( [vx, yy+18 + ((count%2)? step:0) ] ); + new Path.Line(vx, yy, vx, yy + 5 + ((count%2)? step:0)).style.strokeColor = caxes; + txt = new PointText([vx, yy+18 + ((count%2)? step:0) ]); txt.justification = 'center'; txt.fillColor = ctxt; txt.content = data.ratio.toFixed(1); - txt = new PointText( [vx -5, yy+40 ] ); + txt = new PointText([vx -5, yy+40 ]); txt.justification = 'left'; txt.fillColor = '#999'; txt.content = data.curves; - txt.rotate( 90, [vx-5, yy+40 ] ); + txt.rotate(90, [vx-5, yy+40 ]); - if( !data.success ){ - var p = new Path.Line( vx, y, vx, yy ); + if (!data.success) { + var p = new Path.Line(vx, y, vx, yy); p.style.strokeWidth = 5; p.style.strokeColor = '#f00'; } @@ -735,13 +735,13 @@ function plotDataRandom( testdata ){ avgFat/= testdata.length; ny = Math.round(yy - avgPaper * vscale) + 0.5; new Path.Line(x, ny, xx, ny).style.strokeColor = cpaper; - txt = new PointText( [xx, ny] ); + txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cpaper; txt.content = avgPaper.toFixed(1); ny = Math.round(yy - avgFat * vscale) + 0.5; new Path.Line(x, ny, xx, ny).style.strokeColor = cfat; - txt = new PointText( [xx, ny] ); + txt = new PointText([xx, ny]); txt.justification = 'right'; txt.fillColor = cfat; txt.content = avgFat.toFixed(1); @@ -751,76 +751,78 @@ function plotDataRandom( testdata ){ -function drawFatline( v1 ) { +function drawFatline(v1) { function signum(num) { - return ( num > 0 )? 1 : ( num < 0 )? -1 : 0; + return (num > 0)? 1 : (num < 0)? -1 : 0; } - var l = new Line( [v1[0], v1[1]], [v1[6], v1[7]], false ); - var p1 = new Point( v1[2], v1[3] ), p2 = new Point( v1[4], v1[5] ); - var d1 = l.getSide( p1 ) * l.getDistance( p1 ) || 0; - var d2 = l.getSide( p2 ) * l.getDistance( p2 ) || 0; + var l = new Line([v1[0], v1[1]], [v1[6], v1[7]], false); + var p1 = new Point(v1[2], v1[3]), p2 = new Point(v1[4], v1[5]); + var d1 = l.getSide(p1) * l.getDistance(p1) || 0; + var d2 = l.getSide(p2) * l.getDistance(p2) || 0; var dmin, dmax; - if( d1 * d2 > 0){ + if (d1 * d2 > 0) { // 3/4 * min{0, d1, d2} - dmin = 0.75 * Math.min( 0, d1, d2 ); - dmax = 0.75 * Math.max( 0, d1, d2 ); + dmin = 0.75 * Math.min(0, d1, d2); + dmax = 0.75 * Math.max(0, d1, d2); } else { // 4/9 * min{0, d1, d2} - dmin = 4 * Math.min( 0, d1, d2 ) / 9.0; - dmax = 4 * Math.max( 0, d1, d2 ) / 9.0; + dmin = 4 * Math.min(0, d1, d2) / 9.0; + dmax = 4 * Math.max(0, d1, d2) / 9.0; } - var ll = new Path.Line( v1[0], v1[1], v1[6], v1[7] ); - window.__p3.push( ll ); - window.__p3[window.__p3.length-1].style.strokeColor = new Color( 0,0,0.9, 0.8); + var ll = new Path.Line(v1[0], v1[1], v1[6], v1[7]); + window.__p3.push(ll); + window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9, 0.8); var lp1 = ll.segments[0].point; var lp2 = ll.segments[1].point; - var pm = l.vector, pm1 = pm.rotate( signum( dmin ) * -90 ), pm2 = pm.rotate( signum( dmax ) * -90 ); - var p11 = lp1.add( pm1.normalize( Math.abs(dmin) ) ); - var p12 = lp2.add( pm1.normalize( Math.abs(dmin) ) ); - var p21 = lp1.add( pm2.normalize( Math.abs(dmax) ) ); - var p22 = lp2.add( pm2.normalize( Math.abs(dmax) ) ); - window.__p3.push( new Path.Line( p11, p12 ) ); - window.__p3[window.__p3.length-1].style.strokeColor = new Color( 0,0,0.9); - window.__p3.push( new Path.Line( p21, p22 ) ); - window.__p3[window.__p3.length-1].style.strokeColor = new Color( 0,0,0.9); + var pm = l.vector, pm1 = pm.rotate(signum(dmin) * -90), pm2 = pm.rotate(signum(dmax) * -90); + var p11 = lp1.add(pm1.normalize(Math.abs(dmin))); + var p12 = lp2.add(pm1.normalize(Math.abs(dmin))); + var p21 = lp1.add(pm2.normalize(Math.abs(dmax))); + var p22 = lp2.add(pm2.normalize(Math.abs(dmax))); + window.__p3.push(new Path.Line(p11, p12)); + window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9); + window.__p3.push(new Path.Line(p21, p22)); + window.__p3[window.__p3.length-1].style.strokeColor = new Color(0,0,0.9); } -function plotD_vs_t( x, y, arr, arr2, v, dmin, dmax, tmin, tmax, yscale, tvalue ){ +function plotD_vs_t(x, y, arr, arr2, v, dmin, dmax, tmin, tmax, yscale, tvalue) { yscale = yscale || 1; - new Path.Line( x, y-100, x, y+100 ).style.strokeColor = '#aaa'; - new Path.Line( x, y, x + 200, y ).style.strokeColor = '#aaa'; + new Path.Line(x, y-100, x, y+100).style.strokeColor = '#aaa'; + new Path.Line(x, y, x + 200, y).style.strokeColor = '#aaa'; var clr = (tvalue)? '#a00' : '#00a'; - if( window.__p3 ) window.__p3.map(function(a){a.remove();}); + if (window.__p3) window.__p3.map(function(a) {a.remove();}); window.__p3 = []; - drawFatline( v ); + drawFatline(v); - window.__p3.push( new Path.Line( x, y + dmin * yscale, x + 200, y + dmin * yscale ) ); - window.__p3[window.__p3.length-1].style.strokeColor = '#000' - window.__p3.push( new Path.Line( x, y + dmax * yscale, x + 200, y + dmax * yscale ) ); - window.__p3[window.__p3.length-1].style.strokeColor = '#000' - window.__p3.push( new Path.Line( x + tmin * 190, y-100, x + tmin * 190, y+100 ) ); - window.__p3[window.__p3.length-1].style.strokeColor = clr - window.__p3.push( new Path.Line( x + tmax * 190, y-100, x + tmax * 190, y+100 ) ); - window.__p3[window.__p3.length-1].style.strokeColor = clr + window.__p3.push(new Path.Line(x, y + dmin * yscale, x + 200, y + dmin * yscale)); + window.__p3[window.__p3.length-1].style.strokeColor = '#000'; + window.__p3.push(new Path.Line(x, y + dmax * yscale, x + 200, y + dmax * yscale)); + window.__p3[window.__p3.length-1].style.strokeColor = '#000'; + window.__p3.push(new Path.Line(x + tmin * 190, y-100, x + tmin * 190, y+100)); + window.__p3[window.__p3.length-1].style.strokeColor = clr; + window.__p3.push(new Path.Line(x + tmax * 190, y-100, x + tmax * 190, y+100)); + window.__p3[window.__p3.length-1].style.strokeColor = clr; for (var i = 0; i < arr.length; i++) { - window.__p3.push( new Path.Line( new Point( x + arr[i][0] * 190, y + arr[i][1] * yscale ), - new Point( x + arr[i][2] * 190, y + arr[i][3] * yscale ) ) ); + window.__p3.push(new Path.Line(new Point(x + arr[i][0] * 190, y + arr[i][1] * yscale), + new Point(x + arr[i][2] * 190, y + arr[i][3] * yscale))); window.__p3[window.__p3.length-1].style.strokeColor = '#999'; } var pnt = []; var arr2x = [ 0.0, 0.333333333, 0.6666666666, 1.0 ]; for (var i = 0; i < arr2.length; i++) { - pnt.push( new Point( x + arr2x[i] * 190, y + arr2[i] * yscale ) ); - window.__p3.push( new Path.Circle( pnt[pnt.length-1], 2 ) ); - window.__p3[window.__p3.length-1].style.fillColor = '#000' + pnt.push(new Point(x + arr2x[i] * 190, y + arr2[i] * yscale)); + window.__p3.push(new Path.Circle(pnt[pnt.length-1], 2)); + window.__p3[window.__p3.length-1].style.fillColor = '#000'; } - // var pth = new Path( pnt[0], pnt[1], pnt[2], pnt[3] ); + // var pth = new Path(pnt[0], pnt[1], pnt[2], pnt[3]); // pth.closed = true; - window.__p3.push( new Path( new Segment(pnt[0], null, pnt[1].subtract(pnt[0])), new Segment( pnt[3], pnt[2].subtract(pnt[3]), null ) ) ); - window.__p3[window.__p3.length-1].style.strokeColor = clr + window.__p3.push(new Path( + new Segment(pnt[0], null, pnt[1].subtract(pnt[0])), + new Segment(pnt[3], pnt[2].subtract(pnt[3]), null))); + window.__p3[window.__p3.length-1].style.strokeColor = clr; view.draw(); }