Browse Source

*Path: Implemented Object.assign(). See #8838.

Mr.doob 9 years ago
parent
commit
6b53488f03
4 changed files with 503 additions and 533 deletions
  1. 84 96
      src/extras/core/CurvePath.js
  2. 2 4
      src/extras/core/Font.js
  3. 389 405
      src/extras/core/Path.js
  4. 28 28
      src/extras/core/Shape.js

+ 84 - 96
src/extras/core/CurvePath.js

@@ -16,161 +16,149 @@ THREE.CurvePath = function () {
 
 };
 
-THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
-THREE.CurvePath.prototype.constructor = THREE.CurvePath;
+THREE.CurvePath.prototype = Object.assign( Object.create( THREE.Curve.prototype ), {
 
-THREE.CurvePath.prototype.add = function ( curve ) {
+	constructor: THREE.CurvePath,
 
-	this.curves.push( curve );
+	add: function ( curve ) {
 
-};
-
-/*
-THREE.CurvePath.prototype.checkConnection = function() {
-	// TODO
-	// If the ending of curve is not connected to the starting
-	// or the next curve, then, this is not a real path
-};
-*/
+		this.curves.push( curve );
 
-THREE.CurvePath.prototype.closePath = function() {
+	},
 
-	// TODO Test
-	// and verify for vector3 (needs to implement equals)
-	// Add a line curve if start and end of lines are not connected
-	var startPoint = this.curves[ 0 ].getPoint( 0 );
-	var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
+	closePath: function () {
 
-	if ( ! startPoint.equals( endPoint ) ) {
+		// TODO Test
+		// and verify for vector3 (needs to implement equals)
+		// Add a line curve if start and end of lines are not connected
+		var startPoint = this.curves[ 0 ].getPoint( 0 );
+		var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 );
 
-		this.curves.push( new THREE.LineCurve( endPoint, startPoint ) );
+		if ( ! startPoint.equals( endPoint ) ) {
 
-	}
+			this.curves.push( new THREE.LineCurve( endPoint, startPoint ) );
 
-};
+		}
 
-// To get accurate point with reference to
-// entire path distance at time t,
-// following has to be done:
+	},
 
-// 1. Length of each sub path have to be known
-// 2. Locate and identify type of curve
-// 3. Get t for the curve
-// 4. Return curve.getPointAt(t')
+	// To get accurate point with reference to
+	// entire path distance at time t,
+	// following has to be done:
 
-THREE.CurvePath.prototype.getPoint = function( t ) {
+	// 1. Length of each sub path have to be known
+	// 2. Locate and identify type of curve
+	// 3. Get t for the curve
+	// 4. Return curve.getPointAt(t')
 
-	var d = t * this.getLength();
-	var curveLengths = this.getCurveLengths();
-	var i = 0;
+	getPoint: function ( t ) {
 
-	// To think about boundaries points.
+		var d = t * this.getLength();
+		var curveLengths = this.getCurveLengths();
+		var i = 0;
 
-	while ( i < curveLengths.length ) {
+		// To think about boundaries points.
 
-		if ( curveLengths[ i ] >= d ) {
+		while ( i < curveLengths.length ) {
 
-			var diff = curveLengths[ i ] - d;
-			var curve = this.curves[ i ];
+			if ( curveLengths[ i ] >= d ) {
 
-			var u = 1 - diff / curve.getLength();
+				var diff = curveLengths[ i ] - d;
+				var curve = this.curves[ i ];
 
-			return curve.getPointAt( u );
+				var u = 1 - diff / curve.getLength();
 
-		}
+				return curve.getPointAt( u );
 
-		i ++;
+			}
 
-	}
+			i ++;
 
-	return null;
+		}
 
-	// loop where sum != 0, sum > d , sum+1 <d
+		return null;
 
-};
+		// loop where sum != 0, sum > d , sum+1 <d
 
-/*
-THREE.CurvePath.prototype.getTangent = function( t ) {
-};
-*/
+	},
 
-// We cannot use the default THREE.Curve getPoint() with getLength() because in
-// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
-// getPoint() depends on getLength
+	// We cannot use the default THREE.Curve getPoint() with getLength() because in
+	// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
+	// getPoint() depends on getLength
 
-THREE.CurvePath.prototype.getLength = function() {
+	getLength: function () {
 
-	var lens = this.getCurveLengths();
-	return lens[ lens.length - 1 ];
+		var lens = this.getCurveLengths();
+		return lens[ lens.length - 1 ];
 
-};
+	},
 
-// Compute lengths and cache them
-// We cannot overwrite getLengths() because UtoT mapping uses it.
+	// Compute lengths and cache them
+	// We cannot overwrite getLengths() because UtoT mapping uses it.
 
-THREE.CurvePath.prototype.getCurveLengths = function() {
+	getCurveLengths: function () {
 
-	// We use cache values if curves and cache array are same length
+		// We use cache values if curves and cache array are same length
 
-	if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
+		if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
 
-		return this.cacheLengths;
+			return this.cacheLengths;
 
-	}
+		}
 
-	// Get length of sub-curve
-	// Push sums into cached array
+		// Get length of sub-curve
+		// Push sums into cached array
 
-	var lengths = [], sums = 0;
+		var lengths = [], sums = 0;
 
-	for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
+		for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
 
-		sums += this.curves[ i ].getLength();
-		lengths.push( sums );
+			sums += this.curves[ i ].getLength();
+			lengths.push( sums );
 
-	}
+		}
 
-	this.cacheLengths = lengths;
+		this.cacheLengths = lengths;
 
-	return lengths;
+		return lengths;
 
-};
+	},
 
+	/**************************************************************
+	 *	Create Geometries Helpers
+	 **************************************************************/
 
+	/// Generate geometry from path points (for Line or Points objects)
 
-/**************************************************************
- *	Create Geometries Helpers
- **************************************************************/
+	createPointsGeometry: function ( divisions ) {
 
-/// Generate geometry from path points (for Line or Points objects)
+		var pts = this.getPoints( divisions );
+		return this.createGeometry( pts );
 
-THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
+	},
 
-	var pts = this.getPoints( divisions );
-	return this.createGeometry( pts );
+	// Generate geometry from equidistant sampling along the path
 
-};
+	createSpacedPointsGeometry: function ( divisions ) {
 
-// Generate geometry from equidistant sampling along the path
+		var pts = this.getSpacedPoints( divisions );
+		return this.createGeometry( pts );
 
-THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
+	},
 
-	var pts = this.getSpacedPoints( divisions );
-	return this.createGeometry( pts );
+	createGeometry: function ( points ) {
 
-};
+		var geometry = new THREE.Geometry();
 
-THREE.CurvePath.prototype.createGeometry = function( points ) {
+		for ( var i = 0, l = points.length; i < l; i ++ ) {
 
-	var geometry = new THREE.Geometry();
+			var point = points[ i ];
+			geometry.vertices.push( new THREE.Vector3( point.x, point.y, point.z || 0 ) );
 
-	for ( var i = 0, l = points.length; i < l; i ++ ) {
+		}
 
-		var point = points[ i ];
-		geometry.vertices.push( new THREE.Vector3( point.x, point.y, point.z || 0 ) );
+		return geometry;
 
 	}
 
-	return geometry;
-
-};
+} );

+ 2 - 4
src/extras/core/Font.js

@@ -9,9 +9,7 @@ THREE.Font = function ( data ) {
 
 };
 
-THREE.Font.prototype = {
-
-	constructor: THREE.Font,
+Object.assign( THREE.Font.prototype, {
 
 	generateShapes: function ( text, size, divisions ) {
 
@@ -163,4 +161,4 @@ THREE.Font.prototype = {
 
 	}
 
-};
+} );

+ 389 - 405
src/extras/core/Path.js

@@ -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;
+	}
 
-};
+} );

+ 28 - 28
src/extras/core/Shape.js

@@ -17,57 +17,57 @@ THREE.Shape = function () {
 
 };
 
-THREE.Shape.prototype = Object.create( THREE.Path.prototype );
-THREE.Shape.prototype.constructor = THREE.Shape;
+THREE.Shape.prototype = Object.assign( Object.create( THREE.Path.prototype ), {
 
-// Convenience method to return ExtrudeGeometry
+	constructor: THREE.Shape,
 
-THREE.Shape.prototype.extrude = function ( options ) {
+	// Convenience method to return ExtrudeGeometry
 
-	return new THREE.ExtrudeGeometry( this, options );
+	extrude: function ( options ) {
 
-};
+		return new THREE.ExtrudeGeometry( this, options );
 
-// Convenience method to return ShapeGeometry
+	},
 
-THREE.Shape.prototype.makeGeometry = function ( options ) {
+	// Convenience method to return ShapeGeometry
 
-	return new THREE.ShapeGeometry( this, options );
+	makeGeometry: function ( options ) {
 
-};
+		return new THREE.ShapeGeometry( this, options );
 
-// Get points of holes
+	},
 
-THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
+	getPointsHoles: function ( divisions ) {
 
-	var holesPts = [];
+		var holesPts = [];
 
-	for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
+		for ( var i = 0, l = this.holes.length; i < l; i ++ ) {
 
-		holesPts[ i ] = this.holes[ i ].getPoints( divisions );
+			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
 
-	}
+		}
 
-	return holesPts;
+		return holesPts;
 
-};
+	},
 
+	// Get points of shape and holes (keypoints based on segments parameter)
 
-// Get points of shape and holes (keypoints based on segments parameter)
+	extractAllPoints: function ( divisions ) {
 
-THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
+		return {
 
-	return {
+			shape: this.getPoints( divisions ),
+			holes: this.getPointsHoles( divisions )
 
-		shape: this.getPoints( divisions ),
-		holes: this.getPointsHoles( divisions )
+		};
 
-	};
+	},
 
-};
+	extractPoints: function ( divisions ) {
 
-THREE.Shape.prototype.extractPoints = function ( divisions ) {
+		return this.extractAllPoints( divisions );
 
-	return this.extractAllPoints( divisions );
+	}
 
-};
+} );