feat: Added bounding-box crate
This commit is contained in:
165
bounding-box/src/lib.rs
Normal file
165
bounding-box/src/lib.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
use nalgebra::{Point, Point2, SVector};
|
||||
pub trait Num: num::Num + Copy + core::fmt::Debug + 'static {}
|
||||
impl<T: num::Num + Copy + core::fmt::Debug + 'static> Num for T {}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct BoundingBox<T: Num, const D: usize> {
|
||||
/// The point of the bounding box closest to the origin
|
||||
point: Point<T, D>,
|
||||
/// The size of the bounding box in each dimension
|
||||
size: SVector<T, D>,
|
||||
}
|
||||
|
||||
impl<T: Num, const D: usize> BoundingBox<T, D> {
|
||||
pub fn new(point: Point<T, D>, size: SVector<T, D>) -> Self {
|
||||
Self { point, size }
|
||||
}
|
||||
|
||||
pub fn point(&self) -> &Point<T, D> {
|
||||
&self.point
|
||||
}
|
||||
|
||||
pub fn size(&self) -> &SVector<T, D> {
|
||||
&self.size
|
||||
}
|
||||
|
||||
pub fn center(&self) -> Point<T, D>
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
T: core::ops::DivAssign,
|
||||
{
|
||||
self.point + self.size / (T::one() + T::one())
|
||||
}
|
||||
|
||||
pub fn padding(mut self, padding: T) -> Self
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
T: core::ops::DivAssign,
|
||||
T: core::ops::SubAssign,
|
||||
{
|
||||
self.size.iter_mut().for_each(|s| {
|
||||
*s += padding;
|
||||
});
|
||||
let two = T::one() + T::one();
|
||||
self.point
|
||||
.coords
|
||||
.iter_mut()
|
||||
.for_each(|c| *c -= padding / two);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn translate(&mut self, translation: SVector<T, D>)
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
{
|
||||
self.point += translation;
|
||||
}
|
||||
|
||||
pub fn contains(&self, point: &Point<T, D>) -> bool
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
T: core::ops::SubAssign,
|
||||
T: PartialOrd,
|
||||
{
|
||||
let p1 = self.point.coords;
|
||||
let p2 = self.point.coords + self.size;
|
||||
|
||||
point.coords > p1 && point.coords < p2
|
||||
}
|
||||
}
|
||||
|
||||
pub type BoundingBox2D<T> = BoundingBox<T, 2>;
|
||||
pub type BoundingBox3D<T> = BoundingBox<T, 3>;
|
||||
|
||||
impl<T: Num> BoundingBox2D<T> {
|
||||
pub fn new_2d(point1: Point2<T>, point2: Point2<T>) -> Self
|
||||
where
|
||||
T: core::ops::SubAssign,
|
||||
{
|
||||
let size = point2.coords - point1.coords;
|
||||
Self::new(point1, SVector::from(size))
|
||||
}
|
||||
pub fn x1y1(&self) -> Point2<T> {
|
||||
self.point
|
||||
}
|
||||
|
||||
pub fn x2y2(&self) -> Point2<T>
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
{
|
||||
self.point + self.size
|
||||
}
|
||||
|
||||
pub fn x2y1(&self) -> Point2<T>
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
{
|
||||
Point2::new(self.point.x + self.size.x, self.point.y)
|
||||
}
|
||||
|
||||
pub fn x1y2(&self) -> Point2<T>
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
{
|
||||
Point2::new(self.point.x, self.point.y + self.size.y)
|
||||
}
|
||||
|
||||
pub fn corners(&self) -> [Point2<T>; 4]
|
||||
where
|
||||
T: core::ops::AddAssign,
|
||||
{
|
||||
[self.x1y1(), self.x2y1(), self.x2y2(), self.x1y2()]
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bbox_new() {
|
||||
use nalgebra::{Point2, Vector2};
|
||||
|
||||
let point1 = Point2::new(1.0, 2.0);
|
||||
let point2 = Point2::new(4.0, 6.0);
|
||||
let bbox = BoundingBox::new_2d(point1, point2);
|
||||
|
||||
assert_eq!(bbox.point(), &point1);
|
||||
assert_eq!(bbox.size(), &Vector2::new(3.0, 4.0));
|
||||
assert_eq!(bbox.center(), Point2::new(2.5, 4.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bounding_box_center_2d() {
|
||||
use nalgebra::{Point2, Vector2};
|
||||
|
||||
let point = Point2::new(1.0, 2.0);
|
||||
let size = Vector2::new(3.0, 4.0);
|
||||
let bbox = BoundingBox::new(point, size);
|
||||
|
||||
assert_eq!(bbox.point(), &point);
|
||||
assert_eq!(bbox.size(), &size);
|
||||
assert_eq!(bbox.center(), Point2::new(2.5, 4.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bounding_box_center_3d() {
|
||||
use nalgebra::{Point3, Vector3};
|
||||
|
||||
let point = Point3::new(1.0, 2.0, 3.0);
|
||||
let size = Vector3::new(4.0, 5.0, 6.0);
|
||||
let bbox = BoundingBox::new(point, size);
|
||||
|
||||
assert_eq!(bbox.point(), &point);
|
||||
assert_eq!(bbox.size(), &size);
|
||||
assert_eq!(bbox.center(), Point3::new(3.0, 4.5, 6.0));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bounding_box_padding_2d() {
|
||||
use nalgebra::{Point2, Vector2};
|
||||
|
||||
let point = Point2::new(1.0, 2.0);
|
||||
let size = Vector2::new(3.0, 4.0);
|
||||
let bbox = BoundingBox::new(point, size);
|
||||
|
||||
let padded_bbox = bbox.padding(1.0);
|
||||
assert_eq!(padded_bbox.point(), &Point2::new(0.5, 1.5));
|
||||
assert_eq!(padded_bbox.size(), &Vector2::new(4.0, 5.0));
|
||||
}
|
||||
Reference in New Issue
Block a user