use std::ops::Add;
use std::ops::AddAssign;
use std::ops::Neg;
use std::ops::Sub;
use std::fmt::Debug;
use std::iter::{Iterator, FromIterator};
use num_traits::{Float, ToPrimitive};
use spade::SpadeNum;
use spade::PointN;
pub static COORD_PRECISION: f32 = 1e-1;
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Coordinate<T>
where T: Float
{
pub x: T,
pub y: T,
}
impl<T: Float> From<(T, T)> for Coordinate<T> {
fn from(coords: (T, T)) -> Self {
Coordinate{ x: coords.0, y: coords.1 }
}
}
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Bbox<T>
where T: Float
{
pub xmin: T,
pub xmax: T,
pub ymin: T,
pub ymax: T,
}
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Extremes {
pub ymin: usize,
pub xmax: usize,
pub ymax: usize,
pub xmin: usize,
}
impl From<Vec<usize>> for Extremes {
fn from(original: Vec<usize>) -> Extremes {
Extremes {
ymin: original[0],
xmax: original[1],
ymax: original[2],
xmin: original[3],
}
}
}
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct ExtremePoint<T>
where T: Float
{
pub ymin: Point<T>,
pub xmax: Point<T>,
pub ymax: Point<T>,
pub xmin: Point<T>,
}
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Point<T> (pub Coordinate<T>) where T: Float;
impl<T: Float> From<Coordinate<T>> for Point<T> {
fn from(x: Coordinate<T>) -> Point<T> {
Point(x)
}
}
impl<T: Float> From<(T, T)> for Point<T> {
fn from(coords: (T, T)) -> Point<T> {
Point::new(coords.0, coords.1)
}
}
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> PointN for Point<T>
where T: Float + SpadeNum + Debug
{
type Scalar = T;
fn dimensions() -> usize {
2
}
fn from_value(value: Self::Scalar) -> Self {
Point::new(value, value)
}
fn nth(&self, index: usize) -> &Self::Scalar {
match index {
0 => &self.0.x,
1 => &self.0.y,
_ => unreachable!()
}
}
fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar {
match index {
0 => &mut self.0.x,
1 => &mut self.0.y,
_ => unreachable!()
}
}
}
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, Serialize, Deserialize)]
pub struct MultiPoint<T>(pub Vec<Point<T>>) where T: Float;
impl<T: Float, IP: Into<Point<T>>> From<IP> for MultiPoint<T> {
fn from(x: IP) -> MultiPoint<T> {
MultiPoint(vec![x.into()])
}
}
impl<T: Float, IP: Into<Point<T>>> From<Vec<IP>> for MultiPoint<T> {
fn from(v: Vec<IP>) -> MultiPoint<T> {
MultiPoint(v.into_iter().map(|p| p.into()).collect())
}
}
impl<T: Float, IP: Into<Point<T>>> FromIterator<IP> for MultiPoint<T> {
fn from_iter<I: IntoIterator<Item=IP>>(iter: I) -> Self {
MultiPoint(iter.into_iter().map(|p| p.into()).collect())
}
}
impl<T: Float> IntoIterator for MultiPoint<T> {
type Item = Point<T>;
type IntoIter = ::std::vec::IntoIter<Point<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(PartialEq, Clone, Copy, Debug, Serialize, Deserialize)]
pub struct Line<T>
where T: Float
{
pub start: Point<T>,
pub end: Point<T>
}
impl<T> Line<T>
where T: Float
{
pub fn new(start: Point<T>, end: Point<T>) -> Line<T> {
Line {start: start, end: end}
}
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub struct LineString<T>(pub Vec<Point<T>>) where T: Float;
impl<T: Float, IP: Into<Point<T>>> From<Vec<IP>> for LineString<T> {
fn from(v: Vec<IP>) -> Self {
LineString(v.into_iter().map(|p| p.into()).collect())
}
}
impl<T: Float, IP: Into<Point<T>>> FromIterator<IP> for LineString<T> {
fn from_iter<I: IntoIterator<Item=IP>>(iter: I) -> Self {
LineString(iter.into_iter().map(|p| p.into()).collect())
}
}
impl<T: Float> IntoIterator for LineString<T> {
type Item = Point<T>;
type IntoIter = ::std::vec::IntoIter<Point<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub struct MultiLineString<T>(pub Vec<LineString<T>>) where T: Float;
impl<T: Float, ILS: Into<LineString<T>>> From<ILS> for MultiLineString<T> {
fn from(ls: ILS) -> Self {
MultiLineString(vec![ls.into()])
}
}
impl<T: Float, ILS: Into<LineString<T>>> FromIterator<ILS> for MultiLineString<T> {
fn from_iter<I: IntoIterator<Item=ILS>>(iter: I) -> Self {
MultiLineString(iter.into_iter().map(|ls| ls.into()).collect())
}
}
impl<T: Float> IntoIterator for MultiLineString<T> {
type Item = LineString<T>;
type IntoIter = ::std::vec::IntoIter<LineString<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub struct Polygon<T>
where T: Float
{
pub exterior: LineString<T>,
pub interiors: Vec<LineString<T>>
}
impl<T> Polygon<T>
where T: Float
{
pub fn new(exterior: LineString<T>, interiors: Vec<LineString<T>>) -> Polygon<T> {
Polygon { exterior: exterior, interiors: interiors }
}
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub struct MultiPolygon<T>(pub Vec<Polygon<T>>) where T: Float;
impl<T: Float, IP: Into<Polygon<T>>> From<IP> for MultiPolygon<T> {
fn from(x: IP) -> Self {
MultiPolygon(vec![x.into()])
}
}
impl<T: Float, IP: Into<Polygon<T>>> FromIterator<IP> for MultiPolygon<T> {
fn from_iter<I: IntoIterator<Item=IP>>(iter: I) -> Self {
MultiPolygon(iter.into_iter().map(|p| p.into()).collect())
}
}
impl<T: Float> IntoIterator for MultiPolygon<T> {
type Item = Polygon<T>;
type IntoIter = ::std::vec::IntoIter<Polygon<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(PartialEq, Clone, Debug)]
pub struct GeometryCollection<T>(pub Vec<Geometry<T>>) where T: Float;
impl<T: Float, IG: Into<Geometry<T>>> From<IG> for GeometryCollection<T> {
fn from(x: IG) -> Self {
GeometryCollection(vec![x.into()])
}
}
impl<T: Float, IG: Into<Geometry<T>>> FromIterator<IG> for GeometryCollection<T> {
fn from_iter<I: IntoIterator<Item=IG>>(iter: I) -> Self {
GeometryCollection(iter.into_iter().map(|g| g.into()).collect())
}
}
impl<T: Float> IntoIterator for GeometryCollection<T> {
type Item = Geometry<T>;
type IntoIter = ::std::vec::IntoIter<Geometry<T>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[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>)
}
impl<T: Float> From<Point<T>> for Geometry<T> { fn from(x: Point<T>) -> Geometry<T> { Geometry::Point(x) } }
impl<T: Float> From<LineString<T>> for Geometry<T> { fn from(x: LineString<T>) -> Geometry<T> { Geometry::LineString(x) } }
impl<T: Float> From<Polygon<T>> for Geometry<T> { fn from(x: Polygon<T>) -> Geometry<T> { Geometry::Polygon(x) } }
impl<T: Float> From<MultiPoint<T>> for Geometry<T> { fn from(x: MultiPoint<T>) -> Geometry<T> { Geometry::MultiPoint(x) } }
impl<T: Float> From<MultiLineString<T>> for Geometry<T> { fn from(x: MultiLineString<T>) -> Geometry<T> { Geometry::MultiLineString(x) } }
impl<T: Float> From<MultiPolygon<T>> for Geometry<T> { fn from(x: MultiPolygon<T>) -> Geometry<T> { Geometry::MultiPolygon(x) } }
#[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);
let p: Point<f32> = (0f32, 1f32).into();
assert_eq!(p.x(), 0.);
assert_eq!(p.y(), 1.);
}
#[test]
fn polygon_new_test() {
let exterior = LineString(vec![Point::new(0., 0.), Point::new(1., 1.),
Point::new(1., 0.), Point::new(0., 0.)]);
let interiors = vec![LineString(vec![Point::new(0.1, 0.1), Point::new(0.9, 0.9),
Point::new(0.9, 0.1), Point::new(0.1, 0.1)])];
let p = Polygon::new(exterior.clone(), interiors.clone());
assert_eq!(p.exterior, exterior);
assert_eq!(p.interiors, interiors);
}
#[test]
fn iters() {
let _: MultiPoint<_> = vec![(0., 0.), (1., 2.)].into();
let _: MultiPoint<_> = vec![(0., 0.), (1., 2.)].into_iter().collect();
let _: LineString<_> = vec![(0., 0.), (1., 2.)].into();
let _: LineString<_> = vec![(0., 0.), (1., 2.)].into_iter().collect();
}
}