use num_traits::Float;
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,
{
pub fn new(x: T, y: T) -> Point<T> {
Point(Coordinate { x, 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 x_y(&self) -> (T, T) {
(self.0.x, self.0.y)
}
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)
}
}
impl<T> Point<T>
where
T: CoordinateType,
{
pub fn dot(&self, other: Point<T>) -> T {
self.x() * other.x() + self.y() * other.y()
}
pub fn cross_prod(&self, point_b: Point<T>, point_c: Point<T>) -> T {
(point_b.x() - self.x()) * (point_c.y() - self.y())
- (point_b.y() - self.y()) * (point_c.x() - self.x())
}
}
impl<T> Point<T>
where
T: CoordinateType + Float,
{
pub fn to_degrees(&self) -> Point<T> {
let (x, y) = self.x_y();
let x = x.to_degrees();
let y = y.to_degrees();
Point::new(x, y)
}
pub fn to_radians(&self) -> Point<T> {
let (x, y) = self.x_y();
let x = x.to_radians();
let y = y.to_radians();
Point::new(x, y)
}
}
impl<T> Neg for Point<T>
where
T: CoordinateType + Neg<Output = T>,
{
type Output = Point<T>;
fn neg(self) -> Point<T> {
Point::new(-self.x(), -self.y())
}
}
impl<T> Add for Point<T>
where
T: CoordinateType,
{
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,
{
type Output = Point<T>;
fn sub(self, rhs: Point<T>) -> Point<T> {
Point::new(self.x() - rhs.x(), self.y() - rhs.y())
}
}
#[cfg(feature = "rstar")]
impl<T> ::rstar::Point for Point<T>
where
T: ::num_traits::Float + ::rstar::RTreeNum,
{
type Scalar = T;
const DIMENSIONS: usize = 2;
fn generate<F>(f: F) -> Self
where
F: Fn(usize) -> Self::Scalar,
{
Point::new(f(0), f(1))
}
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: CoordinateType> From<[T; 2]> for Point<T> {
fn from(coords: [T; 2]) -> Point<T> {
Point::new(coords[0], coords[1])
}
}