use core::ops::{Add, Div, Mul, Sub};
use crate::util::{feq, Ray};
#[derive(Clone, Default, Debug, Copy, PartialEq, PartialOrd)]
pub struct Coordinate(
pub f64,
pub f64,
);
impl From<Coordinate> for (f64, f64) {
fn from(item: Coordinate) -> (f64, f64) {
(item.0, item.1)
}
}
impl From<(f64, f64)> for Coordinate {
fn from(item: (f64, f64)) -> Coordinate {
Coordinate(item.0, item.1)
}
}
impl From<geo_types::Coord<f64>> for Coordinate {
fn from(value: geo_types::Coord<f64>) -> Self {
Coordinate(value.x, value.y)
}
}
impl From<Coordinate> for geo_types::Coord<f64> {
fn from(value: Coordinate) -> geo_types::Coord<f64> {
geo_types::geometry::Coord {
x: value.0,
y: value.1,
}
}
}
impl Add for Coordinate {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0, self.1 + rhs.1)
}
}
impl Sub for Coordinate {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0, self.1 - rhs.1)
}
}
impl Mul<f64> for Coordinate {
type Output = Self;
fn mul(self, rhs: f64) -> Self::Output {
Self(self.0 * rhs, self.1 * rhs)
}
}
impl Div<f64> for Coordinate {
type Output = Self;
fn div(self, rhs: f64) -> Self::Output {
if rhs == 0. {
return self;
}
Self(self.0 / rhs, self.1 / rhs)
}
}
impl Div<Coordinate> for Coordinate {
type Output = f64;
fn div(self, rhs: Self) -> Self::Output {
if rhs.0 == 0. && rhs.1 == 0. {
0.
} else if rhs.1 == 0. {
return self.0 / rhs.0;
} else {
return self.1 / rhs.1;
}
}
}
impl Coordinate {
pub fn new(x: f64, y: f64) -> Self {
Self(x, y)
}
pub fn get_val(&self) -> (f64, f64) {
(self.0, self.1)
}
pub fn inner_product(&self, rhs: &Self) -> f64 {
self.0 * rhs.0 + self.1 * rhs.1
}
pub fn outer_product(&self, rhs: &Self) -> f64 {
self.0 * rhs.1 - self.1 * rhs.0
}
pub fn norm(&self) -> f64 {
self.inner_product(self).sqrt()
}
pub fn dist_coord(&self, rhs: &Coordinate) -> f64 {
f64::sqrt((self.0 - rhs.0) * (self.0 - rhs.0) + (self.1 - rhs.1) * (self.1 - rhs.1))
}
pub fn dist_ray(&self, rhs: &Ray) -> f64 {
if rhs.is_degenerated() {
return self.dist_coord(&rhs.origin);
}
f64::abs((*self - rhs.origin).outer_product(&rhs.angle)) / rhs.angle.norm()
}
pub fn eq(&self, rhs: &Self) -> bool {
feq(self.0, rhs.0) && feq(self.1, rhs.1)
}
}