// import { Point } from './Point';
/**
* @class
* @memberof JC
*/
function Curve() {}
Curve.prototype = {
constructor: Curve,
getPoint: function( t ) {
console.warn( 'Curve: Warning, getPoint() not implemented!', t );
return null;
},
getPointAt: function( u ) {
let t = this.getUtoTmapping( u );
return this.getPoint( t );
},
getPoints: function( divisions ) {
if ( isNaN( divisions ) ) divisions = 5;
let points = [];
for ( let d = 0; d <= divisions; d ++ ) {
points.push( this.getPoint( d / divisions ) );
}
return points;
},
getSpacedPoints: function( divisions ) {
if ( isNaN( divisions ) ) divisions = 5;
let points = [];
for ( let d = 0; d <= divisions; d ++ ) {
points.push( this.getPointAt( d / divisions ) );
}
return points;
},
getLength: function() {
let lengths = this.getLengths();
return lengths[lengths.length - 1];
},
getLengths: function( divisions ) {
if (isNaN(divisions)) {
divisions = ( this.__arcLengthDivisions ) ?
( this.__arcLengthDivisions ) :
200;
}
if ( this.cacheArcLengths
&& ( this.cacheArcLengths.length === divisions + 1 )
&& ! this.needsUpdate ) {
return this.cacheArcLengths;
}
this.needsUpdate = false;
let cache = [];
let current;
let last = this.getPoint( 0 );
let p;
let sum = 0;
cache.push( 0 );
for ( p = 1; p <= divisions; p ++ ) {
current = this.getPoint( p / divisions );
sum += current.distanceTo( last );
cache.push( sum );
last = current;
}
this.cacheArcLengths = cache;
return cache;
},
updateArcLengths: function() {
this.needsUpdate = true;
this.getLengths();
},
getUtoTmapping: function( u, distance ) {
let arcLengths = this.getLengths();
let i = 0;
let il = arcLengths.length;
let t;
let targetArcLength;
if ( distance ) {
targetArcLength = distance;
} else {
targetArcLength = u * arcLengths[il - 1];
}
let low = 0;
let high = il - 1;
let comparison;
while ( low <= high ) {
i = Math.floor( low + ( high - low ) / 2 );
comparison = arcLengths[i] - targetArcLength;
if ( comparison < 0 ) {
low = i + 1;
} else if ( comparison > 0 ) {
high = i - 1;
} else {
high = i;
break;
}
}
i = high;
if ( arcLengths[i] === targetArcLength ) {
t = i / ( il - 1 );
return t;
}
let lengthBefore = arcLengths[i];
let lengthAfter = arcLengths[i + 1];
let segmentLength = lengthAfter - lengthBefore;
let segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
t = ( i + segmentFraction ) / ( il - 1 );
return t;
},
getTangent: function( t ) {
let delta = 0.0001;
let t1 = t - delta;
let t2 = t + delta;
// NOTE: svg and bezier accept out of [0, 1] value
// if ( t1 < 0 ) t1 = 0;
// if ( t2 > 1 ) t2 = 1;
let pt1 = this.getPoint( t1 );
let pt2 = this.getPoint( t2 );
let vec = pt2.clone().sub( pt1 );
return vec.normalize();
},
getTangentAt: function( u ) {
let t = this.getUtoTmapping( u );
return this.getTangent( t );
},
};
export {Curve};