SplineCurve class
class SplineCurve extends Curve2D { List<Vector2> points; SplineCurve( [this.points = null] ) { if (points == null) points = []; } getPoint( t ) { var v = new Vector2.zero(); var c = new List(4); var point, intPoint, weight; point = ( points.length - 1 ) * t; intPoint = point.floor().toInt(); weight = point - intPoint; c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1; c[ 1 ] = intPoint; c[ 2 ] = intPoint > points.length - 2 ? points.length -1 : intPoint + 1; c[ 3 ] = intPoint > points.length - 3 ? points.length -1 : intPoint + 2; v.x = CurveUtils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight ); v.y = CurveUtils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight ); return v; } }
Extends
Curve<Vector2> > Curve2D > SplineCurve
Properties
Methods
List getLengths({num divisions: null}) #
inherited from Curve
List getLengths( {num divisions: null} ) { if (divisions == null) divisions = (_arcLengthDivisions != null) ? (_arcLengthDivisions): 200; if ( cacheArcLengths != null && ( cacheArcLengths.length == divisions + 1 ) && !needsUpdate) { //console.log( "cached", this.cacheArcLengths ); return cacheArcLengths; } needsUpdate = false; var cache = []; var current; var last = getPoint( 0.0 ); var sum = 0; cache.add( 0 ); for ( var p = 1; p <= divisions; p ++ ) { current = getPoint ( p / divisions ); var distance; // TODO(nelsonsilva) - Must move distanceTo to IVector interface os create a new IHasDistance if (current is Vector3) { distance = (current as Vector3).absoluteError( last as Vector3 ); } else { distance = (current as Vector2).absoluteError( last as Vector2); } sum += distance; cache.add( sum ); last = current; } cacheArcLengths = cache; return cache; // { sums: cache, sum:sum }; Sum is in the last element. }
Vector2 getNormalVector(t) #
inherited from Curve2D
Vector2 getNormalVector( t ) { var vec = this.getTangent( t ); return new Vector2( -vec.y , vec.x ); }
dynamic getPoint(t) #
getPoint( t ) { var v = new Vector2.zero(); var c = new List(4); var point, intPoint, weight; point = ( points.length - 1 ) * t; intPoint = point.floor().toInt(); weight = point - intPoint; c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1; c[ 1 ] = intPoint; c[ 2 ] = intPoint > points.length - 2 ? points.length -1 : intPoint + 1; c[ 3 ] = intPoint > points.length - 3 ? points.length -1 : intPoint + 2; v.x = CurveUtils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight ); v.y = CurveUtils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight ); return v; }
V getPointAt(u) #
inherited from Curve
V getPointAt( u ) { var t = getUtoTmapping( u ); return getPoint( t ); }
List<V> getPoints([num divisions = null, closedPath = false]) #
inherited from Curve
List<V> getPoints( [num divisions = null, closedPath = false] ) { if (divisions == null) divisions = 5; var d, pts = []; for ( d = 0; d <= divisions; d ++ ) { pts.add( this.getPoint( d / divisions ) ); } return pts; }
List<V> getSpacedPoints([num divisions = 5, closedPath = false]) #
inherited from Curve
List<V> getSpacedPoints( [num divisions = 5, closedPath = false] ) { var d, pts = []; for ( d = 0; d <= divisions; d ++ ) { pts.add( this.getPointAt( d / divisions ) ); } return pts; }
V getTangent(t) #
inherited from Curve
V getTangent( t ) { 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; var pt1 = getPoint( t1 ); var pt2 = getPoint( t2 ); var vec = pt2 - pt1; return vec.normalize(); }
V getTangentAt(u) #
inherited from Curve
V getTangentAt( u ) { var t = getUtoTmapping( u ); return getTangent( t ); }
List<V> getUPoints([List uList, closedPath = false]) #
inherited from Curve
List<V> getUPoints( [List uList , closedPath = false] ) { var pts = []; for ( var u in uList ) { pts.add( this.getPointAt( u ) ); } return pts; }
dynamic getUtoTmapping(u, {distance: null}) #
inherited from Curve
getUtoTmapping( u, {distance: null} ) { var arcLengths = getLengths(); int i = 0, il = arcLengths.length; var targetArcLength; // The targeted u distance value to get if (distance != null) { targetArcLength = distance; } else { targetArcLength = u * arcLengths[ il - 1 ]; } //var time = Date.now(); // binary search for the index with largest value smaller than target u distance var low = 0, high = il - 1, comparison; while ( low <= high ) { i = ( low + ( high - low ) / 2 ).floor().toInt(); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats comparison = arcLengths[ i ] - targetArcLength; if ( comparison < 0 ) { low = i + 1; continue; } else if ( comparison > 0 ) { high = i - 1; continue; } else { high = i; break; // DONE } } i = high; //console.log('b' , i, low, high, Date.now()- time); if ( arcLengths[ i ] == targetArcLength ) { var t = i / ( il - 1 ); return t; } // we could get finer grain at lengths, or use simple interpolatation between two points var lengthBefore = arcLengths[ i ]; var lengthAfter = arcLengths[ i + 1 ]; var segmentLength = lengthAfter - lengthBefore; // determine where we are between the 'before' and 'after' points var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; // add that fractional amount to t var t = ( i + segmentFraction ) / ( il -1 ); return t; }