use super::geo::*;
use super::has_bounds::*;
use super::coordinate::*;
pub trait BoundingBox : Geo+Sized {
fn from_min_max(min: Self::Point, max: Self::Point) -> Self;
fn bounds_for_points<PointIter: IntoIterator<Item=Self::Point>>(points: PointIter) -> Self {
let mut points = points.into_iter();
let first_point = points.next();
if let Some(first_point) = first_point {
let (mut min, mut max) = (first_point, first_point);
for point in points {
min = Self::Point::from_smallest_components(min, point);
max = Self::Point::from_biggest_components(max, point);
}
Self::from_min_max(min, max)
} else {
Self::empty()
}
}
fn min(&self) -> Self::Point;
fn max(&self) -> Self::Point;
fn empty() -> Self {
Self::from_min_max(Self::Point::origin(), Self::Point::origin())
}
#[inline]
fn is_empty(&self) -> bool {
self.min() == self.max()
}
fn union_bounds(self, target: Self) -> Self {
if self.is_empty() {
target
} else if target.is_empty() {
self
} else {
Self::from_min_max(Self::Point::from_smallest_components(self.min(), target.min()), Self::Point::from_biggest_components(self.max(), target.max()))
}
}
fn overlaps(&self, target: &Self) -> bool {
let (min1, max1) = (self.min(), self.max());
let (min2, max2) = (target.min(), target.max());
for p_index in 0..Self::Point::len() {
if min1.get(p_index) > max2.get(p_index) { return false; }
if min2.get(p_index) > max1.get(p_index) { return false; }
}
true
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Bounds<Point: Coordinate>(pub Point, pub Point);
impl<Point: Coordinate> BoundingBox for (Point, Point) {
#[inline]
fn from_min_max(min: Self::Point, max: Self::Point) -> Self {
(min, max)
}
#[inline]
fn min(&self) -> Self::Point {
Point::from_smallest_components(self.0, self.1)
}
#[inline]
fn max(&self) -> Self::Point {
Point::from_biggest_components(self.0, self.1)
}
}
impl<Point: Coordinate> HasBoundingBox for Bounds<Point> {
fn get_bounding_box<Bounds: BoundingBox<Point=Self::Point>>(&self) -> Bounds {
Bounds::from_min_max(self.min(), self.max())
}
}
impl<Point: Coordinate> Geo for Bounds<Point> {
type Point=Point;
}
impl<Point: Coordinate> BoundingBox for Bounds<Point> {
#[inline]
fn from_min_max(min: Self::Point, max: Self::Point) -> Self {
Bounds(min, max)
}
#[inline]
fn min(&self) -> Self::Point {
self.0
}
#[inline]
fn max(&self) -> Self::Point {
self.1
}
}