diff --git a/src/Magnum/Math/Bezier.h b/src/Magnum/Math/Bezier.h index f51743226..c77126b1b 100644 --- a/src/Magnum/Math/Bezier.h +++ b/src/Magnum/Math/Bezier.h @@ -44,6 +44,18 @@ namespace Magnum { namespace Math { namespace Implementation { + /* Compared to traits in Range.h it handles also arbitrary other dimension + count */ + template struct BezierTraits { + typedef T Type; + }; + template struct BezierTraits<2, T> { + typedef Vector2 Type; + }; + template struct BezierTraits<3, T> { + typedef Vector3 Type; + }; + template struct BezierConverter; } @@ -70,6 +82,15 @@ template class Bezier { public: typedef T Type; /**< @brief Underlying data type */ + /** + * @brief Underlying vector type + * @m_since_latest + * + * @cpp T @ce in 1D, @ref Math::Vector2 "Vector2" in 2D, + * @ref Math::Vector3 "Vector3" in 3D. + */ + typedef typename Implementation::BezierTraits::Type VectorType; + enum: UnsignedInt { Order = order, /**< Order of Bézier curve */ Dimensions = dimensions /**< Dimensions of control points */ @@ -96,11 +117,10 @@ template class Bezier { * underlying types. See @ref CubicHermite::fromBezier() for the * inverse operation. */ - template static #ifndef DOXYGEN_GENERATING_OUTPUT - typename std::enable_if, VectorType>::value && order == 3, Bezier>::type + template static typename std::enable_if>::type #else - Bezier + static Bezier #endif fromCubicHermite(const CubicHermite& a, const CubicHermite& b) { return {a.point(), a.outTangent()/T(3) - a.point(), b.point() - b.inTangent()/T(3), b.point()}; @@ -124,7 +144,7 @@ template class Bezier { explicit Bezier(Magnum::NoInitT) noexcept: Bezier{typename Containers::Implementation::GenerateSequence::Type{}, Magnum::NoInit} {} /** @brief Construct a Bézier curve with given array of control points */ - template constexpr /*implicit*/ Bezier(const Vector& first, U... next) noexcept: _data{first, next...} { + template constexpr /*implicit*/ Bezier(const VectorType& first, U... next) noexcept: _data{first, next...} { static_assert(sizeof...(U) + 1 == order + 1, "Wrong number of arguments"); } @@ -155,11 +175,11 @@ template class Bezier { * post-processing step (https://github.com/mosra/m.css/issues/56) */ #ifdef DOXYGEN_GENERATING_OUTPUT - Vector* data(); - constexpr const Vector* data() const; /**< @overload */ + VectorType* data(); + constexpr const VectorType* data() const; /**< @overload */ #else - auto data() -> Vector(&)[order + 1] { return _data; } - constexpr auto data() const -> const Vector(&)[order + 1] { return _data; } + auto data() -> VectorType(&)[order + 1] { return _data; } + constexpr auto data() const -> const VectorType(&)[order + 1] { return _data; } #endif /** @brief Equality comparison */ @@ -179,9 +199,9 @@ template class Bezier { * * @p i should not be larger than @ref Order. */ - Vector& operator[](std::size_t i) { return _data[i]; } + VectorType& operator[](std::size_t i) { return _data[i]; } /* returns const& so [][] operations are also constexpr */ - constexpr const Vector& operator[](std::size_t i) const { return _data[i]; } /**< @overload */ + constexpr const VectorType& operator[](std::size_t i) const { return _data[i]; } /**< @overload */ /** * @brief Interpolate the curve at given position @@ -190,7 +210,7 @@ template class Bezier { * the [De Casteljau's algorithm](https://en.wikipedia.org/wiki/De_Casteljau%27s_algorithm). * @see @ref subdivide() */ - Vector value(T t) const { + VectorType value(T t) const { Bezier iPoints[order + 1]; calculateIntermediatePoints(iPoints, t); return iPoints[0][order]; @@ -216,11 +236,11 @@ template class Bezier { private: /* Implementation for Bezier::Bezier(const Bezier&) */ - template constexpr explicit Bezier(Containers::Implementation::Sequence, const Bezier& other) noexcept: _data{Vector(other._data[sequence])...} {} + template constexpr explicit Bezier(Containers::Implementation::Sequence, const Bezier& other) noexcept: _data{VectorType(other._data[sequence])...} {} /* Implementation for Bezier::Bezier(ZeroInitT) and Bezier::Bezier(NoInitT) */ /* MSVC 2015 can't handle {} here */ - template constexpr explicit Bezier(Containers::Implementation::Sequence, U): _data{Vector((static_cast(sequence), U{typename U::Init{}}))...} {} + template constexpr explicit Bezier(Containers::Implementation::Sequence, U): _data{VectorType{U{(static_cast(sequence), typename U::Init{})}}...} {} /* Calculates and returns all intermediate points generated when using De Casteljau's algorithm */ void calculateIntermediatePoints(Bezier(&iPoints)[order + 1], T t) const { @@ -234,7 +254,7 @@ template class Bezier { } } - Vector _data[order + 1]; + VectorType _data[order + 1]; }; /** diff --git a/src/Magnum/Math/Test/BezierTest.cpp b/src/Magnum/Math/Test/BezierTest.cpp index 6ff7ceae2..7975253ff 100644 --- a/src/Magnum/Math/Test/BezierTest.cpp +++ b/src/Magnum/Math/Test/BezierTest.cpp @@ -157,12 +157,7 @@ void BezierTest::constructNoInit() { } void BezierTest::constructConversion() { - #ifndef CORRADE_MSVC2017_COMPATIBILITY constexpr QuadraticBezier2Dd a{Vector2d{0.5, 1.0}, Vector2d{1.1, 0.3}, Vector2d{0.1, 1.2}}; - #else - /* https://developercommunity.visualstudio.com/content/problem/259204/1572-regression-ice-in-constexpr-code-involving-de.html */ - constexpr QuadraticBezier2Dd a{Vector<2, Double>{0.5, 1.0}, Vector<2, Double>{1.1, 0.3}, Vector<2, Double>{0.1, 1.2}}; - #endif constexpr QuadraticBezier2D b{a}; CORRADE_COMPARE(b, (QuadraticBezier2D{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}})); @@ -198,12 +193,7 @@ void BezierTest::constructCopy() { void BezierTest::convert() { constexpr QBezier2D a{0.5f, 1.1f, 0.1f, 1.0f, 0.3f, 1.2f}; - #ifndef CORRADE_MSVC2017_COMPATIBILITY constexpr QuadraticBezier2D b{Vector2{0.5f, 1.0f}, Vector2{1.1f, 0.3f}, Vector2{0.1f, 1.2f}}; - #else - /* https://developercommunity.visualstudio.com/content/problem/259204/1572-regression-ice-in-constexpr-code-involving-de.html */ - constexpr QuadraticBezier2D b{Vector<2, Float>{0.5f, 1.0f}, Vector<2, Float>{1.1f, 0.3f}, Vector<2, Float>{0.1f, 1.2f}}; - #endif constexpr QuadraticBezier2D c{a}; CORRADE_COMPARE(c, b);