use ::std::convert::Into;
use ::std::ops::Add;
use ::std::ops::AddAssign;
use ::std::ops::Div;
use ::std::ops::DivAssign;
use ::std::ops::Mul;
use ::std::ops::MulAssign;
use ::std::ops::Neg;
use ::std::ops::Rem;
use ::std::ops::Sub;
use ::std::ops::SubAssign;
use ::num_traits::sign::{abs, signum, Signed};
use super::internal::FromClamped;
use super::internal::Num;
use super::NumTuple;
use super::Rect;
use super::Size;
#[derive(Copy, Clone, Debug)]
pub struct Point<N: Num = f32>(pub N, pub N);
impl<N: Num> Point<N> {
pub fn x(&self) -> N {
self.first()
}
pub fn y(&self) -> N {
self.second()
}
pub fn move_x(&mut self, x: N) {
self.0 += x;
}
pub fn move_y(&mut self, y: N) {
self.1 += y;
}
pub fn set_x(&mut self, x: N) {
self.set_first(x);
}
pub fn set_y(&mut self, y: N) {
self.set_second(y);
}
pub fn rect_to(&self, other: Self) -> Rect<N> {
let xy = self.min(other);
let other_xy = self.max(other);
let size = xy.distance_to(other_xy);
Rect(xy, size)
}
pub fn distance_to(&self, other: Self) -> Size<N> {
Size::new(other.first() - self.first(), other.second() - self.second())
}
}
impl<N: Num> NumTuple<N> for Point<N> {
fn new(x: N, y: N) -> Self {
Point(x, y)
}
fn first(&self) -> N {
self.0
}
fn second(&self) -> N {
self.1
}
fn set_first(&mut self, n: N) {
self.0 = n;
}
fn set_second(&mut self, n: N) {
self.1 = n;
}
fn set(&mut self, first: N, second: N) {
self.0 = first;
self.1 = second;
}
fn get(&mut self) -> (N, N) {
(self.0, self.1)
}
}
impl<N: Num> Point<N> {
pub fn to_clamped<T: Num + FromClamped<N>>(&self) -> Point<T> {
NumTuple::new(
T::from_clamped(self.first()),
T::from_clamped(self.second()),
)
}
pub fn to<T: Num + From<N>>(&self) -> Point<T> {
NumTuple::new(T::from(self.first()), T::from(self.second()))
}
}
impl<N: Num + Signed> Point<N> {
pub fn sign(&self) -> Self {
Self(signum(self.0), signum(self.1))
}
pub fn sign_exclusive_dir(&self) -> Self {
let w_abs = abs(self.first());
let h_abs = abs(self.second());
if w_abs > h_abs {
Self(signum(self.first()), N::zero())
} else {
Self(N::zero(), signum(self.second()))
}
}
}
impl Point<f32> {
pub fn overlaps(self, Point(w, h): Self, xy1: Self, xy2: Self) -> bool {
let Point(x_min, y_min) = xy1.min(xy2);
let Point(x_max, y_max) = xy1.max(xy2);
let half_w = w / 2.0;
let x = self.0 + half_w;
let other_half_w = (x_max - x_min) / 2.0;
let other_x = x_min + other_half_w;
let dist_x = (x - other_x).abs();
if dist_x > (half_w + other_half_w) {
return false;
}
let half_h = h / 2.0;
let y = self.1 + half_h;
let other_half_h = (y_max - y_min) / 2.0;
let other_y = y_min + other_half_h;
let dist_y = (y - other_y).abs();
if dist_y > (half_h + other_half_h) {
return false;
}
true
}
pub fn floor(self) -> Self {
Self::new(self.first().floor(), self.second().floor())
}
pub fn ceil(self) -> Self {
Self::new(self.first().ceil(), self.second().ceil())
}
pub fn round(self) -> Self {
Self::new(self.first().round(), self.second().round())
}
}
impl<N: Num> Add<Self> for Point<N> {
type Output = Self;
fn add(self, other: Self) -> Self {
NumTuple::new(self.first() + other.first(), self.second() + other.second())
}
}
impl<N: Num> AddAssign<Self> for Point<N> {
fn add_assign(&mut self, other: Self) {
*self = *self + other;
}
}
impl<N: Num> Sub<Self> for Point<N> {
type Output = Self;
fn sub(self, other: Self) -> Self {
Point::new(self.0 - other.0, self.1 - other.1)
}
}
impl<N: Num> SubAssign<Self> for Point<N> {
fn sub_assign(&mut self, other: Self) {
*self = *self - other;
}
}
impl<N: Num> Mul<Self> for Point<N> {
type Output = Self;
fn mul(self, other: Self) -> Self {
Point::new(self.0 * other.0, self.1 * other.1)
}
}
impl<N: Num> MulAssign<Self> for Point<N> {
fn mul_assign(&mut self, other: Self) {
*self = *self * other;
}
}
impl<N: Num> Div<Self> for Point<N> {
type Output = Self;
fn div(self, other: Self) -> Self {
Point::new(self.0 / other.0, self.1 / other.1)
}
}
impl<N: Num> DivAssign<Self> for Point<N> {
fn div_assign(&mut self, other: Self) {
*self = *self / other;
}
}
impl<N: Num> Rem<Self> for Point<N> {
type Output = Self;
fn rem(self, other: Self) -> Self {
Point::new(self.0 % other.0, self.1 % other.1)
}
}
impl<N: Num> Add<Size<N>> for Point<N> {
type Output = Self;
fn add(self, other: Size<N>) -> Self {
NumTuple::new(self.x() + other.width(), self.y() + other.height())
}
}
impl<N: Num> AddAssign<Size<N>> for Point<N> {
fn add_assign(&mut self, other: Size<N>) {
*self = *self + other;
}
}
impl<N: Num> Sub<Size<N>> for Point<N> {
type Output = Self;
fn sub(self, other: Size<N>) -> Self {
Point::new(self.x() - other.width(), self.y() - other.height())
}
}
impl<N: Num> SubAssign<Size<N>> for Point<N> {
fn sub_assign(&mut self, other: Size<N>) {
*self = *self - other;
}
}
impl<N: Num> Mul<Size<N>> for Point<N> {
type Output = Self;
fn mul(self, other: Size<N>) -> Self {
Point::new(self.x() * other.width(), self.y() * other.height())
}
}
impl<N: Num> MulAssign<Size<N>> for Point<N> {
fn mul_assign(&mut self, other: Size<N>) {
*self = *self * other;
}
}
impl<N: Num> Div<Size<N>> for Point<N> {
type Output = Self;
fn div(self, other: Size<N>) -> Self {
Point::new(self.x() / other.width(), self.y() / other.height())
}
}
impl<N: Num> DivAssign<Size<N>> for Point<N> {
fn div_assign(&mut self, other: Size<N>) {
*self = *self / other;
}
}
impl<N: Num> Mul<N> for Point<N> {
type Output = Self;
fn mul(self, other: N) -> Self {
Point::new(self.0 * other, self.1 * other)
}
}
impl<N: Num> MulAssign<N> for Point<N> {
fn mul_assign(&mut self, other: N) {
*self = *self * other;
}
}
impl<N: Num> Div<N> for Point<N> {
type Output = Self;
fn div(self, other: N) -> Self {
Point::new(self.0 / other, self.1 / other)
}
}
impl<N: Num> DivAssign<N> for Point<N> {
fn div_assign(&mut self, other: N) {
*self = *self / other;
}
}
impl<N: Num + Signed> Neg for Point<N> {
type Output = Self;
fn neg(self) -> Self::Output {
Self(-self.x(), -self.y())
}
}
impl<N: Num> From<(N, N)> for Point<N> {
fn from((x, y): (N, N)) -> Self {
Self::new(x, y)
}
}
impl<N: Num> Into<(N, N)> for Point<N> {
fn into(self) -> (N, N) {
(self.0, self.1)
}
}
impl<N: Num> PartialEq for Point<N> {
fn eq(&self, other: &Self) -> bool {
self.0 == other.0 && self.1 == other.1
}
}