package org.andork.bspline; public class FastFloatBSplineEvaluator extends FloatBSplineEvaluator { private float[ ] points; private int pointsStride; private float[ ] knots; private float param; private int knotIndex; private int multiplicity; public FastFloatBSplineEvaluator bspline( FloatArrayBSpline bspline ) { return degree( bspline.degree ).dimension( bspline.dimension ).points( bspline.points ).knots( bspline.knots ) .pointsStride( bspline.dimension ); } @Override public FastFloatBSplineEvaluator degree( int degree ) { return ( FastFloatBSplineEvaluator ) super.degree( degree ); } @Override public FastFloatBSplineEvaluator dimension( int dimension ) { return ( FastFloatBSplineEvaluator ) super.dimension( dimension ); } public FastFloatBSplineEvaluator points( float[ ] points ) { this.points = points; return this; } public FastFloatBSplineEvaluator pointsStride( int pointsStride ) { this.pointsStride = pointsStride; return this; } public FastFloatBSplineEvaluator knots( float[ ] knots ) { if( this.knots != knots ) { this.knots = knots; knotIndex = -1; } return this; } public void splineModified( ) { knotIndex = -1; } public void eval( float param , float[ ] out ) { eval( param , out , 0 ); } public void eval( float param , float[ ] out , int outIndex ) { updateState( param ); eval( degree , dimension , knots , knotIndex , multiplicity , points , pointsStride , param , out , outIndex ); } private void updateState( float param ) { float lastKnot = knots[ knots.length - 1 ]; if( param < knots[ 0 ] || param > lastKnot ) { throw new IllegalArgumentException( "param (" + param + ") is out of range: [" + knots[ 0 ] + ", " + lastKnot + ")" ); } if( param == lastKnot ) { knotIndex = knots.length - 1; multiplicity = 1; while( knotIndex > 0 && knots[ knotIndex - 1 ] == lastKnot ) { knotIndex-- ; multiplicity++ ; } } else if( knotIndex >= 0 && param > this.param ) { if( param < knots[ knotIndex + 1 ] ) { multiplicity = 0; } else { knotIndex++ ; multiplicity = 1; // NOTE: param < lastKnot, so index + 1 must be in bounds float nextKnot = knots[ knotIndex ]; while( knots[ knotIndex + 1 ] == nextKnot ) { knotIndex++ ; multiplicity++ ; } if( knots[ knotIndex + 1 ] < param ) { knotIndex = -1; } else if( knots[ knotIndex ] != param ) { multiplicity = 0; } } } this.param = param; if( knotIndex < 0 || param < knots[ knotIndex ] ) { knotIndex = BSplines.binarySearch( knots , 0 , knots.length , param ); multiplicity = 0; for( int i = knotIndex ; i >= 0 && knots[ i ] == param ; i-- ) { multiplicity++ ; } } } }