blob: b9cdc5f75495b56c31396aa03f3ca48d07be1fb8 [file]
#include <catch.hpp>
#include "rive/math/mat2d.hpp"
#include "rive/math/math_types.hpp"
namespace rive
{
TEST_CASE("IAABB_join", "[IAABB]")
{
CHECK(IAABB{1, -2, 99, 101}.join(IAABB{0, 0, 100, 100}) ==
IAABB{0, -2, 100, 101});
CHECK(IAABB{1, -2, 99, 101}.join(IAABB{2, -3, 98, 103}) ==
IAABB{1, -3, 99, 103});
}
TEST_CASE("IAABB_intersect", "[IAABB]")
{
CHECK(IAABB{1, -2, 99, 101}.intersect(IAABB{0, 0, 100, 100}) ==
IAABB{1, 0, 99, 100});
CHECK(IAABB{1, -2, 99, 101}.intersect(IAABB{2, -3, 98, 103}) ==
IAABB{2, -2, 98, 101});
}
TEST_CASE("IAABB_empty", "[IAABB]")
{
CHECK(IAABB{0, 0, 0, 0}.empty());
CHECK(IAABB{0, 0, 0, 1}.empty());
CHECK(IAABB{0, 0, 1, 0}.empty());
CHECK(!IAABB{0, 0, 1, 1}.empty());
CHECK(IAABB{0, 0, -1, -1}.empty());
CHECK(IAABB{std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::max(),
std::numeric_limits<int32_t>::min(),
std::numeric_limits<int32_t>::min()}
.empty());
}
TEST_CASE("isEmptyOrNaN", "[AABB]")
{
auto inf = std::numeric_limits<float>::infinity();
auto nan = std::numeric_limits<float>::quiet_NaN();
CHECK(!AABB{0, 0, 1, 1}.isEmptyOrNaN());
CHECK(!AABB{-inf, -inf, inf, inf}.isEmptyOrNaN());
CHECK(AABB{0, 0, 0, 0}.isEmptyOrNaN());
CHECK(AABB{0, 0, -1, -2}.isEmptyOrNaN());
CHECK(AABB{inf, inf, -inf, -inf}.isEmptyOrNaN());
CHECK(AABB{inf, -inf, -inf, inf}.isEmptyOrNaN());
CHECK(AABB{-inf, inf, inf, -inf}.isEmptyOrNaN());
CHECK(AABB{nan, 0, 10, 10}.isEmptyOrNaN());
CHECK(AABB{0, nan, 10, 10}.isEmptyOrNaN());
CHECK(AABB{0, 0, nan, 10}.isEmptyOrNaN());
CHECK(AABB{0, 0, 10, nan}.isEmptyOrNaN());
CHECK(AABB{nan, nan, 10, 10}.isEmptyOrNaN());
CHECK(AABB{nan, nan, nan, 10}.isEmptyOrNaN());
CHECK(AABB{nan, nan, nan, nan}.isEmptyOrNaN());
}
TEST_CASE("AABB contains", "[AABB]")
{
CHECK(AABB{0, 0, 100, 100}.contains(Vec2D(20, 20)));
CHECK(AABB{0, 0, 100, 100}.contains(Vec2D(0, 0)));
CHECK(AABB{0, 0, 100, 100}.contains(Vec2D(100, 100)));
CHECK(!AABB{0, 0, 100, 100}.contains(Vec2D(200, 200)));
CHECK(!AABB{0, 0, 100, 100}.contains(Vec2D(-200, -200)));
auto leftBoundary = 0.f;
auto rightBoundary = 100.f;
CHECK(!AABB{leftBoundary, 0, rightBoundary, 100.0}.contains(
Vec2D(leftBoundary - std::numeric_limits<float>::epsilon(), 50)));
CHECK(!AABB{leftBoundary, 0, rightBoundary, 100.0}.contains(Vec2D(
rightBoundary + rightBoundary * std::numeric_limits<float>::epsilon(),
50)));
}
TEST_CASE("IAABB overlaps", "[AABB]")
{
// Completely contained
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{10, 10, 90, 90}));
// Coincident
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{0, 0, 100, 100}));
// One edge out of range
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{-1000, 10, 90, 90}));
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{10, -1000, 90, 90}));
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{10, 10, 1000, 90}));
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{10, 10, 90, 1000}));
// One edge still in range
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{-1000, -1000, 1000, 90}));
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{-1000, -1000, 90, 1000}));
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{-1000, 10, 1000, 1000}));
CHECK(IAABB{0, 0, 100, 100}.overlaps(IAABB{10, -1000, 1000, 1000}));
// Disjoint
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{110, 10, 190, 90}));
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{10, 110, 90, 190}));
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{-110, 10, -10, 90}));
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{10, -110, 90, -10}));
// Abutting, but disjoint
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{-10, 10, 0, 90}));
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{10, -10, 90, 0}));
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{100, 10, 190, 90}));
CHECK(!IAABB{0, 0, 100, 100}.overlaps(IAABB{10, 100, 190, 90}));
}
TEST_CASE("AABB overlaps", "[AABB]")
{
// Completely contained
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, 10.0f, 90.0f, 90.0f}));
// Coincident
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{0.0f, 0.0f, 100.0f, 100.0f}));
// One edge out of range
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{-1000.0f, 10.0f, 90.0f, 90.0f}));
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, -1000.0f, 90.0f, 90.0f}));
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, 10.0f, 1000.0f, 90.0f}));
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, 10.0f, 90.0f, 1000.0f}));
// One edge still in range
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{-1000, -1000, 1000, 90}));
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{-1000, -1000, 90, 1000}));
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{-1000.0f, 10.0f, 1000.0f, 1000.0f}));
CHECK(AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, -1000.0f, 1000.0f, 1000.0f}));
// Disjoint
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{110.0f, 10.0f, 190.0f, 90.0f}));
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, 110.0f, 90.0f, 190.0f}));
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{-110.0f, 10.0f, -10.0f, 90.0f}));
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, -110.0f, 90.0f, -10.0f}));
// Abuting, but disjoint
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{-10.0f, 10.0f, 0.0f, 90.0f}));
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, -10.0f, 90.0f, 0.0f}));
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{100.0f, 10.0f, 190.0f, 90.0f}));
CHECK(!AABB{0.0f, 0.0f, 100.0f, 100.0f}.overlaps(
AABB{10.0f, 100.0f, 190.0f, 90.0f}));
}
TEST_CASE("TAABB::makeMaximal", "[AABB]")
{
auto testType = [](auto valueForType) {
using T = decltype(valueForType);
std::ignore = valueForType;
constexpr auto Min = std::numeric_limits<T>::min();
constexpr auto Max = std::numeric_limits<T>::max();
CHECK(TAABB<T>::makeMaximal() == TAABB<T>{Min, Min, Max, Max});
};
testType(int16_t{});
testType(uint16_t{});
testType(int32_t{});
testType(uint32_t{});
testType(int64_t{});
testType(uint64_t{});
}
TEST_CASE("TAABB::makeMaximallyNegative", "[AABB]")
{
auto testType = [](auto valueForType) {
using T = decltype(valueForType);
std::ignore = valueForType;
constexpr auto Min = std::numeric_limits<T>::min();
constexpr auto Max = std::numeric_limits<T>::max();
CHECK(TAABB<T>::makeMaximallyNegative() ==
TAABB<T>{Max, Max, Min, Min});
};
testType(int16_t{});
testType(uint16_t{});
testType(int32_t{});
testType(uint32_t{});
testType(int64_t{});
testType(uint64_t{});
}
} // namespace rive