use num_traits::{Float, ToPrimitive};
use std::ops::Add;
use std::ops::Neg;
use std::ops::Sub;
use {Coordinate, CoordinateType};
#[derive(PartialEq, Clone, Copy, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Point<T>(pub Coordinate<T>)
where
T: CoordinateType;
impl<T: CoordinateType> From<Coordinate<T>> for Point<T> {
fn from(x: Coordinate<T>) -> Point<T> {
Point(x)
}
}
impl<T: CoordinateType> 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: CoordinateType + 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()
}
pub fn cross_prod(&self, point_b: &Point<T>, point_c: &Point<T>) -> T
where
T: Float,
{
(point_b.x() - self.x()) * (point_c.y() - self.y())
- (point_b.y() - self.y()) * (point_c.x() - self.x())
}
}
impl<T> Neg for Point<T>
where
T: CoordinateType + 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: CoordinateType + 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: CoordinateType + ToPrimitive,
{
type Output = Point<T>;
fn sub(self, rhs: Point<T>) -> Point<T> {
Point::new(self.x() - rhs.x(), self.y() - rhs.y())
}
}
#[cfg(feature = "spade")]
impl<T> ::spade::PointN for Point<T>
where
T: ::num_traits::Float + ::spade::SpadeNum + ::std::fmt::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!(),
}
}
}
#[cfg(feature = "spade")]
impl<T> ::spade::TwoDimensional for Point<T>
where
T: ::num_traits::Float + ::spade::SpadeNum + ::std::fmt::Debug,
{
}
impl<T: CoordinateType> From<[T; 2]> for Point<T> {
fn from(coords: [T; 2]) -> Point<T> {
Point::new(coords[0], coords[1])
}
}