$search
00001 00008 /***************************************************************************** 00009 ** Ifdefs 00010 *****************************************************************************/ 00011 00012 #ifndef ECL_GEOMETRY_POLYNOMIALS_HPP_ 00013 #define ECL_GEOMETRY_POLYNOMIALS_HPP_ 00014 00015 /***************************************************************************** 00016 ** Includes 00017 *****************************************************************************/ 00018 00019 #include <cmath> 00020 #include "cartesian_point.hpp" 00021 #include "function_math.hpp" 00022 #include "pascals_triangle.hpp" 00023 #include <ecl/config/macros.hpp> 00024 #include <ecl/concepts/macros.hpp> 00025 #include <ecl/concepts/streams.hpp> 00026 #include <ecl/containers/array.hpp> 00027 #include <ecl/exceptions/standard_exception.hpp> 00028 #include <ecl/errors/compile_time_assert.hpp> 00029 #include <ecl/utilities/blueprints.hpp> 00030 #include <ecl/formatters/floats.hpp> 00031 #include <iostream> 00032 00033 /***************************************************************************** 00034 ** Namespaces 00035 *****************************************************************************/ 00036 00037 namespace ecl { 00038 00039 /***************************************************************************** 00040 ** Interface [Polynomial] 00041 *****************************************************************************/ 00080 template <unsigned int N> 00081 class ECL_PUBLIC Polynomial : public BluePrintFactory< Polynomial<N> >, public FunctionMath< Polynomial<N> > { 00082 public: 00083 /********************* 00084 ** Convenience 00085 **********************/ 00086 typedef Array<double,N+1> Coefficients; 00088 /********************* 00089 ** C&D 00090 **********************/ 00098 Polynomial() : coeff(Coefficients::Constant(0.0)) {}; 00099 00124 template<typename Derived> 00125 Polynomial(const BluePrint< Derived > &blueprint) { 00126 blueprint.implementApply(*this); 00127 } 00128 virtual ~Polynomial() {} 00129 00130 /********************* 00131 ** Transform 00132 **********************/ 00147 void shift_horizontal(const double &shift); 00148 // void stretch_horizontal(double multiplier); 00149 00150 /********************* 00151 ** Derivatives 00152 **********************/ 00160 Polynomial<N-1> derivative() const { 00161 Polynomial<N-1> derivative_polynomial; 00162 typename Polynomial<N-1>::Coefficients &derivative_coefficients = derivative_polynomial.coefficients(); 00163 for ( unsigned int i = 0; i < N; ++i ) { 00164 derivative_coefficients[i] = (i+1)*coeff[i+1]; 00165 } 00166 return derivative_polynomial; 00167 } 00176 double derivative(const double &x) const; 00185 double dderivative(const double &x) const; 00186 00187 /********************* 00188 ** Accessors 00189 **********************/ 00204 Coefficients& coefficients() { return coeff; }; 00210 const Coefficients& coefficients() const { return coeff; }; 00211 00220 double operator ()(const double &x) const; 00221 00234 template <typename OutputStream, unsigned int Degree> 00235 friend OutputStream& operator << (OutputStream &ostream, const Polynomial<Degree> &polynomial); 00236 00237 private: 00238 Coefficients coeff; 00239 }; 00240 00249 template <> 00250 class ECL_PUBLIC Polynomial<0> { 00251 public: 00252 /********************* 00253 ** Convenience 00254 **********************/ 00255 typedef Array<double,1> Coefficients; 00257 /********************* 00258 ** C&D 00259 **********************/ 00266 Polynomial() : coeff(Coefficients::Constant(0.0)) {}; 00267 virtual ~Polynomial() {}; 00268 00269 /********************* 00270 ** Transform 00271 **********************/ 00278 void shift_horizontal(const double& /* shift */) {}; // Does nothing. 00279 00280 /********************* 00281 ** Derivatives 00282 **********************/ 00290 Polynomial<0> derivative() const { 00291 return Polynomial<0>(); 00292 } 00300 double derivative(const double& /* x */ ) const { 00301 return 0.0; 00302 }; 00310 double dderivative(const double& /* x */) const { 00311 return 0.0; 00312 }; 00313 00314 /********************* 00315 ** Accessors 00316 **********************/ 00331 Coefficients& coefficients() { return coeff; }; 00337 const Coefficients& coefficients() const { return coeff; }; 00338 00346 double operator ()(const double& /* x */) const { 00347 return coeff[0]; 00348 }; 00349 00350 private: 00351 Coefficients coeff; 00352 }; 00353 00354 /***************************************************************************** 00355 ** Typedefs 00356 *****************************************************************************/ 00357 00358 typedef Polynomial<1> LinearFunction; 00359 typedef Polynomial<2> QuadraticPolynomial; 00360 typedef Polynomial<3> CubicPolynomial; 00361 typedef Polynomial<5> QuinticPolynomial; 00363 /***************************************************************************** 00364 * Implementation [Polynomial - Transform] 00365 ****************************************************************************/ 00366 template <unsigned int N> 00367 void Polynomial<N>::shift_horizontal(const double &shift) 00368 { 00369 PascalsTriangle<N> pascals_triangle; 00370 typename PascalsTriangle<N>::const_iterator iter; 00371 double tmp; 00372 00373 for ( unsigned int i = 0; i < N; ++i ) { 00374 tmp = -1*shift; 00375 int j = i+1; 00376 for ( iter = (pascals_triangle.begin(i)+1); iter != pascals_triangle.end(i); ++iter ) { // skip the first one 00377 coeff[i] += (*iter)*tmp*coeff[j]; 00378 tmp *= (-1*shift); 00379 ++j; 00380 } 00381 } 00382 } 00383 /***************************************************************************** 00384 * Implementation [Polynomial - Access] 00385 ****************************************************************************/ 00386 template <unsigned int N> 00387 double Polynomial<N>::operator()(const double &x) const 00388 { 00389 double tmp = x; 00390 double value = coeff[0]; 00391 for ( unsigned int i = 1; i <= N; ++i ) { 00392 value += coeff[i]*tmp; 00393 tmp *= x; 00394 } 00395 return value; 00396 } 00397 template <unsigned int N> 00398 double Polynomial<N>::derivative(const double &x) const { 00399 00400 if ( N > 0 ) { 00401 return derivative()(x); 00402 } else { 00403 return 0.0; 00404 } 00405 } 00406 00407 template <unsigned int N> 00408 double Polynomial<N>::dderivative(const double &x) const { 00409 00410 if ( N > 1 ) { 00411 return derivative().derivative()(x); 00412 } else { 00413 return 0.0; 00414 } 00415 } 00416 00417 /***************************************************************************** 00418 ** Streaming Operator [Polynomial] 00419 *****************************************************************************/ 00420 00421 template <typename OutputStream, unsigned int Degree> 00422 OutputStream& operator << (OutputStream &ostream, const Polynomial<Degree> &polynomial) 00423 { 00424 ecl_compile_time_concept_check(StreamConcept<OutputStream>); 00425 00426 Format<double> format; 00427 format.precision(2); 00428 00429 ostream << format(polynomial.coeff[0]); 00430 for (unsigned int i = 1; i <= Degree; ++i) { 00431 ostream << " + " << format(polynomial.coeff[i]) << "x^" << i; 00432 } 00433 ostream.flush(); 00434 00435 return ostream; 00436 } 00437 00438 /***************************************************************************** 00439 ** BluePrints 00440 *****************************************************************************/ 00441 00442 namespace blueprints { 00443 00444 /***************************************************************************** 00445 ** Interface [LinearInterpolation] 00446 *****************************************************************************/ 00447 00462 class LinearInterpolation : public ecl::BluePrint<LinearInterpolation> { 00463 public: 00467 typedef ecl::LinearFunction base_type; 00478 LinearInterpolation(const double x_i, const double y_i, const double x_f, const double y_f) : 00479 x_initial(x_i), 00480 y_initial(y_i), 00481 x_final(x_f), 00482 y_final(y_f) 00483 {} 00484 00485 virtual ~LinearInterpolation() {} 00486 00494 ecl::LinearFunction instantiate(); 00495 00502 void apply(ecl::LinearFunction& function) const; 00503 00504 private: 00505 double x_initial, y_initial; 00506 double x_final, y_final; 00507 }; 00508 00509 /***************************************************************************** 00510 ** Interface [LinearPointSlope] 00511 *****************************************************************************/ 00525 class LinearPointSlopeForm : public ecl::BluePrint<LinearPointSlopeForm> { 00526 public: 00530 typedef ecl::LinearFunction base_type; 00540 LinearPointSlopeForm(const double x_f, const double y_f, const double s) : 00541 slope(s), 00542 x_final(x_f), 00543 y_final(y_f) 00544 {} 00545 00546 virtual ~LinearPointSlopeForm() {} 00547 00555 ecl::LinearFunction instantiate(); 00556 00563 void apply(ecl::LinearFunction& function) const; 00564 00565 private: 00566 double slope; 00567 double x_final, y_final; 00568 }; 00569 00570 00571 /***************************************************************************** 00572 ** Interface [CubicDerivativeInterpolation] 00573 *****************************************************************************/ 00574 00591 class CubicDerivativeInterpolation : public ecl::BluePrint<CubicDerivativeInterpolation> { 00592 public: 00596 typedef ecl::CubicPolynomial base_type; 00609 CubicDerivativeInterpolation(const double x_i, const double y_i, const double ydot_i, 00610 const double x_f, const double y_f, const double ydot_f) : 00611 x_initial(x_i), 00612 y_initial(y_i), 00613 ydot_initial(ydot_i), 00614 x_final(x_f), 00615 y_final(y_f), 00616 ydot_final(ydot_f) 00617 {} 00618 00619 virtual ~CubicDerivativeInterpolation() {} 00627 ecl::CubicPolynomial instantiate(); 00628 00635 void apply(ecl::CubicPolynomial& polynomial) const; 00636 00637 private: 00638 double x_initial, y_initial, ydot_initial; 00639 double x_final, y_final, ydot_final; 00640 }; 00641 /***************************************************************************** 00642 ** Interface [CubicSecondDerivativeInterpolation] 00643 *****************************************************************************/ 00644 00661 class CubicSecondDerivativeInterpolation : public ecl::BluePrint<CubicSecondDerivativeInterpolation> { 00662 public: 00666 typedef ecl::CubicPolynomial base_type; 00679 CubicSecondDerivativeInterpolation(const double x_i, const double y_i, const double yddot_i, 00680 const double x_f, const double y_f, const double yddot_f) : 00681 x_initial(x_i), 00682 y_initial(y_i), 00683 yddot_initial(yddot_i), 00684 x_final(x_f), 00685 y_final(y_f), 00686 yddot_final(yddot_f) 00687 {} 00688 00689 virtual ~CubicSecondDerivativeInterpolation() {} 00690 00698 base_type instantiate(); 00699 00706 void apply(base_type& polynomial) const; 00707 00708 private: 00709 double x_initial, y_initial, yddot_initial; 00710 double x_final, y_final, yddot_final; 00711 }; 00712 00713 /***************************************************************************** 00714 ** Interface [QuinticInterpolation] 00715 *****************************************************************************/ 00716 00735 class QuinticInterpolation : public ecl::BluePrint<QuinticInterpolation> { 00736 public: 00740 typedef ecl::QuinticPolynomial base_type; 00755 QuinticInterpolation(const double x_i, const double y_i, const double ydot_i, const double yddot_i, 00756 const double x_f, const double y_f, const double ydot_f, const double yddot_f) : 00757 x_initial(x_i), 00758 y_initial(y_i), 00759 ydot_initial(ydot_i), 00760 yddot_initial(yddot_i), 00761 x_final(x_f), 00762 y_final(y_f), 00763 ydot_final(ydot_f), 00764 yddot_final(yddot_f) 00765 {} 00766 00767 virtual ~QuinticInterpolation() {} 00768 00776 ecl::QuinticPolynomial instantiate(); 00777 00784 void apply(ecl::QuinticPolynomial& polynomial) const; 00785 00786 private: 00787 double x_initial, y_initial, ydot_initial, yddot_initial; 00788 double x_final, y_final, ydot_final, yddot_final; 00789 }; 00790 00791 }; // namespace blueprints 00792 00793 /***************************************************************************** 00794 ** BluePrintFactory 00795 *****************************************************************************/ 00796 00797 using blueprints::LinearInterpolation; 00798 using blueprints::LinearPointSlopeForm; 00799 using blueprints::CubicDerivativeInterpolation; 00800 using blueprints::CubicSecondDerivativeInterpolation; 00801 using blueprints::QuinticInterpolation; 00802 00814 template<unsigned int N> 00815 class BluePrintFactory< Polynomial<N> > { 00816 public: 00817 BluePrintFactory() {}; 00818 ~BluePrintFactory() {}; 00819 }; 00820 00835 template<> 00836 class BluePrintFactory< LinearFunction > { 00837 public: 00850 static LinearInterpolation Interpolation(const double x_i, const double y_i, const double x_f, const double y_f); 00859 static LinearPointSlopeForm PointSlopeForm(const double x_f, const double y_f, const double slope); 00860 virtual ~BluePrintFactory() {} 00861 }; 00862 00878 template<> 00879 class BluePrintFactory< CubicPolynomial > { 00880 public: 00898 static CubicDerivativeInterpolation DerivativeInterpolation(const double x_i, const double y_i, const double ydot_i, 00899 const double x_f, const double y_f, const double ydot_f); 00900 00918 static CubicSecondDerivativeInterpolation SecondDerivativeInterpolation(const double x_i, const double y_i, const double yddot_i, 00919 const double x_f, const double y_f, const double yddot_f); 00920 00921 virtual ~BluePrintFactory() {} 00922 }; 00923 00938 template<> 00939 class BluePrintFactory< QuinticPolynomial > { 00940 public: 00960 static QuinticInterpolation Interpolation(const double x_i, const double y_i, const double ydot_i, const double yddot_i, 00961 const double x_f, const double y_f, const double ydot_f, const double yddot_f); 00962 00963 virtual ~BluePrintFactory() {} 00964 }; 00965 00966 00967 /***************************************************************************** 00968 ** Interface [Maximum|Minimum][Polynomial] 00969 *****************************************************************************/ 00978 template<> 00979 class ECL_PUBLIC Maximum< LinearFunction > { 00980 public: 00991 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const LinearFunction &function); 00992 virtual ~Maximum() {} 00993 }; 00994 01002 template<> 01003 class ECL_PUBLIC Maximum<CubicPolynomial> { 01004 public: 01015 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const CubicPolynomial& cubic); 01016 virtual ~Maximum() {} 01017 }; 01018 01027 template<> 01028 class ECL_PUBLIC Minimum< LinearFunction > { 01029 public: 01040 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const LinearFunction &function); 01041 virtual ~Minimum() {} 01042 }; 01043 01051 template<> 01052 class ECL_PUBLIC Minimum<CubicPolynomial> { 01053 public: 01064 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const CubicPolynomial& cubic); 01065 virtual ~Minimum() {} 01066 }; 01067 01068 /***************************************************************************** 01069 ** Interface [Intersection][LinearFunction] 01070 *****************************************************************************/ 01076 template<> 01077 class ECL_PUBLIC Intersection< LinearFunction > { 01078 public: 01079 Intersection() : last_operation_failed(false) {} 01080 virtual ~Intersection() {} 01090 ECL_PUBLIC CartesianPoint2d operator()(const LinearFunction& f, const LinearFunction& g) ecl_throw_decl(StandardException); 01091 01098 bool fail() const { return last_operation_failed; } 01099 01100 private: 01101 bool last_operation_failed; 01102 }; 01103 01104 /***************************************************************************** 01105 ** Interface [Synthetic Division] 01106 *****************************************************************************/ 01112 template<> 01113 class ECL_PUBLIC Division<QuadraticPolynomial> { 01114 public: 01115 Division() {}; 01116 virtual ~Division() {}; 01124 ECL_PUBLIC LinearFunction operator()(const QuadraticPolynomial &p, const double &factor, double &remainder); 01125 }; 01126 01132 template<> 01133 class ECL_PUBLIC Division<CubicPolynomial> { 01134 public: 01135 Division() {}; 01136 virtual ~Division() {}; 01144 ECL_PUBLIC QuadraticPolynomial operator()(const CubicPolynomial &p, const double &factor, double &remainder); 01145 }; 01146 01147 /***************************************************************************** 01148 ** Interface [Roots] 01149 *****************************************************************************/ 01155 template<> 01156 class ECL_PUBLIC Roots<LinearFunction> { 01157 public: 01158 Roots() {} 01159 virtual ~Roots() {} 01166 ECL_PUBLIC Array<double> operator()(const LinearFunction& p); 01167 }; 01168 01174 template<> 01175 class ECL_PUBLIC Roots<QuadraticPolynomial> { 01176 public: 01177 Roots() {} 01178 virtual ~Roots() {} 01185 ECL_PUBLIC Array<double> operator()(const QuadraticPolynomial& p); 01186 }; 01192 template<> 01193 class ECL_PUBLIC Roots<CubicPolynomial> { 01194 public: 01195 Roots() {} 01196 virtual ~Roots() {} 01203 ECL_PUBLIC Array<double> operator()(const CubicPolynomial& p); 01204 }; 01205 01206 /***************************************************************************** 01207 ** Interfaces [FunctionMath] 01208 *****************************************************************************/ 01220 template <> 01221 class ECL_PUBLIC FunctionMath<LinearFunction> { 01222 public: 01223 FunctionMath() {}; 01224 virtual ~FunctionMath() {}; 01230 static CartesianPoint2d Intersection(const LinearFunction &f, const LinearFunction &g) ecl_throw_decl(StandardException) { 01231 CartesianPoint2d point; 01232 ecl_try { 01233 ecl::Intersection< LinearFunction > intersection; 01234 point = intersection(f,g); 01235 } ecl_catch( const StandardException &e ) { 01236 ecl_throw(StandardException(LOC,e)); 01237 } 01238 return point; 01239 } 01245 static Array<double> Roots(const LinearFunction &function) { 01246 return ecl::Roots<LinearFunction>()(function); 01247 } 01253 static double Minimum(const double& x_begin, const double& x_end, const LinearFunction &function) { 01254 return ecl::Minimum<LinearFunction>()(x_begin, x_end, function); 01255 } 01261 static double Maximum(const double& x_begin, const double& x_end, const LinearFunction &function) { 01262 return ecl::Maximum<LinearFunction>()(x_begin, x_end, function); 01263 } 01264 }; 01272 template <> 01273 class ECL_PUBLIC FunctionMath<QuadraticPolynomial> { 01274 public: 01275 FunctionMath() {}; 01276 virtual ~FunctionMath() {}; 01282 static Array<double> Roots(const QuadraticPolynomial &p) { 01283 return ecl::Roots<QuadraticPolynomial>()(p); 01284 } 01288 static LinearFunction Division(const QuadraticPolynomial &p, const double &factor, double &remainder) { 01289 LinearFunction f(ecl::Division<QuadraticPolynomial>()(p,factor,remainder)); 01290 return f; 01291 } 01292 }; 01293 01301 template <> 01302 class ECL_PUBLIC FunctionMath<CubicPolynomial> { 01303 public: 01304 FunctionMath() {}; 01305 virtual ~FunctionMath() {}; 01311 static Array<double> Roots(const CubicPolynomial &p) { 01312 return ecl::Roots<CubicPolynomial>()(p); 01313 } 01317 static QuadraticPolynomial Division(const CubicPolynomial &p, const double &factor, double &remainder) { 01318 QuadraticPolynomial q(ecl::Division<CubicPolynomial>()(p,factor,remainder)); 01319 return q; 01320 } 01326 static double Minimum(const double& x_begin, const double& x_end, const CubicPolynomial &function) { 01327 return ecl::Minimum<CubicPolynomial>()(x_begin, x_end, function); 01328 } 01334 static double Maximum(const double& x_begin, const double& x_end, const CubicPolynomial &function) { 01335 return ecl::Maximum<CubicPolynomial>()(x_begin, x_end, function); 01336 } 01337 }; 01338 01339 }; // namespace ecl 01340 01341 #endif /*ECL_GEOMETRY_POLYNOMIALS_HPP_*/