use std::ops::{Add, Sub, Mul, Div, Index, IndexMut};
use rand::{Rng, Rand, RandomRange};
use interpolation::Spatial;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Point {
pub x: f64,
pub y: f64,
}
impl Point {
pub fn origin() -> Self {
Self {x: 0.0, y: 0.0}
}
pub fn is_finite(self) -> bool {
self.x.is_finite() && self.y.is_finite()
}
pub fn is_normal(self) -> bool {
self.x.is_normal() && self.y.is_normal()
}
pub fn is_not_normal(self) -> bool {
!self.x.is_normal() && !self.y.is_normal()
}
pub fn abs(self) -> Self {
Self {x: self.x.abs(), y: self.y.abs()}
}
pub fn round(self) -> Self {
Self {x: self.x.round(), y: self.y.round()}
}
pub fn min(self, other: Self) -> Self {
Self {
x: self.x.min(other.x),
y: self.y.min(other.y),
}
}
pub fn max(self, other: Self) -> Self {
Self {
x: self.x.max(other.x),
y: self.y.max(other.y),
}
}
pub fn square_len(self) -> f64 {
self.x.powi(2) + self.y.powi(2)
}
pub fn len(self) -> f64 {
self.square_len().sqrt()
}
pub fn atan2(self) -> f64 {
self.y.atan2(self.x)
}
}
impl From<(f64, f64)> for Point {
fn from(pt: (f64, f64)) -> Self {
Self {x: pt.0, y: pt.1}
}
}
impl From<[f64; 2]> for Point {
fn from(pt: [f64; 2]) -> Self {
Self {x: pt[0], y: pt[1]}
}
}
impl From<Point> for [f64; 2] {
fn from(pt: Point) -> Self {
[pt.x, pt.y]
}
}
impl Add for Point {
type Output = Self;
fn add(self, other: Self) -> Self::Output {
Self {
x: self.x + other.x,
y: self.y + other.y,
}
}
}
impl Sub for Point {
type Output = Self;
fn sub(self, other: Self) -> Self::Output {
Self {
x: self.x - other.x,
y: self.y - other.y,
}
}
}
impl Mul<f64> for Point {
type Output = Self;
fn mul(self, other: f64) -> Self::Output {
Self {
x: self.x * other,
y: self.y * other,
}
}
}
impl Div<f64> for Point {
type Output = Self;
fn div(self, other: f64) -> Self::Output {
Self {
x: self.x / other,
y: self.y / other,
}
}
}
impl Index<usize> for Point {
type Output = f64;
fn index(&self, index: usize) -> &Self::Output {
match index {
0 => &self.x,
1 => &self.y,
_ => panic!("Invalid coordinate for Point: {}", index),
}
}
}
impl IndexMut<usize> for Point {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.x,
1 => &mut self.y,
_ => panic!("Invalid coordinate for Point: {}", index),
}
}
}
impl Spatial for Point {
type Scalar = f64;
#[inline(always)]
fn add(&self, other: &Self) -> Self {
*self + *other
}
#[inline(always)]
fn sub(&self, other: &Self) -> Self {
*self - *other
}
#[inline(always)]
fn scale(&self, scalar: &Self::Scalar) -> Self {
*self * *scalar
}
}
impl Rand for Point {
fn rand<R: Rng>(rng: &mut R) -> Self {
Self {
x: rng.gen(),
y: rng.gen(),
}
}
}
impl RandomRange for Point {
fn random_range<R: Rng>(rng: &mut R, p1: Self, p2: Self) -> Self {
let min = p1.min(p2);
let max = p1.max(p2);
Point {
x: RandomRange::random_range(rng, min.x, max.x),
y: RandomRange::random_range(rng, min.y, max.y),
}
}
}