|
@@ -38,233 +38,233 @@ THREE.Curve = function () {
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-// Virtual base class method to overwrite and implement in subclasses
|
|
|
|
-// - t [0 .. 1]
|
|
|
|
|
|
+THREE.Curve.prototype = {
|
|
|
|
|
|
-THREE.Curve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
+ constructor: THREE.Curve,
|
|
|
|
|
|
- console.warn( "THREE.Curve: Warning, getPoint() not implemented!" );
|
|
|
|
- return null;
|
|
|
|
|
|
+ // Virtual base class method to overwrite and implement in subclasses
|
|
|
|
+ // - t [0 .. 1]
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ getPoint: function ( t ) {
|
|
|
|
|
|
-// Get point at relative position in curve according to arc length
|
|
|
|
-// - u [0 .. 1]
|
|
|
|
|
|
+ console.warn( "THREE.Curve: Warning, getPoint() not implemented!" );
|
|
|
|
+ return null;
|
|
|
|
|
|
-THREE.Curve.prototype.getPointAt = function ( u ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- var t = this.getUtoTmapping( u );
|
|
|
|
- return this.getPoint( t );
|
|
|
|
|
|
+ // Get point at relative position in curve according to arc length
|
|
|
|
+ // - u [0 .. 1]
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ getPointAt: function ( u ) {
|
|
|
|
|
|
-// Get sequence of points using getPoint( t )
|
|
|
|
|
|
+ var t = this.getUtoTmapping( u );
|
|
|
|
+ return this.getPoint( t );
|
|
|
|
|
|
-THREE.Curve.prototype.getPoints = function ( divisions ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- if ( ! divisions ) divisions = 5;
|
|
|
|
|
|
+ // Get sequence of points using getPoint( t )
|
|
|
|
|
|
- var d, pts = [];
|
|
|
|
|
|
+ getPoints: function ( divisions ) {
|
|
|
|
|
|
- for ( d = 0; d <= divisions; d ++ ) {
|
|
|
|
|
|
+ if ( ! divisions ) divisions = 5;
|
|
|
|
|
|
- pts.push( this.getPoint( d / divisions ) );
|
|
|
|
|
|
+ var d, pts = [];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ for ( d = 0; d <= divisions; d ++ ) {
|
|
|
|
|
|
- return pts;
|
|
|
|
|
|
+ pts.push( this.getPoint( d / divisions ) );
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-// Get sequence of points using getPointAt( u )
|
|
|
|
|
|
+ return pts;
|
|
|
|
|
|
-THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- if ( ! divisions ) divisions = 5;
|
|
|
|
|
|
+ // Get sequence of points using getPointAt( u )
|
|
|
|
|
|
- var d, pts = [];
|
|
|
|
|
|
+ getSpacedPoints: function ( divisions ) {
|
|
|
|
|
|
- for ( d = 0; d <= divisions; d ++ ) {
|
|
|
|
|
|
+ if ( ! divisions ) divisions = 5;
|
|
|
|
|
|
- pts.push( this.getPointAt( d / divisions ) );
|
|
|
|
|
|
+ var d, pts = [];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ for ( d = 0; d <= divisions; d ++ ) {
|
|
|
|
|
|
- return pts;
|
|
|
|
-
|
|
|
|
-};
|
|
|
|
|
|
+ pts.push( this.getPointAt( d / divisions ) );
|
|
|
|
|
|
-// Get total curve arc length
|
|
|
|
-
|
|
|
|
-THREE.Curve.prototype.getLength = function () {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var lengths = this.getLengths();
|
|
|
|
- return lengths[ lengths.length - 1 ];
|
|
|
|
|
|
+ return pts;
|
|
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-// Get list of cumulative segment lengths
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-THREE.Curve.prototype.getLengths = function ( divisions ) {
|
|
|
|
|
|
+ // Get total curve arc length
|
|
|
|
|
|
- if ( ! divisions ) divisions = ( this.__arcLengthDivisions ) ? ( this.__arcLengthDivisions ) : 200;
|
|
|
|
|
|
+ getLength: function () {
|
|
|
|
|
|
- if ( this.cacheArcLengths
|
|
|
|
- && ( this.cacheArcLengths.length === divisions + 1 )
|
|
|
|
- && ! this.needsUpdate ) {
|
|
|
|
|
|
+ var lengths = this.getLengths();
|
|
|
|
+ return lengths[ lengths.length - 1 ];
|
|
|
|
|
|
- //console.log( "cached", this.cacheArcLengths );
|
|
|
|
- return this.cacheArcLengths;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ // Get list of cumulative segment lengths
|
|
|
|
|
|
- this.needsUpdate = false;
|
|
|
|
|
|
+ getLengths: function ( divisions ) {
|
|
|
|
|
|
- var cache = [];
|
|
|
|
- var current, last = this.getPoint( 0 );
|
|
|
|
- var p, sum = 0;
|
|
|
|
|
|
+ if ( ! divisions ) divisions = ( this.__arcLengthDivisions ) ? ( this.__arcLengthDivisions ) : 200;
|
|
|
|
|
|
- cache.push( 0 );
|
|
|
|
|
|
+ if ( this.cacheArcLengths
|
|
|
|
+ && ( this.cacheArcLengths.length === divisions + 1 )
|
|
|
|
+ && ! this.needsUpdate ) {
|
|
|
|
|
|
- for ( p = 1; p <= divisions; p ++ ) {
|
|
|
|
|
|
+ //console.log( "cached", this.cacheArcLengths );
|
|
|
|
+ return this.cacheArcLengths;
|
|
|
|
|
|
- current = this.getPoint ( p / divisions );
|
|
|
|
- sum += current.distanceTo( last );
|
|
|
|
- cache.push( sum );
|
|
|
|
- last = current;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ this.needsUpdate = false;
|
|
|
|
|
|
- this.cacheArcLengths = cache;
|
|
|
|
|
|
+ var cache = [];
|
|
|
|
+ var current, last = this.getPoint( 0 );
|
|
|
|
+ var p, sum = 0;
|
|
|
|
|
|
- return cache; // { sums: cache, sum:sum }; Sum is in the last element.
|
|
|
|
|
|
+ cache.push( 0 );
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ for ( p = 1; p <= divisions; p ++ ) {
|
|
|
|
|
|
|
|
+ current = this.getPoint ( p / divisions );
|
|
|
|
+ sum += current.distanceTo( last );
|
|
|
|
+ cache.push( sum );
|
|
|
|
+ last = current;
|
|
|
|
|
|
-THREE.Curve.prototype.updateArcLengths = function() {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- this.needsUpdate = true;
|
|
|
|
- this.getLengths();
|
|
|
|
|
|
+ this.cacheArcLengths = cache;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return cache; // { sums: cache, sum:sum }; Sum is in the last element.
|
|
|
|
|
|
-// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
|
|
|
|
|
|
+ updateArcLengths: function() {
|
|
|
|
|
|
- var arcLengths = this.getLengths();
|
|
|
|
|
|
+ this.needsUpdate = true;
|
|
|
|
+ this.getLengths();
|
|
|
|
|
|
- var i = 0, il = arcLengths.length;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- var targetArcLength; // The targeted u distance value to get
|
|
|
|
|
|
+ // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant
|
|
|
|
|
|
- if ( distance ) {
|
|
|
|
|
|
+ getUtoTmapping: function ( u, distance ) {
|
|
|
|
|
|
- targetArcLength = distance;
|
|
|
|
|
|
+ var arcLengths = this.getLengths();
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ var i = 0, il = arcLengths.length;
|
|
|
|
|
|
- targetArcLength = u * arcLengths[ il - 1 ];
|
|
|
|
|
|
+ var targetArcLength; // The targeted u distance value to get
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( distance ) {
|
|
|
|
|
|
- //var time = Date.now();
|
|
|
|
|
|
+ targetArcLength = distance;
|
|
|
|
|
|
- // binary search for the index with largest value smaller than target u distance
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- var low = 0, high = il - 1, comparison;
|
|
|
|
|
|
+ targetArcLength = u * arcLengths[ il - 1 ];
|
|
|
|
|
|
- while ( low <= high ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
|
|
|
|
|
|
+ //var time = Date.now();
|
|
|
|
|
|
- comparison = arcLengths[ i ] - targetArcLength;
|
|
|
|
|
|
+ // binary search for the index with largest value smaller than target u distance
|
|
|
|
|
|
- if ( comparison < 0 ) {
|
|
|
|
|
|
+ var low = 0, high = il - 1, comparison;
|
|
|
|
|
|
- low = i + 1;
|
|
|
|
|
|
+ while ( low <= high ) {
|
|
|
|
|
|
- } else if ( comparison > 0 ) {
|
|
|
|
|
|
+ i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
|
|
|
|
|
|
- high = i - 1;
|
|
|
|
|
|
+ comparison = arcLengths[ i ] - targetArcLength;
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ if ( comparison < 0 ) {
|
|
|
|
|
|
- high = i;
|
|
|
|
- break;
|
|
|
|
|
|
+ low = i + 1;
|
|
|
|
|
|
- // DONE
|
|
|
|
|
|
+ } else if ( comparison > 0 ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ high = i - 1;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- i = high;
|
|
|
|
|
|
+ high = i;
|
|
|
|
+ break;
|
|
|
|
|
|
- //console.log('b' , i, low, high, Date.now()- time);
|
|
|
|
|
|
+ // DONE
|
|
|
|
|
|
- if ( arcLengths[ i ] === targetArcLength ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var t = i / ( il - 1 );
|
|
|
|
- return t;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ i = high;
|
|
|
|
|
|
- // we could get finer grain at lengths, or use simple interpolation between two points
|
|
|
|
|
|
+ //console.log('b' , i, low, high, Date.now()- time);
|
|
|
|
|
|
- var lengthBefore = arcLengths[ i ];
|
|
|
|
- var lengthAfter = arcLengths[ i + 1 ];
|
|
|
|
|
|
+ if ( arcLengths[ i ] === targetArcLength ) {
|
|
|
|
|
|
- var segmentLength = lengthAfter - lengthBefore;
|
|
|
|
|
|
+ var t = i / ( il - 1 );
|
|
|
|
+ return t;
|
|
|
|
|
|
- // determine where we are between the 'before' and 'after' points
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
|
|
|
|
|
|
+ // we could get finer grain at lengths, or use simple interpolation between two points
|
|
|
|
|
|
- // add that fractional amount to t
|
|
|
|
|
|
+ var lengthBefore = arcLengths[ i ];
|
|
|
|
+ var lengthAfter = arcLengths[ i + 1 ];
|
|
|
|
|
|
- var t = ( i + segmentFraction ) / ( il - 1 );
|
|
|
|
|
|
+ var segmentLength = lengthAfter - lengthBefore;
|
|
|
|
|
|
- return t;
|
|
|
|
|
|
+ // determine where we are between the 'before' and 'after' points
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
|
|
|
|
|
|
-// Returns a unit vector tangent at t
|
|
|
|
-// In case any sub curve does not implement its tangent derivation,
|
|
|
|
-// 2 points a small delta apart will be used to find its gradient
|
|
|
|
-// which seems to give a reasonable approximation
|
|
|
|
|
|
+ // add that fractional amount to t
|
|
|
|
|
|
-THREE.Curve.prototype.getTangent = function( t ) {
|
|
|
|
|
|
+ var t = ( i + segmentFraction ) / ( il - 1 );
|
|
|
|
|
|
- var delta = 0.0001;
|
|
|
|
- var t1 = t - delta;
|
|
|
|
- var t2 = t + delta;
|
|
|
|
|
|
+ return t;
|
|
|
|
|
|
- // Capping in case of danger
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- if ( t1 < 0 ) t1 = 0;
|
|
|
|
- if ( t2 > 1 ) t2 = 1;
|
|
|
|
|
|
+ // Returns a unit vector tangent at t
|
|
|
|
+ // In case any sub curve does not implement its tangent derivation,
|
|
|
|
+ // 2 points a small delta apart will be used to find its gradient
|
|
|
|
+ // which seems to give a reasonable approximation
|
|
|
|
|
|
- var pt1 = this.getPoint( t1 );
|
|
|
|
- var pt2 = this.getPoint( t2 );
|
|
|
|
|
|
+ getTangent: function( t ) {
|
|
|
|
|
|
- var vec = pt2.clone().sub( pt1 );
|
|
|
|
- return vec.normalize();
|
|
|
|
|
|
+ var delta = 0.0001;
|
|
|
|
+ var t1 = t - delta;
|
|
|
|
+ var t2 = t + delta;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ // Capping in case of danger
|
|
|
|
|
|
|
|
+ if ( t1 < 0 ) t1 = 0;
|
|
|
|
+ if ( t2 > 1 ) t2 = 1;
|
|
|
|
|
|
-THREE.Curve.prototype.getTangentAt = function ( u ) {
|
|
|
|
|
|
+ var pt1 = this.getPoint( t1 );
|
|
|
|
+ var pt2 = this.getPoint( t2 );
|
|
|
|
|
|
- var t = this.getUtoTmapping( u );
|
|
|
|
- return this.getTangent( t );
|
|
|
|
|
|
+ var vec = pt2.clone().sub( pt1 );
|
|
|
|
+ return vec.normalize();
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ },
|
|
|
|
|
|
|
|
+ getTangentAt: function ( u ) {
|
|
|
|
|
|
|
|
+ var t = this.getUtoTmapping( u );
|
|
|
|
+ return this.getTangent( t );
|
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+}
|
|
|
|
|
|
/**************************************************************
|
|
/**************************************************************
|
|
* Utils
|
|
* Utils
|