mirror of
https://github.com/enduro2d/enduro2d.git
synced 2025-12-15 00:11:55 +07:00
math rect class
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "mat2.hpp"
|
#include "mat2.hpp"
|
||||||
#include "mat3.hpp"
|
#include "mat3.hpp"
|
||||||
#include "mat4.hpp"
|
#include "mat4.hpp"
|
||||||
|
#include "rect.hpp"
|
||||||
#include "trig.hpp"
|
#include "trig.hpp"
|
||||||
#include "unit.hpp"
|
#include "unit.hpp"
|
||||||
#include "vec2.hpp"
|
#include "vec2.hpp"
|
||||||
|
|||||||
@@ -28,6 +28,9 @@ namespace e2d
|
|||||||
template < typename T >
|
template < typename T >
|
||||||
class mat4;
|
class mat4;
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
class rect;
|
||||||
|
|
||||||
template < typename T, typename Tag >
|
template < typename T, typename Tag >
|
||||||
class unit;
|
class unit;
|
||||||
|
|
||||||
@@ -79,6 +82,13 @@ namespace e2d
|
|||||||
using m4hi = mat4<i16>;
|
using m4hi = mat4<i16>;
|
||||||
using m4hu = mat4<u16>;
|
using m4hu = mat4<u16>;
|
||||||
|
|
||||||
|
using r4d = rect<f64>;
|
||||||
|
using r4f = rect<f32>;
|
||||||
|
using r4i = rect<i32>;
|
||||||
|
using r4u = rect<u32>;
|
||||||
|
using r4hi = rect<i16>;
|
||||||
|
using r4hu = rect<u16>;
|
||||||
|
|
||||||
struct deg_tag {};
|
struct deg_tag {};
|
||||||
struct rad_tag {};
|
struct rad_tag {};
|
||||||
|
|
||||||
|
|||||||
212
headers/enduro2d/math/rect.hpp
Normal file
212
headers/enduro2d/math/rect.hpp
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "Enduro2D"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2018 Matvey Cherevko
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "_math.hpp"
|
||||||
|
#include "vec2.hpp"
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
class rect final {
|
||||||
|
static_assert(
|
||||||
|
std::is_arithmetic<T>::value,
|
||||||
|
"type of 'rect' must be arithmetic");
|
||||||
|
public:
|
||||||
|
using self_type = rect;
|
||||||
|
using value_type = T;
|
||||||
|
public:
|
||||||
|
vec2<T> position;
|
||||||
|
vec2<T> size;
|
||||||
|
public:
|
||||||
|
rect() noexcept = default;
|
||||||
|
rect(const rect& other) noexcept = default;
|
||||||
|
rect& operator=(const rect& other) noexcept = default;
|
||||||
|
|
||||||
|
rect(T w, T h) noexcept;
|
||||||
|
rect(T x, T y, T w, T h) noexcept;
|
||||||
|
|
||||||
|
rect(const vec2<T>& nsize) noexcept;
|
||||||
|
rect(const vec2<T>& nposition, const vec2<T>& nsize) noexcept;
|
||||||
|
|
||||||
|
template < typename To >
|
||||||
|
rect<To> cast_to() const noexcept;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
template < typename T >
|
||||||
|
rect<T>::rect(T w, T h) noexcept
|
||||||
|
: size(w, h) {}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T>::rect(T x, T y, T w, T h) noexcept
|
||||||
|
: position(x, y)
|
||||||
|
, size(w, h) {}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T>::rect(const vec2<T>& nsize) noexcept
|
||||||
|
: size(nsize) {}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T>::rect(const vec2<T>& nposition, const vec2<T>& nsize) noexcept
|
||||||
|
: position(nposition)
|
||||||
|
, size(nsize) {}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
template < typename To >
|
||||||
|
rect<To> rect<T>::cast_to() const noexcept {
|
||||||
|
return {
|
||||||
|
position.template cast_to<To>(),
|
||||||
|
size.template cast_to<To>()};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace e2d
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// make_rect
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T> make_rect(T w, T h) noexcept {
|
||||||
|
return {w, h};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T> make_rect(T x, T y, T w, T h) noexcept {
|
||||||
|
return {x, y, w, h};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T> make_rect(const vec2<T>& size) noexcept {
|
||||||
|
return {size};
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T> make_rect(const vec2<T>& position, const vec2<T>& size) noexcept {
|
||||||
|
return {position, size};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// rect (==,!=) rect
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool operator==(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
return l.position == r.position
|
||||||
|
&& l.size == r.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool operator!=(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
return !(l == r);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// rect (<,>,<=,>=) rect
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool operator<(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
return l.size.x * l.size.y < r.size.x * r.size.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool operator>(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
return r < l;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool operator<=(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
return !(r < l);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool operator>=(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
return !(l < r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace e2d { namespace math
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// approximately
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool approximately(
|
||||||
|
const rect<T>& l,
|
||||||
|
const rect<T>& r,
|
||||||
|
T precision = math::default_precision<T>()) noexcept
|
||||||
|
{
|
||||||
|
return math::approximately(l.position, r.position, precision)
|
||||||
|
&& math::approximately(l.size, r.size, precision);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// minimum/maximum
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
vec2<T> minimum(const rect<T>& r) noexcept {
|
||||||
|
return math::minimized(r.position, r.position + r.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
vec2<T> maximum(const rect<T>& r) noexcept {
|
||||||
|
return math::maximized(r.position, r.position + r.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// area
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
T area(const rect<T>& r) noexcept {
|
||||||
|
return r.size.x * r.size.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
T abs_area(const rect<T>& r) noexcept {
|
||||||
|
return math::abs(r.size.x * r.size.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// merged
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
rect<T> merged(const rect<T>& l, const rect<T>& r) noexcept {
|
||||||
|
const vec2<T> min = math::minimized(minimum(l), minimum(r));
|
||||||
|
const vec2<T> max = math::maximized(maximum(l), maximum(r));
|
||||||
|
return { min, max - min };
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// inside
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool inside(const rect<T>& r, const vec2<T>& p) noexcept {
|
||||||
|
const vec2<T> min = minimum(r);
|
||||||
|
const vec2<T> max = maximum(r);
|
||||||
|
return p.x >= min.x && p.x <= max.x
|
||||||
|
&& p.y >= min.y && p.y <= max.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// contains_nan
|
||||||
|
//
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
bool contains_nan(const rect<T>& r) noexcept {
|
||||||
|
return math::contains_nan(r.position)
|
||||||
|
|| math::contains_nan(r.size);
|
||||||
|
}
|
||||||
|
}}
|
||||||
109
untests/sources/untests_math/rect.cpp
Normal file
109
untests/sources/untests_math/rect.cpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
* This file is part of the "Enduro2D"
|
||||||
|
* For conditions of distribution and use, see copyright notice in LICENSE.md
|
||||||
|
* Copyright (C) 2018 Matvey Cherevko
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "_math.hpp"
|
||||||
|
using namespace e2d;
|
||||||
|
|
||||||
|
TEST_CASE("rect") {
|
||||||
|
{
|
||||||
|
REQUIRE(r4i().position == v2i(0,0));
|
||||||
|
REQUIRE(r4i().size == v2i(0,0));
|
||||||
|
|
||||||
|
REQUIRE(r4i(1,2).position == v2i(0,0));
|
||||||
|
REQUIRE(r4i(1,2).size == v2i(1,2));
|
||||||
|
|
||||||
|
REQUIRE(r4i(1,2,3,4).position == v2i(1,2));
|
||||||
|
REQUIRE(r4i(1,2,3,4).size == v2i(3,4));
|
||||||
|
|
||||||
|
REQUIRE(r4i(v2i{1,2}).position == v2i(0,0));
|
||||||
|
REQUIRE(r4i(v2i{1,2}).size == v2i(1,2));
|
||||||
|
|
||||||
|
REQUIRE(r4i(v2i{1,2},v2i{3,4}).position == v2i(1,2));
|
||||||
|
REQUIRE(r4i(v2i{1,2},v2i{3,4}).size == v2i(3,4));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(r4f(1,2,3,4).cast_to<i32>() == r4i(1,2,3,4));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(make_rect(2,1) == r4i(0,0,2,1));
|
||||||
|
REQUIRE(make_rect(4,3,2,1) == r4i(4,3,2,1));
|
||||||
|
REQUIRE(make_rect(v2i{2,1}) == r4i(0,0,2,1));
|
||||||
|
REQUIRE(make_rect(v2i{4,3},v2i{2,1}) == r4i(4,3,2,1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto r0 = r4i(1,2,3,4);
|
||||||
|
auto r1 = r4i(r0);
|
||||||
|
REQUIRE(r1 == r4i(1,2,3,4));
|
||||||
|
r1 = r4i(4,3,2,1);
|
||||||
|
REQUIRE(r1 == r4i(4,3,2,1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(r4i(1,2,3,4) == r4i(1,2,3,4));
|
||||||
|
REQUIRE_FALSE(r4i(1,2,3,4) == r4i(1,2,4,3));
|
||||||
|
REQUIRE_FALSE(r4i(1,2,3,4) == r4i(2,1,3,4));
|
||||||
|
REQUIRE_FALSE(r4i(1,2,3,4) == r4i(2,1,4,3));
|
||||||
|
|
||||||
|
REQUIRE_FALSE(r4i(1,2,3,4) != r4i(1,2,3,4));
|
||||||
|
REQUIRE(r4i(1,2,3,4) != r4i(1,2,4,3));
|
||||||
|
REQUIRE(r4i(1,2,3,4) != r4i(2,1,3,4));
|
||||||
|
REQUIRE(r4i(1,2,3,4) != r4i(2,1,4,3));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(r4i(4,4) < r4i(4,5));
|
||||||
|
REQUIRE_FALSE(r4i(4,4) < r4i(3,4));
|
||||||
|
REQUIRE_FALSE(r4i(4,4) < r4i(4,3));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(math::approximately(r4i(1,2,3,4), r4i(1,2,4,5), 1));
|
||||||
|
REQUIRE_FALSE(math::approximately(r4i(1,2,3,4), r4i(1,2,4,5)));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
REQUIRE(math::minimum(r4i(1,2,3,4)) == v2i(1,2));
|
||||||
|
REQUIRE(math::minimum(r4i(1,2,-3,5)) == v2i(-2,2));
|
||||||
|
REQUIRE(math::minimum(r4i(1,2,3,-5)) == v2i(1,-3));
|
||||||
|
REQUIRE(math::minimum(r4i(1,2,-3,-5)) == v2i(-2,-3));
|
||||||
|
|
||||||
|
REQUIRE(math::maximum(r4i(1,2,3,4)) == v2i(4,6));
|
||||||
|
REQUIRE(math::maximum(r4i(1,2,-3,5)) == v2i(1,7));
|
||||||
|
REQUIRE(math::maximum(r4i(1,2,3,-5)) == v2i(4,2));
|
||||||
|
REQUIRE(math::maximum(r4i(1,2,-3,-5)) == v2i(1,2));
|
||||||
|
|
||||||
|
REQUIRE(math::area(r4i(1,2,3,4)) == 12);
|
||||||
|
REQUIRE(math::area(r4i(1,2,3,-4)) == -12);
|
||||||
|
REQUIRE(math::area(r4i(1,2,-3,4)) == -12);
|
||||||
|
REQUIRE(math::area(r4i(1,2,-3,-4)) == 12);
|
||||||
|
|
||||||
|
REQUIRE(math::abs_area(r4i(1,2,3,4)) == 12);
|
||||||
|
REQUIRE(math::abs_area(r4i(1,2,3,-4)) == 12);
|
||||||
|
REQUIRE(math::abs_area(r4i(1,2,-3,4)) == 12);
|
||||||
|
REQUIRE(math::abs_area(r4i(1,2,-3,-4)) == 12);
|
||||||
|
|
||||||
|
REQUIRE(math::merged(r4i(1,2,3,4), r4i(1,2,3,4)) == r4i(1,2,3,4));
|
||||||
|
REQUIRE(math::merged(r4i(1,2,3,4), r4i(0,1,3,4)) == r4i(0,1,4,5));
|
||||||
|
REQUIRE(math::merged(r4i(1,2,3,4), r4i(1,2,4,5)) == r4i(1,2,4,5));
|
||||||
|
REQUIRE(math::merged(r4i(1,2,3,4), r4i(0,1,4,5)) == r4i(0,1,4,5));
|
||||||
|
|
||||||
|
REQUIRE(math::merged(r4i(1,2,3,4), r4i(1,2,-3,-5)) == r4i(-2,-3,6,9));
|
||||||
|
REQUIRE(math::merged(r4i(-1,-2,3,4), r4i(1,2,-3,-5)) == r4i(-2,-3,4,5));
|
||||||
|
|
||||||
|
REQUIRE(math::inside(r4i(1,2,3,4), v2i(1,2)));
|
||||||
|
REQUIRE(math::inside(r4i(1,2,3,4), v2i(4,5)));
|
||||||
|
REQUIRE_FALSE(math::inside(r4i(1,2,3,4), v2i(4,7)));
|
||||||
|
REQUIRE_FALSE(math::inside(r4i(1,2,3,4), v2i(0,5)));
|
||||||
|
|
||||||
|
REQUIRE(math::inside(r4i(1,2,-3,-4), v2i(1,2)));
|
||||||
|
REQUIRE(math::inside(r4i(1,2,-3,-4), v2i(-1,-2)));
|
||||||
|
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(2,2)));
|
||||||
|
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(1,3)));
|
||||||
|
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(-3,2)));
|
||||||
|
REQUIRE_FALSE(math::inside(r4i(1,2,-3,-4), v2i(1,-3)));
|
||||||
|
|
||||||
|
REQUIRE_FALSE(math::contains_nan(r4i(1,2,3,4)));
|
||||||
|
REQUIRE_FALSE(math::contains_nan(r4f(1.f,2.f,3.f,4.f)));
|
||||||
|
REQUIRE(math::contains_nan(r4f(1.f,std::numeric_limits<f32>::quiet_NaN())));
|
||||||
|
REQUIRE(math::contains_nan(r4f(std::numeric_limits<f32>::infinity(), 1.f)));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user