MathTL
numerics/bezier.h
00001 // -*- c++ -*-
00002 
00003 // +--------------------------------------------------------------------+
00004 // | This file is part of MathTL - the Mathematical Template Library    |
00005 // |                                                                    |
00006 // | Copyright (c) 2002-2009                                            |
00007 // | Thorsten Raasch, Manuel Werner                                     |
00008 // +--------------------------------------------------------------------+
00009 
00010 #ifndef _MATHTL_BEZIER_H
00011 #define _MATHTL_BEZIER_H
00012 
00013 #include <cmath>
00014 #include <utils/function.h>
00015 #include <utils/tiny_tools.h>
00016 
00017 namespace MathTL
00018 {
00026   template <int d>
00027   double EvaluateBernsteinPolynomial(const int k, const double x)
00028   {
00029     return ((k < 0 || k > d)
00030             ? 0
00031             : (1-x) * EvaluateBernsteinPolynomial<d-1>(k,  x)
00032             + x   * EvaluateBernsteinPolynomial<d-1>(k-1,x));
00033   }
00034   
00038   template <>
00039   double EvaluateBernsteinPolynomial<0>(const int k, const double x)
00040   {
00041     return (k == 0 ? 1.0 : 0.0);
00042   }
00043 
00047   template <int d>
00048   double EvaluateBernsteinPolynomial_x(const int k, const double x)
00049   {
00050     return d * (EvaluateBernsteinPolynomial<d-1>(k-1, x)
00051                 - EvaluateBernsteinPolynomial<d-1>(k, x));
00052   }
00053 
00057   template <int d>
00058   double EvaluateBernsteinPolynomial_xx(const int k, const double x)
00059   {
00060     return d*(d-1) * (EvaluateBernsteinPolynomial<d-2>(k-2, x)
00061                       - 2*EvaluateBernsteinPolynomial<d-2>(k-1, x)
00062                       + EvaluateBernsteinPolynomial<d-2>(k, x));
00063   }
00064 
00070   inline
00071   double EvaluateBernsteinRepresentation(const double b0, const double b1, const double b2,
00072                                          const double x)
00073   {
00074     const double b10 = (1.-x)*b0+x*b1;
00075     const double b11 = (1.-x)*b1+x*b2;
00076     
00077     return (1.-x)*b10+x*b11;
00078   }
00079   
00085   inline
00086   double EvaluateBernsteinRepresentation(const double b0, const double b1,
00087                                          const double b2, const double b3,
00088                                          const double x)
00089   {
00090     const double b10 (b0+x*(b1-b0)); // = (1.-x)*b0+x*b1;
00091     const double b11 (b1+x*(b2-b1)); // = (1.-x)*b1+x*b2;
00092     const double b12 (b2+x*(b3-b2)); // = (1.-x)*b2+x*b3;
00093     
00094     const double b20 (b10+x*(b11-b10)); // = (1.-x)*b10+x*b11;
00095     const double b21 (b11+x*(b12-b11)); // = (1.-x)*b11+x*b12;
00096 
00097     return b20+x*(b21-b20); // = (1.-x)*b20+x*b21;
00098   }
00099 
00107   inline
00108   double EvaluateBernsteinRepresentation_x(const double b0, const double b1,
00109                                            const double b2, const double b3,
00110                                            const double x)
00111   {
00112     return 3*EvaluateBernsteinRepresentation(b1-b0, b2-b1, b3-b2, x);
00113   }
00114 
00122   inline
00123   double EvaluateBernsteinRepresentation_xx(const double b0, const double b1,
00124                                             const double b2, const double b3,
00125                                             const double x)
00126   {
00127     return 6*((1-x)*(b2-2*b1+b0) + x*(b3-2*b2+b1));
00128   }
00129   
00135   double EvaluateHermiteSpline(const int i, const double x) {
00136     if (i == 0) {
00137       // phi_0, Bezier coefficients are {0,0,1,1,1,0,0}
00138       if (x <= -1. || x >= 1.) {
00139         return 0.;
00140       } else {
00141         return (x <= 0.
00142                 ? EvaluateBernsteinRepresentation(0., 0., 1., 1., x+1.)
00143 //              (x+1)*(x+1)*(1-2*x)
00144                 : EvaluateBernsteinRepresentation(1., 1., 0., 0., x)
00145 //              (1-x)*(1-x)*(2*x+1)
00146                 );
00147       }
00148     } else {
00149       // phi_1, Bezier coefficients are {0,0,-1/3,0,1/3,0,0}
00150       if (x <= -1. || x >= 1.) {
00151         return 0.;
00152       } else {
00153         return (x <= 0.
00154                 ? EvaluateBernsteinRepresentation(0., 0., -1./3., 0., x+1.)
00155                 : EvaluateBernsteinRepresentation(0., 1./3., 0., 0., x));
00156       }
00157     }
00158   }
00159 
00163   inline
00164   double EvaluateHermiteSpline_td(const int i, const int j, const int k, const double x) {
00165 #if 0
00166     const double factor(1<<j);
00167     return sqrt(factor) * EvaluateHermiteSpline(i, factor * x - k);
00168 #else
00169     return twotothejhalf(j) * EvaluateHermiteSpline(i, (1<<j) * x - k);
00170 #endif
00171   }
00172   
00178   inline
00179   double EvaluateHermiteSpline_x(const int i, const double x) {
00180     if (i == 0) {
00181       // phi_0, Bezier coefficients are {0,0,1,1,1,0,0}
00182       if (x <= -1 || x >= 1) {
00183         return 0;
00184       } else {
00185         return (x <= 0
00186                 ? EvaluateBernsteinRepresentation_x(0, 0, 1, 1, x+1.0)
00187                 : EvaluateBernsteinRepresentation_x(1, 1, 0, 0, x));
00188       }
00189     } else {
00190       // phi_1, Bezier coefficients are {0,0,-1/3,0,1/3,0,0}
00191       if (x <= -1 || x >= 1) {
00192         return 0;
00193       } else {
00194         return (x <= 0
00195                 ? EvaluateBernsteinRepresentation_x(0, 0, -1./3., 0, x+1.0)
00196                 : EvaluateBernsteinRepresentation_x(0, 1./3., 0, 0, x));
00197       }
00198     }
00199   }
00200 
00206   inline
00207   double EvaluateHermiteSpline_xx(const int i, const double x) {
00208     if (i == 0) {
00209       // phi_0, Bezier coefficients are {0,0,1,1,1,0,0}
00210       if (x <= -1 || x >= 1) {
00211         return 0;
00212       } else {
00213         return (x <= 0
00214                 ? EvaluateBernsteinRepresentation_xx(0, 0, 1, 1, x+1.0)
00215                 : EvaluateBernsteinRepresentation_xx(1, 1, 0, 0, x));
00216       }
00217     } else {
00218       // phi_1, Bezier coefficients are {0,0,-1/3,0,1/3,0,0}
00219       if (x <= -1 || x >= 1) {
00220         return 0;
00221       } else {
00222         return (x <= 0
00223                 ? EvaluateBernsteinRepresentation_xx(0, 0, -1./3., 0, x+1.0)
00224                 : EvaluateBernsteinRepresentation_xx(0, 1./3., 0, 0, x));
00225       }
00226     }
00227   }
00228 
00232   inline
00233   double EvaluateHermiteSpline_td_x(const int i, const int j, const int k, const double x) {
00234 #if 0
00235     return twotothejhalf(3*j) * EvaluateHermiteSpline_x(i, (1<<j) * x - k);
00236 #else
00237     return (double)(1<<j) * (double)twotothejhalf(j) * EvaluateHermiteSpline_x(i, (1<<j) * x - k);
00238 #endif
00239   }
00240   
00244   inline
00245   double EvaluateHermiteSpline_td_xx(const int i, const int j, const int k, const double x) {
00246 #if 0
00247     return twotothejhalf(5*j) * EvaluateHermiteSpline_xx(i, (1<<j) * x - k);
00248 #else
00249     const double factor = (double)(1<<j);
00250     return factor * factor * twotothejhalf(j) * EvaluateHermiteSpline_xx(i, (1<<j) * x - k);
00251 #endif
00252   }
00253 
00257   class CubicHermiteInterpolant_td : public Function<1>
00258   {
00259   public:
00261     CubicHermiteInterpolant_td(const int j, const int c, const int k)
00262       : j_(j), c_(c), k_(k) {}
00263     
00265     virtual ~CubicHermiteInterpolant_td() {}
00266     
00268     inline double value(const Point<1>& p,
00269                         const unsigned int component = 0) const
00270     {
00271       return EvaluateHermiteSpline_td(c_, j_, k_, p[0]);
00272     }
00273     
00275     void vector_value(const Point<1> &p,
00276                       Vector<double>& values) const
00277     {
00278       values.resize(1, false);
00279       values[0] = value(p);
00280     }
00281     
00283     void set_j(const int j) { j_ = j; }
00284     
00286     void set_c(const int c) { c_ = c; }
00287 
00289     void set_k(const int k) { k_ = k; }
00290     
00291   protected:
00292     int j_, c_, k_;
00293   };
00294   
00298   class CubicHermiteInterpolant2D_td : public Function<2>
00299   {
00300   public:
00302     CubicHermiteInterpolant2D_td(const int j, const int c0, const int c1, const int k0, const int k1)
00303       : j_(j), c0_(c0), c1_(c1), k0_(k0), k1_(k1) {}
00304     
00306     virtual ~CubicHermiteInterpolant2D_td() {}
00307     
00309     inline double value(const Point<2>& p,
00310                         const unsigned int component = 0) const
00311     {
00312       return EvaluateHermiteSpline_td(c0_, j_, k0_, p[0])
00313         * EvaluateHermiteSpline_td(c1_, j_, k1_, p[1]);
00314     }
00315     
00317     void vector_value(const Point<2> &p,
00318                       Vector<double>& values) const
00319     {
00320       values.resize(1, false);
00321       values[0] = value(p);
00322     }
00323     
00325     void set_j(const int j) { j_ = j; }
00326     
00328     void set_c0(const int c0) { c0_ = c0; }
00329 
00331     void set_c1(const int c1) { c1_ = c1; }
00332 
00334     void set_k0(const int k0) { k0_ = k0; }
00335     
00337     void set_k1(const int k1) { k1_ = k1; }
00338     
00339   protected:
00340     int j_, c0_, c1_, k0_, k1_;
00341   };
00342   
00343 }
00344 
00345 #include <numerics/bezier.cpp>
00346 
00347 #endif
 All Classes Functions Variables Typedefs Enumerations