|
|
|
|
@ -6,6 +6,7 @@
|
|
|
|
|
|
|
|
|
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016 |
|
|
|
|
Vladimír Vondruš <mosra@centrum.cz> |
|
|
|
|
Copyright © 2016 Ashwin Ravichandran <ashwinravichandran24@gmail.com> |
|
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a |
|
|
|
|
copy of this software and associated documentation files (the "Software"), |
|
|
|
|
@ -33,22 +34,29 @@
|
|
|
|
|
#include <array> |
|
|
|
|
#include "Vector.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace Magnum { namespace Math { |
|
|
|
|
/**
|
|
|
|
|
@brief Bezier |
|
|
|
|
@tparam order Order of Bezier curve |
|
|
|
|
@tparam dimensions Dimensions of the control points |
|
|
|
|
@tparam T Underlying data type |
|
|
|
|
/**
|
|
|
|
|
@brief Bezier |
|
|
|
|
@tparam order Order of Bezier curve |
|
|
|
|
@tparam dimensions Dimensions of the control points |
|
|
|
|
@tparam T Underlying data type |
|
|
|
|
|
|
|
|
|
See <a href="https://en.wikipedia.org/wiki/B%C3%A9zier_curve">Bezier Curve</a>. |
|
|
|
|
*/ |
|
|
|
|
template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier { |
|
|
|
|
See <a href="https://en.wikipedia.org/wiki/B%C3%A9zier_curve">Bezier Curve</a>. |
|
|
|
|
*/ |
|
|
|
|
template<UnsignedInt order, UnsignedInt dimensions, class T> class Bezier { |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
/** @brief Default constructor */ |
|
|
|
|
constexpr /*implicit*/ Bezier(ZeroInitT = ZeroInit): _points{} {} |
|
|
|
|
|
|
|
|
|
/** @brief Construct Bezier without initializing the contents */ |
|
|
|
|
explicit Bezier(NoInitT) {} |
|
|
|
|
|
|
|
|
|
/** @brief Construct Bezier curve with the given array of control points */ |
|
|
|
|
explicit Bezier(const std::array<Vector<dimensions, T>, order+1> &points) { |
|
|
|
|
_points = points; |
|
|
|
|
template<typename... U> constexpr Bezier(U... u):_points{u...} { |
|
|
|
|
static_assert(sizeof...(U) == order + 1, "Wrong number of arguments"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -58,16 +66,16 @@ namespace Magnum { namespace Math {
|
|
|
|
|
* |
|
|
|
|
* @return Array of two Bezier curves of the same order |
|
|
|
|
*/ |
|
|
|
|
std::array<Bezier<order, dimensions, T >, 2> subdivide(Float t) const { |
|
|
|
|
auto i_points = calculateIntermediatePoints(t); |
|
|
|
|
std::array<Vector<dimensions, T>, order + 1> left, right; |
|
|
|
|
for(UnsignedInt i=0; i<=order; ++i){ |
|
|
|
|
left[i] = i_points[0][i]; |
|
|
|
|
std::array<Bezier<order, dimensions, T>, 2> subdivide(Float t) const { |
|
|
|
|
auto iPoints = calculateIntermediatePoints(t); |
|
|
|
|
Bezier<order, dimensions, T> left, right; |
|
|
|
|
for(std::size_t i = 0; i <= order; ++i) { |
|
|
|
|
left[i] = iPoints[0][i]; |
|
|
|
|
} |
|
|
|
|
for(UnsignedInt i = 0, j = order; j>=0; --j, ++i){ |
|
|
|
|
right[i] = i_points[i][j]; |
|
|
|
|
for(std::size_t i = 0, j = order; i <= order; --j, ++i) { |
|
|
|
|
right[i] = iPoints[i][j]; |
|
|
|
|
} |
|
|
|
|
return {Bezier<order, dimensions, T>(left), Bezier<order, dimensions, T>(right)}; |
|
|
|
|
return {left, right}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -75,10 +83,29 @@ namespace Magnum { namespace Math {
|
|
|
|
|
* De Casteljau's algorithm is used. |
|
|
|
|
* @param t The interpolation factor |
|
|
|
|
*/ |
|
|
|
|
Vector<dimensions, T> lerp (Float t) const { |
|
|
|
|
auto i_points= calculateIntermediatePoints(t); |
|
|
|
|
return i_points[0][order]; |
|
|
|
|
}; |
|
|
|
|
Vector<dimensions, T> lerp(Float t) const { |
|
|
|
|
auto iPoints = calculateIntermediatePoints(t); |
|
|
|
|
return iPoints[0][order]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Control points of Bezier |
|
|
|
|
* @return One-dimensional array of `size` length. |
|
|
|
|
* |
|
|
|
|
* @see @ref operator[]() |
|
|
|
|
*/ |
|
|
|
|
Vector<dimensions, T>*points() {return _points;} |
|
|
|
|
|
|
|
|
|
constexpr const Vector<dimensions, T>*points() const {return _points;} /**< @overload */ |
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief Value at given position |
|
|
|
|
* |
|
|
|
|
* @see @ref points() |
|
|
|
|
*/ |
|
|
|
|
Vector<dimensions, T>&operator[](std::size_t pos) {return _points[pos];} |
|
|
|
|
|
|
|
|
|
constexpr Vector<dimensions, T> operator[](std::size_t pos) const {return _points[pos];} /**< @overload */ |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
@ -87,32 +114,29 @@ namespace Magnum { namespace Math {
|
|
|
|
|
* @param t The interpolation factor |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
std::array<std::array<Vector<dimensions,T>, order + 1>, order + 1> calculateIntermediatePoints(Float t) const { |
|
|
|
|
const auto n = order + 1; |
|
|
|
|
std::array<std::array<Vector<dimensions,T>, n>, n> i_points; |
|
|
|
|
for (UnsignedInt i = 0; i < n; ++i) { |
|
|
|
|
i_points[i][0] = _points[i]; |
|
|
|
|
std::array<Bezier<order, dimensions, T>, order + 1> calculateIntermediatePoints(Float t) const { |
|
|
|
|
std::array<Bezier<order, dimensions, T>, order + 1> iPoints; |
|
|
|
|
for(std::size_t i = 0; i <= order; ++i) { |
|
|
|
|
iPoints[i][0] = _points[i]; |
|
|
|
|
} |
|
|
|
|
for (UnsignedInt r = 1; r < n; ++r) { |
|
|
|
|
for (UnsignedInt i = 0; i < n - r; ++i) { |
|
|
|
|
i_points[i][r] = (1 - t) * i_points[i][r - 1] + t * i_points[i + 1][r - 1]; |
|
|
|
|
for(std::size_t r = 1; r <= order; ++r) { |
|
|
|
|
for(std::size_t i = 0; i <= order - r; ++i) { |
|
|
|
|
iPoints[i][r] = (1 - t)*iPoints[i][r - 1] + t*iPoints[i + 1][r - 1]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return i_points; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
std::array<Vector<dimensions, T >, order + 1> _points; |
|
|
|
|
}; |
|
|
|
|
return iPoints; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template<UnsignedInt dimensions, class T> using QuadraticBezier = Bezier<2, dimensions, T>; |
|
|
|
|
template<UnsignedInt dimensions, class T> using CubicBezier = Bezier <3, dimensions, T>; |
|
|
|
|
template<class T> using QuadraticBezier2D = QuadraticBezier<2, T>; |
|
|
|
|
template<class T> using QuadraticBezier3D = QuadraticBezier<3, T>; |
|
|
|
|
template<class T> using CubicBezier2D = CubicBezier<2, T>; |
|
|
|
|
template<class T> using CubicBezier3D = CubicBezier<3, T>; |
|
|
|
|
Vector<dimensions, T> _points[order + 1]; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
template<UnsignedInt dimensions, class T> using QuadraticBezier = Bezier<2, dimensions, T>; |
|
|
|
|
template<UnsignedInt dimensions, class T> using CubicBezier = Bezier<3, dimensions, T>; |
|
|
|
|
template<class T> using QuadraticBezier2D = QuadraticBezier<2, T>; |
|
|
|
|
template<class T> using QuadraticBezier3D = QuadraticBezier<3, T>; |
|
|
|
|
template<class T> using CubicBezier2D = CubicBezier<2, T>; |
|
|
|
|
template<class T> using CubicBezier3D = CubicBezier<3, T>; |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
#endif //Magnum_Math_Bezier_h
|
|
|
|
|
}} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|