use num::Float;
use std::ops::{Index, IndexMut, AddAssign, SubAssign, MulAssign, DivAssign, Add, Neg, Sub, Mul, Div};
use std::fmt::{Debug, Formatter, Result};
pub struct Point2<T: Float> {
pub x: T,
pub y: T,
}
pub type Point2F = Point2<f32>;
pub type Point2D = Point2<f64>;
impl<T: Float> Point2<T> {
pub fn new_default() -> Point2<T> {
return Point2 {
x: T::zero(),
y: T::zero(),
};
}
pub fn new(x_: T, y_: T) -> Point2<T> {
return Point2 {
x: x_,
y: y_,
};
}
pub fn new_lst(lst: [T; 2]) -> Point2<T> {
return Point2 {
x: lst[0],
y: lst[1],
};
}
}
impl<T: Float> Point2<T> {
pub fn set_scalar(&mut self, s: T) {
self.x = s;
self.y = s;
}
pub fn set_scalar2(&mut self, x: T, y: T) {
self.x = x;
self.y = y;
}
pub fn set_lst(&mut self, lst: [T; 2]) {
self.x = lst[0];
self.y = lst[1];
}
pub fn set_self(&mut self, pt: Point2<T>) {
self.x = pt.x;
self.y = pt.y;
}
pub fn set_zero(&mut self) {
self.x = T::zero();
self.y = T::zero();
}
}
impl<T: Float> Point2<T> {
pub fn add_scalar(&self, v: T) -> Point2<T> {
return Point2::new(self.x + v, self.y + v);
}
pub fn add_vec(&self, v: Point2<T>) -> Point2<T> {
return Point2::new(self.x + v.x, self.y + v.y);
}
pub fn sub_scalar(&self, v: T) -> Point2<T> {
return Point2::new(self.x - v, self.y - v);
}
pub fn sub_vec(&self, v: Point2<T>) -> Point2<T> {
return Point2::new(self.x - v.x, self.y - v.y);
}
pub fn mul_scalar(&self, v: T) -> Point2<T> {
return Point2::new(self.x * v, self.y * v);
}
pub fn mul_vec(&self, v: Point2<T>) -> Point2<T> {
return Point2::new(self.x * v.x, self.y * v.y);
}
pub fn div_scalar(&self, v: T) -> Point2<T> {
return Point2::new(self.x / v, self.y / v);
}
pub fn div_vec(&self, v: Point2<T>) -> Point2<T> {
return Point2::new(self.x / v.x, self.y / v.y);
}
}
impl<T: Float> Point2<T> {
pub fn rsub_scalar(&self, v: T) -> Point2<T> {
return Point2::new(v - self.x, v - self.y);
}
pub fn rsub_vec(&self, v: Point2<T>) -> Point2<T> {
return Point2::new(v.x - self.x, v.y - self.y);
}
pub fn rdiv_scalar(&self, v: T) -> Point2<T> {
return Point2::new(v / self.x, v / self.y);
}
pub fn rdiv_vec(&self, v: Point2<T>) -> Point2<T> {
return Point2::new(v.x / self.x, v.y / self.y);
}
}
impl<T: Float> Point2<T> {
pub fn iadd_scalar(&mut self, v: T) {
self.x = T::add(self.x, v);
self.y = T::add(self.y, v);
}
pub fn iadd_vec(&mut self, v: Point2<T>) {
self.x = T::add(self.x, v.x);
self.y = T::add(self.y, v.y);
}
pub fn isub_scalar(&mut self, v: T) {
self.x = T::sub(self.x, v);
self.y = T::sub(self.y, v);
}
pub fn isub_vec(&mut self, v: Point2<T>) {
self.x = T::sub(self.x, v.x);
self.y = T::sub(self.y, v.y);
}
pub fn imul_scalar(&mut self, v: T) {
self.x = T::mul(self.x, v);
self.y = T::mul(self.y, v);
}
pub fn imul_vec(&mut self, v: Point2<T>) {
self.x = T::mul(self.x, v.x);
self.y = T::mul(self.y, v.y);
}
pub fn idiv_scalar(&mut self, v: T) {
self.x = T::div(self.x, v);
self.y = T::div(self.y, v);
}
pub fn idiv_vec(&mut self, v: Point2<T>) {
self.x = T::div(self.x, v.x);
self.y = T::div(self.y, v.y);
}
}
impl<T: Float> Point2<T> {
pub fn at(&self, i: usize) -> &T {
match i {
0 => return &self.x,
1 => return &self.y,
_ => { panic!() }
}
}
pub fn at_mut(&mut self, i: usize) -> &mut T {
match i {
0 => return &mut self.x,
1 => return &mut self.y,
_ => { panic!() }
}
}
pub fn sum(&self) -> T {
return self.x + self.y;
}
pub fn min(&self) -> T {
return self.x.min(self.y);
}
pub fn max(&self) -> T {
return self.x.max(self.y);
}
pub fn absmin(&self) -> T {
return crate::math_utils::absmin(self.x, self.y);
}
pub fn absmax(&self) -> T {
return crate::math_utils::absmax(self.x, self.y);
}
pub fn dominant_axis(&self) -> usize {
match self.x.abs() > self.y.abs() {
true => 0,
false => 1
}
}
pub fn subminant_axis(&self) -> usize {
match self.x.abs() < self.y.abs() {
true => 0,
false => 1
}
}
pub fn is_equal(&self, other: &Point2<T>) -> bool {
return self.x == other.x && self.y == other.y;
}
}
impl<T: Float> Clone for Point2<T> {
fn clone(&self) -> Self {
return Point2 {
x: self.x,
y: self.y,
};
}
}
impl<T: Float> Copy for Point2<T> {}
impl<T: Float> Index<usize> for Point2<T> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
return self.at(index);
}
}
impl<T: Float> IndexMut<usize> for Point2<T> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
return self.at_mut(index);
}
}
impl<T: Float> AddAssign<T> for Point2<T> {
fn add_assign(&mut self, rhs: T) {
self.iadd_scalar(rhs);
}
}
impl<T: Float> AddAssign for Point2<T> {
fn add_assign(&mut self, rhs: Self) {
self.iadd_vec(rhs);
}
}
impl<T: Float> SubAssign<T> for Point2<T> {
fn sub_assign(&mut self, rhs: T) {
self.isub_scalar(rhs);
}
}
impl<T: Float> SubAssign for Point2<T> {
fn sub_assign(&mut self, rhs: Self) {
self.isub_vec(rhs);
}
}
impl<T: Float> MulAssign<T> for Point2<T> {
fn mul_assign(&mut self, rhs: T) {
self.imul_scalar(rhs);
}
}
impl<T: Float> MulAssign for Point2<T> {
fn mul_assign(&mut self, rhs: Self) {
self.imul_vec(rhs);
}
}
impl<T: Float> DivAssign<T> for Point2<T> {
fn div_assign(&mut self, rhs: T) {
self.idiv_scalar(rhs);
}
}
impl<T: Float> DivAssign for Point2<T> {
fn div_assign(&mut self, rhs: Self) {
self.idiv_vec(rhs);
}
}
impl<T: Float> PartialEq for Point2<T> {
fn eq(&self, other: &Self) -> bool {
return self.is_equal(other);
}
}
impl<T: Float> Eq for Point2<T> {}
impl<T: Float> Neg for Point2<T> {
type Output = Point2<T>;
fn neg(self) -> Self::Output {
return Point2::new(-self.x, -self.y);
}
}
impl<T: Float> Add<T> for Point2<T> {
type Output = Point2<T>;
fn add(self, rhs: T) -> Self::Output {
return self.add_scalar(rhs);
}
}
impl<T: Float> Add for Point2<T> {
type Output = Point2<T>;
fn add(self, rhs: Self) -> Self::Output {
return self.add_vec(rhs);
}
}
impl<T: Float> Sub<T> for Point2<T> {
type Output = Point2<T>;
fn sub(self, rhs: T) -> Self::Output {
return self.sub_scalar(rhs);
}
}
impl<T: Float> Sub for Point2<T> {
type Output = Point2<T>;
fn sub(self, rhs: Self) -> Self::Output {
return self.sub_vec(rhs);
}
}
impl<T: Float> Mul<T> for Point2<T> {
type Output = Point2<T>;
fn mul(self, rhs: T) -> Self::Output {
return self.mul_scalar(rhs);
}
}
impl<T: Float> Mul for Point2<T> {
type Output = Point2<T>;
fn mul(self, rhs: Self) -> Self::Output {
return self.mul_vec(rhs);
}
}
impl<T: Float> Div<T> for Point2<T> {
type Output = Point2<T>;
fn div(self, rhs: T) -> Self::Output {
return self.div_scalar(rhs);
}
}
impl<T: Float> Div for Point2<T> {
type Output = Point2<T>;
fn div(self, rhs: Self) -> Self::Output {
return self.div_vec(rhs);
}
}
impl<T: Float + Debug> Debug for Point2<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
f.debug_tuple("")
.field(&self.x)
.field(&self.y)
.finish()
}
}
pub fn min<T: Float>(a: &Point2<T>, b: &Point2<T>) -> Point2<T> {
return Point2::new(T::min(a.x, b.x), T::min(a.y, b.y));
}
pub fn max<T: Float>(a: &Point2<T>, b: &Point2<T>) -> Point2<T> {
return Point2::new(T::max(a.x, b.x), T::max(a.y, b.y));
}
pub fn clamp<T: Float>(v: &Point2<T>, low: &Point2<T>, high: &Point2<T>) -> Point2<T> {
return Point2::new(crate::math_utils::clamp(v.x, low.x, high.x),
crate::math_utils::clamp(v.y, low.y, high.y));
}
pub fn ceil<T: Float>(a: &Point2<T>) -> Point2<T> {
return Point2::new((a.x).ceil(), (a.y).ceil());
}
pub fn floor<T: Float>(a: &Point2<T>) -> Point2<T> {
return Point2::new((a.x).floor(), (a.y).floor());
}