use crate::{InputType, diagram::Vertex};
use num_traits::AsPrimitive;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::fmt;
#[cfg(feature = "cgmath")]
mod cgmath_impl;
#[cfg(feature = "geo")]
mod geo_impl;
#[cfg(test)]
mod tests;
#[cfg(feature = "mint")]
mod mint_impl;
#[cfg(feature = "nalgebra")]
mod impl_nalgebra;
#[cfg(feature = "glam")]
mod glam_impl;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Hash)]
pub struct Point<T: InputType> {
pub x: T,
pub y: T,
}
impl<T: InputType> Point<T> {
#[inline(always)]
pub const fn new(x: T, y: T) -> Self {
Self { x, y }
}
#[inline(always)]
pub fn as_f64(&self) -> [f64; 2] {
[self.x.as_(), self.y.as_()]
}
#[cfg(all(feature = "ce_corruption_check", feature = "geo"))]
#[inline(always)]
pub fn distance_to_point(&self, x: f64, y: f64) -> f64 {
use geo::{Distance, Euclidean, Point};
let p1: Point = Point::new(x, y);
let p2: Point = Point::from(self.as_f64());
Euclidean.distance(p1, p2)
}
#[inline(always)]
pub fn cast<T2: InputType>(self) -> Point<T2>
where
T: AsPrimitive<T2>,
{
Point::<T2> {
x: self.x.as_(),
y: self.y.as_(),
}
}
}
impl<T: InputType> From<Point<T>> for [f64; 2] {
#[inline]
fn from(coordinate: Point<T>) -> Self {
coordinate.as_f64()
}
}
impl<T: InputType> fmt::Debug for Point<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "({:.12},{:.12})", self.x, self.y,)
}
}
impl<T: InputType> From<&Point<T>> for Point<T> {
#[inline]
fn from(point: &Self) -> Self {
*point
}
}
impl<T: InputType> From<&Line<T>> for Line<T> {
#[inline]
fn from(point: &Self) -> Self {
*point
}
}
impl<T: InputType> From<[T; 2]> for Point<T> {
#[inline]
fn from(p: [T; 2]) -> Self {
Self { x: p[0], y: p[1] }
}
}
impl<T: InputType> From<&[T; 2]> for Point<T> {
#[inline]
fn from(c: &[T; 2]) -> Self {
Self { x: c[0], y: c[1] }
}
}
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Line<T: InputType> {
pub start: Point<T>,
pub end: Point<T>,
}
impl<T: InputType, IT: Copy + Into<Point<T>>> From<[IT; 2]> for Line<T> {
#[inline]
fn from(l: [IT; 2]) -> Self {
Self {
start: l[0].into(),
end: l[1].into(),
}
}
}
impl<T: InputType, IT: Copy + Into<Point<T>>> From<&[IT; 2]> for Line<T> {
#[inline(always)]
fn from(l: &[IT; 2]) -> Self {
Self {
start: l[0].into(),
end: l[1].into(),
}
}
}
impl<T: InputType> Line<T> {
#[inline(always)]
pub fn new(start: Point<T>, end: Point<T>) -> Self {
Self { start, end }
}
#[inline(always)]
pub fn cast<T2: InputType>(self) -> Line<T2>
where
T: AsPrimitive<T2>,
{
Line {
start: self.start.cast::<T2>(),
end: self.end.cast::<T2>(),
}
}
}
impl<T: InputType> From<[T; 4]> for Line<T> {
#[inline]
fn from(l: [T; 4]) -> Self {
Self {
start: Point { x: l[0], y: l[1] },
end: Point { x: l[2], y: l[3] },
}
}
}
impl<T: InputType> From<Line<T>> for [T; 4] {
#[inline]
fn from(l: Line<T>) -> Self {
[l.start.x, l.start.y, l.end.x, l.end.y]
}
}
impl<T: InputType> From<&Line<T>> for [T; 4] {
#[inline]
fn from(l: &Line<T>) -> Self {
[l.start.x, l.start.y, l.end.x, l.end.y]
}
}
impl<T: InputType> From<&[T; 4]> for Line<T> {
#[inline]
fn from(l: &[T; 4]) -> Self {
Self {
start: Point { x: l[0], y: l[1] },
end: Point { x: l[2], y: l[3] },
}
}
}
impl From<&Vertex> for [f32; 2] {
#[inline]
fn from(v: &Vertex) -> Self {
[v.x().as_(), v.y().as_()]
}
}
impl From<&Vertex> for [f64; 2] {
#[inline]
fn from(v: &Vertex) -> Self {
[v.x(), v.y()]
}
}