|
@@ -18,708 +18,692 @@ THREE.Path = function ( points ) {
|
|
|
|
|
|
};
|
|
|
|
|
|
-THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
|
|
|
-THREE.Path.prototype.constructor = THREE.Path;
|
|
|
+THREE.Path.prototype = Object.assign( Object.create( THREE.CurvePath.prototype ), {
|
|
|
|
|
|
-// TODO Clean up PATH API
|
|
|
+ constructor: THREE.Path,
|
|
|
|
|
|
-// Create path using straight lines to connect all points
|
|
|
-// - vectors: array of Vector2
|
|
|
+ // TODO Clean up PATH API
|
|
|
|
|
|
-THREE.Path.prototype.fromPoints = function ( vectors ) {
|
|
|
+ // Create path using straight lines to connect all points
|
|
|
+ // - vectors: array of Vector2
|
|
|
|
|
|
- this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
|
|
|
+ fromPoints: function ( vectors ) {
|
|
|
|
|
|
- for ( var i = 1, l = vectors.length; i < l; i ++ ) {
|
|
|
+ this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
|
|
|
|
|
|
- this.lineTo( vectors[ i ].x, vectors[ i ].y );
|
|
|
+ for ( var i = 1, l = vectors.length; i < l; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
+ this.lineTo( vectors[ i ].x, vectors[ i ].y );
|
|
|
|
|
|
-};
|
|
|
+ }
|
|
|
|
|
|
-// startPath() endPath()?
|
|
|
+ },
|
|
|
|
|
|
-THREE.Path.prototype.moveTo = function ( x, y ) {
|
|
|
+ moveTo: function ( x, y ) {
|
|
|
|
|
|
- this.actions.push( { action: 'moveTo', args: [ x, y ] } );
|
|
|
+ this.actions.push( { action: 'moveTo', args: [ x, y ] } );
|
|
|
|
|
|
-};
|
|
|
+ },
|
|
|
|
|
|
-THREE.Path.prototype.lineTo = function ( x, y ) {
|
|
|
+ lineTo: function ( x, y ) {
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
|
|
|
- this.curves.push( curve );
|
|
|
+ var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- this.actions.push( { action: 'lineTo', args: [ x, y ] } );
|
|
|
+ this.actions.push( { action: 'lineTo', args: [ x, y ] } );
|
|
|
|
|
|
-};
|
|
|
+ },
|
|
|
|
|
|
-THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
|
|
|
+ quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) {
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- var curve = new THREE.QuadraticBezierCurve(
|
|
|
- new THREE.Vector2( x0, y0 ),
|
|
|
- new THREE.Vector2( aCPx, aCPy ),
|
|
|
- new THREE.Vector2( aX, aY )
|
|
|
- );
|
|
|
+ var curve = new THREE.QuadraticBezierCurve(
|
|
|
+ new THREE.Vector2( x0, y0 ),
|
|
|
+ new THREE.Vector2( aCPx, aCPy ),
|
|
|
+ new THREE.Vector2( aX, aY )
|
|
|
+ );
|
|
|
|
|
|
- this.curves.push( curve );
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- this.actions.push( { action: 'quadraticCurveTo', args: [ aCPx, aCPy, aX, aY ] } );
|
|
|
+ this.actions.push( { action: 'quadraticCurveTo', args: [ aCPx, aCPy, aX, aY ] } );
|
|
|
|
|
|
-};
|
|
|
+ },
|
|
|
|
|
|
-THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
|
|
|
+ bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) {
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- var curve = new THREE.CubicBezierCurve(
|
|
|
- new THREE.Vector2( x0, y0 ),
|
|
|
- new THREE.Vector2( aCP1x, aCP1y ),
|
|
|
- new THREE.Vector2( aCP2x, aCP2y ),
|
|
|
- new THREE.Vector2( aX, aY )
|
|
|
- );
|
|
|
+ var curve = new THREE.CubicBezierCurve(
|
|
|
+ new THREE.Vector2( x0, y0 ),
|
|
|
+ new THREE.Vector2( aCP1x, aCP1y ),
|
|
|
+ new THREE.Vector2( aCP2x, aCP2y ),
|
|
|
+ new THREE.Vector2( aX, aY )
|
|
|
+ );
|
|
|
|
|
|
- this.curves.push( curve );
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- this.actions.push( { action: 'bezierCurveTo', args: [ aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ] } );
|
|
|
+ this.actions.push( { action: 'bezierCurveTo', args: [ aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ] } );
|
|
|
|
|
|
-};
|
|
|
+ },
|
|
|
|
|
|
-THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
|
|
|
+ splineThru: function ( pts /*Array of Vector*/ ) {
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- var npts = [ new THREE.Vector2( x0, y0 ) ];
|
|
|
- Array.prototype.push.apply( npts, pts );
|
|
|
+ var npts = [ new THREE.Vector2( x0, y0 ) ];
|
|
|
+ Array.prototype.push.apply( npts, pts );
|
|
|
|
|
|
- var curve = new THREE.SplineCurve( npts );
|
|
|
- this.curves.push( curve );
|
|
|
+ var curve = new THREE.SplineCurve( npts );
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- this.actions.push( { action: 'splineThru', args: args } );
|
|
|
+ this.actions.push( { action: 'splineThru', args: args } );
|
|
|
|
|
|
-};
|
|
|
+ },
|
|
|
|
|
|
-// FUTURE: Change the API or follow canvas API?
|
|
|
+ arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
-THREE.Path.prototype.arc = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
+ this.absarc( aX + x0, aY + y0, aRadius,
|
|
|
+ aStartAngle, aEndAngle, aClockwise );
|
|
|
|
|
|
- this.absarc( aX + x0, aY + y0, aRadius,
|
|
|
- aStartAngle, aEndAngle, aClockwise );
|
|
|
+ },
|
|
|
|
|
|
- };
|
|
|
+ absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
- THREE.Path.prototype.absarc = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
|
|
+ this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
|
|
|
|
|
|
- this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
|
|
|
+ },
|
|
|
|
|
|
- };
|
|
|
+ ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
|
|
|
|
|
|
-THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
+ this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
|
|
|
|
|
|
- this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
|
|
|
+ },
|
|
|
|
|
|
- };
|
|
|
+ absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
|
|
|
|
|
|
+ var args = [
|
|
|
+ aX, aY,
|
|
|
+ xRadius, yRadius,
|
|
|
+ aStartAngle, aEndAngle,
|
|
|
+ aClockwise,
|
|
|
+ aRotation || 0 // aRotation is optional.
|
|
|
+ ];
|
|
|
|
|
|
-THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) {
|
|
|
+ var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- var args = [
|
|
|
- aX, aY,
|
|
|
- xRadius, yRadius,
|
|
|
- aStartAngle, aEndAngle,
|
|
|
- aClockwise,
|
|
|
- aRotation || 0 // aRotation is optional.
|
|
|
- ];
|
|
|
+ var lastPoint = curve.getPoint( 1 );
|
|
|
+ args.push( lastPoint.x );
|
|
|
+ args.push( lastPoint.y );
|
|
|
|
|
|
- var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation );
|
|
|
- this.curves.push( curve );
|
|
|
+ this.actions.push( { action: 'ellipse', args: args } );
|
|
|
|
|
|
- var lastPoint = curve.getPoint( 1 );
|
|
|
- args.push( lastPoint.x );
|
|
|
- args.push( lastPoint.y );
|
|
|
+ },
|
|
|
|
|
|
- this.actions.push( { action: 'ellipse', args: args } );
|
|
|
+ getSpacedPoints: function ( divisions ) {
|
|
|
|
|
|
- };
|
|
|
+ if ( ! divisions ) divisions = 40;
|
|
|
|
|
|
-THREE.Path.prototype.getSpacedPoints = function ( divisions ) {
|
|
|
+ var points = [];
|
|
|
|
|
|
- if ( ! divisions ) divisions = 40;
|
|
|
+ for ( var i = 0; i < divisions; i ++ ) {
|
|
|
|
|
|
- var points = [];
|
|
|
+ points.push( this.getPoint( i / divisions ) );
|
|
|
|
|
|
- for ( var i = 0; i < divisions; i ++ ) {
|
|
|
+ //if ( !this.getPoint( i / divisions ) ) throw "DIE";
|
|
|
|
|
|
- points.push( this.getPoint( i / divisions ) );
|
|
|
+ }
|
|
|
|
|
|
- //if ( !this.getPoint( i / divisions ) ) throw "DIE";
|
|
|
+ if ( this.autoClose ) {
|
|
|
|
|
|
- }
|
|
|
+ points.push( points[ 0 ] );
|
|
|
|
|
|
- if ( this.autoClose ) {
|
|
|
+ }
|
|
|
|
|
|
- points.push( points[ 0 ] );
|
|
|
+ return points;
|
|
|
|
|
|
- }
|
|
|
+ },
|
|
|
|
|
|
- return points;
|
|
|
+ getPoints: function ( divisions ) {
|
|
|
|
|
|
-};
|
|
|
+ divisions = divisions || 12;
|
|
|
|
|
|
-/* Return an array of vectors based on contour of the path */
|
|
|
+ var b2 = THREE.ShapeUtils.b2;
|
|
|
+ var b3 = THREE.ShapeUtils.b3;
|
|
|
|
|
|
-THREE.Path.prototype.getPoints = function( divisions ) {
|
|
|
+ var points = [];
|
|
|
|
|
|
- divisions = divisions || 12;
|
|
|
+ var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
|
|
|
+ laste, tx, ty;
|
|
|
|
|
|
- var b2 = THREE.ShapeUtils.b2;
|
|
|
- var b3 = THREE.ShapeUtils.b3;
|
|
|
+ for ( var i = 0, l = this.actions.length; i < l; i ++ ) {
|
|
|
|
|
|
- var points = [];
|
|
|
+ var item = this.actions[ i ];
|
|
|
|
|
|
- var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
|
|
|
- laste, tx, ty;
|
|
|
+ var action = item.action;
|
|
|
+ var args = item.args;
|
|
|
|
|
|
- for ( var i = 0, l = this.actions.length; i < l; i ++ ) {
|
|
|
+ switch ( action ) {
|
|
|
|
|
|
- var item = this.actions[ i ];
|
|
|
+ case 'moveTo':
|
|
|
|
|
|
- var action = item.action;
|
|
|
- var args = item.args;
|
|
|
+ points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
|
|
|
- switch ( action ) {
|
|
|
+ break;
|
|
|
|
|
|
- case 'moveTo':
|
|
|
+ case 'lineTo':
|
|
|
|
|
|
- points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
+ points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
|
|
|
- break;
|
|
|
+ break;
|
|
|
|
|
|
- case 'lineTo':
|
|
|
+ case 'quadraticCurveTo':
|
|
|
|
|
|
- points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
+ cpx = args[ 2 ];
|
|
|
+ cpy = args[ 3 ];
|
|
|
|
|
|
- break;
|
|
|
+ cpx1 = args[ 0 ];
|
|
|
+ cpy1 = args[ 1 ];
|
|
|
|
|
|
- case 'quadraticCurveTo':
|
|
|
+ if ( points.length > 0 ) {
|
|
|
|
|
|
- cpx = args[ 2 ];
|
|
|
- cpy = args[ 3 ];
|
|
|
+ laste = points[ points.length - 1 ];
|
|
|
|
|
|
- cpx1 = args[ 0 ];
|
|
|
- cpy1 = args[ 1 ];
|
|
|
+ cpx0 = laste.x;
|
|
|
+ cpy0 = laste.y;
|
|
|
|
|
|
- if ( points.length > 0 ) {
|
|
|
+ } else {
|
|
|
|
|
|
- laste = points[ points.length - 1 ];
|
|
|
+ laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
- cpx0 = laste.x;
|
|
|
- cpy0 = laste.y;
|
|
|
+ cpx0 = laste[ laste.length - 2 ];
|
|
|
+ cpy0 = laste[ laste.length - 1 ];
|
|
|
|
|
|
- } else {
|
|
|
+ }
|
|
|
|
|
|
- laste = this.actions[ i - 1 ].args;
|
|
|
+ for ( var j = 1; j <= divisions; j ++ ) {
|
|
|
|
|
|
- cpx0 = laste[ laste.length - 2 ];
|
|
|
- cpy0 = laste[ laste.length - 1 ];
|
|
|
+ var t = j / divisions;
|
|
|
|
|
|
- }
|
|
|
+ tx = b2( t, cpx0, cpx1, cpx );
|
|
|
+ ty = b2( t, cpy0, cpy1, cpy );
|
|
|
|
|
|
- for ( var j = 1; j <= divisions; j ++ ) {
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
- var t = j / divisions;
|
|
|
+ }
|
|
|
|
|
|
- tx = b2( t, cpx0, cpx1, cpx );
|
|
|
- ty = b2( t, cpy0, cpy1, cpy );
|
|
|
+ break;
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
+ case 'bezierCurveTo':
|
|
|
|
|
|
- }
|
|
|
+ cpx = args[ 4 ];
|
|
|
+ cpy = args[ 5 ];
|
|
|
|
|
|
- break;
|
|
|
+ cpx1 = args[ 0 ];
|
|
|
+ cpy1 = args[ 1 ];
|
|
|
|
|
|
- case 'bezierCurveTo':
|
|
|
+ cpx2 = args[ 2 ];
|
|
|
+ cpy2 = args[ 3 ];
|
|
|
|
|
|
- cpx = args[ 4 ];
|
|
|
- cpy = args[ 5 ];
|
|
|
+ if ( points.length > 0 ) {
|
|
|
|
|
|
- cpx1 = args[ 0 ];
|
|
|
- cpy1 = args[ 1 ];
|
|
|
+ laste = points[ points.length - 1 ];
|
|
|
|
|
|
- cpx2 = args[ 2 ];
|
|
|
- cpy2 = args[ 3 ];
|
|
|
+ cpx0 = laste.x;
|
|
|
+ cpy0 = laste.y;
|
|
|
|
|
|
- if ( points.length > 0 ) {
|
|
|
+ } else {
|
|
|
|
|
|
- laste = points[ points.length - 1 ];
|
|
|
+ laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
- cpx0 = laste.x;
|
|
|
- cpy0 = laste.y;
|
|
|
+ cpx0 = laste[ laste.length - 2 ];
|
|
|
+ cpy0 = laste[ laste.length - 1 ];
|
|
|
|
|
|
- } else {
|
|
|
+ }
|
|
|
|
|
|
- laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
- cpx0 = laste[ laste.length - 2 ];
|
|
|
- cpy0 = laste[ laste.length - 1 ];
|
|
|
+ for ( var j = 1; j <= divisions; j ++ ) {
|
|
|
|
|
|
- }
|
|
|
+ var t = j / divisions;
|
|
|
|
|
|
+ tx = b3( t, cpx0, cpx1, cpx2, cpx );
|
|
|
+ ty = b3( t, cpy0, cpy1, cpy2, cpy );
|
|
|
|
|
|
- for ( var j = 1; j <= divisions; j ++ ) {
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
- var t = j / divisions;
|
|
|
+ }
|
|
|
|
|
|
- tx = b3( t, cpx0, cpx1, cpx2, cpx );
|
|
|
- ty = b3( t, cpy0, cpy1, cpy2, cpy );
|
|
|
+ break;
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
+ case 'splineThru':
|
|
|
|
|
|
- }
|
|
|
+ laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
- break;
|
|
|
+ var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
|
|
|
+ var spts = [ last ];
|
|
|
|
|
|
- case 'splineThru':
|
|
|
+ var n = divisions * args[ 0 ].length;
|
|
|
|
|
|
- laste = this.actions[ i - 1 ].args;
|
|
|
+ spts = spts.concat( args[ 0 ] );
|
|
|
|
|
|
- var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
|
|
|
- var spts = [ last ];
|
|
|
+ var spline = new THREE.SplineCurve( spts );
|
|
|
|
|
|
- var n = divisions * args[ 0 ].length;
|
|
|
+ for ( var j = 1; j <= n; j ++ ) {
|
|
|
|
|
|
- spts = spts.concat( args[ 0 ] );
|
|
|
+ points.push( spline.getPointAt( j / n ) );
|
|
|
|
|
|
- var spline = new THREE.SplineCurve( spts );
|
|
|
+ }
|
|
|
|
|
|
- for ( var j = 1; j <= n; j ++ ) {
|
|
|
+ break;
|
|
|
|
|
|
- points.push( spline.getPointAt( j / n ) );
|
|
|
+ case 'arc':
|
|
|
|
|
|
- }
|
|
|
+ var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
+ aRadius = args[ 2 ],
|
|
|
+ aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
|
|
|
+ aClockwise = !! args[ 5 ];
|
|
|
|
|
|
- break;
|
|
|
+ var deltaAngle = aEndAngle - aStartAngle;
|
|
|
+ var angle;
|
|
|
+ var tdivisions = divisions * 2;
|
|
|
|
|
|
- case 'arc':
|
|
|
+ for ( var j = 1; j <= tdivisions; j ++ ) {
|
|
|
|
|
|
- var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
- aRadius = args[ 2 ],
|
|
|
- aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
|
|
|
- aClockwise = !! args[ 5 ];
|
|
|
+ var t = j / tdivisions;
|
|
|
|
|
|
- var deltaAngle = aEndAngle - aStartAngle;
|
|
|
- var angle;
|
|
|
- var tdivisions = divisions * 2;
|
|
|
+ if ( ! aClockwise ) {
|
|
|
|
|
|
- for ( var j = 1; j <= tdivisions; j ++ ) {
|
|
|
+ t = 1 - t;
|
|
|
|
|
|
- var t = j / tdivisions;
|
|
|
+ }
|
|
|
|
|
|
- if ( ! aClockwise ) {
|
|
|
+ angle = aStartAngle + t * deltaAngle;
|
|
|
|
|
|
- t = 1 - t;
|
|
|
+ tx = aX + aRadius * Math.cos( angle );
|
|
|
+ ty = aY + aRadius * Math.sin( angle );
|
|
|
|
|
|
- }
|
|
|
+ //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
|
|
|
- angle = aStartAngle + t * deltaAngle;
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
- tx = aX + aRadius * Math.cos( angle );
|
|
|
- ty = aY + aRadius * Math.sin( angle );
|
|
|
+ }
|
|
|
|
|
|
- //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
+ //console.log(points);
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
+ case 'ellipse':
|
|
|
|
|
|
- //console.log(points);
|
|
|
+ var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
+ xRadius = args[ 2 ],
|
|
|
+ yRadius = args[ 3 ],
|
|
|
+ aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
|
|
|
+ aClockwise = !! args[ 6 ],
|
|
|
+ aRotation = args[ 7 ];
|
|
|
|
|
|
- break;
|
|
|
|
|
|
- case 'ellipse':
|
|
|
+ var deltaAngle = aEndAngle - aStartAngle;
|
|
|
+ var angle;
|
|
|
+ var tdivisions = divisions * 2;
|
|
|
|
|
|
- var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
- xRadius = args[ 2 ],
|
|
|
- yRadius = args[ 3 ],
|
|
|
- aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
|
|
|
- aClockwise = !! args[ 6 ],
|
|
|
- aRotation = args[ 7 ];
|
|
|
+ var cos, sin;
|
|
|
+ if ( aRotation !== 0 ) {
|
|
|
|
|
|
+ cos = Math.cos( aRotation );
|
|
|
+ sin = Math.sin( aRotation );
|
|
|
|
|
|
- var deltaAngle = aEndAngle - aStartAngle;
|
|
|
- var angle;
|
|
|
- var tdivisions = divisions * 2;
|
|
|
+ }
|
|
|
|
|
|
- var cos, sin;
|
|
|
- if ( aRotation !== 0 ) {
|
|
|
+ for ( var j = 1; j <= tdivisions; j ++ ) {
|
|
|
|
|
|
- cos = Math.cos( aRotation );
|
|
|
- sin = Math.sin( aRotation );
|
|
|
+ var t = j / tdivisions;
|
|
|
|
|
|
- }
|
|
|
+ if ( ! aClockwise ) {
|
|
|
|
|
|
- for ( var j = 1; j <= tdivisions; j ++ ) {
|
|
|
+ t = 1 - t;
|
|
|
|
|
|
- var t = j / tdivisions;
|
|
|
+ }
|
|
|
|
|
|
- if ( ! aClockwise ) {
|
|
|
+ angle = aStartAngle + t * deltaAngle;
|
|
|
|
|
|
- t = 1 - t;
|
|
|
+ tx = aX + xRadius * Math.cos( angle );
|
|
|
+ ty = aY + yRadius * Math.sin( angle );
|
|
|
|
|
|
- }
|
|
|
+ if ( aRotation !== 0 ) {
|
|
|
|
|
|
- angle = aStartAngle + t * deltaAngle;
|
|
|
+ var x = tx, y = ty;
|
|
|
|
|
|
- tx = aX + xRadius * Math.cos( angle );
|
|
|
- ty = aY + yRadius * Math.sin( angle );
|
|
|
+ // Rotate the point about the center of the ellipse.
|
|
|
+ tx = ( x - aX ) * cos - ( y - aY ) * sin + aX;
|
|
|
+ ty = ( x - aX ) * sin + ( y - aY ) * cos + aY;
|
|
|
|
|
|
- if ( aRotation !== 0 ) {
|
|
|
+ }
|
|
|
|
|
|
- var x = tx, y = ty;
|
|
|
+ //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
|
|
|
- // Rotate the point about the center of the ellipse.
|
|
|
- tx = ( x - aX ) * cos - ( y - aY ) * sin + aX;
|
|
|
- ty = ( x - aX ) * sin + ( y - aY ) * cos + aY;
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
- //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
-
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
+ //console.log(points);
|
|
|
|
|
|
- }
|
|
|
-
|
|
|
- //console.log(points);
|
|
|
-
|
|
|
- break;
|
|
|
+ break;
|
|
|
|
|
|
- } // end switch
|
|
|
+ } // end switch
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
|
- // Normalize to remove the closing point by default.
|
|
|
- var lastPoint = points[ points.length - 1 ];
|
|
|
- if ( Math.abs( lastPoint.x - points[ 0 ].x ) < Number.EPSILON &&
|
|
|
- Math.abs( lastPoint.y - points[ 0 ].y ) < Number.EPSILON )
|
|
|
- points.splice( points.length - 1, 1 );
|
|
|
+ // Normalize to remove the closing point by default.
|
|
|
+ var lastPoint = points[ points.length - 1 ];
|
|
|
+ if ( Math.abs( lastPoint.x - points[ 0 ].x ) < Number.EPSILON &&
|
|
|
+ Math.abs( lastPoint.y - points[ 0 ].y ) < Number.EPSILON )
|
|
|
+ points.splice( points.length - 1, 1 );
|
|
|
|
|
|
- if ( this.autoClose ) {
|
|
|
+ if ( this.autoClose ) {
|
|
|
|
|
|
- points.push( points[ 0 ] );
|
|
|
+ points.push( points[ 0 ] );
|
|
|
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
- return points;
|
|
|
+ return points;
|
|
|
|
|
|
-};
|
|
|
+ },
|
|
|
|
|
|
-//
|
|
|
-// Breaks path into shapes
|
|
|
-//
|
|
|
-// Assumptions (if parameter isCCW==true the opposite holds):
|
|
|
-// - solid shapes are defined clockwise (CW)
|
|
|
-// - holes are defined counterclockwise (CCW)
|
|
|
-//
|
|
|
-// If parameter noHoles==true:
|
|
|
-// - all subPaths are regarded as solid shapes
|
|
|
-// - definition order CW/CCW has no relevance
|
|
|
-//
|
|
|
+ toShapes: function ( isCCW, noHoles ) {
|
|
|
|
|
|
-THREE.Path.prototype.toShapes = function( isCCW, noHoles ) {
|
|
|
+ function extractSubpaths( inActions ) {
|
|
|
|
|
|
- function extractSubpaths( inActions ) {
|
|
|
+ var subPaths = [], lastPath = new THREE.Path();
|
|
|
|
|
|
- var subPaths = [], lastPath = new THREE.Path();
|
|
|
+ for ( var i = 0, l = inActions.length; i < l; i ++ ) {
|
|
|
|
|
|
- for ( var i = 0, l = inActions.length; i < l; i ++ ) {
|
|
|
+ var item = inActions[ i ];
|
|
|
|
|
|
- var item = inActions[ i ];
|
|
|
+ var args = item.args;
|
|
|
+ var action = item.action;
|
|
|
|
|
|
- var args = item.args;
|
|
|
- var action = item.action;
|
|
|
+ if ( action === 'moveTo' ) {
|
|
|
|
|
|
- if ( action === 'moveTo' ) {
|
|
|
+ if ( lastPath.actions.length !== 0 ) {
|
|
|
|
|
|
- if ( lastPath.actions.length !== 0 ) {
|
|
|
+ subPaths.push( lastPath );
|
|
|
+ lastPath = new THREE.Path();
|
|
|
|
|
|
- subPaths.push( lastPath );
|
|
|
- lastPath = new THREE.Path();
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
+ lastPath[ action ].apply( lastPath, args );
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- lastPath[ action ].apply( lastPath, args );
|
|
|
+ if ( lastPath.actions.length !== 0 ) {
|
|
|
|
|
|
- }
|
|
|
+ subPaths.push( lastPath );
|
|
|
|
|
|
- if ( lastPath.actions.length !== 0 ) {
|
|
|
+ }
|
|
|
+
|
|
|
+ // console.log(subPaths);
|
|
|
|
|
|
- subPaths.push( lastPath );
|
|
|
+ return subPaths;
|
|
|
|
|
|
}
|
|
|
|
|
|
- // console.log(subPaths);
|
|
|
+ function toShapesNoHoles( inSubpaths ) {
|
|
|
|
|
|
- return subPaths;
|
|
|
+ var shapes = [];
|
|
|
|
|
|
- }
|
|
|
+ for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
|
|
|
|
|
|
- function toShapesNoHoles( inSubpaths ) {
|
|
|
+ var tmpPath = inSubpaths[ i ];
|
|
|
|
|
|
- var shapes = [];
|
|
|
+ var tmpShape = new THREE.Shape();
|
|
|
+ tmpShape.actions = tmpPath.actions;
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
|
|
|
- for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) {
|
|
|
+ shapes.push( tmpShape );
|
|
|
|
|
|
- var tmpPath = inSubpaths[ i ];
|
|
|
+ }
|
|
|
|
|
|
- var tmpShape = new THREE.Shape();
|
|
|
- tmpShape.actions = tmpPath.actions;
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
+ //console.log("shape", shapes);
|
|
|
|
|
|
- shapes.push( tmpShape );
|
|
|
+ return shapes;
|
|
|
|
|
|
}
|
|
|
|
|
|
- //console.log("shape", shapes);
|
|
|
+ function isPointInsidePolygon( inPt, inPolygon ) {
|
|
|
|
|
|
- return shapes;
|
|
|
+ var polyLen = inPolygon.length;
|
|
|
|
|
|
- }
|
|
|
+ // inPt on polygon contour => immediate success or
|
|
|
+ // toggling of inside/outside at every single! intersection point of an edge
|
|
|
+ // with the horizontal line through inPt, left of inPt
|
|
|
+ // not counting lowerY endpoints of edges and whole edges on that line
|
|
|
+ var inside = false;
|
|
|
+ for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
|
|
|
|
|
|
- function isPointInsidePolygon( inPt, inPolygon ) {
|
|
|
+ var edgeLowPt = inPolygon[ p ];
|
|
|
+ var edgeHighPt = inPolygon[ q ];
|
|
|
|
|
|
- var polyLen = inPolygon.length;
|
|
|
+ var edgeDx = edgeHighPt.x - edgeLowPt.x;
|
|
|
+ var edgeDy = edgeHighPt.y - edgeLowPt.y;
|
|
|
|
|
|
- // inPt on polygon contour => immediate success or
|
|
|
- // toggling of inside/outside at every single! intersection point of an edge
|
|
|
- // with the horizontal line through inPt, left of inPt
|
|
|
- // not counting lowerY endpoints of edges and whole edges on that line
|
|
|
- var inside = false;
|
|
|
- for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
|
|
|
+ if ( Math.abs( edgeDy ) > Number.EPSILON ) {
|
|
|
|
|
|
- var edgeLowPt = inPolygon[ p ];
|
|
|
- var edgeHighPt = inPolygon[ q ];
|
|
|
+ // not parallel
|
|
|
+ if ( edgeDy < 0 ) {
|
|
|
|
|
|
- var edgeDx = edgeHighPt.x - edgeLowPt.x;
|
|
|
- var edgeDy = edgeHighPt.y - edgeLowPt.y;
|
|
|
+ edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
|
|
|
+ edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
|
|
|
|
|
|
- if ( Math.abs( edgeDy ) > Number.EPSILON ) {
|
|
|
+ }
|
|
|
+ if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
|
|
|
|
|
|
- // not parallel
|
|
|
- if ( edgeDy < 0 ) {
|
|
|
+ if ( inPt.y === edgeLowPt.y ) {
|
|
|
|
|
|
- edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
|
|
|
- edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
|
|
|
+ if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
|
|
|
+ // continue; // no intersection or edgeLowPt => doesn't count !!!
|
|
|
|
|
|
- }
|
|
|
- if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
|
|
|
+ } else {
|
|
|
|
|
|
- if ( inPt.y === edgeLowPt.y ) {
|
|
|
+ var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
|
|
|
+ if ( perpEdge === 0 ) return true; // inPt is on contour ?
|
|
|
+ if ( perpEdge < 0 ) continue;
|
|
|
+ inside = ! inside; // true intersection left of inPt
|
|
|
|
|
|
- if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ?
|
|
|
- // continue; // no intersection or edgeLowPt => doesn't count !!!
|
|
|
+ }
|
|
|
|
|
|
} else {
|
|
|
|
|
|
- var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y );
|
|
|
- if ( perpEdge === 0 ) return true; // inPt is on contour ?
|
|
|
- if ( perpEdge < 0 ) continue;
|
|
|
- inside = ! inside; // true intersection left of inPt
|
|
|
+ // parallel or collinear
|
|
|
+ if ( inPt.y !== edgeLowPt.y ) continue; // parallel
|
|
|
+ // edge lies on the same horizontal line as inPt
|
|
|
+ if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
|
|
|
+ ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
|
|
|
+ // continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
- } else {
|
|
|
-
|
|
|
- // parallel or collinear
|
|
|
- if ( inPt.y !== edgeLowPt.y ) continue; // parallel
|
|
|
- // edge lies on the same horizontal line as inPt
|
|
|
- if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
|
|
|
- ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
|
|
|
- // continue;
|
|
|
-
|
|
|
}
|
|
|
|
|
|
+ return inside;
|
|
|
+
|
|
|
}
|
|
|
|
|
|
- return inside;
|
|
|
+ var isClockWise = THREE.ShapeUtils.isClockWise;
|
|
|
|
|
|
- }
|
|
|
+ var subPaths = extractSubpaths( this.actions );
|
|
|
+ if ( subPaths.length === 0 ) return [];
|
|
|
|
|
|
- var isClockWise = THREE.ShapeUtils.isClockWise;
|
|
|
+ if ( noHoles === true ) return toShapesNoHoles( subPaths );
|
|
|
|
|
|
- var subPaths = extractSubpaths( this.actions );
|
|
|
- if ( subPaths.length === 0 ) return [];
|
|
|
|
|
|
- if ( noHoles === true ) return toShapesNoHoles( subPaths );
|
|
|
+ var solid, tmpPath, tmpShape, shapes = [];
|
|
|
|
|
|
+ if ( subPaths.length === 1 ) {
|
|
|
|
|
|
- var solid, tmpPath, tmpShape, shapes = [];
|
|
|
-
|
|
|
- if ( subPaths.length === 1 ) {
|
|
|
+ tmpPath = subPaths[ 0 ];
|
|
|
+ tmpShape = new THREE.Shape();
|
|
|
+ tmpShape.actions = tmpPath.actions;
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
+ shapes.push( tmpShape );
|
|
|
+ return shapes;
|
|
|
|
|
|
- tmpPath = subPaths[ 0 ];
|
|
|
- tmpShape = new THREE.Shape();
|
|
|
- tmpShape.actions = tmpPath.actions;
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
- shapes.push( tmpShape );
|
|
|
- return shapes;
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
|
|
|
+ holesFirst = isCCW ? ! holesFirst : holesFirst;
|
|
|
|
|
|
- var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() );
|
|
|
- holesFirst = isCCW ? ! holesFirst : holesFirst;
|
|
|
+ // console.log("Holes first", holesFirst);
|
|
|
|
|
|
- // console.log("Holes first", holesFirst);
|
|
|
+ var betterShapeHoles = [];
|
|
|
+ var newShapes = [];
|
|
|
+ var newShapeHoles = [];
|
|
|
+ var mainIdx = 0;
|
|
|
+ var tmpPoints;
|
|
|
|
|
|
- var betterShapeHoles = [];
|
|
|
- var newShapes = [];
|
|
|
- var newShapeHoles = [];
|
|
|
- var mainIdx = 0;
|
|
|
- var tmpPoints;
|
|
|
+ newShapes[ mainIdx ] = undefined;
|
|
|
+ newShapeHoles[ mainIdx ] = [];
|
|
|
|
|
|
- newShapes[ mainIdx ] = undefined;
|
|
|
- newShapeHoles[ mainIdx ] = [];
|
|
|
+ for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
|
|
|
|
|
|
- for ( var i = 0, l = subPaths.length; i < l; i ++ ) {
|
|
|
+ tmpPath = subPaths[ i ];
|
|
|
+ tmpPoints = tmpPath.getPoints();
|
|
|
+ solid = isClockWise( tmpPoints );
|
|
|
+ solid = isCCW ? ! solid : solid;
|
|
|
|
|
|
- tmpPath = subPaths[ i ];
|
|
|
- tmpPoints = tmpPath.getPoints();
|
|
|
- solid = isClockWise( tmpPoints );
|
|
|
- solid = isCCW ? ! solid : solid;
|
|
|
+ if ( solid ) {
|
|
|
|
|
|
- if ( solid ) {
|
|
|
+ if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
|
|
|
|
|
|
- if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++;
|
|
|
+ newShapes[ mainIdx ] = { s: new THREE.Shape(), p: tmpPoints };
|
|
|
+ newShapes[ mainIdx ].s.actions = tmpPath.actions;
|
|
|
+ newShapes[ mainIdx ].s.curves = tmpPath.curves;
|
|
|
|
|
|
- newShapes[ mainIdx ] = { s: new THREE.Shape(), p: tmpPoints };
|
|
|
- newShapes[ mainIdx ].s.actions = tmpPath.actions;
|
|
|
- newShapes[ mainIdx ].s.curves = tmpPath.curves;
|
|
|
+ if ( holesFirst ) mainIdx ++;
|
|
|
+ newShapeHoles[ mainIdx ] = [];
|
|
|
|
|
|
- if ( holesFirst ) mainIdx ++;
|
|
|
- newShapeHoles[ mainIdx ] = [];
|
|
|
+ //console.log('cw', i);
|
|
|
|
|
|
- //console.log('cw', i);
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
|
|
|
|
|
|
- newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } );
|
|
|
+ //console.log('ccw', i);
|
|
|
|
|
|
- //console.log('ccw', i);
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ // only Holes? -> probably all Shapes with wrong orientation
|
|
|
+ if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
|
|
|
|
|
|
- // only Holes? -> probably all Shapes with wrong orientation
|
|
|
- if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths );
|
|
|
|
|
|
+ if ( newShapes.length > 1 ) {
|
|
|
|
|
|
- if ( newShapes.length > 1 ) {
|
|
|
+ var ambiguous = false;
|
|
|
+ var toChange = [];
|
|
|
|
|
|
- var ambiguous = false;
|
|
|
- var toChange = [];
|
|
|
+ for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
|
|
|
|
|
|
- for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
|
|
|
+ betterShapeHoles[ sIdx ] = [];
|
|
|
|
|
|
- betterShapeHoles[ sIdx ] = [];
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
|
|
|
|
|
|
- for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
|
|
|
+ var sho = newShapeHoles[ sIdx ];
|
|
|
|
|
|
- var sho = newShapeHoles[ sIdx ];
|
|
|
+ for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
|
|
|
|
|
|
- for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
|
|
|
+ var ho = sho[ hIdx ];
|
|
|
+ var hole_unassigned = true;
|
|
|
|
|
|
- var ho = sho[ hIdx ];
|
|
|
- var hole_unassigned = true;
|
|
|
+ for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
|
|
|
|
|
|
- for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) {
|
|
|
+ if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
|
|
|
|
|
|
- if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) {
|
|
|
+ if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
|
|
|
+ if ( hole_unassigned ) {
|
|
|
|
|
|
- if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } );
|
|
|
- if ( hole_unassigned ) {
|
|
|
+ hole_unassigned = false;
|
|
|
+ betterShapeHoles[ s2Idx ].push( ho );
|
|
|
|
|
|
- hole_unassigned = false;
|
|
|
- betterShapeHoles[ s2Idx ].push( ho );
|
|
|
+ } else {
|
|
|
|
|
|
- } else {
|
|
|
+ ambiguous = true;
|
|
|
|
|
|
- ambiguous = true;
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+ if ( hole_unassigned ) {
|
|
|
|
|
|
- }
|
|
|
- if ( hole_unassigned ) {
|
|
|
+ betterShapeHoles[ sIdx ].push( ho );
|
|
|
|
|
|
- betterShapeHoles[ sIdx ].push( ho );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+ // console.log("ambiguous: ", ambiguous);
|
|
|
+ if ( toChange.length > 0 ) {
|
|
|
|
|
|
- }
|
|
|
- // console.log("ambiguous: ", ambiguous);
|
|
|
- if ( toChange.length > 0 ) {
|
|
|
+ // console.log("to change: ", toChange);
|
|
|
+ if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
|
|
|
|
|
|
- // console.log("to change: ", toChange);
|
|
|
- if ( ! ambiguous ) newShapeHoles = betterShapeHoles;
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ var tmpHoles;
|
|
|
|
|
|
- var tmpHoles;
|
|
|
+ for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
|
|
|
|
|
|
- for ( var i = 0, il = newShapes.length; i < il; i ++ ) {
|
|
|
+ tmpShape = newShapes[ i ].s;
|
|
|
+ shapes.push( tmpShape );
|
|
|
+ tmpHoles = newShapeHoles[ i ];
|
|
|
|
|
|
- tmpShape = newShapes[ i ].s;
|
|
|
- shapes.push( tmpShape );
|
|
|
- tmpHoles = newShapeHoles[ i ];
|
|
|
+ for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
|
|
|
|
|
|
- for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) {
|
|
|
+ tmpShape.holes.push( tmpHoles[ j ].h );
|
|
|
|
|
|
- tmpShape.holes.push( tmpHoles[ j ].h );
|
|
|
+ }
|
|
|
|
|
|
}
|
|
|
|
|
|
- }
|
|
|
+ //console.log("shape", shapes);
|
|
|
|
|
|
- //console.log("shape", shapes);
|
|
|
+ return shapes;
|
|
|
|
|
|
- return shapes;
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
+} );
|