00001
00008
00009
00010
00011
00012 #ifndef ECL_GEOMETRY_POLYNOMIALS_HPP_
00013 #define ECL_GEOMETRY_POLYNOMIALS_HPP_
00014
00015
00016
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 #include "macros.hpp"
00033
00034
00035
00036
00037
00038 namespace ecl {
00039
00040
00041
00042
00043
00044 template <unsigned int N> class Polynomial;
00045
00046
00047
00048
00049
00061 template<unsigned int N>
00062 class BluePrintFactory< Polynomial<N> > {
00063 public:
00064 BluePrintFactory() {};
00065 ~BluePrintFactory() {};
00066 };
00067
00068
00069
00070
00109 template <unsigned int N>
00110 class ecl_geometry_PUBLIC Polynomial : public BluePrintFactory< Polynomial<N> >, public FunctionMath< Polynomial<N> > {
00111 public:
00112
00113
00114
00115 typedef Array<double,N+1> Coefficients;
00117
00118
00119
00127 Polynomial() : coeff(Coefficients::Constant(0.0)) {};
00128
00153 template<typename Derived>
00154 Polynomial(const BluePrint< Derived > &blueprint) {
00155 blueprint.implementApply(*this);
00156 }
00157 virtual ~Polynomial() {}
00158
00159
00160
00161
00176 void shift_horizontal(const double &shift);
00177
00178
00179
00180
00181
00189 Polynomial<N-1> derivative() const {
00190 Polynomial<N-1> derivative_polynomial;
00191 typename Polynomial<N-1>::Coefficients &derivative_coefficients = derivative_polynomial.coefficients();
00192 for ( unsigned int i = 0; i < N; ++i ) {
00193 derivative_coefficients[i] = (i+1)*coeff[i+1];
00194 }
00195 return derivative_polynomial;
00196 }
00205 double derivative(const double &x) const;
00214 double dderivative(const double &x) const;
00215
00216
00217
00218
00233 Coefficients& coefficients() { return coeff; };
00239 const Coefficients& coefficients() const { return coeff; };
00240
00249 double operator ()(const double &x) const;
00250
00263 template <typename OutputStream, unsigned int Degree>
00264 friend OutputStream& operator << (OutputStream &ostream, const Polynomial<Degree> &polynomial);
00265
00266 private:
00267 Coefficients coeff;
00268 };
00269
00278 template <>
00279 class ECL_PUBLIC Polynomial<0> {
00280 public:
00281
00282
00283
00284 typedef Array<double,1> Coefficients;
00286
00287
00288
00295 Polynomial() : coeff(Coefficients::Constant(0.0)) {};
00296 virtual ~Polynomial() {};
00297
00298
00299
00300
00307 void shift_horizontal(const double& ) {};
00308
00309
00310
00311
00319 Polynomial<0> derivative() const {
00320 return Polynomial<0>();
00321 }
00329 double derivative(const double& ) const {
00330 return 0.0;
00331 };
00339 double dderivative(const double& ) const {
00340 return 0.0;
00341 };
00342
00343
00344
00345
00360 Coefficients& coefficients() { return coeff; };
00366 const Coefficients& coefficients() const { return coeff; };
00367
00375 double operator ()(const double& ) const {
00376 return coeff[0];
00377 };
00378
00379 private:
00380 Coefficients coeff;
00381 };
00382
00383
00384
00385
00386
00387 typedef Polynomial<1> LinearFunction;
00388 typedef Polynomial<2> QuadraticPolynomial;
00389 typedef Polynomial<3> CubicPolynomial;
00390 typedef Polynomial<5> QuinticPolynomial;
00392
00393
00394
00395 template <unsigned int N>
00396 void Polynomial<N>::shift_horizontal(const double &shift)
00397 {
00398 PascalsTriangle<N> pascals_triangle;
00399 typename PascalsTriangle<N>::const_iterator iter;
00400 double tmp;
00401
00402 for ( unsigned int i = 0; i < N; ++i ) {
00403 tmp = -1*shift;
00404 int j = i+1;
00405 for ( iter = (pascals_triangle.begin(i)+1); iter != pascals_triangle.end(i); ++iter ) {
00406 coeff[i] += (*iter)*tmp*coeff[j];
00407 tmp *= (-1*shift);
00408 ++j;
00409 }
00410 }
00411 }
00412
00413
00414
00415 template <unsigned int N>
00416 double Polynomial<N>::operator()(const double &x) const
00417 {
00418 double tmp = x;
00419 double value = coeff[0];
00420 for ( unsigned int i = 1; i <= N; ++i ) {
00421 value += coeff[i]*tmp;
00422 tmp *= x;
00423 }
00424 return value;
00425 }
00426 template <unsigned int N>
00427 double Polynomial<N>::derivative(const double &x) const {
00428
00429 if ( N > 0 ) {
00430 return derivative()(x);
00431 } else {
00432 return 0.0;
00433 }
00434 }
00435
00436 template <unsigned int N>
00437 double Polynomial<N>::dderivative(const double &x) const {
00438
00439 if ( N > 1 ) {
00440 return derivative().derivative()(x);
00441 } else {
00442 return 0.0;
00443 }
00444 }
00445
00446
00447
00448
00449
00450 template <typename OutputStream, unsigned int Degree>
00451 OutputStream& operator << (OutputStream &ostream, const Polynomial<Degree> &polynomial)
00452 {
00453 ecl_compile_time_concept_check(StreamConcept<OutputStream>);
00454
00455 Format<double> format;
00456 format.precision(2);
00457
00458 ostream << format(polynomial.coeff[0]);
00459 for (unsigned int i = 1; i <= Degree; ++i) {
00460 ostream << " + " << format(polynomial.coeff[i]) << "x^" << i;
00461 }
00462 ostream.flush();
00463
00464 return ostream;
00465 }
00466
00467
00468
00469
00470
00471 namespace blueprints {
00472
00473
00474
00475
00476
00491 class ecl_geometry_PUBLIC LinearInterpolation : public ecl::BluePrint<LinearInterpolation> {
00492 public:
00496 typedef ecl::LinearFunction base_type;
00507 LinearInterpolation(const double x_i, const double y_i, const double x_f, const double y_f) :
00508 x_initial(x_i),
00509 y_initial(y_i),
00510 x_final(x_f),
00511 y_final(y_f)
00512 {}
00513
00514 virtual ~LinearInterpolation() {}
00515
00523 ecl::LinearFunction instantiate();
00524
00531 void apply(ecl::LinearFunction& function) const;
00532
00533 private:
00534 double x_initial, y_initial;
00535 double x_final, y_final;
00536 };
00537
00538
00539
00540
00554 class ecl_geometry_PUBLIC LinearPointSlopeForm : public ecl::BluePrint<LinearPointSlopeForm> {
00555 public:
00559 typedef ecl::LinearFunction base_type;
00569 LinearPointSlopeForm(const double x_f, const double y_f, const double s) :
00570 slope(s),
00571 x_final(x_f),
00572 y_final(y_f)
00573 {}
00574
00575 virtual ~LinearPointSlopeForm() {}
00576
00584 ecl::LinearFunction instantiate();
00585
00592 void apply(ecl::LinearFunction& function) const;
00593
00594 private:
00595 double slope;
00596 double x_final, y_final;
00597 };
00598
00599
00600
00601
00602
00603
00620 class ecl_geometry_PUBLIC CubicDerivativeInterpolation : public ecl::BluePrint<CubicDerivativeInterpolation> {
00621 public:
00625 typedef ecl::CubicPolynomial base_type;
00638 CubicDerivativeInterpolation(const double x_i, const double y_i, const double ydot_i,
00639 const double x_f, const double y_f, const double ydot_f) :
00640 x_initial(x_i),
00641 y_initial(y_i),
00642 ydot_initial(ydot_i),
00643 x_final(x_f),
00644 y_final(y_f),
00645 ydot_final(ydot_f)
00646 {}
00647
00648 virtual ~CubicDerivativeInterpolation() {}
00656 ecl::CubicPolynomial instantiate();
00657
00664 void apply(ecl::CubicPolynomial& polynomial) const;
00665
00666 private:
00667 double x_initial, y_initial, ydot_initial;
00668 double x_final, y_final, ydot_final;
00669 };
00670
00671
00672
00673
00690 class ecl_geometry_PUBLIC CubicSecondDerivativeInterpolation : public ecl::BluePrint<CubicSecondDerivativeInterpolation> {
00691 public:
00695 typedef ecl::CubicPolynomial base_type;
00708 CubicSecondDerivativeInterpolation(const double x_i, const double y_i, const double yddot_i,
00709 const double x_f, const double y_f, const double yddot_f) :
00710 x_initial(x_i),
00711 y_initial(y_i),
00712 yddot_initial(yddot_i),
00713 x_final(x_f),
00714 y_final(y_f),
00715 yddot_final(yddot_f)
00716 {}
00717
00718 virtual ~CubicSecondDerivativeInterpolation() {}
00719
00727 base_type instantiate();
00728
00735 void apply(base_type& polynomial) const;
00736
00737 private:
00738 double x_initial, y_initial, yddot_initial;
00739 double x_final, y_final, yddot_final;
00740 };
00741
00742
00743
00744
00745
00764 class ecl_geometry_PUBLIC QuinticInterpolation : public ecl::BluePrint<QuinticInterpolation> {
00765 public:
00769 typedef ecl::QuinticPolynomial base_type;
00784 QuinticInterpolation(const double x_i, const double y_i, const double ydot_i, const double yddot_i,
00785 const double x_f, const double y_f, const double ydot_f, const double yddot_f) :
00786 x_initial(x_i),
00787 y_initial(y_i),
00788 ydot_initial(ydot_i),
00789 yddot_initial(yddot_i),
00790 x_final(x_f),
00791 y_final(y_f),
00792 ydot_final(ydot_f),
00793 yddot_final(yddot_f)
00794 {}
00795
00796 virtual ~QuinticInterpolation() {}
00797
00805 ecl::QuinticPolynomial instantiate();
00806
00813 void apply(ecl::QuinticPolynomial& polynomial) const;
00814
00815 private:
00816 double x_initial, y_initial, ydot_initial, yddot_initial;
00817 double x_final, y_final, ydot_final, yddot_final;
00818 };
00819
00820 };
00821
00822
00823
00824
00825
00826 using blueprints::LinearInterpolation;
00827 using blueprints::LinearPointSlopeForm;
00828 using blueprints::CubicDerivativeInterpolation;
00829 using blueprints::CubicSecondDerivativeInterpolation;
00830 using blueprints::QuinticInterpolation;
00831
00846 template<>
00847 class BluePrintFactory< LinearFunction > {
00848 public:
00861 static LinearInterpolation Interpolation(const double x_i, const double y_i, const double x_f, const double y_f);
00870 static LinearPointSlopeForm PointSlopeForm(const double x_f, const double y_f, const double slope);
00871 virtual ~BluePrintFactory() {}
00872 };
00873
00889 template<>
00890 class BluePrintFactory< CubicPolynomial > {
00891 public:
00909 static CubicDerivativeInterpolation DerivativeInterpolation(const double x_i, const double y_i, const double ydot_i,
00910 const double x_f, const double y_f, const double ydot_f);
00911
00929 static CubicSecondDerivativeInterpolation SecondDerivativeInterpolation(const double x_i, const double y_i, const double yddot_i,
00930 const double x_f, const double y_f, const double yddot_f);
00931
00932 virtual ~BluePrintFactory() {}
00933 };
00934
00949 template<>
00950 class BluePrintFactory< QuinticPolynomial > {
00951 public:
00971 static QuinticInterpolation Interpolation(const double x_i, const double y_i, const double ydot_i, const double yddot_i,
00972 const double x_f, const double y_f, const double ydot_f, const double yddot_f);
00973
00974 virtual ~BluePrintFactory() {}
00975 };
00976
00977
00978
00979
00980
00989 template<>
00990 class ecl_geometry_PUBLIC Maximum< LinearFunction > {
00991 public:
01002 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const LinearFunction &function);
01003 virtual ~Maximum() {}
01004 };
01005
01013 template<>
01014 class ecl_geometry_PUBLIC Maximum<CubicPolynomial> {
01015 public:
01026 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const CubicPolynomial& cubic);
01027 virtual ~Maximum() {}
01028 };
01029
01038 template<>
01039 class ecl_geometry_PUBLIC Minimum< LinearFunction > {
01040 public:
01051 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const LinearFunction &function);
01052 virtual ~Minimum() {}
01053 };
01054
01062 template<>
01063 class ecl_geometry_PUBLIC Minimum<CubicPolynomial> {
01064 public:
01075 ECL_PUBLIC double operator()(const double& x_begin, const double& x_end, const CubicPolynomial& cubic);
01076 virtual ~Minimum() {}
01077 };
01078
01079
01080
01081
01087 template<>
01088 class ecl_geometry_PUBLIC Intersection< LinearFunction > {
01089 public:
01090 Intersection() : last_operation_failed(false) {}
01091 virtual ~Intersection() {}
01101 ECL_PUBLIC CartesianPoint2d operator()(const LinearFunction& f, const LinearFunction& g) ecl_throw_decl(StandardException);
01102
01109 bool fail() const { return last_operation_failed; }
01110
01111 private:
01112 bool last_operation_failed;
01113 };
01114
01115
01116
01117
01123 template<>
01124 class ecl_geometry_PUBLIC Division<QuadraticPolynomial> {
01125 public:
01126 Division() {};
01127 virtual ~Division() {};
01135 ECL_PUBLIC LinearFunction operator()(const QuadraticPolynomial &p, const double &factor, double &remainder);
01136 };
01137
01143 template<>
01144 class ecl_geometry_PUBLIC Division<CubicPolynomial> {
01145 public:
01146 Division() {};
01147 virtual ~Division() {};
01155 ECL_PUBLIC QuadraticPolynomial operator()(const CubicPolynomial &p, const double &factor, double &remainder);
01156 };
01157
01158
01159
01160
01166 template<>
01167 class ecl_geometry_PUBLIC Roots<LinearFunction> {
01168 public:
01169 Roots() {}
01170 virtual ~Roots() {}
01177 ECL_PUBLIC Array<double> operator()(const LinearFunction& p);
01178 };
01179
01185 template<>
01186 class ecl_geometry_PUBLIC Roots<QuadraticPolynomial> {
01187 public:
01188 Roots() {}
01189 virtual ~Roots() {}
01196 ECL_PUBLIC Array<double> operator()(const QuadraticPolynomial& p);
01197 };
01203 template<>
01204 class ecl_geometry_PUBLIC Roots<CubicPolynomial> {
01205 public:
01206 Roots() {}
01207 virtual ~Roots() {}
01214 ECL_PUBLIC Array<double> operator()(const CubicPolynomial& p);
01215 };
01216
01217
01218
01219
01231 template <>
01232 class ECL_PUBLIC FunctionMath<LinearFunction> {
01233 public:
01234 FunctionMath() {};
01235 virtual ~FunctionMath() {};
01241 static CartesianPoint2d Intersection(const LinearFunction &f, const LinearFunction &g) ecl_throw_decl(StandardException) {
01242 CartesianPoint2d point;
01243 ecl_try {
01244 ecl::Intersection< LinearFunction > intersection;
01245 point = intersection(f,g);
01246 } ecl_catch( const StandardException &e ) {
01247 ecl_throw(StandardException(LOC,e));
01248 }
01249 return point;
01250 }
01256 static Array<double> Roots(const LinearFunction &function) {
01257 return ecl::Roots<LinearFunction>()(function);
01258 }
01264 static double Minimum(const double& x_begin, const double& x_end, const LinearFunction &function) {
01265 return ecl::Minimum<LinearFunction>()(x_begin, x_end, function);
01266 }
01272 static double Maximum(const double& x_begin, const double& x_end, const LinearFunction &function) {
01273 return ecl::Maximum<LinearFunction>()(x_begin, x_end, function);
01274 }
01275 };
01283 template <>
01284 class ECL_PUBLIC FunctionMath<QuadraticPolynomial> {
01285 public:
01286 FunctionMath() {};
01287 virtual ~FunctionMath() {};
01293 static Array<double> Roots(const QuadraticPolynomial &p) {
01294 return ecl::Roots<QuadraticPolynomial>()(p);
01295 }
01299 static LinearFunction Division(const QuadraticPolynomial &p, const double &factor, double &remainder) {
01300 LinearFunction f(ecl::Division<QuadraticPolynomial>()(p,factor,remainder));
01301 return f;
01302 }
01303 };
01304
01312 template <>
01313 class ECL_PUBLIC FunctionMath<CubicPolynomial> {
01314 public:
01315 FunctionMath() {};
01316 virtual ~FunctionMath() {};
01322 static Array<double> Roots(const CubicPolynomial &p) {
01323 return ecl::Roots<CubicPolynomial>()(p);
01324 }
01328 static QuadraticPolynomial Division(const CubicPolynomial &p, const double &factor, double &remainder) {
01329 QuadraticPolynomial q(ecl::Division<CubicPolynomial>()(p,factor,remainder));
01330 return q;
01331 }
01337 static double Minimum(const double& x_begin, const double& x_end, const CubicPolynomial &function) {
01338 return ecl::Minimum<CubicPolynomial>()(x_begin, x_end, function);
01339 }
01345 static double Maximum(const double& x_begin, const double& x_end, const CubicPolynomial &function) {
01346 return ecl::Maximum<CubicPolynomial>()(x_begin, x_end, function);
01347 }
01348 };
01349
01350 };
01351
01352 #endif