Math: init Region, Vector2D and Box

This commit is contained in:
Vaxry 2024-06-18 14:10:18 +02:00
parent a8f9373474
commit e9d4a99e13
9 changed files with 852 additions and 3 deletions

View file

@ -30,6 +30,9 @@ endif()
file(GLOB_RECURSE SRCFILES CONFIGURE_DEPENDS "src/*.cpp" "include/*.hpp")
file(GLOB_RECURSE PUBLIC_HEADERS CONFIGURE_DEPENDS "include/*.hpp")
find_package(PkgConfig REQUIRED)
pkg_check_modules(deps REQUIRED IMPORTED_TARGET pixman-1)
add_library(hyprutils SHARED ${SRCFILES})
target_include_directories( hyprutils
PUBLIC "./include"
@ -39,25 +42,31 @@ set_target_properties(hyprutils PROPERTIES
VERSION ${hyprutils_VERSION}
SOVERSION 0
)
target_link_libraries(hyprutils PkgConfig::deps)
# tests
add_custom_target(tests)
add_executable(hyprutils_memory "tests/memory.cpp")
target_link_libraries(hyprutils_memory PRIVATE hyprutils)
target_link_libraries(hyprutils_memory PRIVATE hyprutils PkgConfig::deps)
add_test(NAME "Memory" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_memory "memory")
add_dependencies(tests hyprutils_memory)
add_executable(hyprutils_string "tests/string.cpp")
target_link_libraries(hyprutils_string PRIVATE hyprutils)
target_link_libraries(hyprutils_string PRIVATE hyprutils PkgConfig::deps)
add_test(NAME "String" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_string "string")
add_dependencies(tests hyprutils_string)
add_executable(hyprutils_signal "tests/signal.cpp")
target_link_libraries(hyprutils_signal PRIVATE hyprutils)
target_link_libraries(hyprutils_signal PRIVATE hyprutils PkgConfig::deps)
add_test(NAME "Signal" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_signal "signal")
add_dependencies(tests hyprutils_signal)
add_executable(hyprutils_math "tests/math.cpp")
target_link_libraries(hyprutils_math PRIVATE hyprutils PkgConfig::deps)
add_test(NAME "Math" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests COMMAND hyprutils_math "math")
add_dependencies(tests hyprutils_math)
# Installation
install(TARGETS hyprutils)
install(DIRECTORY "include/hyprutils" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})

View file

@ -0,0 +1,106 @@
#pragma once
#include "./Vector2D.hpp"
#include "./Misc.hpp"
namespace Hyprutils {
namespace Math {
struct SBoxExtents {
Vector2D topLeft;
Vector2D bottomRight;
//
SBoxExtents operator*(const double& scale) const {
return SBoxExtents{topLeft * scale, bottomRight * scale};
}
SBoxExtents round() {
return {topLeft.round(), bottomRight.round()};
}
bool operator==(const SBoxExtents& other) const {
return topLeft == other.topLeft && bottomRight == other.bottomRight;
}
void addExtents(const SBoxExtents& other) {
topLeft = topLeft.getComponentMax(other.topLeft);
bottomRight = bottomRight.getComponentMax(other.bottomRight);
}
};
class CBox {
public:
CBox(double x_, double y_, double w_, double h_) {
x = x_;
y = y_;
w = w_;
h = h_;
}
CBox() {
w = 0;
h = 0;
}
CBox(const double d) {
x = d;
y = d;
w = d;
h = d;
}
CBox(const Vector2D& pos, const Vector2D& size) {
x = pos.x;
y = pos.y;
w = size.x;
h = size.y;
}
CBox& applyFromWlr();
CBox& scale(double scale);
CBox& scaleFromCenter(double scale);
CBox& scale(const Vector2D& scale);
CBox& translate(const Vector2D& vec);
CBox& round();
CBox& transform(const eTransform t, double w, double h);
CBox& addExtents(const SBoxExtents& e);
CBox& expand(const double& value);
CBox& noNegativeSize();
CBox copy() const;
CBox intersection(const CBox& other) const;
bool overlaps(const CBox& other) const;
bool inside(const CBox& bound) const;
SBoxExtents extentsFrom(const CBox&); // this is the big box
Vector2D middle() const;
Vector2D pos() const;
Vector2D size() const;
Vector2D closestPoint(const Vector2D& vec) const;
bool containsPoint(const Vector2D& vec) const;
bool empty() const;
double x = 0, y = 0;
union {
double w;
double width;
};
union {
double h;
double height;
};
double rot = 0; /* rad, ccw */
//
bool operator==(const CBox& rhs) const {
return x == rhs.x && y == rhs.y && w == rhs.w && h == rhs.h;
}
private:
CBox roundInternal();
};
}
}

View file

@ -0,0 +1,16 @@
#pragma once
namespace Hyprutils {
namespace Math {
enum eTransform {
HYPRUTILS_TRANSFORM_NORMAL = 0,
HYPRUTILS_TRANSFORM_90 = 1,
HYPRUTILS_TRANSFORM_180 = 2,
HYPRUTILS_TRANSFORM_270 = 3,
HYPRUTILS_TRANSFORM_FLIPPED = 4,
HYPRUTILS_TRANSFORM_FLIPPED_90 = 5,
HYPRUTILS_TRANSFORM_FLIPPED_180 = 6,
HYPRUTILS_TRANSFORM_FLIPPED_270 = 7,
};
}
}

View file

@ -0,0 +1,70 @@
#pragma once
#include <pixman.h>
#include <vector>
#include "Vector2D.hpp"
#include "Box.hpp"
namespace Hyprutils {
namespace Math {
class CRegion {
public:
/* Create an empty region */
CRegion();
/* Create from a reference. Copies, does not own. */
CRegion(const pixman_region32_t* const ref);
/* Create from a box */
CRegion(double x, double y, double w, double h);
/* Create from a CBox */
CRegion(const CBox& box);
/* Create from a pixman_box32_t */
CRegion(pixman_box32_t* box);
CRegion(const CRegion&);
CRegion(CRegion&&);
~CRegion();
CRegion& operator=(CRegion&& other) {
pixman_region32_copy(&m_rRegion, other.pixman());
return *this;
}
CRegion& operator=(CRegion& other) {
pixman_region32_copy(&m_rRegion, other.pixman());
return *this;
}
CRegion& clear();
CRegion& set(const CRegion& other);
CRegion& add(const CRegion& other);
CRegion& add(double x, double y, double w, double h);
CRegion& add(const CBox& other);
CRegion& subtract(const CRegion& other);
CRegion& intersect(const CRegion& other);
CRegion& intersect(double x, double y, double w, double h);
CRegion& translate(const Vector2D& vec);
CRegion& transform(const eTransform t, double w, double h);
CRegion& invert(pixman_box32_t* box);
CRegion& invert(const CBox& box);
CRegion& scale(float scale);
CRegion& scale(const Vector2D& scale);
CRegion& rationalize();
CBox getExtents();
bool containsPoint(const Vector2D& vec) const;
bool empty() const;
Vector2D closestPoint(const Vector2D& vec) const;
CRegion copy() const;
std::vector<pixman_box32_t> getRects() const;
//
pixman_region32_t* pixman() {
return &m_rRegion;
}
private:
pixman_region32_t m_rRegion;
};
}
}

View file

@ -0,0 +1,164 @@
#pragma once
#include <format>
#include <string>
namespace Hyprutils {
namespace Math {
class Vector2D {
public:
Vector2D(double, double);
Vector2D();
~Vector2D();
double x = 0;
double y = 0;
// returns the scale
double normalize();
Vector2D operator+(const Vector2D& a) const {
return Vector2D(this->x + a.x, this->y + a.y);
}
Vector2D operator-(const Vector2D& a) const {
return Vector2D(this->x - a.x, this->y - a.y);
}
Vector2D operator-() const {
return Vector2D(-this->x, -this->y);
}
Vector2D operator*(const double& a) const {
return Vector2D(this->x * a, this->y * a);
}
Vector2D operator/(const double& a) const {
return Vector2D(this->x / a, this->y / a);
}
bool operator==(const Vector2D& a) const {
return a.x == x && a.y == y;
}
bool operator!=(const Vector2D& a) const {
return a.x != x || a.y != y;
}
Vector2D operator*(const Vector2D& a) const {
return Vector2D(this->x * a.x, this->y * a.y);
}
Vector2D operator/(const Vector2D& a) const {
return Vector2D(this->x / a.x, this->y / a.y);
}
bool operator>(const Vector2D& a) const {
return this->x > a.x && this->y > a.y;
}
bool operator<(const Vector2D& a) const {
return this->x < a.x && this->y < a.y;
}
Vector2D& operator+=(const Vector2D& a) {
this->x += a.x;
this->y += a.y;
return *this;
}
Vector2D& operator-=(const Vector2D& a) {
this->x -= a.x;
this->y -= a.y;
return *this;
}
Vector2D& operator*=(const Vector2D& a) {
this->x *= a.x;
this->y *= a.y;
return *this;
}
Vector2D& operator/=(const Vector2D& a) {
this->x /= a.x;
this->y /= a.y;
return *this;
}
Vector2D& operator*=(const double& a) {
this->x *= a;
this->y *= a;
return *this;
}
Vector2D& operator/=(const double& a) {
this->x /= a;
this->y /= a;
return *this;
}
double distance(const Vector2D& other) const;
double distanceSq(const Vector2D& other) const;
double size() const;
Vector2D clamp(const Vector2D& min, const Vector2D& max = Vector2D{-1, -1}) const;
Vector2D floor() const;
Vector2D round() const;
Vector2D getComponentMax(const Vector2D& other) const;
};
}
}
// absolutely ridiculous formatter spec parsing
#define FORMAT_PARSE(specs__, type__) \
template <typename FormatContext> \
constexpr auto parse(FormatContext& ctx) { \
auto it = ctx.begin(); \
for (; it != ctx.end() && *it != '}'; it++) { \
switch (*it) { specs__ default : throw std::format_error("invalid format specification"); } \
} \
return it; \
}
#define FORMAT_FLAG(spec__, flag__) \
case spec__: (flag__) = true; break;
#define FORMAT_NUMBER(buf__) \
case '0': \
case '1': \
case '2': \
case '3': \
case '4': \
case '5': \
case '6': \
case '7': \
case '8': \
case '9': (buf__).push_back(*it); break;
/**
format specification
- 'j', as json array
- 'X', same as std::format("{}x{}", vec.x, vec.y)
- number, floating point precision, use `0` to format as integer
*/
template <typename CharT>
struct std::formatter<Hyprutils::Math::Vector2D, CharT> : std::formatter<CharT> {
bool formatJson = false;
bool formatX = false;
std::string precision = "";
FORMAT_PARSE(FORMAT_FLAG('j', formatJson) //
FORMAT_FLAG('X', formatX) //
FORMAT_NUMBER(precision),
Hyprutils::Math::Vector2D)
template <typename FormatContext>
auto format(const Hyprutils::Math::Vector2D& vec, FormatContext& ctx) const {
std::string formatString = precision.empty() ? "{}" : std::format("{{:.{}f}}", precision);
if (formatJson)
formatString = std::format("[{0}, {0}]", formatString);
else if (formatX)
formatString = std::format("{0}x{0}", formatString);
else
formatString = std::format("[Vector2D: x: {0}, y: {0}]", formatString);
try {
string buf = std::vformat(formatString, std::make_format_args(vec.x, vec.y));
return std::format_to(ctx.out(), "{}", buf);
} catch (std::format_error& e) { return std::format_to(ctx.out(), "[{}, {}]", vec.x, vec.y); }
}
};
#undef FORMAT_PARSE
#undef FORMAT_FLAG
#undef FORMAT_NUMBER

204
src/math/Box.cpp Normal file
View file

@ -0,0 +1,204 @@
#include <hyprutils/math/Box.hpp>
#include <limits>
#include <algorithm>
#include <cmath>
#define VECINRECT(vec, x1, y1, x2, y2) ((vec).x >= (x1) && (vec).x < (x2) && (vec).y >= (y1) && (vec).y < (y2))
using namespace Hyprutils::Math;
CBox& Hyprutils::Math::CBox::scale(double scale) {
x *= scale;
y *= scale;
w *= scale;
h *= scale;
return *this;
}
CBox& Hyprutils::Math::CBox::scale(const Vector2D& scale) {
x *= scale.x;
y *= scale.y;
w *= scale.x;
h *= scale.y;
return *this;
}
CBox& Hyprutils::Math::CBox::translate(const Vector2D& vec) {
x += vec.x;
y += vec.y;
return *this;
}
Vector2D Hyprutils::Math::CBox::middle() const {
return Vector2D{x + w / 2.0, y + h / 2.0};
}
bool Hyprutils::Math::CBox::containsPoint(const Vector2D& vec) const {
return VECINRECT(vec, x, y, x + w, y + h);
}
bool Hyprutils::Math::CBox::empty() const {
return w == 0 || h == 0;
}
CBox& Hyprutils::Math::CBox::round() {
float newW = x + w - std::round(x);
float newH = y + h - std::round(y);
x = std::round(x);
y = std::round(y);
w = std::round(newW);
h = std::round(newH);
return *this;
}
CBox& Hyprutils::Math::CBox::transform(const eTransform t, double w, double h) {
CBox temp = *this;
if (t % 2 == 0) {
width = temp.width;
height = temp.height;
} else {
width = temp.height;
height = temp.width;
}
switch (t) {
case HYPRUTILS_TRANSFORM_NORMAL:
x = temp.x;
y = temp.y;
break;
case HYPRUTILS_TRANSFORM_90:
x = h - temp.y - temp.height;
y = temp.x;
break;
case HYPRUTILS_TRANSFORM_180:
x = w - temp.x - temp.width;
y = h - temp.y - temp.height;
break;
case HYPRUTILS_TRANSFORM_270:
x = temp.y;
y = w - temp.x - temp.width;
break;
case HYPRUTILS_TRANSFORM_FLIPPED:
x = w - temp.x - temp.width;
y = temp.y;
break;
case HYPRUTILS_TRANSFORM_FLIPPED_90:
x = temp.y;
y = temp.x;
break;
case HYPRUTILS_TRANSFORM_FLIPPED_180:
x = temp.x;
y = h - temp.y - temp.height;
break;
case HYPRUTILS_TRANSFORM_FLIPPED_270:
x = h - temp.y - temp.height;
y = w - temp.x - temp.width;
break;
}
return *this;
}
CBox& Hyprutils::Math::CBox::addExtents(const SBoxExtents& e) {
x -= e.topLeft.x;
y -= e.topLeft.y;
w += e.topLeft.x + e.bottomRight.x;
h += e.topLeft.y + e.bottomRight.y;
return *this;
}
CBox& Hyprutils::Math::CBox::scaleFromCenter(double scale) {
double oldW = w, oldH = h;
w *= scale;
h *= scale;
x -= (w - oldW) / 2.0;
y -= (h - oldH) / 2.0;
return *this;
}
CBox& Hyprutils::Math::CBox::expand(const double& value) {
x -= value;
y -= value;
w += value * 2.0;
h += value * 2.0;
if (w <= 0 || h <= 0) {
w = 0;
h = 0;
}
return *this;
}
CBox& Hyprutils::Math::CBox::noNegativeSize() {
w = std::clamp(w, 0.0, std::numeric_limits<double>::infinity());
h = std::clamp(h, 0.0, std::numeric_limits<double>::infinity());
return *this;
}
CBox Hyprutils::Math::CBox::intersection(const CBox& other) const {
const float newX = std::max(x, other.x);
const float newY = std::max(y, other.y);
const float newBottom = std::min(y + h, other.y + other.h);
const float newRight = std::min(x + w, other.x + other.w);
float newW = newRight - newX;
float newH = newBottom - newY;
if (newW <= 0 || newH <= 0) {
newW = 0;
newH = 0;
}
return {newX, newY, newW, newH};
}
bool Hyprutils::Math::CBox::overlaps(const CBox& other) const {
return (other.x + other.w >= x) && (x + w >= other.x) && (other.y + other.h >= y) && (y + h >= other.y);
}
bool Hyprutils::Math::CBox::inside(const CBox& bound) const {
return bound.x < x && bound.y < y && x + w < bound.x + bound.w && y + h < bound.y + bound.h;
}
CBox Hyprutils::Math::CBox::roundInternal() {
float newW = x + w - std::floor(x);
float newH = y + h - std::floor(y);
return CBox{std::floor(x), std::floor(y), std::floor(newW), std::floor(newH)};
}
CBox Hyprutils::Math::CBox::copy() const {
return CBox{*this};
}
Vector2D Hyprutils::Math::CBox::pos() const {
return {x, y};
}
Vector2D Hyprutils::Math::CBox::size() const {
return {w, h};
}
Vector2D Hyprutils::Math::CBox::closestPoint(const Vector2D& vec) const {
if (containsPoint(vec))
return vec;
Vector2D nv = vec;
nv.x = std::clamp(nv.x, x, x + w);
nv.y = std::clamp(nv.y, y, y + h);
return nv;
}
SBoxExtents Hyprutils::Math::CBox::extentsFrom(const CBox& small) {
return {{small.x - x, small.y - y}, {w - small.w - (small.x - x), h - small.h - (small.y - y)}};
}

204
src/math/Region.cpp Normal file
View file

@ -0,0 +1,204 @@
#include <hyprutils/math/Region.hpp>
#include <cmath>
using namespace Hyprutils::Math;
constexpr const int64_t MAX_REGION_SIDE = 10000000;
Hyprutils::Math::CRegion::CRegion() {
pixman_region32_init(&m_rRegion);
}
Hyprutils::Math::CRegion::CRegion(const pixman_region32_t* const ref) {
pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, ref);
}
Hyprutils::Math::CRegion::CRegion(double x, double y, double w, double h) {
pixman_region32_init_rect(&m_rRegion, x, y, w, h);
}
Hyprutils::Math::CRegion::CRegion(const CBox& box) {
pixman_region32_init_rect(&m_rRegion, box.x, box.y, box.w, box.h);
}
Hyprutils::Math::CRegion::CRegion(pixman_box32_t* box) {
pixman_region32_init_rect(&m_rRegion, box->x1, box->y1, box->x2 - box->x1, box->y2 - box->y1);
}
Hyprutils::Math::CRegion::CRegion(const CRegion& other) {
pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
}
Hyprutils::Math::CRegion::CRegion(CRegion&& other) {
pixman_region32_init(&m_rRegion);
pixman_region32_copy(&m_rRegion, other.pixman());
}
Hyprutils::Math::CRegion::~CRegion() {
pixman_region32_fini(&m_rRegion);
}
CRegion& Hyprutils::Math::CRegion::clear() {
pixman_region32_clear(&m_rRegion);
return *this;
}
CRegion& Hyprutils::Math::CRegion::set(const CRegion& other) {
pixman_region32_copy(&m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& Hyprutils::Math::CRegion::add(const CRegion& other) {
pixman_region32_union(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& Hyprutils::Math::CRegion::add(double x, double y, double w, double h) {
pixman_region32_union_rect(&m_rRegion, &m_rRegion, x, y, w, h);
return *this;
}
CRegion& Hyprutils::Math::CRegion::add(const CBox& other) {
pixman_region32_union_rect(&m_rRegion, &m_rRegion, other.x, other.y, other.w, other.h);
return *this;
}
CRegion& Hyprutils::Math::CRegion::subtract(const CRegion& other) {
pixman_region32_subtract(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& Hyprutils::Math::CRegion::intersect(const CRegion& other) {
pixman_region32_intersect(&m_rRegion, &m_rRegion, const_cast<CRegion*>(&other)->pixman());
return *this;
}
CRegion& Hyprutils::Math::CRegion::intersect(double x, double y, double w, double h) {
pixman_region32_intersect_rect(&m_rRegion, &m_rRegion, x, y, w, h);
return *this;
}
CRegion& Hyprutils::Math::CRegion::invert(pixman_box32_t* box) {
pixman_region32_inverse(&m_rRegion, &m_rRegion, box);
return *this;
}
CRegion& Hyprutils::Math::CRegion::invert(const CBox& box) {
pixman_box32 pixmanBox = {(int32_t)box.x, (int32_t)box.y, (int32_t)box.w + (int32_t)box.x, (int32_t)box.h + (int32_t)box.y};
return this->invert(&pixmanBox);
}
CRegion& Hyprutils::Math::CRegion::translate(const Vector2D& vec) {
pixman_region32_translate(&m_rRegion, vec.x, vec.y);
return *this;
}
CRegion& Hyprutils::Math::CRegion::transform(const eTransform t, double w, double h) {
if (t == HYPRUTILS_TRANSFORM_NORMAL)
return *this;
auto rects = getRects();
clear();
for (auto& r : rects) {
CBox xfmd{(double)r.x1, (double)r.y1, (double)r.x2 - r.x1, (double)r.y2 - r.y1};
xfmd.transform(t, w, h);
add(xfmd);
}
return *this;
}
CRegion& Hyprutils::Math::CRegion::rationalize() {
intersect(CBox{-MAX_REGION_SIDE, -MAX_REGION_SIDE, MAX_REGION_SIDE * 2, MAX_REGION_SIDE * 2});
return *this;
}
CRegion Hyprutils::Math::CRegion::copy() const {
return CRegion(*this);
}
CRegion& Hyprutils::Math::CRegion::scale(float scale_) {
scale({scale_, scale_});
return *this;
}
CRegion& Hyprutils::Math::CRegion::scale(const Vector2D& scale) {
if (scale == Vector2D{1, 1})
return *this;
auto rects = getRects();
clear();
for (auto& r : rects) {
r.x1 = std::floor(r.x1 * scale.x);
r.y1 = std::floor(r.y1 * scale.x);
r.x2 = std::ceil(r.x2 * scale.x);
r.y2 = std::ceil(r.y2 * scale.x);
add(&r);
}
return *this;
}
std::vector<pixman_box32_t> Hyprutils::Math::CRegion::getRects() const {
std::vector<pixman_box32_t> result;
int rectsNum = 0;
const auto RECTSARR = pixman_region32_rectangles(&m_rRegion, &rectsNum);
result.assign(RECTSARR, RECTSARR + rectsNum);
return result;
}
CBox Hyprutils::Math::CRegion::getExtents() {
pixman_box32_t* box = pixman_region32_extents(&m_rRegion);
return {(double)box->x1, (double)box->y1, (double)box->x2 - box->x1, (double)box->y2 - box->y1};
}
bool Hyprutils::Math::CRegion::containsPoint(const Vector2D& vec) const {
return pixman_region32_contains_point(&m_rRegion, vec.x, vec.y, nullptr);
}
bool Hyprutils::Math::CRegion::empty() const {
return !pixman_region32_not_empty(&m_rRegion);
}
Vector2D Hyprutils::Math::CRegion::closestPoint(const Vector2D& vec) const {
if (containsPoint(vec))
return vec;
double bestDist = __FLT_MAX__;
Vector2D leader = vec;
for (auto& box : getRects()) {
double x = 0, y = 0;
if (vec.x >= box.x2)
x = box.x2 - 1;
else if (vec.x < box.x1)
x = box.x1;
else
x = vec.x;
if (vec.y >= box.y2)
y = box.y2 - 1;
else if (vec.y < box.y1)
y = box.y1;
else
y = vec.y;
double distance = pow(x, 2) + pow(y, 2);
if (distance < bestDist) {
bestDist = distance;
leader = {x, y};
}
}
return leader;
}

55
src/math/Vector2D.cpp Normal file
View file

@ -0,0 +1,55 @@
#include <hyprutils/math/Vector2D.hpp>
#include <algorithm>
#include <cmath>
using namespace Hyprutils::Math;
Hyprutils::Math::Vector2D::Vector2D(double xx, double yy) {
x = xx;
y = yy;
}
Hyprutils::Math::Vector2D::Vector2D() {
x = 0;
y = 0;
}
Hyprutils::Math::Vector2D::~Vector2D() {}
double Hyprutils::Math::Vector2D::normalize() {
// get max abs
const auto max = std::abs(x) > std::abs(y) ? std::abs(x) : std::abs(y);
x /= max;
y /= max;
return max;
}
Vector2D Hyprutils::Math::Vector2D::floor() const {
return Vector2D(std::floor(x), std::floor(y));
}
Vector2D Hyprutils::Math::Vector2D::round() const {
return Vector2D(std::round(x), std::round(y));
}
Vector2D Hyprutils::Math::Vector2D::clamp(const Vector2D& min, const Vector2D& max) const {
return Vector2D(std::clamp(this->x, min.x, max.x < min.x ? INFINITY : max.x), std::clamp(this->y, min.y, max.y < min.y ? INFINITY : max.y));
}
double Hyprutils::Math::Vector2D::distance(const Vector2D& other) const {
return std::sqrt(distanceSq(other));
}
double Hyprutils::Math::Vector2D::distanceSq(const Vector2D& other) const {
return (x - other.x) * (x - other.x) + (y - other.y) * (y - other.y);
}
double Hyprutils::Math::Vector2D::size() const {
return std::sqrt(x * x + y * y);
}
Vector2D Hyprutils::Math::Vector2D::getComponentMax(const Vector2D& other) const {
return Vector2D(std::max(this->x, other.x), std::max(this->y, other.y));
}

21
tests/math.cpp Normal file
View file

@ -0,0 +1,21 @@
#include <hyprutils/math/Region.hpp>
#include "shared.hpp"
using namespace Hyprutils::Math;
int main(int argc, char** argv, char** envp) {
CRegion rg = {0, 0, 100, 100};
rg.add(CBox{{}, {20, 200}});
int ret = 0;
EXPECT(rg.getExtents().height, 200);
EXPECT(rg.getExtents().width, 100);
rg.intersect(CBox{10, 10, 300, 300});
EXPECT(rg.getExtents().width, 90);
EXPECT(rg.getExtents().height, 190);
return ret;
}