#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Point {
pub x: f32,
pub y: f32,
}
impl Point {
pub const ORIGIN: Self = Self::new(0.0, 0.0);
pub const fn new(x: f32, y: f32) -> Self {
Self { x, y }
}
#[must_use]
pub fn offset(self, dx: f32, dy: f32) -> Self {
Self::new(self.x + dx, self.y + dy)
}
pub const fn to_array(self) -> [f32; 2] {
[self.x, self.y]
}
}
impl From<[f32; 2]> for Point {
fn from([x, y]: [f32; 2]) -> Self {
Self::new(x, y)
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Rect {
pub x0: f32,
pub y0: f32,
pub x1: f32,
pub y1: f32,
}
impl Rect {
pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
Self::from_edges(x, y, x + width, y + height)
}
pub fn from_edges(left: f32, top: f32, right: f32, bottom: f32) -> Self {
let (x0, x1) = ordered(left, right);
let (y0, y1) = ordered(top, bottom);
Self { x0, y0, x1, y1 }
}
pub fn left(&self) -> f32 {
self.x0
}
pub fn top(&self) -> f32 {
self.y0
}
pub fn right(&self) -> f32 {
self.x1
}
pub fn bottom(&self) -> f32 {
self.y1
}
pub fn width(&self) -> f32 {
self.x1 - self.x0
}
pub fn height(&self) -> f32 {
self.y1 - self.y0
}
pub fn is_empty(&self) -> bool {
!(self.x1 > self.x0 && self.y1 > self.y0)
}
pub fn contains(&self, point: Point) -> bool {
point.x >= self.x0 && point.x < self.x1 && point.y >= self.y0 && point.y < self.y1
}
#[must_use]
pub fn translate(self, by: Point) -> Self {
Self {
x0: self.x0 + by.x,
y0: self.y0 + by.y,
x1: self.x1 + by.x,
y1: self.y1 + by.y,
}
}
pub fn to_xywh(self) -> [f32; 4] {
[self.x0, self.y0, self.width(), self.height()]
}
pub fn origin(&self) -> Point {
Point::new(self.x0, self.y0)
}
pub fn size(&self) -> Size {
Size::new(self.width(), self.height())
}
#[must_use]
pub fn intersect(self, other: Self) -> Self {
if self.is_empty() || other.is_empty() {
return Self::default();
}
Self {
x0: self.x0.max(other.x0),
y0: self.y0.max(other.y0),
x1: self.x1.min(other.x1),
y1: self.y1.min(other.y1),
}
}
pub const EVERYTHING: Self = Self {
x0: f32::NEG_INFINITY,
y0: f32::NEG_INFINITY,
x1: f32::INFINITY,
y1: f32::INFINITY,
};
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Size {
pub width: f32,
pub height: f32,
}
impl Size {
pub const ZERO: Self = Self::new(0.0, 0.0);
pub const fn new(width: f32, height: f32) -> Self {
Self { width, height }
}
}
fn ordered(a: f32, b: f32) -> (f32, f32) {
if b < a {
(b, a)
} else {
(a, b)
}
}