59 #define ACG_BSPLINEBASIS_C
63 #include "BSplineBasis.hh"
75 template<
typename Scalar>
79 const std::vector<Scalar>& _knots)
84 int hi = _knots.size() - 1 - _degree;
86 Scalar upperBound = _knots[hi];
89 return Vec2i(hi-1-_degree, hi - 1);
91 int mid = (lo + hi) >> 1;
93 while (_t < _knots[mid] || _t >= _knots[mid + 1])
100 mid = (lo + hi) >> 1;
103 return Vec2i(mid - _degree, mid);
123 template<
typename Scalar>
128 const std::vector<Scalar>& _knots)
135 int p = _span[1] - _span[0];
143 static std::vector<Scalar> left(p+1);
144 static std::vector<Scalar> right(p+1);
146 if (left.size() < size_t(p+1))
153 for (
int j = 1; j <= p; ++j)
155 left[j] = _t - _knots[i + 1 - j];
156 right[j] = _knots[i + j] - _t;
160 for (
int r = 0; r < j; ++r)
162 Scalar tmp = _N[r] / (right[r + 1] + left[j - r]);
163 _N[r] = saved + right[r + 1] * tmp;
164 saved = left[j - r] * tmp;
171 template<
typename Scalar>
177 const std::vector<Scalar>& _knots,
178 std::vector<Scalar>* _functionVals )
182 int p = _span[1] - _span[0];
188 static std::vector< std::vector<Scalar> > ndu(p1);
189 static std::vector<Scalar> left(p1);
190 static std::vector<Scalar> right(p1);
191 static std::vector<Scalar> a(2*p1);
193 if (ndu[0].size() <
size_t(p1))
196 for (
int i = 0; i < p1; ++i)
210 for (
int j = 1; j <= p; ++j)
212 left[j]= _t - _knots[i + 1 - j];
213 right[j]= _knots[i + j] - _t;
216 for (
int r = 0; r < j; ++r)
219 ndu[j][r] = right[r+1] + left[j-r];
220 Scalar tmp = ndu[r][j-1] / ndu[j][r];
222 ndu[r][j] = saved + right[r+1] * tmp;
223 saved = left[j-r] * tmp;
231 for (
int j = 0; j <= p; ++j)
232 (*_functionVals)[j] = ndu[j][p];
239 for (
int r = 0; r <= p; ++r)
244 for (
int k = 1; k <= _der; ++k)
247 int rk = r - k, pk = p - k;
251 a[s2 + 0] = a[s1 + 0] / ndu[pk+1][rk];
252 d = a[s2] * ndu[rk][pk];
255 int j1 = (rk >= -1) ? 1 : -rk;
256 int j2 = (r - 1 <= pk) ? k-1 : p-r;
258 for (
int j = j1; j <= j2; ++j)
260 a[s2 + j] = (a[s1 + j] - a[s1 + j-1]) / ndu[pk+1][rk+j];
261 d += a[s2 + j] * ndu[rk+j][pk];
266 a[s2 + k] = -a[s1 + k-1] / ndu[pk+1][r];
267 d += a[s2 + k] * ndu[r][pk];
281 for (
int k = 1; k <= _der; ++k)
283 Scalar rf = Scalar(r);
284 for (
int j = 0; j <= p; ++j)
293 template<
typename Scalar>
298 const std::vector<Scalar>& _knots)
300 int m = _knots.size() - 1;
303 if ((_i == 0 && _t == _knots[0]) || (_i == m - _degree - 1 && _t == _knots[m]))
307 if (_t >= _knots[_i] && _t < _knots[_i + 1])
313 double Nin1 = basisFunction(_i, _degree - 1, _t, _knots);
314 double Nin2 = basisFunction(_i + 1, _degree - 1, _t, _knots);
318 if ((_knots[_i + _degree] - _knots[_i]) != 0)
319 fac1 = (_t - _knots[_i]) / (_knots[_i + _degree] - _knots[_i]);
323 if ((_knots[_i + 1 + _degree] - _knots[_i + 1]) != 0)
324 fac2 = (_knots[_i + 1 + _degree] - _t) / (_knots[_i + 1 + _degree] - _knots[_i + 1]);
328 return (fac1*Nin1 + fac2*Nin2);
332 template<
typename Scalar>
338 const std::vector<Scalar>& _knots)
340 assert(_degree >= 0);
345 return basisFunction(_i, _degree, _t, _knots);
347 Scalar Nin1 = derivativeBasisFunction(_i, _degree - 1, _t, _der - 1, _knots);
348 Scalar Nin2 = derivativeBasisFunction(_i + 1, _degree - 1, _t, _der - 1, _knots);
351 if (std::abs(_knots[_i + _degree] - _knots[_i]) > 1e-6)
352 fac1 = Scalar(_degree) / (_knots[_i + _degree] - _knots[_i]);
355 if (std::abs(_knots[_i + _degree + 1] - _knots[_i + 1]) > 1e-6)
356 fac2 = Scalar(_degree) / (_knots[_i + _degree + 1] - _knots[_i + 1]);
358 return (fac1*Nin1 - fac2*Nin2);
void bsplineBasisFunctions(std::vector< Scalar > &_N, const Vec2i &_span, Scalar _t, const std::vector< Scalar > &_knots)
Evaluate basis functions in a span.
Namespace providing different geometric functions concerning angles.
VectorT< signed int, 2 > Vec2i
Vec2i bsplineSpan(Scalar _t, int _degree, const std::vector< Scalar > &_knots)
Find the span of a parameter value.
void bsplineBasisDerivatives(std::vector< Scalar > &_ders, const Vec2i &_span, Scalar _t, int _der, const std::vector< Scalar > &_knots, std::vector< Scalar > *_functionVals)
Compute derivatives of basis functions in a span.
Scalar bsplineBasisFunction(int _i, int _degree, Scalar _t, const std::vector< Scalar > &_knots)
Evaluate a single basis function.
Scalar bsplineBasisDerivative(int _i, int _degree, Scalar _t, int _der, const std::vector< Scalar > &_knots)
Compute derivative of a single basis function.