MathTL
|
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