use interpolation::Spatial;
use point::Point;
use std::cmp::Ordering;
use std::num::Float;
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Envelope<X, Y, P> {
pub points: Vec<P>,
phantom_x: ::std::marker::PhantomData<X>,
phantom_y: ::std::marker::PhantomData<Y>,
}
impl<X, Y, P> Envelope<X, Y, P>
where
X: PartialOrd,
Y: Spatial,
Y::Scalar: Float,
P: Point<X, Y>,
{
#[inline]
pub fn new() -> Envelope<X, Y, P> {
Envelope {
points: Vec::new(),
phantom_x: ::std::marker::PhantomData,
phantom_y: ::std::marker::PhantomData,
}
}
#[inline]
pub fn from_points(mut points: Vec<P>) -> Envelope<X, Y, P> {
points.sort_by(|a, b| if a.x() < b.x() { Ordering::Less }
else if a.x() > b.x() { Ordering::Greater }
else { Ordering::Equal });
Envelope {
points: points,
phantom_x: ::std::marker::PhantomData,
phantom_y: ::std::marker::PhantomData,
}
}
pub fn add_point(&mut self, point: P) {
self.points.push(point);
self.points.sort_by(|a, b| if a.x() < b.x() { Ordering::Less }
else if a.x() > b.x() { Ordering::Greater }
else { Ordering::Equal });
}
#[inline]
pub fn y(&self, x: X) -> Option<Y> {
if self.points.len() <= 1 { return None }
let mut i = 1;
while i < self.points.len() - 1 && x >= self.points[i].x() {
i += 1;
}
Some(Point::interpolate(x, &self.points[i-1], &self.points[i]))
}
}