// BoundingBox library for 2D bounding boxes and spatial intersection tests.
///|
pub struct Rect2D {
min_x : Double
min_y : Double
max_x : Double
max_y : Double
} derive(Eq, Debug)
///|
pub impl Show for Rect2D with fn output(self, logger) {
logger.write_string("{min_x: ")
logger.write_string(self.min_x.to_string())
logger.write_string(", min_y: ")
logger.write_string(self.min_y.to_string())
logger.write_string(", max_x: ")
logger.write_string(self.max_x.to_string())
logger.write_string(", max_y: ")
logger.write_string(self.max_y.to_string())
logger.write_string("}")
}
///|
pub fn Rect2D::new(
min_x : Double,
min_y : Double,
max_x : Double,
max_y : Double,
) -> Rect2D {
{ min_x, min_y, max_x, max_y }
}
///|
pub fn Rect2D::empty() -> Rect2D {
{
min_x: 1000000000.0,
min_y: 1000000000.0,
max_x: -1000000000.0,
max_y: -1000000000.0,
}
}
///|
pub fn Rect2D::from_point(p : Vec2) -> Rect2D {
{ min_x: p.x, min_y: p.y, max_x: p.x, max_y: p.y }
}
///|
pub fn Rect2D::from_points(points : Array[Vec2]) -> Rect2D {
if points.is_empty() {
Rect2D::empty()
} else {
let mut min_x = points[0].x
let mut min_y = points[0].y
let mut max_x = points[0].x
let mut max_y = points[0].y
for i = 1; i < points.length(); i = i + 1 {
let p = points[i]
if p.x < min_x {
min_x = p.x
}
if p.y < min_y {
min_y = p.y
}
if p.x > max_x {
max_x = p.x
}
if p.y > max_y {
max_y = p.y
}
}
{ min_x, min_y, max_x, max_y }
}
}
///|
pub fn Rect2D::width(self : Rect2D) -> Double {
if self.max_x < self.min_x {
0.0
} else {
self.max_x - self.min_x
}
}
///|
pub fn Rect2D::height(self : Rect2D) -> Double {
if self.max_y < self.min_y {
0.0
} else {
self.max_y - self.min_y
}
}
///|
pub fn Rect2D::center(self : Rect2D) -> Vec2 {
{ x: (self.min_x + self.max_x) * 0.5, y: (self.min_y + self.max_y) * 0.5 }
}
///|
pub fn Rect2D::union(self : Rect2D, other : Rect2D) -> Rect2D {
if self.is_empty() {
other
} else if other.is_empty() {
self
} else {
{
min_x: if self.min_x < other.min_x {
self.min_x
} else {
other.min_x
},
min_y: if self.min_y < other.min_y {
self.min_y
} else {
other.min_y
},
max_x: if self.max_x > other.max_x {
self.max_x
} else {
other.max_x
},
max_y: if self.max_y > other.max_y {
self.max_y
} else {
other.max_y
},
}
}
}
///|
pub fn Rect2D::intersection(self : Rect2D, other : Rect2D) -> Rect2D {
let min_x = if self.min_x > other.min_x { self.min_x } else { other.min_x }
let min_y = if self.min_y > other.min_y { self.min_y } else { other.min_y }
let max_x = if self.max_x < other.max_x { self.max_x } else { other.max_x }
let max_y = if self.max_y < other.max_y { self.max_y } else { other.max_y }
if min_x > max_x || min_y > max_y {
Rect2D::empty()
} else {
{ min_x, min_y, max_x, max_y }
}
}
///|
pub fn Rect2D::intersects(self : Rect2D, other : Rect2D) -> Bool {
!(self.max_x < other.min_x ||
self.min_x > other.max_x ||
self.max_y < other.min_y ||
self.min_y > other.max_y)
}
///|
pub fn Rect2D::contains_point(self : Rect2D, p : Vec2) -> Bool {
p.x >= self.min_x &&
p.x <= self.max_x &&
p.y >= self.min_y &&
p.y <= self.max_y
}
///|
pub fn Rect2D::contains_rect(self : Rect2D, other : Rect2D) -> Bool {
other.min_x >= self.min_x &&
other.max_x <= self.max_x &&
other.min_y >= self.min_y &&
other.max_y <= self.max_y
}
///|
pub fn Rect2D::expand(self : Rect2D, amount : Double) -> Rect2D {
{
min_x: self.min_x - amount,
min_y: self.min_y - amount,
max_x: self.max_x + amount,
max_y: self.max_y + amount,
}
}
///|
pub fn Rect2D::corners(self : Rect2D) -> Array[Vec2] {
[
Vec2::new(self.min_x, self.min_y),
Vec2::new(self.max_x, self.min_y),
Vec2::new(self.max_x, self.max_y),
Vec2::new(self.min_x, self.max_y),
]
}
///|
pub fn Rect2D::is_empty(self : Rect2D) -> Bool {
self.min_x > self.max_x || self.min_y > self.max_y
}