00001
00034 #ifndef SEEN_BEZIER_H
00035 #define SEEN_BEZIER_H
00036
00037 #include <2geom/coord.h>
00038 #include <valarray>
00039 #include <2geom/isnan.h>
00040 #include <2geom/d2.h>
00041 #include <2geom/solver.h>
00042 #include <boost/optional/optional.hpp>
00043
00044 namespace Geom {
00045
00046 inline Coord subdivideArr(Coord t, Coord const *v, Coord *left, Coord *right, unsigned order) {
00047
00048
00049
00050
00051
00052
00053
00054 unsigned N = order+1;
00055 std::valarray<Coord> row(N);
00056 for (unsigned i = 0; i < N; i++)
00057 row[i] = v[i];
00058
00059
00060 const double omt = (1-t);
00061 if(left)
00062 left[0] = row[0];
00063 if(right)
00064 right[order] = row[order];
00065 for (unsigned i = 1; i < N; i++) {
00066 for (unsigned j = 0; j < N - i; j++) {
00067 row[j] = omt*row[j] + t*row[j+1];
00068 }
00069 if(left)
00070 left[i] = row[0];
00071 if(right)
00072 right[order-i] = row[order-i];
00073 }
00074 return (row[0]);
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095 }
00096
00097 template <typename T>
00098 inline T bernsteinValueAt(double t, T const *c_, unsigned n) {
00099 double u = 1.0 - t;
00100 double bc = 1;
00101 double tn = 1;
00102 T tmp = c_[0]*u;
00103 for(unsigned i=1; i<n; i++){
00104 tn = tn*t;
00105 bc = bc*(n-i+1)/i;
00106 tmp = (tmp + tn*bc*c_[i])*u;
00107 }
00108 return (tmp + tn*t*c_[n]);
00109 }
00110
00111
00112 class Bezier {
00113 private:
00114 std::valarray<Coord> c_;
00115
00116 friend Bezier portion(const Bezier & a, Coord from, Coord to);
00117
00118 friend OptInterval bounds_fast(Bezier const & b);
00119
00120 friend Bezier derivative(const Bezier & a);
00121
00122 protected:
00123 Bezier(Coord const c[], unsigned ord) : c_(c, ord+1){
00124
00125 }
00126
00127 public:
00128 unsigned int order() const { return c_.size()-1;}
00129 unsigned int size() const { return c_.size();}
00130
00131 Bezier() {}
00132 Bezier(const Bezier& b) :c_(b.c_) {}
00133 Bezier &operator=(Bezier const &other) {
00134 if ( c_.size() != other.c_.size() ) {
00135 c_.resize(other.c_.size());
00136 }
00137 c_ = other.c_;
00138 return *this;
00139 }
00140
00141 struct Order {
00142 unsigned order;
00143 explicit Order(Bezier const &b) : order(b.order()) {}
00144 explicit Order(unsigned o) : order(o) {}
00145 operator unsigned() const { return order; }
00146 };
00147
00148
00149 Bezier(Order ord) : c_(0., ord.order+1) {
00150 assert(ord.order == order());
00151 }
00152
00153 explicit Bezier(Coord c0) : c_(0., 1) {
00154 c_[0] = c0;
00155 }
00156
00157
00158 Bezier(Coord c0, Coord c1) : c_(0., 2) {
00159 c_[0] = c0; c_[1] = c1;
00160 }
00161
00162
00163 Bezier(Coord c0, Coord c1, Coord c2) : c_(0., 3) {
00164 c_[0] = c0; c_[1] = c1; c_[2] = c2;
00165 }
00166
00167
00168 Bezier(Coord c0, Coord c1, Coord c2, Coord c3) : c_(0., 4) {
00169 c_[0] = c0; c_[1] = c1; c_[2] = c2; c_[3] = c3;
00170 }
00171
00172 void resize (unsigned int n, Coord v = 0)
00173 {
00174 c_.resize (n, v);
00175 }
00176
00177 void clear()
00178 {
00179 c_.resize(0);
00180 }
00181
00182 inline unsigned degree() const { return order(); }
00183
00184
00185 typedef Coord output_type;
00186 inline bool isZero() const {
00187 for(unsigned i = 0; i <= order(); i++) {
00188 if(c_[i] != 0) return false;
00189 }
00190 return true;
00191 }
00192 inline bool isConstant() const {
00193 for(unsigned i = 1; i <= order(); i++) {
00194 if(c_[i] != c_[0]) return false;
00195 }
00196 return true;
00197 }
00198 inline bool isFinite() const {
00199 for(unsigned i = 0; i <= order(); i++) {
00200 if(!IS_FINITE(c_[i])) return false;
00201 }
00202 return true;
00203 }
00204 inline Coord at0() const { return c_[0]; }
00205 inline Coord at1() const { return c_[order()]; }
00206
00207 inline Coord valueAt(double t) const {
00208 int n = order();
00209 double u, bc, tn, tmp;
00210 int i;
00211 u = 1.0 - t;
00212 bc = 1;
00213 tn = 1;
00214 tmp = c_[0]*u;
00215 for(i=1; i<n; i++){
00216 tn = tn*t;
00217 bc = bc*(n-i+1)/i;
00218 tmp = (tmp + tn*bc*c_[i])*u;
00219 }
00220 return (tmp + tn*t*c_[n]);
00221
00222 }
00223 inline Coord operator()(double t) const { return valueAt(t); }
00224
00225 SBasis toSBasis() const;
00226
00227
00228
00229
00230
00231
00232
00233
00234 inline Coord &operator[](unsigned ix) { return c_[ix]; }
00235 inline Coord const &operator[](unsigned ix) const { return const_cast<std::valarray<Coord>&>(c_)[ix]; }
00236
00237 inline void setPoint(unsigned ix, double val) { c_[ix] = val; }
00238
00242 std::vector<Coord> valueAndDerivatives(Coord t, unsigned n_derivs) const {
00243
00244
00245
00246
00247 std::vector<Coord> val_n_der(n_derivs + 1, Coord(0.0));
00248
00249
00250 std::valarray<Coord> d_(order()+1);
00251 for (unsigned i = 0; i < size(); i++) {
00252 d_[i] = c_[i];
00253 }
00254
00255 unsigned nn = n_derivs + 1;
00256 if(n_derivs > order()) {
00257 nn = order()+1;
00258 }
00259 for (unsigned di = 0; di < nn; di++) {
00260
00261 val_n_der[di] = bernsteinValueAt(t, &d_[0], order() - di);
00262 for (unsigned i = 0; i < order() - di; i++) {
00263 d_[i] = (order()-di)*(d_[i+1] - d_[i]);
00264 }
00265 }
00266
00267 return val_n_der;
00268 }
00269
00270 std::pair<Bezier, Bezier > subdivide(Coord t) const {
00271 Bezier a(Bezier::Order(*this)), b(Bezier::Order(*this));
00272 subdivideArr(t, &const_cast<std::valarray<Coord>&>(c_)[0], &a.c_[0], &b.c_[0], order());
00273 return std::pair<Bezier, Bezier >(a, b);
00274 }
00275
00276 std::vector<double> roots() const {
00277 std::vector<double> solutions;
00278 find_bernstein_roots(&const_cast<std::valarray<Coord>&>(c_)[0], order(), solutions, 0, 0.0, 1.0);
00279 return solutions;
00280 }
00281 std::vector<double> roots(Interval const ivl) const {
00282 std::vector<double> solutions;
00283 find_bernstein_roots(&const_cast<std::valarray<Coord>&>(c_)[0], order(), solutions, 0, ivl[0], ivl[1]);
00284 return solutions;
00285 }
00286 };
00287
00288
00289 void bezier_to_sbasis (SBasis & sb, Bezier const& bz);
00290
00291
00292 inline
00293 SBasis Bezier::toSBasis() const {
00294 SBasis sb;
00295 bezier_to_sbasis(sb, (*this));
00296 return sb;
00297
00298 }
00299
00300
00301 inline Bezier operator+(const Bezier & a, double v) {
00302 Bezier result = Bezier(Bezier::Order(a));
00303 for(unsigned i = 0; i <= a.order(); i++)
00304 result[i] = a[i] + v;
00305 return result;
00306 }
00307
00308 inline Bezier operator-(const Bezier & a, double v) {
00309 Bezier result = Bezier(Bezier::Order(a));
00310 for(unsigned i = 0; i <= a.order(); i++)
00311 result[i] = a[i] - v;
00312 return result;
00313 }
00314
00315 inline Bezier operator*(const Bezier & a, double v) {
00316 Bezier result = Bezier(Bezier::Order(a));
00317 for(unsigned i = 0; i <= a.order(); i++)
00318 result[i] = a[i] * v;
00319 return result;
00320 }
00321
00322 inline Bezier operator/(const Bezier & a, double v) {
00323 Bezier result = Bezier(Bezier::Order(a));
00324 for(unsigned i = 0; i <= a.order(); i++)
00325 result[i] = a[i] / v;
00326 return result;
00327 }
00328
00329 inline Bezier reverse(const Bezier & a) {
00330 Bezier result = Bezier(Bezier::Order(a));
00331 for(unsigned i = 0; i <= a.order(); i++)
00332 result[i] = a[a.order() - i];
00333 return result;
00334 }
00335
00336 inline Bezier portion(const Bezier & a, double from, double to) {
00337
00338 std::valarray<Coord> res(a.order() + 1);
00339 if(from == 0) {
00340 if(to == 1) { return Bezier(a); }
00341 subdivideArr(to, &const_cast<Bezier&>(a).c_[0], &res[0], NULL, a.order());
00342 return Bezier(&res[0], a.order());
00343 }
00344 subdivideArr(from, &const_cast<Bezier&>(a).c_[0], NULL, &res[0], a.order());
00345 if(to == 1) return Bezier(&res[0], a.order());
00346 std::valarray<Coord> res2(a.order()+1);
00347 subdivideArr((to - from)/(1 - from), &res[0], &res2[0], NULL, a.order());
00348 return Bezier(&res2[0], a.order());
00349 }
00350
00351
00352 inline std::vector<Point> bezier_points(const D2<Bezier > & a) {
00353 std::vector<Point> result;
00354 for(unsigned i = 0; i <= a[0].order(); i++) {
00355 Point p;
00356 for(unsigned d = 0; d < 2; d++) p[d] = a[d][i];
00357 result.push_back(p);
00358 }
00359 return result;
00360 }
00361
00362 inline Bezier derivative(const Bezier & a) {
00363
00364 if(a.order() == 1) return Bezier(a.c_[1]-a.c_[0]);
00365 Bezier der(Bezier::Order(a.order()-1));
00366
00367 for(unsigned i = 0; i < a.order(); i++) {
00368 der.c_[i] = a.order()*(a.c_[i+1] - a.c_[i]);
00369 }
00370 return der;
00371 }
00372
00373 inline Bezier integral(const Bezier & a) {
00374 Bezier inte(Bezier::Order(a.order()+1));
00375
00376 inte[0] = 0;
00377 for(unsigned i = 0; i < inte.order(); i++) {
00378 inte[i+1] = inte[i] + a[i]/(inte.order());
00379 }
00380 return inte;
00381 }
00382
00383 inline OptInterval bounds_fast(Bezier const & b) {
00384 return Interval::fromArray(&const_cast<Bezier&>(b).c_[0], b.size());
00385 }
00386
00387
00388 inline OptInterval bounds_exact(Bezier const & b) {
00389 return bounds_exact(b.toSBasis());
00390 }
00391
00392 inline OptInterval bounds_local(Bezier const & b, OptInterval i) {
00393
00394 if (i) {
00395 return bounds_fast(portion(b, i->min(), i->max()));
00396 } else {
00397 return OptInterval();
00398 }
00399 }
00400
00401 inline std::ostream &operator<< (std::ostream &out_file, const Bezier & b) {
00402 for(unsigned i = 0; i < b.size(); i++) {
00403 out_file << b[i] << ", ";
00404 }
00405 return out_file;
00406 }
00407
00408 }
00409 #endif //SEEN_BEZIER_H
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420