mirror of https://github.com/mosra/magnum.git
7 changed files with 796 additions and 1 deletions
@ -0,0 +1,425 @@
|
||||
#ifndef Magnum_Math_Range_h |
||||
#define Magnum_Math_Range_h |
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
/** @file
|
||||
* @brief Class @ref Magnum::Math::Range, @ref Magnum::Math::Range2D, @ref Magnum::Math::Range3D, alias @ref Magnum::Math::Range1D |
||||
*/ |
||||
|
||||
#include "Math/Vector3.h" |
||||
|
||||
namespace Magnum { namespace Math { |
||||
|
||||
namespace Implementation { |
||||
template<UnsignedInt, class> struct RangeTraits; |
||||
|
||||
template<class T> struct RangeTraits<1, T> { typedef Vector<1, T> Type; }; |
||||
template<class T> struct RangeTraits<2, T> { typedef Vector2<T> Type; }; |
||||
template<class T> struct RangeTraits<3, T> { typedef Vector3<T> Type; }; |
||||
} |
||||
|
||||
/**
|
||||
@brief N-dimensional range |
||||
|
||||
Axis-aligned line (in 1D), rectangle (in 2D) or cube (in 3D). Minimal |
||||
coordinate is inclusive, maximal exclusive. See @ref Range1D, @ref Range2D and |
||||
@ref Range3D specializations for given dimension count. |
||||
*/ |
||||
template<UnsignedInt dimensions, class T> class Range { |
||||
template<UnsignedInt, class> friend class Range; |
||||
|
||||
public: |
||||
/**
|
||||
* @brief Underlying vector type |
||||
* |
||||
* `T` in 1D, @ref Vector2<T> in 2D, @ref Vector3<T> in 3D. |
||||
*/ |
||||
typedef typename Implementation::RangeTraits<dimensions, T>::Type VectorType; |
||||
|
||||
/**
|
||||
* Create range from minimal coordinates and size |
||||
* @param min Minimal coordinates |
||||
* @param size Range size |
||||
*/ |
||||
static Range<dimensions, T> fromSize(const VectorType& min, const VectorType& size) { |
||||
return {min, min+size}; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Construct zero range |
||||
* |
||||
* Construct zero-size range positioned at origin. |
||||
*/ |
||||
constexpr Range(): _min{}, _max{} {} |
||||
|
||||
/** @brief Construct range from minimal and maximal coordinates */ |
||||
constexpr Range(const VectorType& min, const VectorType& max): _min(min), _max(max) {} |
||||
|
||||
/** @brief Copy constructor */ |
||||
constexpr Range(const Range<dimensions, T>&) = default; |
||||
|
||||
/**
|
||||
* @brief Construct range from another of different type |
||||
* |
||||
* Performs only default casting on the values, no rounding or |
||||
* anything else. Example usage: |
||||
* @code |
||||
* Range2D<Float> floatingPoint({1.3f, 2.7f}, {-15.0f, 7.0f}); |
||||
* Range2D<Byte> integral(floatingPoint); // {{1, 2}, {-15, 7}}
|
||||
* @endcode |
||||
*/ |
||||
template<class U> constexpr explicit Range(const Range<dimensions, U>& other): _min(other._min), _max(other._max) {} |
||||
|
||||
/** @brief Equality comparison */ |
||||
constexpr bool operator==(const Range<dimensions, T>& other) const { |
||||
return _min == other._min && _max == other._max; |
||||
} |
||||
|
||||
/** @brief Non-equality comparison */ |
||||
constexpr bool operator!=(const Range<dimensions, T>& other) const { |
||||
return !operator==(other); |
||||
} |
||||
|
||||
/**
|
||||
* @brief Minimal coordinates (inclusive) |
||||
* |
||||
* @see @ref size(), @ref Range2D::bottomLeft(), |
||||
* @ref Range3D::backBottomLeft() |
||||
*/ |
||||
VectorType& min() { return _min; } |
||||
constexpr const VectorType min() const { return _min; } /**< @overload */ |
||||
|
||||
/**
|
||||
* @brief Maximal coordinates (exclusive) |
||||
* |
||||
* @see @ref size(), @ref Range2D::topRight(), |
||||
* @ref Range3D::frontTopRight() |
||||
*/ |
||||
VectorType& max() { return _max; } |
||||
constexpr const VectorType max() const { return _max; } /**< @overload */ |
||||
|
||||
/**
|
||||
* @brief Range size |
||||
* |
||||
* @see @ref min(), @ref max(), @ref Range2D::sizeX(), |
||||
* @ref Range2D::sizeY(), @ref Range3D::sizeX(), |
||||
* @ref Range3D::sizeY(), @ref Range3D::sizeZ() |
||||
*/ |
||||
VectorType size() const { return _max - _min; } |
||||
|
||||
/**
|
||||
* @brief Translated range |
||||
* |
||||
* Translates the minimal and maximal coordinates by given amount. Size |
||||
* remains the same. |
||||
*/ |
||||
Range<dimensions, T> translated(const VectorType& vector) const; |
||||
|
||||
private: |
||||
VectorType _min, _max; |
||||
}; |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
#define MAGNUM_RANGE_SUBCLASS_IMPLEMENTATION(dimensions, Type, VectorType) \ |
||||
static Type<T> fromSize(const VectorType<T>& min, const VectorType<T>& size) { \
|
||||
return Range<dimensions, T>::fromSize(min, size); \
|
||||
} \
|
||||
Type<T> translated(const VectorType<T>& vector) const { \
|
||||
return Range<dimensions, T>::translated(vector); \
|
||||
} |
||||
#endif |
||||
|
||||
#ifndef CORRADE_GCC46_COMPATIBILITY |
||||
/**
|
||||
@brief One-dimensional range |
||||
|
||||
Convenience alternative to <tt>%Range<1, T></tt>. See @ref Range for more |
||||
information. |
||||
@note Not available on GCC < 4.7. Use <tt>%Range<1, T></tt> instead. |
||||
*/ |
||||
template<class T> using Range1D = Range<1, T>; |
||||
#endif |
||||
|
||||
/**
|
||||
@brief Two-dimensional range |
||||
|
||||
See @ref Range for more information. |
||||
@see @ref Range1D, @ref Range3D |
||||
*/ |
||||
template<class T> class Range2D: public Range<2, T> { |
||||
public: |
||||
/** @copydoc Range() */ |
||||
constexpr Range2D() = default; |
||||
|
||||
/** @copydoc Range(const VectorType&, const VectorType&) */ |
||||
constexpr Range2D(const Vector2<T>& min, const Vector2<T>& max): Range<2, T>(min, max) {} |
||||
|
||||
/** @copydoc Range(const Range&) */ |
||||
constexpr Range2D(const Range<2, T>& other): Range<2, T>(other) {} |
||||
|
||||
/** @copydoc Range(const Range<dimensions, U>&) */ |
||||
template<class U> constexpr explicit Range2D(const Range2D<U>& other): Range<2, T>(other) {} |
||||
|
||||
/**
|
||||
* @brief Bottom left corner |
||||
* |
||||
* Equivalent to @ref min(). |
||||
*/ |
||||
Vector2<T>& bottomLeft() { return Range<2, T>::min(); } |
||||
constexpr Vector2<T> bottomLeft() const { return Range<2, T>::min(); } /**< @overload */ |
||||
|
||||
/** @brief Bottom right corner */ |
||||
constexpr Vector2<T> bottomRight() const { |
||||
return {Range<2, T>::max().x(), Range<2, T>::min().y()}; |
||||
} |
||||
|
||||
/** @brief Top left corner */ |
||||
constexpr Vector2<T> topLeft() const { |
||||
return {Range<2, T>::min().x(), Range<2, T>::max().y()}; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Top right corner |
||||
* |
||||
* Equivalent to @ref max(). |
||||
*/ |
||||
Vector2<T>& topRight() { return Range<2, T>::max(); } |
||||
constexpr Vector2<T> topRight() const { return Range<2, T>::max(); } /**< @overload */ |
||||
|
||||
/** @brief Left edge */ |
||||
T& left() { return Range<2, T>::min().x(); } |
||||
constexpr T left() const { return Range<2, T>::min().x(); } /**< @overload */ |
||||
|
||||
/** @brief Right edge */ |
||||
T& right() { return Range<2, T>::max().x(); } |
||||
constexpr T right() const { return Range<2, T>::max().x(); } /**< @overload */ |
||||
|
||||
/** @brief Bottom edge */ |
||||
T& bottom() { return Range<2, T>::min().y(); } |
||||
constexpr T bottom() const { return Range<2, T>::min().y(); } /**< @overload */ |
||||
|
||||
/** @brief Top edge */ |
||||
T& top() { return Range<2, T>::max().y(); } |
||||
constexpr T top() const { return Range<2, T>::max().y(); } /**< @overload */ |
||||
|
||||
/**
|
||||
* @brief %Range width |
||||
* |
||||
* @see @ref size() |
||||
*/ |
||||
T sizeX() const { |
||||
return Range<2, T>::max().x() - Range<2, T>::min().x(); |
||||
} |
||||
|
||||
/**
|
||||
* @brief %Range height |
||||
* |
||||
* @see @ref size() |
||||
*/ |
||||
T sizeY() const { |
||||
return Range<2, T>::max().y() - Range<2, T>::min().y(); |
||||
} |
||||
|
||||
MAGNUM_RANGE_SUBCLASS_IMPLEMENTATION(2, Range2D, Vector2) |
||||
}; |
||||
|
||||
/**
|
||||
@brief Two-dimensional range |
||||
|
||||
See @ref Range for more information. |
||||
@see @ref Range1D, @ref Range2D |
||||
*/ |
||||
template<class T> class Range3D: public Range<3, T> { |
||||
public: |
||||
/** @copydoc Range() */ |
||||
constexpr Range3D() = default; |
||||
|
||||
/** @copydoc Range(const VectorType&, const VectorType&) */ |
||||
constexpr Range3D(const Vector3<T>& min, const Vector3<T>& max): Range<3, T>(min, max) {} |
||||
|
||||
/** @copydoc Range(const Range&) */ |
||||
constexpr Range3D(const Range<3, T>& other): Range<3, T>(other) {} |
||||
|
||||
/** @copydoc Range(const Range<dimensions, U>&) */ |
||||
template<class U> constexpr explicit Range3D(const Range3D<U>& other): Range<3, T>(other) {} |
||||
|
||||
/**
|
||||
* @brief Back bottom left corner |
||||
* |
||||
* Equivalent to @ref min(). |
||||
*/ |
||||
Vector3<T>& backBottomLeft() { return Range<3, T>::min(); } |
||||
constexpr Vector3<T> backBottomLeft() const { return Range<3, T>::min(); } /**< @overload */ |
||||
|
||||
/** @brief Back bottom right corner */ |
||||
constexpr Vector3<T> backBottomRight() const { |
||||
return {Range<3, T>::max().x(), Range<3, T>::min().y(), Range<3, T>::min().z()}; |
||||
} |
||||
|
||||
/** @brief Back top right corner */ |
||||
constexpr Vector3<T> backTopLeft() const { |
||||
return {Range<3, T>::min().x(), Range<3, T>::max().y(), Range<3, T>::min().z()}; |
||||
} |
||||
|
||||
/** @brief Back top right corner */ |
||||
constexpr Vector3<T> backTopRight() const { |
||||
return {Range<3, T>::max().x(), Range<3, T>::max().y(), Range<3, T>::min().z()}; |
||||
} |
||||
|
||||
/**
|
||||
* @brief Front top right corner |
||||
* |
||||
* Equivalent to @ref max(). |
||||
*/ |
||||
Vector3<T>& frontTopRight() { return Range<3, T>::max(); } |
||||
constexpr Vector3<T> frontTopRight() const { return Range<3, T>::max(); } /**< @overload */ |
||||
|
||||
/** @brief Front top left corner */ |
||||
constexpr Vector3<T> frontTopLeft() const { |
||||
return {Range<3, T>::min().x(), Range<3, T>::max().y(), Range<3, T>::max().z()}; |
||||
} |
||||
|
||||
/** @brief Front bottom right corner */ |
||||
constexpr Vector3<T> frontBottomRight() const { |
||||
return {Range<3, T>::max().x(), Range<3, T>::min().y(), Range<3, T>::max().z()}; |
||||
} |
||||
|
||||
/** @brief Front bottom left corner */ |
||||
constexpr Vector3<T> frontBottomLeft() const { |
||||
return {Range<3, T>::min().x(), Range<3, T>::min().y(), Range<3, T>::max().z()}; |
||||
} |
||||
|
||||
/** @brief Left edge */ |
||||
T& left() { return Range<3, T>::min().x(); } |
||||
constexpr T left() const { return Range<3, T>::min().x(); } /**< @overload */ |
||||
|
||||
/** @brief Right edge */ |
||||
T& right() { return Range<3, T>::max().x(); } |
||||
constexpr T right() const { return Range<3, T>::max().x(); } /**< @overload */ |
||||
|
||||
/** @brief Bottom edge */ |
||||
T& bottom() { return Range<3, T>::min().y(); } |
||||
constexpr T bottom() const { return Range<3, T>::min().y(); } /**< @overload */ |
||||
|
||||
/** @brief Top edge */ |
||||
T& top() { return Range<3, T>::max().y(); } |
||||
constexpr T top() const { return Range<3, T>::max().y(); } /**< @overload */ |
||||
|
||||
/** @brief Back edge */ |
||||
T& back() { return Range<3, T>::min().z(); } |
||||
constexpr T back() const { return Range<3, T>::min().z(); } /**< @overload */ |
||||
|
||||
/** @brief Front edge */ |
||||
T& front() { return Range<3, T>::max().z(); } |
||||
constexpr T front() const { return Range<3, T>::max().z(); } /**< @overload */ |
||||
|
||||
/**
|
||||
* @brief %Range width |
||||
* |
||||
* @see @ref size() |
||||
*/ |
||||
T sizeX() const { |
||||
return Range<3, T>::max().x() - Range<3, T>::min().x(); |
||||
} |
||||
|
||||
/**
|
||||
* @brief %Range height |
||||
* |
||||
* @see @ref size() |
||||
*/ |
||||
T sizeY() const { |
||||
return Range<3, T>::max().y() - Range<3, T>::min().y(); |
||||
} |
||||
|
||||
/**
|
||||
* @brief %Range depth |
||||
* |
||||
* @see @ref size() |
||||
*/ |
||||
T sizeZ() const { |
||||
return Range<3, T>::max().z() - Range<3, T>::min().z(); |
||||
} |
||||
|
||||
MAGNUM_RANGE_SUBCLASS_IMPLEMENTATION(3, Range3D, Vector3) |
||||
}; |
||||
|
||||
/** @debugoperator{Magnum::Math::Range} */ |
||||
template<UnsignedInt dimensions, class T> Corrade::Utility::Debug operator<<(Corrade::Utility::Debug debug, const Range<dimensions, T>& value) { |
||||
debug << "Range({"; |
||||
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, false); |
||||
debug << value.min()[0]; |
||||
for(UnsignedInt i = 1; i != dimensions; ++i) debug << ", " << value.min()[i]; |
||||
debug << "}, {" << value.max()[0]; |
||||
for(UnsignedInt i = 1; i != dimensions; ++i) debug << ", " << value.max()[i]; |
||||
debug << "})"; |
||||
debug.setFlag(Corrade::Utility::Debug::SpaceAfterEachValue, true); |
||||
return debug; |
||||
} |
||||
|
||||
template<UnsignedInt dimensions, class T> Range<dimensions, T> Range<dimensions, T>::translated(const VectorType& vector) const { |
||||
return {_min + vector, _max + vector}; |
||||
} |
||||
|
||||
}} |
||||
|
||||
namespace Corrade { namespace Utility { |
||||
|
||||
/** @configurationvalue{Magnum::Math::Range} */ |
||||
template<Magnum::UnsignedInt dimensions, class T> struct ConfigurationValue<Magnum::Math::Range<dimensions, T>> { |
||||
ConfigurationValue() = delete; |
||||
|
||||
/** @brief Writes elements separated with spaces */ |
||||
static std::string toString(const Magnum::Math::Range<dimensions, T>& value, const ConfigurationValueFlags flags) { |
||||
return ConfigurationValue<Magnum::Math::Vector<dimensions*2, T>>::toString( |
||||
reinterpret_cast<const Magnum::Math::Vector<dimensions*2, T>&>(value), flags); |
||||
} |
||||
|
||||
/** @brief Reads elements separated with whitespace */ |
||||
static Magnum::Math::Range<dimensions, T> fromString(const std::string& stringValue, const ConfigurationValueFlags flags) { |
||||
const auto vec = ConfigurationValue<Magnum::Math::Vector<dimensions*2, T>>::fromString(stringValue, flags); |
||||
return *reinterpret_cast<const Magnum::Math::Range<dimensions, T>*>(vec.data()); |
||||
} |
||||
}; |
||||
|
||||
/** @configurationvalue{Magnum::Math::Range2D} */ |
||||
template<class T> struct ConfigurationValue<Magnum::Math::Range2D<T>>: public ConfigurationValue<Magnum::Math::Range<2, T>> {}; |
||||
|
||||
/** @configurationvalue{Magnum::Math::Range3D} */ |
||||
template<class T> struct ConfigurationValue<Magnum::Math::Range3D<T>>: public ConfigurationValue<Magnum::Math::Range<3, T>> {}; |
||||
|
||||
#ifndef DOXYGEN_GENERATING_OUTPUT |
||||
extern template struct MAGNUM_EXPORT ConfigurationValue<Magnum::Math::Range<2, Magnum::Float>>; |
||||
extern template struct MAGNUM_EXPORT ConfigurationValue<Magnum::Math::Range<2, Magnum::Int>>; |
||||
extern template struct MAGNUM_EXPORT ConfigurationValue<Magnum::Math::Range<3, Magnum::Float>>; |
||||
extern template struct MAGNUM_EXPORT ConfigurationValue<Magnum::Math::Range<3, Magnum::Int>>; |
||||
#ifndef MAGNUM_TARGET_GLES |
||||
extern template struct MAGNUM_EXPORT ConfigurationValue<Magnum::Math::Range<2, Magnum::Double>>; |
||||
extern template struct MAGNUM_EXPORT ConfigurationValue<Magnum::Math::Range<3, Magnum::Double>>; |
||||
#endif |
||||
#endif |
||||
|
||||
}} |
||||
|
||||
#endif |
||||
@ -0,0 +1,311 @@
|
||||
/*
|
||||
This file is part of Magnum. |
||||
|
||||
Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz> |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a |
||||
copy of this software and associated documentation files (the "Software"), |
||||
to deal in the Software without restriction, including without limitation |
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||||
and/or sell copies of the Software, and to permit persons to whom the |
||||
Software is furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included |
||||
in all copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
||||
DEALINGS IN THE SOFTWARE. |
||||
*/ |
||||
|
||||
#include <sstream> |
||||
#include <TestSuite/Tester.h> |
||||
#include <Utility/Configuration.h> |
||||
|
||||
#include "Math/Range.h" |
||||
|
||||
#ifdef MAGNUM_BUILD_DEPRECATED |
||||
#include "Math/Geometry/Rectangle.h" |
||||
#endif |
||||
|
||||
namespace Magnum { namespace Math { namespace Test { |
||||
|
||||
class RangeTest: public Corrade::TestSuite::Tester { |
||||
public: |
||||
RangeTest(); |
||||
|
||||
void construct(); |
||||
void constructDefault(); |
||||
void constructFromSize(); |
||||
void constructConversion(); |
||||
void constructCopy(); |
||||
|
||||
void access(); |
||||
void compare(); |
||||
void size(); |
||||
|
||||
void translated(); |
||||
|
||||
void subclassTypes(); |
||||
void subclass(); |
||||
|
||||
void debug(); |
||||
void configuration(); |
||||
}; |
||||
|
||||
typedef Math::Range<1, Float> Range1D; |
||||
typedef Math::Range2D<Float> Range2D; |
||||
typedef Math::Range3D<Float> Range3D; |
||||
typedef Math::Range1D<Int> Range1Di; |
||||
typedef Math::Range2D<Int> Range2Di; |
||||
typedef Math::Range3D<Int> Range3Di; |
||||
typedef Vector2<Int> Vector2i; |
||||
typedef Vector3<Int> Vector3i; |
||||
|
||||
RangeTest::RangeTest() { |
||||
addTests({&RangeTest::construct, |
||||
&RangeTest::constructDefault, |
||||
&RangeTest::constructFromSize, |
||||
&RangeTest::constructConversion, |
||||
&RangeTest::constructCopy, |
||||
|
||||
&RangeTest::access, |
||||
&RangeTest::compare, |
||||
&RangeTest::size, |
||||
|
||||
&RangeTest::translated, |
||||
|
||||
&RangeTest::subclassTypes, |
||||
&RangeTest::subclass, |
||||
|
||||
&RangeTest::debug, |
||||
&RangeTest::configuration}); |
||||
} |
||||
|
||||
void RangeTest::construct() { |
||||
constexpr Range1Di a(3, 23); |
||||
constexpr Range2Di b({3, 5}, {23, 78}); |
||||
constexpr Range3Di c({3, 5, -7}, {23, 78, 2}); |
||||
|
||||
CORRADE_COMPARE(a, (Range<1, Int>(3, 23))); |
||||
CORRADE_COMPARE(b, (Range<2, Int>({3, 5}, {23, 78}))); |
||||
CORRADE_COMPARE(c, (Range<3, Int>({3, 5, -7}, {23, 78, 2}))); |
||||
} |
||||
|
||||
void RangeTest::constructDefault() { |
||||
constexpr Range1Di a; |
||||
constexpr Range2Di b; |
||||
constexpr Range3Di c; |
||||
|
||||
CORRADE_COMPARE(a, Range1Di(0, 0)); |
||||
CORRADE_COMPARE(b, Range2Di({0, 0}, {0, 0})); |
||||
CORRADE_COMPARE(c, Range3Di({0, 0, 0}, {0, 0, 0})); |
||||
} |
||||
|
||||
void RangeTest::constructFromSize() { |
||||
CORRADE_COMPARE(Range1Di::fromSize(3, 23), Range1Di(3, 26)); |
||||
CORRADE_COMPARE(Range2Di::fromSize({3, 5}, {23, 78}), Range2Di({3, 5}, {26, 83})); |
||||
CORRADE_COMPARE(Range3Di::fromSize({3, 5, -7}, {23, 78, 9}), Range3Di({3, 5, -7}, {26, 83, 2})); |
||||
} |
||||
|
||||
void RangeTest::constructConversion() { |
||||
constexpr Range1D a(1.3f, -15.0f); |
||||
constexpr Range2D b({1.3f, 2.7f}, {-15.0f, 7.0f}); |
||||
constexpr Range3D c({1.3f, 2.7f, -1.5f}, {-15.0f, 7.0f, 0.3f}); |
||||
|
||||
#ifndef CORRADE_GCC46_COMPATIBILITY |
||||
constexpr /* Not constexpr under GCC < 4.7 */ |
||||
#endif |
||||
Range1Di d(a); |
||||
CORRADE_COMPARE(d, Range1Di(1, -15)); |
||||
|
||||
#ifndef CORRADE_GCC46_COMPATIBILITY |
||||
constexpr /* Not constexpr under GCC < 4.7 */ |
||||
#endif |
||||
Range2Di e(b); |
||||
CORRADE_COMPARE(e, Range2Di({1, 2}, {-15, 7})); |
||||
|
||||
#ifndef CORRADE_GCC46_COMPATIBILITY |
||||
constexpr /* Not constexpr under GCC < 4.7 */ |
||||
#endif |
||||
Range3Di f(c); |
||||
CORRADE_COMPARE(f, Range3Di({1, 2, -1}, {-15, 7, 0})); |
||||
|
||||
/* Implicit conversion is not allowed */ |
||||
CORRADE_VERIFY(!(std::is_convertible<Range<2, Float>, Range<2, Int>>::value)); |
||||
CORRADE_VERIFY(!(std::is_convertible<Range1D, Range1Di>::value)); |
||||
CORRADE_VERIFY(!(std::is_convertible<Range2D, Range2Di>::value)); |
||||
CORRADE_VERIFY(!(std::is_convertible<Range3D, Range3Di>::value)); |
||||
} |
||||
|
||||
void RangeTest::constructCopy() { |
||||
constexpr Range1Di a(3, 23); |
||||
constexpr Range2Di b({3, 5}, {23, 78}); |
||||
constexpr Range3Di c({3, 5, -7}, {23, 78, 2}); |
||||
|
||||
constexpr Range1Di d(a); |
||||
constexpr Range2Di e(b); |
||||
constexpr Range3Di f(c); |
||||
|
||||
CORRADE_COMPARE(d, Range1Di(3, 23)); |
||||
CORRADE_COMPARE(e, Range2Di({3, 5}, {23, 78})); |
||||
CORRADE_COMPARE(f, Range3Di({3, 5, -7}, {23, 78, 2})); |
||||
} |
||||
|
||||
void RangeTest::access() { |
||||
Range1Di line(34, 47); |
||||
Range2Di rect({34, 23}, {47, 30}); |
||||
Range3Di cube({34, 23, -17}, {47, 30, 12}); |
||||
|
||||
constexpr Range1Di cline(34, 47); |
||||
constexpr Range2Di crect({34, 23}, {47, 30}); |
||||
constexpr Range3Di ccube({34, 23, -17}, {47, 30, 12}); |
||||
|
||||
CORRADE_COMPARE(line.min(), 34); |
||||
CORRADE_COMPARE(cline.min(), 34); |
||||
CORRADE_COMPARE(line.max(), 47); |
||||
CORRADE_COMPARE(cline.max(), 47); |
||||
|
||||
CORRADE_COMPARE(rect.bottomLeft(), Vector2i(34, 23)); |
||||
CORRADE_COMPARE(rect.topRight(), Vector2i(47, 30)); |
||||
constexpr Vector2i bottomLeft = crect.bottomLeft(); |
||||
constexpr Vector2i topRight = crect.topRight(); |
||||
CORRADE_COMPARE(bottomLeft, Vector2i(34, 23)); |
||||
CORRADE_COMPARE(topRight, Vector2i(47, 30)); |
||||
|
||||
CORRADE_COMPARE(rect.left(), 34); |
||||
CORRADE_COMPARE(rect.right(), 47); |
||||
CORRADE_COMPARE(rect.bottom(), 23); |
||||
CORRADE_COMPARE(rect.top(), 30); |
||||
constexpr Int left2 = crect.left(); |
||||
constexpr Int right2 = crect.right(); |
||||
constexpr Int bottom2 = crect.bottom(); |
||||
constexpr Int top2 = crect.top(); |
||||
CORRADE_COMPARE(left2, 34); |
||||
CORRADE_COMPARE(right2, 47); |
||||
CORRADE_COMPARE(bottom2, 23); |
||||
CORRADE_COMPARE(top2, 30); |
||||
|
||||
CORRADE_COMPARE(cube.backBottomLeft(), Vector3i(34, 23, -17)); |
||||
CORRADE_COMPARE(cube.frontTopRight(), Vector3i(47, 30, 12)); |
||||
constexpr Vector3i backBottomLeft = ccube.backBottomLeft(); |
||||
constexpr Vector3i frontTopRight = ccube.frontTopRight(); |
||||
CORRADE_COMPARE(backBottomLeft, Vector3i(34, 23, -17)); |
||||
CORRADE_COMPARE(frontTopRight, Vector3i(47, 30, 12)); |
||||
|
||||
CORRADE_COMPARE(cube.left(), 34); |
||||
CORRADE_COMPARE(cube.right(), 47); |
||||
CORRADE_COMPARE(cube.bottom(), 23); |
||||
CORRADE_COMPARE(cube.top(), 30); |
||||
CORRADE_COMPARE(cube.back(), -17); |
||||
CORRADE_COMPARE(cube.front(), 12); |
||||
constexpr Int left3 = ccube.left(); |
||||
constexpr Int right3 = ccube.right(); |
||||
constexpr Int bottom3 = ccube.bottom(); |
||||
constexpr Int top3 = ccube.top(); |
||||
constexpr Int back3 = ccube.back(); |
||||
constexpr Int front3 = ccube.front(); |
||||
CORRADE_COMPARE(left3, 34); |
||||
CORRADE_COMPARE(right3, 47); |
||||
CORRADE_COMPARE(bottom3, 23); |
||||
CORRADE_COMPARE(top3, 30); |
||||
CORRADE_COMPARE(back3, -17); |
||||
CORRADE_COMPARE(front3, 12); |
||||
|
||||
CORRADE_COMPARE(rect.bottomRight(), Vector2i(47, 23)); |
||||
CORRADE_COMPARE(rect.topLeft(), Vector2i(34, 30)); |
||||
|
||||
CORRADE_COMPARE(cube.backBottomRight(), Vector3i(47, 23, -17)); |
||||
CORRADE_COMPARE(cube.backTopLeft(), Vector3i(34, 30, -17)); |
||||
CORRADE_COMPARE(cube.backTopRight(), Vector3i(47, 30, -17)); |
||||
CORRADE_COMPARE(cube.frontBottomLeft(), Vector3i(34, 23, 12)); |
||||
CORRADE_COMPARE(cube.frontBottomRight(), Vector3i(47, 23, 12)); |
||||
CORRADE_COMPARE(cube.frontTopLeft(), Vector3i(34, 30, 12)); |
||||
} |
||||
|
||||
void RangeTest::compare() { |
||||
CORRADE_VERIFY(Range2Di({34, 23}, {47, 30}) == Range2Di({34, 23}, {47, 30})); |
||||
CORRADE_VERIFY(Range2Di({34, 23}, {47, 30}) != Range2Di({34, 23}, {48, 30})); |
||||
CORRADE_VERIFY(Range2Di({34, 23}, {47, 30}) != Range2Di({35, 23}, {47, 30})); |
||||
|
||||
CORRADE_VERIFY(Range1D(1.0f, 1.0f) != Range1D(1.0f + TypeTraits<Float>::epsilon()*2, 1.0f)); |
||||
CORRADE_VERIFY(Range1D(1.0f, 1.0f) != Range1D(1.0f, 1.0f + TypeTraits<Float>::epsilon()*2)); |
||||
CORRADE_VERIFY(Range1D(1.0f, 1.0f) == Range1D(1.0f + TypeTraits<Float>::epsilon()/2.0f, |
||||
1.0f + TypeTraits<Float>::epsilon()/2.0f)); |
||||
} |
||||
|
||||
void RangeTest::size() { |
||||
const Range1Di line(34, 47); |
||||
const Range2Di rect({34, 23}, {47, 30}); |
||||
const Range3Di cube({34, 23, -17}, {47, 30, 12}); |
||||
|
||||
CORRADE_COMPARE(line.size(), 13); |
||||
CORRADE_COMPARE(rect.size(), Vector2i(13, 7)); |
||||
CORRADE_COMPARE(cube.size(), Vector3i(13, 7, 29)); |
||||
|
||||
CORRADE_COMPARE(rect.sizeX(), 13); |
||||
CORRADE_COMPARE(rect.sizeY(), 7); |
||||
|
||||
CORRADE_COMPARE(cube.sizeX(), 13); |
||||
CORRADE_COMPARE(cube.sizeY(), 7); |
||||
CORRADE_COMPARE(cube.sizeZ(), 29); |
||||
} |
||||
|
||||
void RangeTest::translated() { |
||||
Range2Di a({34, 23}, {47, 30}); |
||||
Range2Di b({17, 63}, {30, 70}); |
||||
|
||||
CORRADE_COMPARE(a.translated({-17, 40}), b); |
||||
CORRADE_COMPARE(a.size(), b.size()); |
||||
} |
||||
|
||||
template<class T> class BasicRect: public Math::Range<2, T> { |
||||
public: |
||||
template<class ...U> BasicRect(U&&... args): Math::Range<2, T>{std::forward<U>(args)...} {} |
||||
|
||||
MAGNUM_RANGE_SUBCLASS_IMPLEMENTATION(2, BasicRect, Vector2) |
||||
}; |
||||
|
||||
typedef BasicRect<Int> Recti; |
||||
|
||||
void RangeTest::subclassTypes() { |
||||
const Vector2i a; |
||||
CORRADE_VERIFY((std::is_same<decltype(Recti::fromSize(a, a)), Recti>::value)); |
||||
|
||||
const Recti r; |
||||
CORRADE_VERIFY((std::is_same<decltype(r.translated(a)), Recti>::value)); |
||||
} |
||||
|
||||
void RangeTest::subclass() { |
||||
CORRADE_COMPARE(Recti::fromSize({3, 5}, {23, 78}), |
||||
Recti(Vector2i{3, 5}, Vector2i{26, 83})); |
||||
|
||||
CORRADE_COMPARE(Recti(Vector2i{34, 23}, Vector2i{47, 30}).translated({-17, 40}), |
||||
Recti(Vector2i{17, 63}, Vector2i{30, 70})); |
||||
} |
||||
|
||||
void RangeTest::debug() { |
||||
std::ostringstream o; |
||||
Debug(&o) << Range2Di({34, 23}, {47, 30}); |
||||
|
||||
CORRADE_COMPARE(o.str(), "Range({34, 23}, {47, 30})\n"); |
||||
} |
||||
|
||||
void RangeTest::configuration() { |
||||
Corrade::Utility::Configuration c; |
||||
|
||||
Range2D rect({3.0f, 3.125f}, {9.0f, 9.55f}); |
||||
std::string value("3 3.125 9 9.55"); |
||||
|
||||
c.setValue("rectangle", rect); |
||||
CORRADE_COMPARE(c.value("rectangle"), value); |
||||
CORRADE_COMPARE(c.value<Range2D>("rectangle"), rect); |
||||
} |
||||
|
||||
}}} |
||||
|
||||
CORRADE_TEST_MAIN(Magnum::Math::Test::RangeTest) |
||||
Loading…
Reference in new issue