diff --git a/doc/changelog.dox b/doc/changelog.dox index cd6021195..74ab2ecf6 100644 --- a/doc/changelog.dox +++ b/doc/changelog.dox @@ -73,6 +73,8 @@ See also: to @ref Math::join() for operating with @ref Math::Range instances - Added @ref Math::Range::contains() overloading taking a range, in addition to vector +- @ref Math::Range is now constructible from a @ref std::pair of values, + making it usable in combination with @ref Math::minmax(), for example - Added @ref Math::Constants::piQuarter() - Added a convenience function @ref Math::select() as a constant interpolation counterpart to @ref Math::lerp() diff --git a/doc/snippets/MagnumMath.cpp b/doc/snippets/MagnumMath.cpp index d2ec57234..a63a79301 100644 --- a/doc/snippets/MagnumMath.cpp +++ b/doc/snippets/MagnumMath.cpp @@ -28,6 +28,7 @@ #include "Magnum/Math/DualComplex.h" #include "Magnum/Math/DualQuaternion.h" #include "Magnum/Math/Half.h" +#include "Magnum/Math/Range.h" #include "Magnum/Math/Algorithms/GramSchmidt.h" using namespace Magnum; @@ -858,4 +859,12 @@ Debug{} << Math::Vector3{a}; // prints {16968, 48552, 15993} /* [Half-usage-vector] */ } +{ +/* [Range-construct-minmax] */ +Vector3 a, b, c; +Range3D bounds{Math::minmax({a, b, c})}; +/* [Range-construct-minmax] */ +static_cast(bounds); +} + } diff --git a/src/Magnum/Math/Functions.h b/src/Magnum/Math/Functions.h index 760f87bc8..80af3f9dd 100644 --- a/src/Magnum/Math/Functions.h +++ b/src/Magnum/Math/Functions.h @@ -345,7 +345,8 @@ template inline T max(std::initializer_list list) { /** @brief Minimum and maximum of two values -@see @ref min(), @ref max(), @ref clamp(), @ref Vector::minmax() +@see @ref min(), @ref max(), @ref clamp(), @ref Vector::minmax(), + @ref Range::Range(const std::pair&) */ #ifdef DOXYGEN_GENERATING_OUTPUT template inline std::pair minmax(const T& a, const T& b); @@ -379,6 +380,7 @@ namespace Implementation { @brief Minimum and maximum of a range If the range is empty, returns default-constructed values. +@see @ref Range::Range(const std::pair&) */ template std::pair minmax(Corrade::Containers::ArrayView range) { if(range.empty()) return {}; diff --git a/src/Magnum/Math/Range.h b/src/Magnum/Math/Range.h index 6ba1a3702..1f1700f3c 100644 --- a/src/Magnum/Math/Range.h +++ b/src/Magnum/Math/Range.h @@ -82,9 +82,28 @@ template class Range { /** @brief Construct without initializing the contents */ explicit Range(NoInitT) noexcept: _min{NoInit}, _max{NoInit} {} - /** @brief Construct range from minimal and maximal coordinates */ + /** @brief Construct a range from minimal and maximal coordinates */ constexpr /*implicit*/ Range(const VectorType& min, const VectorType& max) noexcept: _min{min}, _max{max} {} + /** + * @brief Construct a range from a pair of minimal and maximal coordinates + * + * Useful in combination with e.g. @ref minmax(), here for example to + * calculate bounds of a triangle: + * + * @snippet MagnumMath.cpp Range-construct-minmax + * + * @todo std::pair constructors are not constexpr in C++11, make it so in C++14 */ + /*implicit*/ Range(const std::pair& minmax) noexcept: + _min{minmax.first}, _max{minmax.second} {} + + /** @overload */ + /** @todo std::pair constructors are not constexpr in C++11, make it so in C++14 */ + #ifndef DOXYGEN_GENERATING_OUTPUT + template> + #endif + /*implicit*/ Range(const std::pair, Vector>& minmax) noexcept: _min{minmax.first}, _max{minmax.second} {} + /** * @brief Construct range from another of different type * diff --git a/src/Magnum/Math/Test/RangeTest.cpp b/src/Magnum/Math/Test/RangeTest.cpp index 9d9de731b..b5fe84f87 100644 --- a/src/Magnum/Math/Test/RangeTest.cpp +++ b/src/Magnum/Math/Test/RangeTest.cpp @@ -101,6 +101,7 @@ struct RangeTest: Corrade::TestSuite::Tester { void constructDefault(); void constructNoInit(); void constructFromSize(); + void constructPair(); void constructConversion(); void constructCopy(); void convert(); @@ -141,6 +142,7 @@ RangeTest::RangeTest() { &RangeTest::constructDefault, &RangeTest::constructNoInit, &RangeTest::constructFromSize, + &RangeTest::constructPair, &RangeTest::constructConversion, &RangeTest::constructCopy, &RangeTest::convert, @@ -238,6 +240,24 @@ void RangeTest::constructFromSize() { CORRADE_COMPARE(Range3Di::fromSize({3, 5, -7}, {23, 78, 9}), Range3Di({3, 5, -7}, {26, 83, 2})); } +void RangeTest::constructPair() { + Vector2i a{10, 22}; + Vector2i b{30, 18}; + Vector2i c{20, 25}; + + Range1Di bounds1a{Math::minmax>({a.x(), b.x(), c.x()})}; + Range1Di bounds1b{std::pair, Math::Vector<1, Int>>{10, 30}}; + Range1Di bounds1c{10, 30}; + CORRADE_COMPARE(bounds1a, bounds1c); + CORRADE_COMPARE(bounds1b, bounds1c); + + Range2Di bounds2a{Math::minmax({a, b, c})}; + Range2Di bounds2b{std::pair, Math::Vector<2, Int>>{{10, 18}, {30, 25}}}; + Range2Di bounds2c{{10, 18}, {30, 25}}; + CORRADE_COMPARE(bounds2a, bounds2c); + CORRADE_COMPARE(bounds2b, bounds2c); +} + void RangeTest::constructConversion() { constexpr Range1D a(1.3f, -15.0f); constexpr Range2D b({1.3f, 2.7f}, {-15.0f, 7.0f});