Merge pull request #40 from rsaarelm/master
Utility methods for AA boxes
This commit is contained in:
commit
07f01efbc5
2 changed files with 120 additions and 10 deletions
|
@ -15,7 +15,59 @@
|
|||
|
||||
//! Axis-aligned bounding boxes
|
||||
|
||||
use point::{Point2, Point3};
|
||||
use point::{Point, Point2, Point3};
|
||||
use vector::{Vector, Vec2, Vec3};
|
||||
use array::build;
|
||||
use std::fmt;
|
||||
use std::num::{zero, one};
|
||||
use std::iter::Iterator;
|
||||
|
||||
pub trait Aabb
|
||||
<
|
||||
S: Primitive,
|
||||
V: Vector<S, Slice>,
|
||||
P: Point<S, V, Slice>,
|
||||
Slice
|
||||
> {
|
||||
fn new(p1: P, p2: P) -> Self;
|
||||
fn min<'a>(&'a self) -> &'a P;
|
||||
fn max<'a>(&'a self) -> &'a P;
|
||||
#[inline] fn dim(&self) -> V { self.max().sub_p(self.min()) }
|
||||
#[inline] fn volume(&self) -> S { self.dim().comp_mul() }
|
||||
#[inline] fn center(&self) -> P {
|
||||
let two = one::<S>() + one::<S>();
|
||||
self.min().add_v(&self.dim().div_s(two))
|
||||
}
|
||||
|
||||
// Tests whether a point is cointained in the box, inclusive for min corner
|
||||
// and exclusive for the max corner.
|
||||
#[inline] fn contains(&self, p: &P) -> bool {
|
||||
p.sub_p(self.min()).iter().all(|x| *x >= zero::<S>()) &&
|
||||
self.max().sub_p(p).iter().all(|x| *x > zero::<S>())
|
||||
}
|
||||
|
||||
// Returns a new AABB that is grown to include the given point.
|
||||
fn grow(&self, p: &P) -> Self {
|
||||
let min : P = build(|i| self.min().i(i).min(p.i(i)));
|
||||
let max : P = build(|i| self.max().i(i).max(p.i(i)));
|
||||
Aabb::new(min, max)
|
||||
}
|
||||
|
||||
// Returns a new AABB that has its points translated by the given vector.
|
||||
fn add_v(&self, v: &V) -> Self {
|
||||
Aabb::new(self.min().add_v(v), self.max().add_v(v))
|
||||
}
|
||||
|
||||
fn mul_s(&self, s: S) -> Self {
|
||||
Aabb::new(self.min().mul_s(s.clone()), self.max().mul_s(s.clone()))
|
||||
}
|
||||
|
||||
fn mul_v(&self, v: &V) -> Self {
|
||||
let min : P = Point::from_vec(&self.min().to_vec().mul_v(v));
|
||||
let max : P = Point::from_vec(&self.max().to_vec().mul_v(v));
|
||||
Aabb::new(min, max)
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct Aabb2<S> {
|
||||
|
@ -26,7 +78,7 @@ pub struct Aabb2<S> {
|
|||
impl<S: Num + Orderable> Aabb2<S> {
|
||||
/// Construct a new axis-aligned bounding box from two points.
|
||||
#[inline]
|
||||
pub fn new(p1: &Point2<S>, p2: &Point2<S>) -> Aabb2<S> {
|
||||
pub fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> {
|
||||
Aabb2 {
|
||||
min: Point2::new(p1.x.min(&p2.x), p1.y.min(&p2.y)),
|
||||
max: Point2::new(p1.x.max(&p2.x), p1.y.max(&p2.y)),
|
||||
|
@ -34,6 +86,18 @@ impl<S: Num + Orderable> Aabb2<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: Primitive> Aabb<S, Vec2<S>, Point2<S>, [S, ..2]> for Aabb2<S> {
|
||||
fn new(p1: Point2<S>, p2: Point2<S>) -> Aabb2<S> { Aabb2::new(p1, p2) }
|
||||
#[inline] fn min<'a>(&'a self) -> &'a Point2<S> { &self.min }
|
||||
#[inline] fn max<'a>(&'a self) -> &'a Point2<S> { &self.max }
|
||||
}
|
||||
|
||||
impl<S: fmt::Show> ToStr for Aabb2<S> {
|
||||
fn to_str(&self) -> ~str {
|
||||
format!("[{} - {}]", self.min.to_str(), self.max.to_str())
|
||||
}
|
||||
}
|
||||
|
||||
#[deriving(Clone, Eq)]
|
||||
pub struct Aabb3<S> {
|
||||
min: Point3<S>,
|
||||
|
@ -43,10 +107,22 @@ pub struct Aabb3<S> {
|
|||
impl<S: Num + Orderable> Aabb3<S> {
|
||||
/// Construct a new axis-aligned bounding box from two points.
|
||||
#[inline]
|
||||
pub fn new(p1: &Point3<S>, p2: &Point3<S>) -> Aabb3<S> {
|
||||
pub fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> {
|
||||
Aabb3 {
|
||||
min: Point3::new(p1.x.min(&p2.x), p1.y.min(&p2.y), p1.z.min(&p2.z)),
|
||||
max: Point3::new(p1.x.max(&p2.x), p1.y.max(&p2.y), p1.z.max(&p2.z)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Primitive> Aabb<S, Vec3<S>, Point3<S>, [S, ..3]> for Aabb3<S> {
|
||||
fn new(p1: Point3<S>, p2: Point3<S>) -> Aabb3<S> { Aabb3::new(p1, p2) }
|
||||
#[inline] fn min<'a>(&'a self) -> &'a Point3<S> { &self.min }
|
||||
#[inline] fn max<'a>(&'a self) -> &'a Point3<S> { &self.max }
|
||||
}
|
||||
|
||||
impl<S: fmt::Show> ToStr for Aabb3<S> {
|
||||
fn to_str(&self) -> ~str {
|
||||
format!("[{} - {}]", self.min.to_str(), self.max.to_str())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,47 @@
|
|||
use cgmath::aabb::{Aabb2, Aabb3};
|
||||
use cgmath::aabb::*;
|
||||
use cgmath::point::{Point2, Point3};
|
||||
use cgmath::vector::{Vec2, Vec3};
|
||||
|
||||
#[test]
|
||||
fn test_aabb() {
|
||||
let aabb = Aabb2::new(&Point2::new(-20f64, 30f64), &Point2::new(10f64, -10f64));
|
||||
assert_eq!(aabb.min, Point2::new(-20f64, -10f64));
|
||||
assert_eq!(aabb.max, Point2::new(10f64, 30f64));
|
||||
let aabb = Aabb2::new(Point2::new(-20, 30), Point2::new(10, -10));
|
||||
assert_eq!(aabb.min(), &Point2::new(-20, -10));
|
||||
assert_eq!(aabb.max(), &Point2::new(10, 30));
|
||||
assert_eq!(aabb.dim(), Vec2::new(30, 40));
|
||||
assert_eq!(aabb.volume(), 30 * 40);
|
||||
assert_eq!(aabb.center(), Point2::new(-5, 10));
|
||||
|
||||
let aabb = Aabb3::new(&Point3::new(-20f64, 30f64, 0f64), &Point3::new(10f64, -10f64, -5f64));
|
||||
assert_eq!(aabb.min, Point3::new(-20f64, -10f64, -5f64));
|
||||
assert_eq!(aabb.max, Point3::new(10f64, 30f64, 0f64));
|
||||
assert!(aabb.contains(&Point2::new(0, 0)));
|
||||
assert!(!aabb.contains(&Point2::new(-50, -50)));
|
||||
assert!(!aabb.contains(&Point2::new(50, 50)));
|
||||
|
||||
assert_eq!(aabb.grow(&Point2::new(0, 0)), aabb);
|
||||
assert_eq!(aabb.grow(&Point2::new(100, 100)),
|
||||
Aabb2::new(Point2::new(-20, -10), Point2::new(100, 100)));
|
||||
assert_eq!(aabb.grow(&Point2::new(-100, -100)),
|
||||
Aabb2::new(Point2::new(-100, -100), Point2::new(10, 30)));
|
||||
|
||||
let aabb = Aabb3::new(Point3::new(-20, 30, 5), Point3::new(10, -10, -5));
|
||||
assert_eq!(aabb.min(), &Point3::new(-20, -10, -5));
|
||||
assert_eq!(aabb.max(), &Point3::new(10, 30, 5));
|
||||
assert_eq!(aabb.dim(), Vec3::new(30, 40, 10));
|
||||
assert_eq!(aabb.volume(), 30 * 40 * 10);
|
||||
assert_eq!(aabb.center(), Point3::new(-5, 10, 0));
|
||||
|
||||
assert!(aabb.contains(&Point3::new(0, 0, 0)));
|
||||
assert!(!aabb.contains(&Point3::new(-100, 0, 0)));
|
||||
assert!(!aabb.contains(&Point3::new(100, 0, 0)));
|
||||
assert!(aabb.contains(&Point3::new(9, 29, -1)));
|
||||
assert!(!aabb.contains(&Point3::new(10, 30, 5)));
|
||||
assert!(aabb.contains(&Point3::new(-20, -10, -5)));
|
||||
assert!(!aabb.contains(&Point3::new(-21, -11, -6)));
|
||||
|
||||
assert_eq!(aabb.add_v(&Vec3::new(1, 2, 3)),
|
||||
Aabb3::new(Point3::new(-19, 32, 8), Point3::new(11, -8, -2)));
|
||||
|
||||
assert_eq!(aabb.mul_s(2),
|
||||
Aabb3::new(Point3::new(-40, -20, -10), Point3::new(20, 60, 10)));
|
||||
|
||||
assert_eq!(aabb.mul_v(&Vec3::new(1, 2, 3)),
|
||||
Aabb3::new(Point3::new(-20, -20, -15), Point3::new(10, 60, 15)));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue