| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /** | ||
| 2 | * \file bezier_curve.h | ||
| 3 | * \brief class allowing to create a Bezier curve of dimension 1 <= n <= 3. | ||
| 4 | * \author Steve T. | ||
| 5 | * \version 0.1 | ||
| 6 | * \date 06/17/2013 | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _CLASS_BEZIERCURVE | ||
| 10 | #define _CLASS_BEZIERCURVE | ||
| 11 | |||
| 12 | #include <iostream> | ||
| 13 | #include <stdexcept> | ||
| 14 | #include <vector> | ||
| 15 | |||
| 16 | #include "MathDefs.h" | ||
| 17 | #include "bernstein.h" | ||
| 18 | #include "cross_implementation.h" | ||
| 19 | #include "curve_abc.h" | ||
| 20 | #include "curve_constraint.h" | ||
| 21 | #include "piecewise_curve.h" | ||
| 22 | |||
| 23 | namespace ndcurves { | ||
| 24 | /// \class BezierCurve. | ||
| 25 | /// \brief Represents a Bezier curve of arbitrary dimension and order. | ||
| 26 | /// For degree lesser than 4, the evaluation is analitycal. Otherwise | ||
| 27 | /// the bernstein polynoms are used to evaluate the spline at a given location. | ||
| 28 | /// | ||
| 29 | template <typename Time = double, typename Numeric = Time, bool Safe = false, | ||
| 30 | typename Point = Eigen::Matrix<Numeric, Eigen::Dynamic, 1> > | ||
| 31 | struct bezier_curve : public curve_abc<Time, Numeric, Safe, Point> { | ||
| 32 | typedef Point point_t; | ||
| 33 | typedef Eigen::Matrix<Numeric, Eigen::Dynamic, 1> vector_x_t; | ||
| 34 | typedef Eigen::Ref<const vector_x_t> vector_x_ref_t; | ||
| 35 | typedef Time time_t; | ||
| 36 | typedef Numeric num_t; | ||
| 37 | typedef curve_constraints<point_t> curve_constraints_t; | ||
| 38 | typedef std::vector<point_t, Eigen::aligned_allocator<point_t> > t_point_t; | ||
| 39 | typedef typename t_point_t::const_iterator cit_point_t; | ||
| 40 | typedef bezier_curve<Time, Numeric, Safe, Point> bezier_curve_t; | ||
| 41 | typedef std::shared_ptr<bezier_curve_t> bezier_curve_ptr_t; | ||
| 42 | typedef piecewise_curve<Time, Numeric, Safe, point_t, point_t, bezier_curve_t> | ||
| 43 | piecewise_curve_t; | ||
| 44 | typedef curve_abc<Time, Numeric, Safe, point_t> curve_abc_t; // parent class | ||
| 45 | typedef typename curve_abc_t::curve_ptr_t curve_ptr_t; | ||
| 46 | |||
| 47 | /* Constructors - destructors */ | ||
| 48 | public: | ||
| 49 | /// \brief Empty constructor. Curve obtained this way can not perform other | ||
| 50 | /// class functions. | ||
| 51 | /// | ||
| 52 |
1/2✓ Branch 3 taken 121 times.
✗ Branch 4 not taken.
|
242 | bezier_curve() : dim_(0), T_min_(0), T_max_(0) {} |
| 53 | |||
| 54 | /// \brief Constructor. | ||
| 55 | /// Given the first and last point of a control points set, create the bezier | ||
| 56 | /// curve. \param PointsBegin : an iterator pointing to the first element of | ||
| 57 | /// a control point container. \param PointsEnd : an iterator pointing to | ||
| 58 | /// the last element of a control point container. \param T_min : | ||
| 59 | /// lower bound of time, curve will be defined for time in [T_min, T_max]. | ||
| 60 | /// \param T_max : upper bound of time, curve will be defined for time | ||
| 61 | /// in [T_min, T_max]. \param mult_T : ... (default value is 1.0). | ||
| 62 | /// | ||
| 63 | template <typename In> | ||
| 64 | 12084 | bezier_curve(In PointsBegin, In PointsEnd, const time_t T_min = 0., | |
| 65 | const time_t T_max = 1., const time_t mult_T = 1.) | ||
| 66 | 12084 | : dim_(PointsBegin->size()), | |
| 67 | 12084 | T_min_(T_min), | |
| 68 | 12084 | T_max_(T_max), | |
| 69 | 12084 | mult_T_(mult_T), | |
| 70 | 12084 | size_(std::distance(PointsBegin, PointsEnd)), | |
| 71 | 12084 | degree_(size_ - 1), | |
| 72 |
2/4✓ Branch 3 taken 6042 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 6042 times.
✗ Branch 7 not taken.
|
24168 | bernstein_(ndcurves::makeBernstein<num_t>((unsigned int)degree_)) { |
| 73 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6042 times.
|
12084 | if (bernstein_.size() != size_) { |
| 74 | ✗ | throw std::invalid_argument("Invalid size of polynomial"); | |
| 75 | } | ||
| 76 | 12084 | In it(PointsBegin); | |
| 77 |
2/4✓ Branch 0 taken 6042 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6042 times.
|
12084 | if (Safe && (size_ < 1 || T_max_ <= T_min_)) { |
| 78 | ✗ | throw std::invalid_argument( | |
| 79 | "can't create bezier min bound is higher than max bound"); | ||
| 80 | } | ||
| 81 |
3/3✓ Branch 1 taken 113 times.
✓ Branch 2 taken 22083 times.
✓ Branch 3 taken 6019 times.
|
56430 | for (; it != PointsEnd; ++it) { |
| 82 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 22173 times.
|
44346 | if (Safe && static_cast<size_t>(it->size()) != dim_) |
| 83 | ✗ | throw std::invalid_argument( | |
| 84 | "All the control points must have the same dimension."); | ||
| 85 |
2/4✓ Branch 2 taken 22173 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 113 times.
✗ Branch 6 not taken.
|
44346 | control_points_.push_back(*it); |
| 86 | } | ||
| 87 | 12084 | } | |
| 88 | |||
| 89 | /// \brief Constructor with constraints. | ||
| 90 | /// This constructor will add 4 points (2 after the first one, 2 before the | ||
| 91 | /// last one) to ensure that velocity and acceleration constraints are | ||
| 92 | /// respected. \param PointsBegin : an iterator pointing to the first | ||
| 93 | /// element of a control point container. \param PointsEnd : an iterator | ||
| 94 | /// pointing to the last element of a control point container. \param | ||
| 95 | /// constraints : constraints applying on start / end velocities and | ||
| 96 | /// acceleration. \param T_min : lower bound of time, curve will be | ||
| 97 | /// defined for time in [T_min, T_max]. \param T_max : upper bound of | ||
| 98 | /// time, curve will be defined for time in [T_min, T_max]. \param mult_T : | ||
| 99 | /// ... (default value is 1.0). | ||
| 100 | /// | ||
| 101 | template <typename In> | ||
| 102 | 5 | bezier_curve(In PointsBegin, In PointsEnd, | |
| 103 | const curve_constraints_t& constraints, const time_t T_min = 0., | ||
| 104 | const time_t T_max = 1., const time_t mult_T = 1.) | ||
| 105 | 5 | : dim_(PointsBegin->size()), | |
| 106 | 5 | T_min_(T_min), | |
| 107 | 5 | T_max_(T_max), | |
| 108 | 5 | mult_T_(mult_T), | |
| 109 | 5 | size_(std::distance(PointsBegin, PointsEnd) + 4), | |
| 110 | 5 | degree_(size_ - 1), | |
| 111 |
2/4✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
|
10 | bernstein_(ndcurves::makeBernstein<num_t>((unsigned int)degree_)) { |
| 112 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
5 | if (Safe && (size_ < 1 || T_max_ <= T_min_)) { |
| 113 | ✗ | throw std::invalid_argument( | |
| 114 | "can't create bezier min bound is higher than max bound"); | ||
| 115 | } | ||
| 116 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | t_point_t updatedList = |
| 117 | add_constraints<In>(PointsBegin, PointsEnd, constraints); | ||
| 118 |
2/2✓ Branch 4 taken 19 times.
✓ Branch 5 taken 3 times.
|
36 | for (cit_point_t cit = updatedList.begin(); cit != updatedList.end(); |
| 119 | 31 | ++cit) { | |
| 120 |
1/2✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
|
31 | if (Safe && static_cast<size_t>(cit->size()) != dim_) |
| 121 | ✗ | throw std::invalid_argument( | |
| 122 | "All the control points must have the same dimension."); | ||
| 123 |
1/2✓ Branch 2 taken 19 times.
✗ Branch 3 not taken.
|
31 | control_points_.push_back(*cit); |
| 124 | } | ||
| 125 | 5 | } | |
| 126 | |||
| 127 | 4198 | bezier_curve(const bezier_curve& other) | |
| 128 | 4198 | : dim_(other.dim_), | |
| 129 | 4198 | T_min_(other.T_min_), | |
| 130 | 4198 | T_max_(other.T_max_), | |
| 131 | 4198 | mult_T_(other.mult_T_), | |
| 132 | 4198 | size_(other.size_), | |
| 133 | 4198 | degree_(other.degree_), | |
| 134 | 4198 | bernstein_(other.bernstein_), | |
| 135 |
2/4✓ Branch 2 taken 2099 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2099 times.
✗ Branch 6 not taken.
|
4198 | control_points_(other.control_points_) {} |
| 136 | |||
| 137 | ///\brief Destructor | ||
| 138 | 16824 | virtual ~bezier_curve() {} | |
| 139 | |||
| 140 | /*Operations*/ | ||
| 141 | /// \brief Evaluation of the bezier curve at time t. | ||
| 142 | /// \param t : time when to evaluate the curve. | ||
| 143 | /// \return \f$x(t)\f$ point corresponding on curve at time t. | ||
| 144 | 840212 | virtual point_t operator()(const time_t t) const { | |
| 145 | 840212 | check_conditions(); | |
| 146 |
6/6✓ Branch 0 taken 420104 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 420102 times.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 420102 times.
|
840212 | if (Safe & !(T_min_ <= t && t <= T_max_)) { |
| 147 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
8 | throw std::invalid_argument( |
| 148 | "can't evaluate bezier curve, time t is out of range"); // TODO | ||
| 149 | } | ||
| 150 |
2/2✓ Branch 0 taken 400 times.
✓ Branch 1 taken 419702 times.
|
840204 | if (size_ == 1) { |
| 151 |
2/4✓ Branch 2 taken 400 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 400 times.
✗ Branch 6 not taken.
|
800 | return mult_T_ * control_points_[0]; |
| 152 | } else { | ||
| 153 | 839404 | return evalHorner(t); | |
| 154 | } | ||
| 155 | } | ||
| 156 | |||
| 157 | /** | ||
| 158 | * @brief isApprox check if other and *this are approximately equals. | ||
| 159 | * Only two curves of the same class can be approximately equals, for | ||
| 160 | * comparison between different type of curves see isEquivalent | ||
| 161 | * @param other the other curve to check | ||
| 162 | * @param prec the precision threshold, default | ||
| 163 | * Eigen::NumTraits<Numeric>::dummy_precision() | ||
| 164 | * @return true if the two curves are approximately equals | ||
| 165 | */ | ||
| 166 | 50 | bool isApprox( | |
| 167 | const bezier_curve_t& other, | ||
| 168 | const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const { | ||
| 169 |
2/2✓ Branch 2 taken 24 times.
✓ Branch 3 taken 1 times.
|
100 | bool equal = ndcurves::isApprox<num_t>(T_min_, other.min()) && |
| 170 | 50 | ndcurves::isApprox<num_t>(T_max_, other.max()) && | |
| 171 |
3/4✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23 times.
✓ Branch 5 taken 1 times.
|
48 | dim_ == other.dim() && degree_ == other.degree() && |
| 172 |
2/4✓ Branch 0 taken 23 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 23 times.
✗ Branch 3 not taken.
|
92 | size_ == other.size_ && |
| 173 |
1/2✓ Branch 0 taken 25 times.
✗ Branch 1 not taken.
|
146 | ndcurves::isApprox<Numeric>(mult_T_, other.mult_T_) && |
| 174 |
1/2✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
|
46 | bernstein_ == other.bernstein_; |
| 175 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
50 | if (!equal) return false; |
| 176 |
2/2✓ Branch 0 taken 99 times.
✓ Branch 1 taken 20 times.
|
238 | for (size_t i = 0; i < size_; ++i) { |
| 177 |
2/2✓ Branch 3 taken 3 times.
✓ Branch 4 taken 96 times.
|
198 | if (!control_points_.at(i).isApprox(other.control_points_.at(i), prec)) |
| 178 | 6 | return false; | |
| 179 | } | ||
| 180 | 40 | return true; | |
| 181 | } | ||
| 182 | |||
| 183 | 40 | virtual bool isApprox( | |
| 184 | const curve_abc_t* other, | ||
| 185 | const Numeric prec = Eigen::NumTraits<Numeric>::dummy_precision()) const { | ||
| 186 | 40 | const bezier_curve_t* other_cast = | |
| 187 |
1/2✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
|
40 | dynamic_cast<const bezier_curve_t*>(other); |
| 188 |
2/2✓ Branch 0 taken 15 times.
✓ Branch 1 taken 5 times.
|
40 | if (other_cast) |
| 189 | 30 | return isApprox(*other_cast, prec); | |
| 190 | else | ||
| 191 | 10 | return false; | |
| 192 | } | ||
| 193 | |||
| 194 | 20 | virtual bool operator==(const bezier_curve_t& other) const { | |
| 195 | 20 | return isApprox(other); | |
| 196 | } | ||
| 197 | |||
| 198 | 6 | virtual bool operator!=(const bezier_curve_t& other) const { | |
| 199 | 6 | return !(*this == other); | |
| 200 | } | ||
| 201 | |||
| 202 | /// \brief Compute the derived curve at order N. | ||
| 203 | /// Computes the derivative order N, \f$\frac{d^Nx(t)}{dt^N}\f$ of bezier | ||
| 204 | /// curve of parametric equation x(t). \param order : order of derivative. | ||
| 205 | /// \return \f$\frac{d^Nx(t)}{dt^N}\f$ derivative order N of the curve. | ||
| 206 | 10654 | bezier_curve_t compute_derivate(const std::size_t order) const { | |
| 207 |
1/2✓ Branch 1 taken 5327 times.
✗ Branch 2 not taken.
|
10654 | check_conditions(); |
| 208 |
2/2✓ Branch 0 taken 1897 times.
✓ Branch 1 taken 3430 times.
|
10654 | if (order == 0) { |
| 209 |
1/2✓ Branch 1 taken 1897 times.
✗ Branch 2 not taken.
|
3794 | return *this; |
| 210 | } | ||
| 211 |
1/2✓ Branch 1 taken 3430 times.
✗ Branch 2 not taken.
|
6860 | t_point_t derived_wp; |
| 212 | 6860 | for (typename t_point_t::const_iterator pit = control_points_.begin(); | |
| 213 |
2/2✓ Branch 3 taken 10848 times.
✓ Branch 4 taken 3430 times.
|
28556 | pit != control_points_.end() - 1; ++pit) { |
| 214 |
4/8✓ Branch 4 taken 10848 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 10848 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 10848 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 10832 times.
✗ Branch 14 not taken.
|
21696 | derived_wp.push_back((num_t)degree_ * (*(pit + 1) - (*pit))); |
| 215 | } | ||
| 216 |
2/2✓ Branch 1 taken 501 times.
✓ Branch 2 taken 2929 times.
|
6860 | if (derived_wp.empty()) { |
| 217 |
3/6✓ Branch 1 taken 501 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 501 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 501 times.
✗ Branch 8 not taken.
|
1002 | derived_wp.push_back(point_t::Zero(dim_)); |
| 218 | } | ||
| 219 |
1/2✓ Branch 2 taken 3430 times.
✗ Branch 3 not taken.
|
6860 | bezier_curve_t deriv(derived_wp.begin(), derived_wp.end(), T_min_, T_max_, |
| 220 | 6860 | mult_T_ * (1. / (T_max_ - T_min_))); | |
| 221 |
1/2✓ Branch 1 taken 3430 times.
✗ Branch 2 not taken.
|
6860 | return deriv.compute_derivate(order - 1); |
| 222 | 6860 | } | |
| 223 | |||
| 224 | /// \brief Compute the derived curve at order N. | ||
| 225 | /// \param order : order of derivative. | ||
| 226 | /// \return A pointer to \f$\frac{d^Nx(t)}{dt^N}\f$ derivative order N of the | ||
| 227 | /// curve. | ||
| 228 | 4 | bezier_curve_t* compute_derivate_ptr(const std::size_t order) const { | |
| 229 |
1/4✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4 | return new bezier_curve_t(compute_derivate(order)); |
| 230 | } | ||
| 231 | |||
| 232 | /// \brief Compute the primitive of the curve at order N. | ||
| 233 | /// Computes the primitive at order N of bezier curve of parametric equation | ||
| 234 | /// \f$x(t)\f$. <br> At order \f$N=1\f$, the primitve \f$X(t)\f$ of | ||
| 235 | /// \f$x(t)\f$ is such as \f$\frac{dX(t)}{dt} = x(t)\f$. \param order : order | ||
| 236 | /// of the primitive. \param init : constant valuefor the first point of the | ||
| 237 | /// primitive (can tipycally be zero) \return primitive at order N of x(t). | ||
| 238 | 38 | bezier_curve_t compute_primitive(const std::size_t order, | |
| 239 | const point_t& init) const { | ||
| 240 |
1/2✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
|
38 | check_conditions(); |
| 241 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
|
38 | if (order == 0) { |
| 242 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
17 | return *this; |
| 243 | } | ||
| 244 | 21 | num_t new_degree_inv = 1. / ((num_t)(degree_ + 1)); | |
| 245 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
21 | t_point_t n_wp; |
| 246 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
21 | point_t current_sum(init); |
| 247 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
21 | n_wp.push_back(current_sum); |
| 248 | 21 | for (typename t_point_t::const_iterator pit = control_points_.begin(); | |
| 249 |
2/2✓ Branch 2 taken 35 times.
✓ Branch 3 taken 11 times.
|
84 | pit != control_points_.end(); ++pit) { |
| 250 |
1/2✓ Branch 2 taken 35 times.
✗ Branch 3 not taken.
|
63 | current_sum += *pit; |
| 251 |
3/6✓ Branch 1 taken 35 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 35 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 28 times.
✗ Branch 8 not taken.
|
63 | n_wp.push_back(current_sum * new_degree_inv); |
| 252 | } | ||
| 253 |
1/2✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
21 | bezier_curve_t integ(n_wp.begin(), n_wp.end(), T_min_, T_max_, |
| 254 | 21 | mult_T_ * (T_max_ - T_min_)); | |
| 255 |
1/2✓ Branch 1 taken 11 times.
✗ Branch 2 not taken.
|
21 | return integ.compute_primitive(order - 1); |
| 256 | 21 | } | |
| 257 | |||
| 258 | 37 | bezier_curve_t compute_primitive(const std::size_t order) const { | |
| 259 |
3/6✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 18 times.
✗ Branch 8 not taken.
|
37 | return compute_primitive(order, point_t::Zero(dim_)); |
| 260 | } | ||
| 261 | |||
| 262 | bezier_curve_t* compute_primitive_ptr(const std::size_t order, | ||
| 263 | const point_t& init) const { | ||
| 264 | return new bezier_curve_t(compute_primitive(order, init)); | ||
| 265 | } | ||
| 266 | |||
| 267 | /// \brief Computes a Bezier curve of order degrees higher than the current | ||
| 268 | /// curve, but strictly equivalent. Order elevation is required for addition | ||
| 269 | /// / substraction and other comparison operations. \param order : number of | ||
| 270 | /// order the curve must be updated \return An equivalent Bezier, with one | ||
| 271 | /// more degree. | ||
| 272 | 30 | bezier_curve_t elevate(const std::size_t order) const { | |
| 273 |
2/4✓ Branch 1 taken 21 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 21 times.
✗ Branch 5 not taken.
|
30 | t_point_t new_waypoints = control_points_, temp_waypoints; |
| 274 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 21 times.
|
84 | for (std::size_t i = 1; i <= order; ++i) { |
| 275 | 54 | num_t new_degree_inv = 1. / ((num_t)(degree_ + i)); | |
| 276 |
1/2✓ Branch 3 taken 44 times.
✗ Branch 4 not taken.
|
54 | temp_waypoints.push_back(*new_waypoints.begin()); |
| 277 | 54 | num_t idx_deg_inv = 0.; | |
| 278 | 54 | for (typename t_point_t::const_iterator pit = new_waypoints.begin() + 1; | |
| 279 |
2/2✓ Branch 2 taken 120 times.
✓ Branch 3 taken 44 times.
|
185 | pit != new_waypoints.end(); ++pit) { |
| 280 | 131 | idx_deg_inv += new_degree_inv; | |
| 281 |
4/10✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 120 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 120 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 120 times.
✗ Branch 10 not taken.
✓ Branch 12 taken 120 times.
✗ Branch 13 not taken.
|
131 | temp_waypoints.push_back(idx_deg_inv * (*(pit - 1)) + |
| 282 |
1/2✓ Branch 2 taken 120 times.
✗ Branch 3 not taken.
|
262 | (1 - idx_deg_inv) * (*pit)); |
| 283 | } | ||
| 284 |
1/2✓ Branch 4 taken 44 times.
✗ Branch 5 not taken.
|
54 | temp_waypoints.push_back(*(new_waypoints.end() - 1)); |
| 285 |
1/2✓ Branch 1 taken 44 times.
✗ Branch 2 not taken.
|
54 | new_waypoints = temp_waypoints; |
| 286 | 54 | temp_waypoints.clear(); | |
| 287 | } | ||
| 288 | 30 | return bezier_curve_t(new_waypoints.begin(), new_waypoints.end(), T_min_, | |
| 289 |
1/2✓ Branch 3 taken 21 times.
✗ Branch 4 not taken.
|
60 | T_max_, mult_T_); |
| 290 | 30 | } | |
| 291 | |||
| 292 | /// \brief Elevate the Bezier curve of order degrees higher than the current | ||
| 293 | /// curve, but strictly equivalent. Order elevation is required for addition | ||
| 294 | /// / substraction and other comparison operations. \param order : number of | ||
| 295 | /// order the curve must be updated | ||
| 296 | 24 | void elevate_self(const std::size_t order) { | |
| 297 |
3/6✓ Branch 0 taken 17 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 17 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 17 times.
✗ Branch 7 not taken.
|
24 | if (order > 0) (*this) = elevate(order); |
| 298 | 24 | } | |
| 299 | |||
| 300 | /// \brief Evaluate the derivative order N of curve at time t. | ||
| 301 | /// If derivative is to be evaluated several times, it is | ||
| 302 | /// rather recommended to compute derived curve using compute_derivate. | ||
| 303 | /// \param order : order of derivative. | ||
| 304 | /// \param t : time when to evaluate the curve. | ||
| 305 | /// \return \f$\frac{d^Nx(t)}{dt^N}\f$ point corresponding on derived curve | ||
| 306 | /// of order N at time t. | ||
| 307 | /// | ||
| 308 | 3764 | virtual point_t derivate(const time_t t, const std::size_t order) const { | |
| 309 |
2/4✓ Branch 1 taken 1882 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1882 times.
✗ Branch 5 not taken.
|
3764 | return compute_derivate(order)(t); |
| 310 | } | ||
| 311 | |||
| 312 | /// \brief Evaluate all Bernstein polynomes for a certain degree. | ||
| 313 | /// A bezier curve with N control points is represented by : \f$x(t) = | ||
| 314 | /// \sum_{i=0}^{N} B_i^N(t) P_i\f$ with \f$ B_i^N(t) = \binom{N}{i}t^i | ||
| 315 | /// (1-t)^{N-i} \f$.<br/> Warning: the horner scheme is about 100 times faster | ||
| 316 | /// than this method.<br> This method will probably be removed in the future | ||
| 317 | /// as the computation of bernstein polynomial is very costly. \param t : time | ||
| 318 | /// when to evaluate the curve. \return \f$x(t)\f$ point corresponding on | ||
| 319 | /// curve at time t. | ||
| 320 | /// | ||
| 321 | 200020 | point_t evalBernstein(const Numeric t) const { | |
| 322 | 200020 | const Numeric u = (t - T_min_) / (T_max_ - T_min_); | |
| 323 |
2/4✓ Branch 1 taken 200020 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 200020 times.
✗ Branch 5 not taken.
|
200020 | point_t res = point_t::Zero(dim_); |
| 324 | typename t_point_t::const_iterator control_points_it = | ||
| 325 | 200020 | control_points_.begin(); | |
| 326 | 200020 | for (typename std::vector<Bern<Numeric> >::const_iterator cit = | |
| 327 | 200020 | bernstein_.begin(); | |
| 328 |
2/2✓ Branch 3 taken 1200070 times.
✓ Branch 4 taken 200020 times.
|
1400090 | cit != bernstein_.end(); ++cit, ++control_points_it) { |
| 329 |
3/6✓ Branch 3 taken 1200070 times.
✗ Branch 4 not taken.
✓ Branch 6 taken 1200070 times.
✗ Branch 7 not taken.
✓ Branch 9 taken 1200070 times.
✗ Branch 10 not taken.
|
1200070 | res += cit->operator()(u) * (*control_points_it); |
| 330 | } | ||
| 331 |
2/4✓ Branch 1 taken 200020 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 200020 times.
✗ Branch 5 not taken.
|
400040 | return res * mult_T_; |
| 332 | 200020 | } | |
| 333 | |||
| 334 | /// \brief Evaluate all Bernstein polynomes for a certain degree using | ||
| 335 | /// Horner's scheme. A bezier curve with N control points is expressed as : | ||
| 336 | /// \f$x(t) = \sum_{i=0}^{N} B_i^N(t) P_i\f$.<br> To evaluate the position on | ||
| 337 | /// curve at time t,we can apply the Horner's scheme : <br> \f$ x(t) = | ||
| 338 | /// (1-t)^N(\sum_{i=0}^{N} \binom{N}{i} \frac{1-t}{t}^i P_i) \f$.<br> Horner's | ||
| 339 | /// scheme : for a polynom of degree N expressed by : <br> \f$x(t) = a_0 + | ||
| 340 | /// a_1t + a_2t^2 + ... + a_nt^n\f$ where \f$number of additions = N\f$ / | ||
| 341 | /// f$number of multiplication = N!\f$<br> Using Horner's method, the polynom | ||
| 342 | /// is transformed into : <br> \f$x(t) = a_0 + t(a_1 + t(a_2+t(...))\f$ with N | ||
| 343 | /// additions and multiplications. \param t : time when to evaluate the curve. | ||
| 344 | /// \return \f$x(t)\f$ point corresponding on curve at time t. | ||
| 345 | /// | ||
| 346 | 1239444 | point_t evalHorner(const Numeric t) const { | |
| 347 | 1239444 | const Numeric u = (t - T_min_) / (T_max_ - T_min_); | |
| 348 | typename t_point_t::const_iterator control_points_it = | ||
| 349 | 1239444 | control_points_.begin(); | |
| 350 | Numeric u_op, bc, tn; | ||
| 351 | 1239444 | u_op = 1.0 - u; | |
| 352 | 1239444 | bc = 1; | |
| 353 | 1239444 | tn = 1; | |
| 354 |
2/4✓ Branch 2 taken 619722 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 619654 times.
✗ Branch 6 not taken.
|
1239444 | point_t tmp = (*control_points_it) * u_op; |
| 355 | 1239444 | ++control_points_it; | |
| 356 |
2/2✓ Branch 0 taken 2452898 times.
✓ Branch 1 taken 619722 times.
|
6145240 | for (unsigned int i = 1; i < degree_; i++, ++control_points_it) { |
| 357 | 4905796 | tn = tn * u; | |
| 358 | 4905796 | bc = bc * ((num_t)(degree_ - i + 1)) / i; | |
| 359 |
4/8✓ Branch 2 taken 2452898 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 2452898 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 2452898 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 2452898 times.
✗ Branch 12 not taken.
|
4905796 | tmp = (tmp + tn * bc * (*control_points_it)) * u_op; |
| 360 | } | ||
| 361 |
4/8✓ Branch 2 taken 619722 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 619722 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 619722 times.
✗ Branch 9 not taken.
✓ Branch 11 taken 619654 times.
✗ Branch 12 not taken.
|
2478888 | return (tmp + tn * u * (*control_points_it)) * mult_T_; |
| 362 | 1226212 | } | |
| 363 | |||
| 364 | 800500 | const t_point_t& waypoints() const { return control_points_; } | |
| 365 | |||
| 366 | 296 | const point_t waypointAtIndex(const std::size_t index) const { | |
| 367 | 296 | point_t waypoint; | |
| 368 |
1/2✓ Branch 1 taken 148 times.
✗ Branch 2 not taken.
|
296 | if (index < control_points_.size()) { |
| 369 |
1/2✓ Branch 2 taken 134 times.
✗ Branch 3 not taken.
|
296 | waypoint = control_points_[index]; |
| 370 | } | ||
| 371 | 296 | return waypoint; | |
| 372 | ✗ | } | |
| 373 | |||
| 374 | /// \brief Evaluate the curve value at time t using deCasteljau algorithm. | ||
| 375 | /// The algorithm will compute the \f$N-1\f$ centroids of parameters | ||
| 376 | /// \f${t,1-t}\f$ of consecutive \f$N\f$ control points of bezier curve, and | ||
| 377 | /// perform it iteratively until getting one point in the list which will be | ||
| 378 | /// the evaluation of bezier curve at time \f$t\f$. \param t : time when to | ||
| 379 | /// evaluate the curve. \return \f$x(t)\f$ point corresponding on curve at | ||
| 380 | /// time t. | ||
| 381 | /// | ||
| 382 | 400000 | point_t evalDeCasteljau(const Numeric t) const { | |
| 383 | // normalize time : | ||
| 384 | 400000 | const Numeric u = (t - T_min_) / (T_max_ - T_min_); | |
| 385 |
1/2✓ Branch 2 taken 400000 times.
✗ Branch 3 not taken.
|
400000 | t_point_t pts = deCasteljauReduction(waypoints(), u); |
| 386 |
2/2✓ Branch 1 taken 1600000 times.
✓ Branch 2 taken 400000 times.
|
2000000 | while (pts.size() > 1) { |
| 387 |
1/2✓ Branch 1 taken 1600000 times.
✗ Branch 2 not taken.
|
1600000 | pts = deCasteljauReduction(pts, u); |
| 388 | } | ||
| 389 |
2/4✓ Branch 2 taken 400000 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 400000 times.
✗ Branch 6 not taken.
|
800000 | return pts[0] * mult_T_; |
| 390 | 400000 | } | |
| 391 | |||
| 392 | t_point_t deCasteljauReduction(const Numeric t) const { | ||
| 393 | const Numeric u = (t - T_min_) / (T_max_ - T_min_); | ||
| 394 | return deCasteljauReduction(waypoints(), u); | ||
| 395 | } | ||
| 396 | |||
| 397 | /// \brief Compute de Casteljau's reduction of the given list of points at | ||
| 398 | /// time t. For the list \f$pts\f$ of N points, compute a new list of points | ||
| 399 | /// of size N-1 :<br> \f$<br>( pts[0]*(1-t)+pts[1], pts[1]*(1-t)+pts[2], ..., | ||
| 400 | /// pts[0]*(N-2)+pts[N-1] )\f$<br> with t the time when to evaluate bezier | ||
| 401 | /// curve.<br>\ The new list contains centroid of parameters \f${t,1-t}\f$ of | ||
| 402 | /// consecutive points in the list. \param pts : list of points. \param u : | ||
| 403 | /// NORMALIZED time when to evaluate the curve. \return reduced list of point | ||
| 404 | /// (size of pts - 1). | ||
| 405 | /// | ||
| 406 | 4000072 | t_point_t deCasteljauReduction(const t_point_t& pts, const Numeric u) const { | |
| 407 |
2/4✓ Branch 0 taken 2000036 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2000036 times.
|
4000072 | if (u < 0 || u > 1) { |
| 408 | ✗ | throw std::out_of_range("In deCasteljau reduction : u is not in [0;1]"); | |
| 409 | } | ||
| 410 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2000036 times.
|
4000072 | if (pts.size() == 1) { |
| 411 | ✗ | return pts; | |
| 412 | } | ||
| 413 | |||
| 414 |
1/2✓ Branch 1 taken 2000036 times.
✗ Branch 2 not taken.
|
4000072 | t_point_t new_pts; |
| 415 |
2/2✓ Branch 4 taken 7800095 times.
✓ Branch 5 taken 2000036 times.
|
19600262 | for (cit_point_t cit = pts.begin(); cit != (pts.end() - 1); ++cit) { |
| 416 |
5/10✓ Branch 3 taken 7800095 times.
✗ Branch 4 not taken.
✓ Branch 7 taken 7800095 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 7800095 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 7800095 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 7800083 times.
✗ Branch 17 not taken.
|
15600190 | new_pts.push_back((1 - u) * (*cit) + u * (*(cit + 1))); |
| 417 | } | ||
| 418 | 4000072 | return new_pts; | |
| 419 | 4000072 | } | |
| 420 | |||
| 421 | /// \brief Split the bezier curve in 2 at time t. | ||
| 422 | /// \param t : list of points. | ||
| 423 | /// \return pair containing the first element of both bezier curve obtained. | ||
| 424 | /// | ||
| 425 | 20 | std::pair<bezier_curve_t, bezier_curve_t> split(const Numeric t) const { | |
| 426 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
20 | check_conditions(); |
| 427 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
20 | if (fabs(t - T_max_) < MARGIN) { |
| 428 | ✗ | throw std::runtime_error( | |
| 429 | "can't split curve, interval range is equal to original curve"); | ||
| 430 | } | ||
| 431 |
2/4✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
✓ Branch 7 taken 10 times.
✗ Branch 8 not taken.
|
20 | t_point_t wps_first(size_), wps_second(size_); |
| 432 | 20 | const Numeric u = (t - T_min_) / (T_max_ - T_min_); | |
| 433 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
20 | t_point_t casteljau_pts = waypoints(); |
| 434 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
20 | wps_first[0] = casteljau_pts.front(); |
| 435 |
1/2✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
20 | wps_second[degree_] = casteljau_pts.back(); |
| 436 | 20 | size_t id = 1; | |
| 437 |
2/2✓ Branch 1 taken 36 times.
✓ Branch 2 taken 10 times.
|
92 | while (casteljau_pts.size() > 1) { |
| 438 |
1/2✓ Branch 1 taken 36 times.
✗ Branch 2 not taken.
|
72 | casteljau_pts = deCasteljauReduction(casteljau_pts, u); |
| 439 |
1/2✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
|
72 | wps_first[id] = casteljau_pts.front(); |
| 440 |
1/2✓ Branch 3 taken 36 times.
✗ Branch 4 not taken.
|
72 | wps_second[degree_ - id] = casteljau_pts.back(); |
| 441 | 72 | ++id; | |
| 442 | } | ||
| 443 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
20 | bezier_curve_t c_first(wps_first.begin(), wps_first.end(), T_min_, t, |
| 444 | 20 | mult_T_); | |
| 445 |
1/2✓ Branch 2 taken 10 times.
✗ Branch 3 not taken.
|
20 | bezier_curve_t c_second(wps_second.begin(), wps_second.end(), t, T_max_, |
| 446 | 20 | mult_T_); | |
| 447 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
40 | return std::make_pair(c_first, c_second); |
| 448 | 20 | } | |
| 449 | |||
| 450 | /// \brief Split the bezier curve in several curves, all accessible | ||
| 451 | /// within a piecewise_curve_t. | ||
| 452 | /// \param times : list of times of size n. | ||
| 453 | /// \return a piecewise_curve_t comprising n+1 curves | ||
| 454 | /// | ||
| 455 | 6 | piecewise_curve_t split(const vector_x_t& times) const { | |
| 456 | 6 | std::vector<bezier_curve_t> curves; | |
| 457 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
6 | bezier_curve_t current = *this; |
| 458 |
2/2✓ Branch 2 taken 5 times.
✓ Branch 3 taken 3 times.
|
16 | for (int i = 0; i < times.rows(); ++i) { |
| 459 | 10 | std::pair<bezier_curve_t, bezier_curve_t> pairsplit = | |
| 460 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
|
10 | current.split(times[i]); |
| 461 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | curves.push_back(pairsplit.first); |
| 462 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | current = pairsplit.second; |
| 463 | } | ||
| 464 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
6 | curves.push_back(current); |
| 465 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
6 | piecewise_curve_t res; |
| 466 | 22 | for (typename std::vector<bezier_curve_t>::const_iterator cit = | |
| 467 | 12 | curves.begin(); | |
| 468 |
2/2✓ Branch 3 taken 8 times.
✓ Branch 4 taken 3 times.
|
22 | cit != curves.end(); ++cit) { |
| 469 |
3/8✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 8 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 8 times.
✗ Branch 9 not taken.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
|
16 | typename piecewise_curve_t::curve_ptr_t ptr(new bezier_curve_t(*cit)); |
| 470 |
1/2✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
|
16 | res.add_curve_ptr(ptr); |
| 471 | } | ||
| 472 | 12 | return res; | |
| 473 | 6 | } | |
| 474 | |||
| 475 | /// \brief Extract a bezier curve defined between \f$[t_1,t_2]\f$ from the | ||
| 476 | /// actual bezier curve | ||
| 477 | /// defined between \f$[T_{min},T_{max}]\f$ with \f$T_{min} \leq t_1 | ||
| 478 | /// \leq t_2 \leq T_{max}\f$. | ||
| 479 | /// \param t1 : start time of bezier curve extracted. | ||
| 480 | /// \param t2 : end time of bezier curve extracted. | ||
| 481 | /// \return bezier curve extract defined between \f$[t_1,t_2]\f$. | ||
| 482 | /// | ||
| 483 | 4 | bezier_curve_t extract(const Numeric t1, const Numeric t2) { | |
| 484 |
4/8✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 4 times.
|
4 | if (t1 < T_min_ || t1 > T_max_ || t2 < T_min_ || t2 > T_max_) { |
| 485 | ✗ | throw std::out_of_range("In Extract curve : times out of bounds"); | |
| 486 | } | ||
| 487 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | if (fabs(t1 - T_min_) < MARGIN && |
| 488 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | fabs(t2 - T_max_) < MARGIN) // t1=T_min and t2=T_max |
| 489 | { | ||
| 490 | 1 | return bezier_curve_t(waypoints().begin(), waypoints().end(), T_min_, | |
| 491 |
1/2✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | T_max_, mult_T_); |
| 492 | } | ||
| 493 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 2 times.
|
3 | if (fabs(t1 - T_min_) < MARGIN) // t1=T_min |
| 494 | { | ||
| 495 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return split(t2).first; |
| 496 | } | ||
| 497 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (fabs(t2 - T_max_) < MARGIN) // t2=T_max |
| 498 | { | ||
| 499 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return split(t1).second; |
| 500 | } | ||
| 501 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | std::pair<bezier_curve_t, bezier_curve_t> c_split = this->split(t1); |
| 502 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | return c_split.second.split(t2).first; |
| 503 | 1 | } | |
| 504 | |||
| 505 | /// \brief Compute the cross product of the current bezier curve by another | ||
| 506 | /// bezier curve. | ||
| 507 | /// The cross product p1Xp2 of 2 bezier curves p1 and p2 is defined such that | ||
| 508 | /// forall t, p1Xp2(t) = p1(t) X p2(t), with X designing the cross product. | ||
| 509 | /// This method of course only makes sense for dimension 3 curves. | ||
| 510 | /// It assumes that a method point_t cross(const point_t&, const point_t&) has | ||
| 511 | /// been defined | ||
| 512 | /// \param pOther other polynomial to compute the cross product with. | ||
| 513 | /// \return a new polynomial defining the cross product between this and | ||
| 514 | /// pother | ||
| 515 | 10 | bezier_curve_t cross(const bezier_curve_t& g) const { | |
| 516 | // See Farouki and Rajan 1988 Alogirthms for polynomials in Bernstein form | ||
| 517 | // and http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node10.html | ||
| 518 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | assert_operator_compatible(g); |
| 519 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
|
10 | if (dim() != 3) |
| 520 | ✗ | throw std::invalid_argument( | |
| 521 | "Can't perform cross product on Bezier curves with dimensions != 3 "); | ||
| 522 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | int m = (int)(degree()); |
| 523 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | int n = (int)(g.degree()); |
| 524 | unsigned int mj, n_ij, mn_i; | ||
| 525 |
1/2✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
|
10 | t_point_t new_waypoints; |
| 526 |
3/3✓ Branch 0 taken 4 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 4 times.
|
74 | for (int i = 0; i <= m + n; ++i) { |
| 527 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
64 | bezier_curve_t::point_t current_point = |
| 528 |
2/4✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 18 times.
✗ Branch 5 not taken.
|
64 | bezier_curve_t::point_t::Zero(dim()); |
| 529 |
2/2✓ Branch 2 taken 70 times.
✓ Branch 3 taken 32 times.
|
204 | for (int j = std::max(0, i - n); j <= std::min(m, i); ++j) { |
| 530 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
140 | mj = bin(m, j); |
| 531 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
140 | n_ij = bin(n, i - j); |
| 532 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
140 | mn_i = bin(m + n, i); |
| 533 | 140 | num_t mul = num_t(mj * n_ij) / num_t(mn_i); | |
| 534 |
4/8✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 70 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 70 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 70 times.
✗ Branch 11 not taken.
|
140 | current_point += |
| 535 |
1/2✓ Branch 1 taken 70 times.
✗ Branch 2 not taken.
|
140 | mul * ndcurves::cross(waypointAtIndex(j), g.waypointAtIndex(i - j)); |
| 536 | } | ||
| 537 |
1/2✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
|
64 | new_waypoints.push_back(current_point); |
| 538 | } | ||
| 539 | 10 | return bezier_curve_t(new_waypoints.begin(), new_waypoints.end(), min(), | |
| 540 |
3/6✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 5 times.
✗ Branch 10 not taken.
|
20 | max(), mult_T_ * g.mult_T_); |
| 541 | 10 | } | |
| 542 | |||
| 543 | /// \brief Compute the cross product of the current bezier b by a point | ||
| 544 | /// point. | ||
| 545 | /// The cross product pXpoint of is defined such that | ||
| 546 | /// forall t, bXpoint(t) = b(t) X point, with X designing the cross product. | ||
| 547 | /// This method of course only makes sense for dimension 3 polynomials. | ||
| 548 | /// \param point point to compute the cross product with. | ||
| 549 | /// \return a new polynomial defining the cross product between this and | ||
| 550 | /// point | ||
| 551 | 1 | bezier_curve_t cross(const bezier_curve_t::point_t& point) const { | |
| 552 | // See Farouki and Rajan 1988 Alogirthms for polynomials in Bernstein form | ||
| 553 | // and http://web.mit.edu/hyperbook/Patrikalakis-Maekawa-Cho/node10.html | ||
| 554 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 1 times.
|
1 | if (dim() != 3) |
| 555 | ✗ | throw std::invalid_argument( | |
| 556 | "Can't perform cross product on Bezier curves with dimensions != 3 "); | ||
| 557 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | t_point_t new_waypoints; |
| 558 | 1 | for (typename t_point_t::const_iterator cit = waypoints().begin(); | |
| 559 |
2/2✓ Branch 3 taken 6 times.
✓ Branch 4 taken 1 times.
|
7 | cit != waypoints().end(); ++cit) { |
| 560 |
3/6✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 6 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 6 times.
✗ Branch 9 not taken.
|
6 | new_waypoints.push_back(ndcurves::cross(*cit, point)); |
| 561 | } | ||
| 562 | 1 | return bezier_curve_t(new_waypoints.begin(), new_waypoints.end(), min(), | |
| 563 |
3/6✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
|
2 | max(), mult_T_); |
| 564 | 1 | } | |
| 565 | |||
| 566 | 16 | bezier_curve_t& operator+=(const bezier_curve_t& other) { | |
| 567 |
2/2✓ Branch 1 taken 9 times.
✓ Branch 2 taken 3 times.
|
16 | assert_operator_compatible(other); |
| 568 | 13 | bezier_curve_t other_elevated = | |
| 569 | other * | ||
| 570 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
13 | (other.mult_T_ / this->mult_T_); // TODO remove mult_T_ from Bezier |
| 571 |
4/6✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 9 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 5 times.
|
13 | if (other.degree() > degree()) { |
| 572 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
6 | elevate_self(other.degree() - degree()); |
| 573 |
3/4✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 2 times.
|
7 | } else if (other_elevated.degree() < degree()) { |
| 574 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
|
3 | other_elevated.elevate_self(degree() - other_elevated.degree()); |
| 575 | } | ||
| 576 | 13 | typename t_point_t::const_iterator otherit = | |
| 577 | 13 | other_elevated.control_points_.begin(); | |
| 578 | 13 | for (typename t_point_t::iterator it = control_points_.begin(); | |
| 579 |
2/2✓ Branch 4 taken 43 times.
✓ Branch 5 taken 9 times.
|
68 | it != control_points_.end(); ++it, ++otherit) { |
| 580 |
1/2✓ Branch 3 taken 43 times.
✗ Branch 4 not taken.
|
55 | (*it) += (*otherit); |
| 581 | } | ||
| 582 | 13 | return *this; | |
| 583 | 13 | } | |
| 584 | |||
| 585 | 22 | bezier_curve_t& operator-=(const bezier_curve_t& other) { | |
| 586 |
2/2✓ Branch 1 taken 13 times.
✓ Branch 2 taken 3 times.
|
22 | assert_operator_compatible(other); |
| 587 |
1/2✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
|
19 | bezier_curve_t other_elevated = other * (other.mult_T_ / this->mult_T_); |
| 588 |
4/6✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 13 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✓ Branch 7 taken 9 times.
|
19 | if (other.degree() > degree()) { |
| 589 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 4 times.
✗ Branch 8 not taken.
|
6 | elevate_self(other.degree() - degree()); |
| 590 |
3/4✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 5 times.
✓ Branch 5 taken 4 times.
|
13 | } else if (other_elevated.degree() < degree()) { |
| 591 |
2/4✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 5 times.
✗ Branch 6 not taken.
|
7 | other_elevated.elevate_self(degree() - other_elevated.degree()); |
| 592 | } | ||
| 593 | 19 | typename t_point_t::const_iterator otherit = | |
| 594 | 19 | other_elevated.control_points_.begin(); | |
| 595 | 19 | for (typename t_point_t::iterator it = control_points_.begin(); | |
| 596 |
2/2✓ Branch 4 taken 62 times.
✓ Branch 5 taken 13 times.
|
99 | it != control_points_.end(); ++it, ++otherit) { |
| 597 |
1/2✓ Branch 3 taken 62 times.
✗ Branch 4 not taken.
|
80 | (*it) -= (*otherit); |
| 598 | } | ||
| 599 | 19 | return *this; | |
| 600 | 19 | } | |
| 601 | |||
| 602 | 11 | bezier_curve_t& operator+=(const bezier_curve_t::point_t& point) { | |
| 603 | 11 | for (typename t_point_t::iterator it = control_points_.begin(); | |
| 604 |
2/2✓ Branch 3 taken 28 times.
✓ Branch 4 taken 7 times.
|
49 | it != control_points_.end(); ++it) { |
| 605 |
1/2✓ Branch 2 taken 28 times.
✗ Branch 3 not taken.
|
38 | (*it) += point; |
| 606 | } | ||
| 607 | 11 | return *this; | |
| 608 | } | ||
| 609 | |||
| 610 | 9 | bezier_curve_t& operator-=(const bezier_curve_t::point_t& point) { | |
| 611 | 9 | for (typename t_point_t::iterator it = control_points_.begin(); | |
| 612 |
2/2✓ Branch 3 taken 16 times.
✓ Branch 4 taken 5 times.
|
35 | it != control_points_.end(); ++it) { |
| 613 |
1/2✓ Branch 2 taken 16 times.
✗ Branch 3 not taken.
|
26 | (*it) -= point; |
| 614 | } | ||
| 615 | 9 | return *this; | |
| 616 | } | ||
| 617 | |||
| 618 | 6 | bezier_curve_t& operator/=(const double d) { | |
| 619 | 6 | for (typename t_point_t::iterator it = control_points_.begin(); | |
| 620 |
2/2✓ Branch 3 taken 20 times.
✓ Branch 4 taken 4 times.
|
32 | it != control_points_.end(); ++it) { |
| 621 |
1/2✓ Branch 2 taken 20 times.
✗ Branch 3 not taken.
|
26 | (*it) /= d; |
| 622 | } | ||
| 623 | 6 | return *this; | |
| 624 | } | ||
| 625 | |||
| 626 | 39 | bezier_curve_t& operator*=(const double d) { | |
| 627 | 39 | for (typename t_point_t::iterator it = control_points_.begin(); | |
| 628 |
2/2✓ Branch 3 taken 110 times.
✓ Branch 4 taken 27 times.
|
183 | it != control_points_.end(); ++it) { |
| 629 |
1/2✓ Branch 2 taken 110 times.
✗ Branch 3 not taken.
|
144 | (*it) *= d; |
| 630 | } | ||
| 631 | 39 | return *this; | |
| 632 | } | ||
| 633 | |||
| 634 | private: | ||
| 635 | /// \brief Ensure constraints of bezier curve. | ||
| 636 | /// Add 4 points (2 after the first one, 2 before the last one) to Bezier | ||
| 637 | /// curve to ensure that velocity and acceleration constraints are respected. | ||
| 638 | /// | ||
| 639 | template <typename In> | ||
| 640 | 5 | t_point_t add_constraints(In PointsBegin, In PointsEnd, | |
| 641 | const curve_constraints_t& constraints) { | ||
| 642 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | t_point_t res; |
| 643 | 5 | num_t T = T_max_ - T_min_; | |
| 644 | 5 | num_t T_square = T * T; | |
| 645 |
6/12✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
✓ Branch 16 taken 3 times.
✗ Branch 17 not taken.
|
5 | point_t P0, P1, P2, P_n_2, P_n_1, PN; |
| 646 |
1/2✓ Branch 2 taken 3 times.
✗ Branch 3 not taken.
|
5 | P0 = *PointsBegin; |
| 647 |
1/2✓ Branch 3 taken 3 times.
✗ Branch 4 not taken.
|
5 | PN = *(PointsEnd - 1); |
| 648 |
4/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
|
5 | P1 = P0 + constraints.init_vel * T / (num_t)degree_; |
| 649 |
4/8✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
|
5 | P_n_1 = PN - constraints.end_vel * T / (num_t)degree_; |
| 650 |
5/10✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
|
5 | P2 = constraints.init_acc * T_square / (num_t)(degree_ * (degree_ - 1)) + |
| 651 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | 2 * P1 - P0; |
| 652 |
5/10✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 3 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 3 times.
✗ Branch 11 not taken.
✓ Branch 13 taken 3 times.
✗ Branch 14 not taken.
|
5 | P_n_2 = constraints.end_acc * T_square / (num_t)(degree_ * (degree_ - 1)) + |
| 653 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | 2 * P_n_1 - PN; |
| 654 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | res.push_back(P0); |
| 655 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | res.push_back(P1); |
| 656 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | res.push_back(P2); |
| 657 |
3/3✓ Branch 3 taken 1 times.
✓ Branch 4 taken 1 times.
✓ Branch 5 taken 2 times.
|
6 | for (In it = PointsBegin + 1; it != PointsEnd - 1; ++it) { |
| 658 |
2/4✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | res.push_back(*it); |
| 659 | } | ||
| 660 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | res.push_back(P_n_2); |
| 661 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | res.push_back(P_n_1); |
| 662 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | res.push_back(PN); |
| 663 | 10 | return res; | |
| 664 | 3 | } | |
| 665 | |||
| 666 | 850926 | void check_conditions() const { | |
| 667 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 425463 times.
|
850926 | if (control_points_.size() == 0) { |
| 668 | ✗ | throw std::runtime_error( | |
| 669 | "Error in bezier curve : there is no control points set / did you " | ||
| 670 | "use empty constructor ?"); | ||
| 671 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 425463 times.
|
850926 | } else if (dim_ == 0) { |
| 672 | ✗ | throw std::runtime_error( | |
| 673 | "Error in bezier curve : Dimension of points is zero / did you use " | ||
| 674 | "empty constructor ?"); | ||
| 675 | } | ||
| 676 | 850926 | } | |
| 677 | |||
| 678 | 66 | void assert_operator_compatible(const bezier_curve_t& other) const { | |
| 679 |
4/4✓ Branch 2 taken 29 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 27 times.
|
124 | if ((fabs(min() - other.min()) > MARGIN) || |
| 680 |
2/2✓ Branch 2 taken 2 times.
✓ Branch 3 taken 27 times.
|
58 | (fabs(max() - other.max()) > MARGIN)) { |
| 681 |
1/2✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
12 | throw std::invalid_argument( |
| 682 | "Can't perform base operation (+ - ) on two Bezier curves with " | ||
| 683 | "different time ranges"); | ||
| 684 | } | ||
| 685 | 54 | } | |
| 686 | |||
| 687 | /*Operations*/ | ||
| 688 | |||
| 689 | public: | ||
| 690 | /*Helpers*/ | ||
| 691 | /// \brief Get dimension of curve. | ||
| 692 | /// \return dimension of curve. | ||
| 693 | 10854 | std::size_t virtual dim() const { return dim_; }; | |
| 694 | /// \brief Get the minimum time for which the curve is defined | ||
| 695 | /// \return \f$t_{min}\f$, lower bound of time range. | ||
| 696 | 678 | virtual time_t min() const { return T_min_; } | |
| 697 | /// \brief Get the maximum time for which the curve is defined. | ||
| 698 | /// \return \f$t_{max}\f$, upper bound of time range. | ||
| 699 | 1848 | virtual time_t max() const { return T_max_; } | |
| 700 | /// \brief Get the degree of the curve. | ||
| 701 | /// \return \f$degree\f$, the degree of the curve. | ||
| 702 | 470 | virtual std::size_t degree() const { return degree_; } | |
| 703 | /*Helpers*/ | ||
| 704 | |||
| 705 | /* Attributes */ | ||
| 706 | /// Dim of curve | ||
| 707 | std::size_t dim_; | ||
| 708 | /// Starting time of cubic hermite spline : T_min_ is equal to first time of | ||
| 709 | /// control points. | ||
| 710 | /*const*/ time_t T_min_; | ||
| 711 | /// Ending time of cubic hermite spline : T_max_ is equal to last time of | ||
| 712 | /// control points. | ||
| 713 | /*const*/ time_t T_max_; | ||
| 714 | /*const*/ time_t mult_T_; | ||
| 715 | /*const*/ std::size_t size_; | ||
| 716 | /*const*/ std::size_t degree_; | ||
| 717 | /*const*/ std::vector<Bern<Numeric> > bernstein_; | ||
| 718 | /*const*/ t_point_t control_points_; | ||
| 719 | /* Attributes */ | ||
| 720 | |||
| 721 | static bezier_curve_t zero(const std::size_t dim, const time_t T = 1.) { | ||
| 722 | std::vector<point_t> ts; | ||
| 723 | ts.push_back(point_t::Zero(dim)); | ||
| 724 | return bezier_curve_t(ts.begin(), ts.end(), 0., T); | ||
| 725 | } | ||
| 726 | |||
| 727 | // Serialization of the class | ||
| 728 | friend class boost::serialization::access; | ||
| 729 | |||
| 730 | template <class Archive> | ||
| 731 | 100 | void serialize(Archive& ar, const unsigned int version) { | |
| 732 | if (version) { | ||
| 733 | // Do something depending on version ? | ||
| 734 | } | ||
| 735 |
2/4✓ Branch 1 taken 50 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 50 times.
✗ Branch 6 not taken.
|
100 | ar& BOOST_SERIALIZATION_BASE_OBJECT_NVP(curve_abc_t); |
| 736 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("dim", dim_); |
| 737 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("T_min", T_min_); |
| 738 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("T_max", T_max_); |
| 739 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("mult_T", mult_T_); |
| 740 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("size", size_); |
| 741 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("degree", degree_); |
| 742 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("bernstein", bernstein_); |
| 743 |
1/2✓ Branch 2 taken 50 times.
✗ Branch 3 not taken.
|
100 | ar& boost::serialization::make_nvp("control_points", control_points_); |
| 744 | 100 | } | |
| 745 | }; // End struct bezier_curve | ||
| 746 | |||
| 747 | template <typename T, typename N, bool S, typename P> | ||
| 748 | 11 | bezier_curve<T, N, S, P> operator+(const bezier_curve<T, N, S, P>& p1, | |
| 749 | const bezier_curve<T, N, S, P>& p2) { | ||
| 750 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
11 | bezier_curve<T, N, S, P> res(p1); |
| 751 |
3/4✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
19 | return res += p2; |
| 752 | 11 | } | |
| 753 | |||
| 754 | template <typename T, typename N, bool S, typename P> | ||
| 755 | 6 | bezier_curve<T, N, S, P> operator-(const bezier_curve<T, N, S, P>& p1) { | |
| 756 | 6 | std::vector<typename bezier_curve<T, N, S, P>::point_t> ts; | |
| 757 |
3/4✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 19 times.
✓ Branch 4 taken 4 times.
|
31 | for (std::size_t i = 0; i <= p1.degree(); ++i) { |
| 758 |
4/8✓ Branch 1 taken 19 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 19 times.
✗ Branch 5 not taken.
✓ Branch 7 taken 19 times.
✗ Branch 8 not taken.
✓ Branch 10 taken 19 times.
✗ Branch 11 not taken.
|
25 | ts.push_back(bezier_curve<T, N, S, P>::point_t::Zero(p1.dim())); |
| 759 | } | ||
| 760 |
3/6✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 4 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 4 times.
✗ Branch 10 not taken.
|
6 | bezier_curve<T, N, S, P> res(ts.begin(), ts.end(), p1.min(), p1.max()); |
| 761 |
1/2✓ Branch 1 taken 4 times.
✗ Branch 2 not taken.
|
6 | res -= p1; |
| 762 | 12 | return res; | |
| 763 | 6 | } | |
| 764 | |||
| 765 | template <typename T, typename N, bool S, typename P> | ||
| 766 | 11 | bezier_curve<T, N, S, P> operator-(const bezier_curve<T, N, S, P>& p1, | |
| 767 | const bezier_curve<T, N, S, P>& p2) { | ||
| 768 |
1/2✓ Branch 1 taken 9 times.
✗ Branch 2 not taken.
|
11 | bezier_curve<T, N, S, P> res(p1); |
| 769 |
3/4✓ Branch 1 taken 6 times.
✓ Branch 2 taken 3 times.
✓ Branch 4 taken 6 times.
✗ Branch 5 not taken.
|
19 | return res -= p2; |
| 770 | 11 | } | |
| 771 | |||
| 772 | template <typename T, typename N, bool S, typename P> | ||
| 773 | 5 | bezier_curve<T, N, S, P> operator-( | |
| 774 | const bezier_curve<T, N, S, P>& p1, | ||
| 775 | const typename bezier_curve<T, N, S, P>::point_t& point) { | ||
| 776 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | bezier_curve<T, N, S, P> res(p1); |
| 777 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
10 | return res -= point; |
| 778 | 5 | } | |
| 779 | |||
| 780 | template <typename T, typename N, bool S, typename P> | ||
| 781 | 1 | bezier_curve<T, N, S, P> operator-( | |
| 782 | const typename bezier_curve<T, N, S, P>::point_t& point, | ||
| 783 | const bezier_curve<T, N, S, P>& p1) { | ||
| 784 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | bezier_curve<T, N, S, P> res(-p1); |
| 785 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | return res += point; |
| 786 | 1 | } | |
| 787 | |||
| 788 | template <typename T, typename N, bool S, typename P> | ||
| 789 | 5 | bezier_curve<T, N, S, P> operator+( | |
| 790 | const bezier_curve<T, N, S, P>& p1, | ||
| 791 | const typename bezier_curve<T, N, S, P>::point_t& point) { | ||
| 792 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | bezier_curve<T, N, S, P> res(p1); |
| 793 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
10 | return res += point; |
| 794 | 5 | } | |
| 795 | |||
| 796 | template <typename T, typename N, bool S, typename P> | ||
| 797 | 1 | bezier_curve<T, N, S, P> operator+( | |
| 798 | const typename bezier_curve<T, N, S, P>::point_t& point, | ||
| 799 | const bezier_curve<T, N, S, P>& p1) { | ||
| 800 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | bezier_curve<T, N, S, P> res(p1); |
| 801 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | return res += point; |
| 802 | 1 | } | |
| 803 | |||
| 804 | template <typename T, typename N, bool S, typename P> | ||
| 805 | 5 | bezier_curve<T, N, S, P> operator/(const bezier_curve<T, N, S, P>& p1, | |
| 806 | const double k) { | ||
| 807 |
1/2✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
|
5 | bezier_curve<T, N, S, P> res(p1); |
| 808 |
2/4✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
10 | return res /= k; |
| 809 | 5 | } | |
| 810 | |||
| 811 | template <typename T, typename N, bool S, typename P> | ||
| 812 | 33 | bezier_curve<T, N, S, P> operator*(const bezier_curve<T, N, S, P>& p1, | |
| 813 | const double k) { | ||
| 814 |
1/2✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
|
33 | bezier_curve<T, N, S, P> res(p1); |
| 815 |
2/4✓ Branch 1 taken 23 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 23 times.
✗ Branch 5 not taken.
|
66 | return res *= k; |
| 816 | 33 | } | |
| 817 | |||
| 818 | template <typename T, typename N, bool S, typename P> | ||
| 819 | 1 | bezier_curve<T, N, S, P> operator*(const double k, | |
| 820 | const bezier_curve<T, N, S, P>& p1) { | ||
| 821 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | bezier_curve<T, N, S, P> res(p1); |
| 822 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | return res *= k; |
| 823 | 1 | } | |
| 824 | |||
| 825 | } // namespace ndcurves | ||
| 826 | |||
| 827 | DEFINE_CLASS_TEMPLATE_VERSION( | ||
| 828 | SINGLE_ARG(typename Time, typename Numeric, bool Safe, typename Point), | ||
| 829 | SINGLE_ARG(ndcurves::bezier_curve<Time, Numeric, Safe, Point>)) | ||
| 830 | |||
| 831 | #endif //_CLASS_BEZIERCURVE | ||
| 832 |