curve_abc.h 5.35 KB
Newer Older
1
/**
Guilhem Saurel's avatar
Guilhem Saurel committed
2
3
4
5
6
7
8
9
 * \file curve_abc.h
 * \brief interface for a Curve of arbitrary dimension.
 * \author Steve T.
 * \version 0.1
 * \date 06/17/2013
 *
 * Interface for a curve
 */
10

11
12
#ifndef _STRUCT_CURVE_ABC
#define _STRUCT_CURVE_ABC
13
14

#include "MathDefs.h"
15
16
#include "serialization/archive.hpp"
#include "serialization/eigen-matrix.hpp"
17
#include <boost/serialization/shared_ptr.hpp>
18
#include <boost/smart_ptr/shared_ptr.hpp>
19

20
#include <functional>
21

Guilhem Saurel's avatar
Format    
Guilhem Saurel committed
22
namespace curves {
23
24
25
26
27
28
29

template <typename T>
bool isApprox(const T a, const T b, const T eps = 1e-6)
{
    return fabs(a - b) < eps;
}

Guilhem Saurel's avatar
Guilhem Saurel committed
30
31
32
/// \struct curve_abc.
/// \brief Represents a curve of dimension Dim.
/// If value of parameter Safe is false, no verification is made on the evaluation of the curve.
Guilhem Saurel's avatar
Format    
Guilhem Saurel committed
33
34
35
36
37
38
template <typename Time = double, typename Numeric = Time, bool Safe = false,
          typename Point = Eigen::Matrix<Numeric, Eigen::Dynamic, 1>, typename Point_derivate = Point>
struct curve_abc : std::unary_function<Time, Point>, public serialization::Serializable {
  typedef Point point_t;
  typedef Point_derivate point_derivate_t;
  typedef Time time_t;
39
  typedef Numeric num_t;
40
41
  typedef curve_abc<Time, Numeric, Safe, point_t,point_derivate_t> curve_t; // parent class
  typedef boost::shared_ptr<curve_t> curve_ptr_t;
42

Guilhem Saurel's avatar
Guilhem Saurel committed
43
44
45
46
  /* Constructors - destructors */
 public:
  /// \brief Constructor.
  curve_abc() {}
47

Guilhem Saurel's avatar
Guilhem Saurel committed
48
49
50
  /// \brief Destructor.
  virtual ~curve_abc() {}
  /* Constructors - destructors */
51

Guilhem Saurel's avatar
Guilhem Saurel committed
52
53
54
55
56
  /*Operations*/
  ///  \brief Evaluation of the cubic spline at time t.
  ///  \param t : time when to evaluate the spine
  ///  \return \f$x(t)\f$, point corresponding on curve at time t.
  virtual point_t operator()(const time_t t) const = 0;
t steve's avatar
t steve committed
57

58
59
60

  ///  \brief Compute the derived curve at order N.
  ///  \param order : order of derivative.
61
62
  ///  \return A pointer to \f$\frac{d^Nx(t)}{dt^N}\f$ derivative order N of the curve.
  virtual curve_t* compute_derivate_ptr(const std::size_t order) const = 0;
63

Guilhem Saurel's avatar
Guilhem Saurel committed
64
65
66
67
  /// \brief Evaluate the derivative of order N of curve at time t.
  /// \param t : time when to evaluate the spline.
  /// \param order : order of derivative.
  /// \return \f$\frac{d^Nx(t)}{dt^N}\f$, point corresponding on derivative curve of order N at time t.
68
69
  virtual point_derivate_t derivate(const time_t t, const std::size_t order) const = 0;

70
71
72
73
74
75
76
77
78
  /**
   * @brief isEquivalent check if other and *this are approximately equal by values, given a precision treshold.
   * This test is done by discretizing both curves and evaluating them and their derivatives.
   * @param other the other curve to check
   * @param order the order up to which the derivatives of the curves are checked for equality
   * @param prec the precision treshold, default Eigen::NumTraits<Numeric>::dummy_precision()
   * @return true is the two curves are approximately equals
   */
  bool isEquivalent(const curve_t* other, const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision(),const size_t order = 5) const{
79
80
    bool equal  = curves::isApprox<num_t> (min(), other->min())
               && curves::isApprox<num_t> (max(), other->max())
81
82
83
84
               && (dim() == other->dim());
    if(!equal){
      return false;
    }
85
    time_t inc = (max() - min()) / 10.; // FIXME : define this step somewhere ??
86
    // check the value along the two curves
87
    time_t t = min();
88
89
90
91
    while(t<= max()){
      if(!(*this)(t).isApprox(other->operator()(t),prec)){
        return false;
      }
92
      t += inc;
93
94
95
96
97
98
99
100
    }
    //  check if the derivatives are equals
    for(size_t n = 1 ; n <= order ; ++n){
      t = min();
      while(t<= max()){
        if(!derivate(t,n).isApprox(other->derivate(t,n),prec)){
          return false;
        }
101
        t += inc;
102
103
104
105
      }
    }
    return true;
  }
106

107
  /**
108
109
110
   * @brief isApprox check if other and *this are approximately equals given a precision treshold
   * Only two curves of the same class can be approximately equals,
   * for comparison between different type of curves see isEquivalent.
111
112
113
114
   * @param other the other curve to check
   * @param prec the precision treshold, default Eigen::NumTraits<Numeric>::dummy_precision()
   * @return true is the two curves are approximately equals
   */
115
  virtual bool isApprox(const curve_t* other, const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const = 0;
116

Guilhem Saurel's avatar
Guilhem Saurel committed
117
  /*Operations*/
118

Guilhem Saurel's avatar
Guilhem Saurel committed
119
120
121
122
123
124
125
126
127
128
  /*Helpers*/
  /// \brief Get dimension of curve.
  /// \return dimension of curve.
  virtual std::size_t dim() const = 0;
  /// \brief Get the minimum time for which the curve is defined.
  /// \return \f$t_{min}\f$, lower bound of time range.
  virtual time_t min() const = 0;
  /// \brief Get the maximum time for which the curve is defined.
  /// \return \f$t_{max}\f$, upper bound of time range.
  virtual time_t max() const = 0;
129
130
131
132
  /// \brief Get the degree of the curve.
  /// \return \f$degree\f$, the degree of the curve.
  virtual std::size_t  degree() const =0;

Guilhem Saurel's avatar
Guilhem Saurel committed
133
134
  std::pair<time_t, time_t> timeRange() { return std::make_pair(min(), max()); }
  /*Helpers*/
135

Guilhem Saurel's avatar
Guilhem Saurel committed
136
137
138
  // Serialization of the class
  friend class boost::serialization::access;
  template <class Archive>
Pierre Fernbach's avatar
Pierre Fernbach committed
139
  void serialize(Archive& /*ar*/, const unsigned int version) {
Guilhem Saurel's avatar
Guilhem Saurel committed
140
141
142
143
144
    if (version) {
      // Do something depending on version ?
    }
  }
};
145
BOOST_SERIALIZATION_ASSUME_ABSTRACT(curve_abc)
Guilhem Saurel's avatar
Guilhem Saurel committed
146
147
}  // namespace curves
#endif  //_STRUCT_CURVE_ABC