127 lines
2.5 KiB
C
127 lines
2.5 KiB
C
#pragma once
|
|
|
|
#include <BAN/Math.h>
|
|
#include <BAN/Optional.h>
|
|
|
|
#include <stdint.h>
|
|
|
|
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<Rectangle> 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;
|
|
}
|
|
};
|