@@ -128,11 +128,14 @@ inline X Spline<X,Y>::solve( X x, typename PointContainer::const_iterator &segme
128128 // If we hit the end of the points while searching, return the end point of the last valid segment
129129 // this is just a linear search right now - it should be possible to optimise this using points.lower_bound
130130 // to quickly find a better start point for the search.
131- X co[4 ];
132- basis.coefficients ( X ( 1 ), co );
131+ X endCo[4 ];
132+ basis.coefficients ( X ( 1 ), endCo );
133+ X startCo[4 ];
134+ basis.coefficients ( X ( 0 ), startCo );
133135 X xp[4 ] = { X (0 ), X (0 ), X (0 ), X (0 ) };
134136
135137 segment = points.begin ();
138+ It prevSegment = segment;
136139 for ( int pointNum = 0 ;; pointNum += basis.step )
137140 {
138141 It xIt ( segment );
@@ -142,8 +145,20 @@ inline X Spline<X,Y>::solve( X x, typename PointContainer::const_iterator &segme
142145 xIt++;
143146 }
144147
145- if ( xp[0 ] * co [0 ] + xp[1 ] * co [1 ] + xp[2 ] * co [2 ] + xp[3 ] * co [3 ] > x )
148+ if ( xp[0 ] * endCo [0 ] + xp[1 ] * endCo [1 ] + xp[2 ] * endCo [2 ] + xp[3 ] * endCo [3 ] > x )
146149 {
150+ // We've crossed the target value, we can stop the search
151+
152+ if ( segment != points.begin () && xp[0 ] * startCo[0 ] + xp[1 ] * startCo[1 ] + xp[2 ] * startCo[2 ] + xp[3 ] * startCo[3 ] > x )
153+ {
154+ // We've not only crossed the target, we'd already jumped past it at the start of
155+ // this segment... this could happen when there is a discontinuity between segments
156+ // ( ie. for the "constant" basis ). In this case, we want to take the end of the
157+ // previous segment
158+ segment = prevSegment;
159+ return X ( 1 );
160+ }
161+
147162 break ;
148163 }
149164
@@ -154,6 +169,7 @@ inline X Spline<X,Y>::solve( X x, typename PointContainer::const_iterator &segme
154169 return X ( 1 );
155170 }
156171
172+ prevSegment = segment;
157173 for ( unsigned i=0 ; i<basis.step ; i++ )
158174 {
159175 segment++;
0 commit comments