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
00033
00034
00035
00036
00037 namespace ecl {
00038
00039
00040
00041
00080 template <unsigned int N>
00081 class ECL_PUBLIC Polynomial : public BluePrintFactory< Polynomial<N> >, public FunctionMath< Polynomial<N> > {
00082 public:
00083
00084
00085
00086 typedef Array<double,N+1> Coefficients;
00088
00089
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
00132
00147 void shift_horizontal(const double &shift);
00148
00149
00150
00151
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
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
00254
00255 typedef Array<double,1> Coefficients;
00257
00258
00259
00266 Polynomial() : coeff(Coefficients::Constant(0.0)) {};
00267 virtual ~Polynomial() {};
00268
00269
00270
00271
00278 void shift_horizontal(const double& ) {};
00279
00280
00281
00282
00290 Polynomial<0> derivative() const {
00291 return Polynomial<0>();
00292 }
00300 double derivative(const double& ) const {
00301 return 0.0;
00302 };
00310 double dderivative(const double& ) const {
00311 return 0.0;
00312 };
00313
00314
00315
00316
00331 Coefficients& coefficients() { return coeff; };
00337 const Coefficients& coefficients() const { return coeff; };
00338
00346 double operator ()(const double& ) const {
00347 return coeff[0];
00348 };
00349
00350 private:
00351 Coefficients coeff;
00352 };
00353
00354
00355
00356
00357
00358 typedef Polynomial<1> LinearFunction;
00359 typedef Polynomial<2> QuadraticPolynomial;
00360 typedef Polynomial<3> CubicPolynomial;
00361 typedef Polynomial<5> QuinticPolynomial;
00363
00364
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 ) {
00377 coeff[i] += (*iter)*tmp*coeff[j];
00378 tmp *= (-1*shift);
00379 ++j;
00380 }
00381 }
00382 }
00383
00384
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
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
00440
00441
00442 namespace blueprints {
00443
00444
00445
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
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
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
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
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 };
00792
00793
00794
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
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
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
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
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
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 };
01340
01341 #endif