diff --git a/doc/changelog.dox b/doc/changelog.dox index bc1218500..4fa43cc8a 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -140,6 +140,12 @@ See also: - @ref Math::Matrix3::rotation() const and @ref Math::Matrix4::rotation() const now allow non-uniform scaling, but expect the roation/scaling part to be orthogonal after normalization +- @ref Math::angle(), @ref Math::Vector::lengthInverted(), + @ref Math::Vector::normalized(), @ref Math::Vector::resized(), + @ref Math::Vector::projected(), @ref Math::Vector::projectedOntoNormalized() + and @ref Math::Vector2::aspectRatio() are now enabled only for + floating-point types to avoid errors when using these functions + accidentally on integral vectors @subsubsection changelog-latest-changes-meshtools MeshTools library diff --git a/src/Magnum/Math/Vector.h b/src/Magnum/Math/Vector.h index a8167c559..2ffe11c84 100644 --- a/src/Magnum/Math/Vector.h +++ b/src/Magnum/Math/Vector.h @@ -84,17 +84,24 @@ template inline T dot(const Vector& a, const /** @relatesalso Vector @brief Angle between normalized vectors -Expects that both vectors are normalized. @f[ +Expects that both vectors are normalized. Enabled only for floating-point +types. @f[ \theta = acos \left( \frac{\boldsymbol a \cdot \boldsymbol b}{|\boldsymbol a| |\boldsymbol b|} \right) = acos (\boldsymbol a \cdot \boldsymbol b) @f] @see @ref Vector::isNormalized(), @ref angle(const Complex&, const Complex&), @ref angle(const Quaternion&, const Quaternion&) */ -template inline Rad angle(const Vector& normalizedA, const Vector& normalizedB) { +template inline +#ifdef DOXYGEN_GENERATING_OUTPUT +Rad +#else +typename std::enable_if::value, Rad>::type +#endif +angle(const Vector& normalizedA, const Vector& normalizedB) { CORRADE_ASSERT(normalizedA.isNormalized() && normalizedB.isNormalized(), "Math::angle(): vectors must be normalized", {}); - return Rad(std::acos(dot(normalizedA, normalizedB))); + return Rad(std::acos(dot(normalizedA, normalizedB))); } /** @@ -468,28 +475,39 @@ template class Vector { /** * @brief Inverse vector length * - * @f[ + * Enabled only for floating-point types. @f[ * \frac{1}{|\boldsymbol a|} = \frac{1}{\sqrt{\boldsymbol a \cdot \boldsymbol a}} * @f] * @see @ref length(), @ref Math::sqrtInverted(), @ref normalized(), * @ref resized() */ - T lengthInverted() const { return T(1)/length(); } + #ifdef DOXYGEN_GENERATING_OUTPUT + T + #else + template typename std::enable_if::value, T>::type + #endif + lengthInverted() const { return T(1)/length(); } /** * @brief Normalized vector (of unit length) * + * Enabled only for floating-point types. * @see @ref isNormalized(), @ref lengthInverted(), @ref resized() * @m_keyword{normalize(),GLSL normalize(),} */ - Vector normalized() const { return *this*lengthInverted(); } + #ifdef DOXYGEN_GENERATING_OUTPUT + Vector + #else + template typename std::enable_if::value, Vector>::type + #endif + normalized() const { return *this*lengthInverted(); } /** * @brief Resized vector * * Convenience equivalent to the following code. Due to operation order * this function is faster than the obvious way of sizing - * @ref normalized() vector. + * a @ref normalized() vector. Enabled only for floating-point types. * * @code{.cpp} * vec*(vec.lengthInverted()*length) // the parentheses are important @@ -497,19 +515,30 @@ template class Vector { * * @see @ref normalized() */ - Vector resized(T length) const { + #ifdef DOXYGEN_GENERATING_OUTPUT + Vector + #else + template typename std::enable_if::value, Vector>::type + #endif + resized(T length) const { return *this*(lengthInverted()*length); } /** * @brief Vector projected onto line * - * Returns vector projected onto @p line. @f[ + * Returns a vector projected onto @p line. Enabled only for + * floating-point types. @f[ * \operatorname{proj}_{\boldsymbol{b}}\,(\boldsymbol{a}) = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b * @f] * @see @ref Math::dot(), @ref projectedOntoNormalized() */ - Vector projected(const Vector& line) const { + #ifdef DOXYGEN_GENERATING_OUTPUT + Vector + #else + template typename std::enable_if::value, Vector>::type + #endif + projected(const Vector& line) const { return line*Math::dot(*this, line)/line.dot(); } @@ -517,13 +546,18 @@ template class Vector { * @brief Vector projected onto normalized line * * Slightly faster alternative to @ref projected(), expects @p line to - * be normalized. @f[ + * be normalized. Enabled only for floating-point types. @f[ * \operatorname{proj}_{\boldsymbol{b}}\,(\boldsymbol{a}) = \frac{\boldsymbol a \cdot \boldsymbol b}{\boldsymbol b \cdot \boldsymbol b} \boldsymbol b = * (\boldsymbol a \cdot \boldsymbol b) \boldsymbol b * @f] * @see @ref Math::dot() */ - Vector projectedOntoNormalized(const Vector& line) const; + #ifdef DOXYGEN_GENERATING_OUTPUT + Vector + #else + template typename std::enable_if::value, Vector>::type + #endif + projectedOntoNormalized(const Vector& line) const; /** * @brief Flipped vector @@ -1159,16 +1193,16 @@ extern template MAGNUM_EXPORT Corrade::Utility::Debug& operator<<(Corrade::Utili return Math::Vector::operator/(other); \ } \ \ - Type normalized() const { \ + template typename std::enable_if::value, Type>::type normalized() const { \ return Math::Vector::normalized(); \ } \ - Type resized(T length) const { \ + template typename std::enable_if::value, Type>::type resized(T length) const { \ return Math::Vector::resized(length); \ } \ - Type projected(const Math::Vector& other) const { \ + template typename std::enable_if::value, Type>::type projected(const Math::Vector& other) const { \ return Math::Vector::projected(other); \ } \ - Type projectedOntoNormalized(const Math::Vector& other) const { \ + template typename std::enable_if::value, Type>::type projectedOntoNormalized(const Math::Vector& other) const { \ return Math::Vector::projectedOntoNormalized(other); \ } \ constexpr Type flipped() const { \ @@ -1318,7 +1352,13 @@ template inline Vector Vector::oper return out; } -template inline Vector Vector::projectedOntoNormalized(const Vector& line) const { +template +#ifdef DOXYGEN_GENERATING_OUTPUT +inline Vector +#else +template inline typename std::enable_if::value, Vector>::type +#endif +Vector::projectedOntoNormalized(const Vector& line) const { CORRADE_ASSERT(line.isNormalized(), "Math::Vector::projectedOntoNormalized(): line must be normalized", {}); return line*Math::dot(*this, line); } diff --git a/src/Magnum/Math/Vector2.h b/src/Magnum/Math/Vector2.h index e1298eb46..1f33fb91a 100644 --- a/src/Magnum/Math/Vector2.h +++ b/src/Magnum/Math/Vector2.h @@ -168,11 +168,17 @@ template class Vector2: public Vector<2, T> { /** * @brief Aspect ratio * - * Returns quotient of the two elements. @f[ + * Returns quotient of the two elements. Enabled only for + * floating-point types. @f[ * a = \frac{v_x}{v_y} * @f] */ - T aspectRatio() const { return x()/y(); } + #ifdef DOXYGEN_GENERATING_OUTPUT + T + #else + template typename std::enable_if::value, T>::type + #endif + aspectRatio() const { return x()/y(); } MAGNUM_VECTOR_SUBCLASS_IMPLEMENTATION(2, Vector2) };