use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Neg;
use std::ops::Sub;
use num::{Float, ToPrimitive};
pub static COORD_PRECISION: f32 = 1e-1;
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct Coordinate<T>
where T: Float
{
pub x: T,
pub y: T,
}
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct Bbox<T>
where T: Float
{
pub xmin: T,
pub xmax: T,
pub ymin: T,
pub ymax: T,
}
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct Point<T> (pub Coordinate<T>) where T: Float;
impl<T> Point<T>
where T: Float + ToPrimitive
{
pub fn new(x: T, y: T) -> Point<T> {
Point(Coordinate { x: x, y: y })
}
pub fn x(&self) -> T {
self.0.x
}
pub fn set_x(&mut self, x: T) -> &mut Point<T> {
self.0.x = x;
self
}
pub fn y(&self) -> T {
self.0.y
}
pub fn set_y(&mut self, y: T) -> &mut Point<T> {
self.0.y = y;
self
}
pub fn lng(&self) -> T {
self.x()
}
pub fn set_lng(&mut self, lng: T) -> &mut Point<T> {
self.set_x(lng)
}
pub fn lat(&self) -> T {
self.y()
}
pub fn set_lat(&mut self, lat: T) -> &mut Point<T> {
self.set_y(lat)
}
pub fn dot(&self, point: &Point<T>) -> T {
self.x() * point.x() + self.y() * point.y()
}
}
impl<T> Neg for Point<T>
where T: Float + Neg<Output = T> + ToPrimitive
{
type Output = Point<T>;
fn neg(self) -> Point<T> {
Point::new(-self.x(), -self.y())
}
}
impl<T> Add for Point<T>
where T: Float + ToPrimitive
{
type Output = Point<T>;
fn add(self, rhs: Point<T>) -> Point<T> {
Point::new(self.x() + rhs.x(), self.y() + rhs.y())
}
}
impl<T> Sub for Point<T>
where T: Float + ToPrimitive
{
type Output = Point<T>;
fn sub(self, rhs: Point<T>) -> Point<T> {
Point::new(self.x() - rhs.x(), self.y() - rhs.y())
}
}
impl<T> Add for Bbox<T>
where T: Float + ToPrimitive
{
type Output = Bbox<T>;
fn add(self, rhs: Bbox<T>) -> Bbox<T> {
Bbox{
xmin: if self.xmin <= rhs.xmin {self.xmin} else {rhs.xmin},
xmax: if self.xmax >= rhs.xmax {self.xmax} else {rhs.xmax},
ymin: if self.ymin <= rhs.ymin {self.ymin} else {rhs.ymin},
ymax: if self.ymax >= rhs.ymax {self.ymax} else {rhs.ymax},
}
}
}
impl<T> AddAssign for Bbox<T>
where T: Float + ToPrimitive
{
fn add_assign(&mut self, rhs: Bbox<T>){
self.xmin = if self.xmin <= rhs.xmin {self.xmin} else {rhs.xmin};
self.xmax = if self.xmax >= rhs.xmax {self.xmax} else {rhs.xmax};
self.ymin = if self.ymin <= rhs.ymin {self.ymin} else {rhs.ymin};
self.ymax = if self.ymax >= rhs.ymax {self.ymax} else {rhs.ymax};
}
}
#[derive(PartialEq, Clone, Debug)]
pub struct MultiPoint<T>(pub Vec<Point<T>>) where T: Float;
#[derive(PartialEq, Clone, Debug)]
pub struct LineString<T>(pub Vec<Point<T>>) where T: Float;
#[derive(PartialEq, Clone, Debug)]
pub struct MultiLineString<T>(pub Vec<LineString<T>>) where T: Float;
#[derive(PartialEq, Clone, Debug)]
pub struct Polygon<T>(pub LineString<T>, pub Vec<LineString<T>>) where T: Float;
#[derive(PartialEq, Clone, Debug)]
pub struct MultiPolygon<T>(pub Vec<Polygon<T>>) where T: Float;
#[derive(PartialEq, Clone, Debug)]
pub struct GeometryCollection<T>(pub Vec<Geometry<T>>) where T: Float;
#[derive(PartialEq, Clone, Debug)]
pub enum Geometry<T>
where T: Float
{
Point(Point<T>),
LineString(LineString<T>),
Polygon(Polygon<T>),
MultiPoint(MultiPoint<T>),
MultiLineString(MultiLineString<T>),
MultiPolygon(MultiPolygon<T>),
GeometryCollection(GeometryCollection<T>)
}
#[cfg(test)]
mod test {
use ::types::*;
#[test]
fn type_test() {
let c = Coordinate {
x: 40.02f64,
y: 116.34,
};
let p = Point(c);
let Point(c2) = p;
assert_eq!(c, c2);
assert_eq!(c.x, c2.x);
assert_eq!(c.y, c2.y);
}
}