use std::convert::TryFrom;
use std::ops::{
Add, AddAssign, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub, SubAssign,
};
use crate::math::Vec2;
#[derive(Copy, Clone, Default, Debug, PartialEq)]
pub struct Point2 {
pub x: f64,
pub y: f64,
}
impl Point2 {
pub const ZERO: Point2 = Point2 { x: 0.0, y: 0.0 };
pub fn new(x: f64, y: f64) -> Self {
Point2 { x, y }
}
pub fn splat(value: f64) -> Self {
Point2 { x: value, y: value }
}
pub fn to_vec2(&self) -> Vec2 {
(*self).into()
}
}
impl Add<Point2> for Point2 {
type Output = Point2;
fn add(self, rhs: Point2) -> Self::Output {
Point2 {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl AddAssign<Point2> for Point2 {
fn add_assign(&mut self, rhs: Point2) {
*self = *self + rhs;
}
}
impl Add<Vec2> for Point2 {
type Output = Point2;
fn add(self, rhs: Vec2) -> Self::Output {
Point2 {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
impl AddAssign<Vec2> for Point2 {
fn add_assign(&mut self, rhs: Vec2) {
*self = *self + rhs;
}
}
impl Sub<Point2> for Point2 {
type Output = Vec2;
fn sub(self, rhs: Point2) -> Self::Output {
Vec2::new(self.x - rhs.x, self.y - rhs.y)
}
}
impl Sub<Vec2> for Point2 {
type Output = Point2;
fn sub(self, rhs: Vec2) -> Self::Output {
Point2 {
x: self.x - rhs.x,
y: self.y - rhs.y,
}
}
}
impl SubAssign<Vec2> for Point2 {
fn sub_assign(&mut self, rhs: Vec2) {
*self = *self - rhs;
}
}
impl Mul<f64> for Point2 {
type Output = Point2;
fn mul(self, rhs: f64) -> Self {
Point2 {
x: self.x * rhs,
y: self.y * rhs,
}
}
}
impl MulAssign<f64> for Point2 {
fn mul_assign(&mut self, rhs: f64) {
*self = *self * rhs;
}
}
impl Mul<Point2> for f64 {
type Output = Point2;
fn mul(self, rhs: Point2) -> Self::Output {
rhs * self
}
}
impl Div<f64> for Point2 {
type Output = Point2;
fn div(self, rhs: f64) -> Self::Output {
let rhs_inverse = 1.0 / rhs;
Point2 {
x: self.x * rhs_inverse,
y: self.y * rhs_inverse,
}
}
}
impl DivAssign<f64> for Point2 {
fn div_assign(&mut self, rhs: f64) {
*self = *self / rhs;
}
}
impl Neg for Point2 {
type Output = Point2;
fn neg(self) -> Self::Output {
Point2 {
x: -self.x,
y: -self.y,
}
}
}
impl From<[f64; 3]> for Point2 {
fn from(s: [f64; 3]) -> Self {
Point2 { x: s[0], y: s[1] }
}
}
impl From<(f64, f64, f64)> for Point2 {
fn from(t: (f64, f64, f64)) -> Self {
Point2 { x: t.0, y: t.1 }
}
}
impl From<Vec2> for Point2 {
fn from(v: Vec2) -> Self {
Point2 { x: v.x, y: v.y }
}
}
impl TryFrom<Vec<f64>> for Point2 {
type Error = &'static str;
fn try_from(v: Vec<f64>) -> Result<Self, Self::Error> {
if v.len() != 2 {
Err("Point2 can only be build from a vector of length 2.")
} else {
Ok(Point2 { x: v[0], y: v[1] })
}
}
}
impl TryFrom<&[f64]> for Point2 {
type Error = &'static str;
fn try_from(s: &[f64]) -> Result<Self, Self::Error> {
if s.len() != 2 {
Err("Point2 can only be build from a slice of length 2.")
} else {
Ok(Point2 { x: s[0], y: s[1] })
}
}
}
impl Index<usize> for Point2 {
type Output = f64;
fn index(&self, index: usize) -> &Self::Output {
match index {
0 => &self.x,
1 => &self.y,
_ => panic!(
"index out of bounds: the len is 2 but the index is {}",
index
),
}
}
}
impl IndexMut<usize> for Point2 {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
match index {
0 => &mut self.x,
1 => &mut self.y,
_ => panic!(
"index out of bounds: the len is 2 but the index is {}",
index
),
}
}
}