use core::marker::PhantomData;
use geometry_coords::CoordinateScalar;
use geometry_cs::{Cartesian, CoordinateSystem};
use geometry_tag::PointTag;
use geometry_trait::{Geometry, Point as PointTrait, PointMut};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub struct Point<T: CoordinateScalar, const D: usize, Cs: CoordinateSystem = Cartesian> {
coords: [T; D],
_cs: PhantomData<Cs>,
}
#[cfg(feature = "serde")]
impl<T, const D: usize, Cs> serde::Serialize for Point<T, D, Cs>
where
T: CoordinateScalar + serde::Serialize,
Cs: CoordinateSystem,
{
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeTuple;
let mut tup = serializer.serialize_tuple(D)?;
for coord in &self.coords {
tup.serialize_element(coord)?;
}
tup.end()
}
}
#[cfg(feature = "serde")]
impl<'de, T, const D: usize, Cs> serde::Deserialize<'de> for Point<T, D, Cs>
where
T: CoordinateScalar + serde::Deserialize<'de>,
Cs: CoordinateSystem,
{
fn deserialize<De: serde::Deserializer<'de>>(deserializer: De) -> Result<Self, De::Error> {
struct CoordsVisitor<T, const D: usize>(PhantomData<T>);
impl<'de, T, const D: usize> serde::de::Visitor<'de> for CoordsVisitor<T, D>
where
T: CoordinateScalar + serde::Deserialize<'de>,
{
type Value = [T; D];
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "a sequence of {D} coordinates")
}
fn visit_seq<A: serde::de::SeqAccess<'de>>(
self,
mut seq: A,
) -> Result<[T; D], A::Error> {
let mut coords: [T; D] = [T::ZERO; D];
for (i, slot) in coords.iter_mut().enumerate() {
*slot = seq
.next_element::<T>()?
.ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
}
Ok(coords)
}
}
let coords = deserializer.deserialize_tuple(D, CoordsVisitor::<T, D>(PhantomData))?;
Ok(Point {
coords,
_cs: PhantomData,
})
}
}
pub type Point2D<T, Cs = Cartesian> = Point<T, 2, Cs>;
pub type Point3D<T, Cs = Cartesian> = Point<T, 3, Cs>;
impl<T: CoordinateScalar, Cs: CoordinateSystem> Point<T, 1, Cs> {
#[must_use]
pub const fn new(v0: T) -> Self {
Self {
coords: [v0],
_cs: PhantomData,
}
}
}
impl<T: CoordinateScalar, Cs: CoordinateSystem> Point<T, 2, Cs> {
#[must_use]
pub const fn new(v0: T, v1: T) -> Self {
Self {
coords: [v0, v1],
_cs: PhantomData,
}
}
#[inline]
#[must_use]
pub const fn x(&self) -> T {
self.coords[0]
}
#[inline]
#[must_use]
pub const fn y(&self) -> T {
self.coords[1]
}
#[inline]
pub fn set_x(&mut self, value: T) {
self.coords[0] = value;
}
#[inline]
pub fn set_y(&mut self, value: T) {
self.coords[1] = value;
}
}
impl<T: CoordinateScalar, Cs: CoordinateSystem> Point<T, 3, Cs> {
#[must_use]
pub const fn new(v0: T, v1: T, v2: T) -> Self {
Self {
coords: [v0, v1, v2],
_cs: PhantomData,
}
}
#[inline]
#[must_use]
pub const fn x(&self) -> T {
self.coords[0]
}
#[inline]
#[must_use]
pub const fn y(&self) -> T {
self.coords[1]
}
#[inline]
#[must_use]
pub const fn z(&self) -> T {
self.coords[2]
}
#[inline]
pub fn set_x(&mut self, value: T) {
self.coords[0] = value;
}
#[inline]
pub fn set_y(&mut self, value: T) {
self.coords[1] = value;
}
#[inline]
pub fn set_z(&mut self, value: T) {
self.coords[2] = value;
}
}
impl<T: CoordinateScalar, const D: usize, Cs: CoordinateSystem> Default for Point<T, D, Cs> {
#[inline]
fn default() -> Self {
Self {
coords: [T::ZERO; D],
_cs: PhantomData,
}
}
}
impl<T: CoordinateScalar, const D: usize, Cs: CoordinateSystem> Geometry for Point<T, D, Cs> {
type Kind = PointTag;
type Point = Self;
}
impl<T: CoordinateScalar, const D: usize, Cs: CoordinateSystem> PointTrait for Point<T, D, Cs> {
type Scalar = T;
type Cs = Cs;
const DIM: usize = D;
#[inline]
fn get<const DIDX: usize>(&self) -> T {
self.coords[DIDX]
}
}
impl<T: CoordinateScalar, const D: usize, Cs: CoordinateSystem> PointMut for Point<T, D, Cs> {
#[inline]
fn set<const DIDX: usize>(&mut self, value: T) {
self.coords[DIDX] = value;
}
}