Skip to content

Commit bb0adc7

Browse files
committed
Spline : Fix evaluation when there are discontinuities in basis
1 parent 752a0e6 commit bb0adc7

File tree

1 file changed

+19
-3
lines changed

1 file changed

+19
-3
lines changed

include/IECore/Spline.inl

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)