123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- import { Curve } from './Curve.js';
- import { LineCurve } from '../curves/LineCurve.js';
- /**
- * @author zz85 / http://www.lab4games.net/zz85/blog
- *
- **/
- /**************************************************************
- * Curved Path - a curve path is simply a array of connected
- * curves, but retains the api of a curve
- **************************************************************/
- function CurvePath() {
- Curve.call( this );
- this.curves = [];
- this.autoClose = false; // Automatically closes the path
- }
- CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), {
- constructor: CurvePath,
- add: function ( curve ) {
- this.curves.push( curve );
- },
- closePath: function () {
- // 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 );
- if ( ! startPoint.equals( endPoint ) ) {
- this.curves.push( new 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')
- getPoint: function ( t ) {
- var d = t * this.getLength();
- var curveLengths = this.getCurveLengths();
- var i = 0;
- // To think about boundaries points.
- while ( i < curveLengths.length ) {
- if ( curveLengths[ i ] >= d ) {
- var diff = curveLengths[ i ] - d;
- var curve = this.curves[ i ];
- var segmentLength = curve.getLength();
- var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength;
- return curve.getPointAt( u );
- }
- i ++;
- }
- return null;
- // loop where sum != 0, sum > d , sum+1 <d
- },
- // 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
- getLength: function () {
- var lens = this.getCurveLengths();
- return lens[ lens.length - 1 ];
- },
- // cacheLengths must be recalculated.
- updateArcLengths: function () {
- this.needsUpdate = true;
- this.cacheLengths = null;
- this.getCurveLengths();
- },
- // Compute lengths and cache them
- // We cannot overwrite getLengths() because UtoT mapping uses it.
- getCurveLengths: function () {
- // We use cache values if curves and cache array are same length
- if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) {
- return this.cacheLengths;
- }
- // Get length of sub-curve
- // Push sums into cached array
- var lengths = [], sums = 0;
- for ( var i = 0, l = this.curves.length; i < l; i ++ ) {
- sums += this.curves[ i ].getLength();
- lengths.push( sums );
- }
- this.cacheLengths = lengths;
- return lengths;
- },
- getSpacedPoints: function ( divisions ) {
- if ( divisions === undefined ) divisions = 40;
- var points = [];
- for ( var i = 0; i <= divisions; i ++ ) {
- points.push( this.getPoint( i / divisions ) );
- }
- if ( this.autoClose ) {
- points.push( points[ 0 ] );
- }
- return points;
- },
- getPoints: function ( divisions ) {
- divisions = divisions || 12;
- var points = [], last;
- for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) {
- var curve = curves[ i ];
- var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2
- : ( curve && curve.isLineCurve ) ? 1
- : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length
- : divisions;
- var pts = curve.getPoints( resolution );
- for ( var j = 0; j < pts.length; j ++ ) {
- var point = pts[ j ];
- if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates
- points.push( point );
- last = point;
- }
- }
- if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) {
- points.push( points[ 0 ] );
- }
- return points;
- }
- } );
- export { CurvePath };
|