blob: 62db4c4fd991e836451ec0c3910c72140ff9de64 [file] [log] [blame]
#include "rive/math/aabb.hpp"
#include <algorithm>
#include <cmath>
using namespace rive;
AABB::AABB(Span<Vec2D> pts) {
if (pts.size() == 0) {
minX = minY = maxX = maxY = 0;
return;
}
float L = pts[0].x(), R = L, T = pts[0].y(), B = T;
for (size_t i = 1; i < pts.size(); ++i) {
L = std::min(L, pts[i].x());
R = std::max(R, pts[i].x());
T = std::min(T, pts[i].y());
B = std::max(B, pts[i].y());
}
minX = L;
maxX = R;
minY = T;
maxY = B;
}
bool AABB::contains(const AABB& a, const AABB& b) {
return a[0] <= b[0] && a[1] <= b[1] && b[2] <= a[2] && b[3] <= a[3];
}
bool AABB::isValid(const AABB& a) {
float dx = a[2] - a[0];
float dy = a[3] - a[1];
return dx >= 0.0f && dy >= 0.0f && std::isfinite(a[0]) && std::isfinite(a[1]) &&
std::isfinite(a[2]) && std::isfinite(a[3]);
}
bool AABB::testOverlap(const AABB& a, const AABB& b) {
float d1x = b[0] - a[2];
float d1y = b[1] - a[3];
float d2x = a[0] - b[2];
float d2y = a[1] - b[3];
if (d1x > 0.0 || d1y > 0.0) {
return false;
}
if (d2x > 0.0 || d2y > 0.0) {
return false;
}
return true;
}
void AABB::transform(AABB& out, const AABB& a, const Mat2D& matrix) {
const auto p1 = matrix * Vec2D(a[0], a[1]);
const auto p2 = matrix * Vec2D(a[2], a[1]);
const auto p3 = matrix * Vec2D(a[2], a[3]);
const auto p4 = matrix * Vec2D(a[0], a[3]);
out[0] = std::fmin(p1[0], std::fmin(p2[0], std::fmin(p3[0], p4[0])));
out[1] = std::fmin(p1[1], std::fmin(p2[1], std::fmin(p3[1], p4[1])));
out[2] = std::fmax(p1[0], std::fmax(p2[0], std::fmax(p3[0], p4[0])));
out[3] = std::fmax(p1[1], std::fmax(p2[1], std::fmax(p3[1], p4[1])));
}
static inline float graphics_roundf(float x) { return std::floor(x + 0.5f); }
static inline int graphics_round(float x) { return (int)graphics_roundf(x); }
IAABB AABB::round() const {
return {
graphics_round(left()),
graphics_round(top()),
graphics_round(right()),
graphics_round(bottom()),
};
}