#pragma once #include #include #include struct Position { int32_t x; int32_t y; }; struct Rectangle { int32_t min_x; int32_t min_y; int32_t max_x; int32_t max_y; int32_t width() const { return max_x - min_x; } int32_t height() const { return max_y - min_y; } int32_t area() const { return width() * height(); } bool contains(Position position) const { if (position.x < min_x || position.x >= max_x) return false; if (position.y < min_y || position.y >= max_y) return false; return true; } BAN::Optional get_overlap(Rectangle other) const { if (width() == 0 || height() == 0 || other.width() == 0 || other.height() == 0) return {}; const auto min_x = BAN::Math::max(this->min_x, other.min_x); const auto min_y = BAN::Math::max(this->min_y, other.min_y); const auto max_x = BAN::Math::min(this->max_x, other.max_x); const auto max_y = BAN::Math::min(this->max_y, other.max_y); if (min_x >= max_x || min_y >= max_y) return {}; return Rectangle { .min_x = min_x, .min_y = min_y, .max_x = max_x, .max_y = max_y, }; } Rectangle get_bounding_box(Rectangle other) const { const auto min_x = BAN::Math::min(this->min_x, other.min_x); const auto min_y = BAN::Math::min(this->min_y, other.min_y); const auto max_x = BAN::Math::max(this->max_x, other.max_x); const auto max_y = BAN::Math::max(this->max_y, other.max_y); return Rectangle { .min_x = min_x, .min_y = min_y, .max_x = max_x, .max_y = max_y, }; } bool operator==(const Rectangle& other) const { return min_x == other.min_x && min_y == other.min_y && max_x == other.max_x && max_y == other.max_y; } }; struct Circle { int32_t x; int32_t y; int32_t radius; bool contains(Position position) const { int32_t dx = position.x - x; int32_t dy = position.y - y; return dx * dx + dy * dy <= radius * radius; } }; struct Range { uint32_t start { 0 }; uint32_t count { 0 }; bool is_continuous_with(const Range& range) const { return start <= range.start + range.count && range.start <= start + count; } uint32_t distance_between(const Range& range) const { if (is_continuous_with(range)) return 0; if (start < range.start) return range.start - (start + count); return start - (range.start + range.count); } void merge_with(const Range& range) { const uint32_t new_start = BAN::Math::min(start, range.start); const uint32_t new_end = BAN::Math::max(start + count, range.start + range.count); start = new_start; count = new_end - new_start; } };