1 #ifndef MSP_INTERPOLATE_BEZIERSPLINE_H_
2 #define MSP_INTERPOLATE_BEZIERSPLINE_H_
8 namespace Interpolate {
10 template<typename T, unsigned D>
13 static Polynomial<T, D> b(unsigned);
17 A spline composed of bezier curves. Each segment has D-1 control points
18 between the knots which determine the shape of the curve. Bezier splines
19 with 2- or 3-dimensional values are commonly used in graphics.
21 template<typename T, unsigned D, unsigned N = 1>
22 class BezierSpline: public Spline<T, D, N>
25 using typename Spline<T, D, N>::Knot;
27 BezierSpline(const std::vector<Knot> &);
30 template<typename T, unsigned D>
31 inline Polynomial<T, D> Bernstein<T, D>::b(unsigned k)
34 throw std::invalid_argument("Bernstein::b");
36 LinAl::Vector<T, D+1> coeff;
38 int c = ((D-k)%2 ? -1 : 1);
39 for(unsigned i=0; i<=D-k; ++i)
42 c = c*-1*static_cast<int>(D-k-i)/static_cast<int>(i+1);
46 for(unsigned i=0; i<k; ++i)
48 for(unsigned i=2; i<=k; ++i)
51 for(unsigned i=0; i<=D; ++i)
54 return Polynomial<T, D>(coeff);
57 template<typename T, unsigned D, unsigned N>
58 inline BezierSpline<T, D, N>::BezierSpline(const std::vector<Knot> &k):
59 Spline<T, D, N>(k.front())
61 typedef SplineValue<T, N> SV;
64 throw std::invalid_argument("BezierSpline::BezierSpline");
66 Polynomial<T, D> b[D+1];
67 for(unsigned i=0; i<=D; ++i)
68 b[i] = Bernstein<T, D>::b(i);
70 for(unsigned i=0; i+D<k.size(); i+=D)
72 T dx = k[i+D].x-k[i].x;
73 Polynomial<T, 1> t(LinAl::Vector<T, 2>(T(1)/dx, -k[i].x/dx));
74 Polynomial<T, D> p[N];
75 for(unsigned j=0; j<N; ++j)
77 for(unsigned c=0; c<=D; ++c)
78 p[j] += b[c]*SV::get(k[i+c].y, j);
81 this->add_segment(p, k[i+D].x);
85 } // namespace Interpolate