use crate::coordinates::{ Distance, Neighbors };
use serde::{ Deserialize, Serialize };
use std::fmt::Debug;
use std::hash::Hash;
use std::marker::PhantomData;
#[derive(Debug)]
pub struct Square;
#[ derive( Debug, Clone, Copy, PartialEq, Eq, Hash, Default ) ]
pub struct FourConnected;
#[ derive( Debug, Clone, Copy, PartialEq, Eq, Hash, Default ) ]
pub struct EightConnected;
#[ derive( Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash, Default ) ]
pub struct Coordinate< Connectivity >
{
pub x : i32,
pub y : i32,
#[ serde( skip ) ]
pub _marker : PhantomData< Connectivity >,
}
impl< Connectivity > Coordinate< Connectivity >
{
pub const fn new( x : i32, y : i32 ) -> Self
{
Self
{
x,
y,
_marker : PhantomData,
}
}
}
impl< Connectivity > From< ( i32, i32 ) > for Coordinate< Connectivity >
{
fn from( ( x, y ) : ( i32, i32 ) ) -> Self
{
Self::new( x, y )
}
}
impl< Connectivity > From< [ i32; 2 ] > for Coordinate< Connectivity >
{
fn from( [ x, y ] : [ i32; 2 ] ) -> Self
{
Self::new( x, y )
}
}
impl< Connectivity > Into< ( i32, i32 ) > for Coordinate< Connectivity >
{
fn into( self ) -> ( i32, i32 )
{
( self.x, self.y )
}
}
impl< Connectivity > std::ops::Add for Coordinate< Connectivity >
{
type Output = Self;
fn add( self, rhs : Self ) -> Self::Output
{
Self::new( self.x + rhs.x, self.y + rhs.y )
}
}
impl< Connectivity > std::ops::Sub for Coordinate< Connectivity >
{
type Output = Self;
fn sub( self, rhs : Self ) -> Self::Output
{
Self::new( self.x - rhs.x, self.y - rhs.y )
}
}
impl< Connectivity > std::ops::Mul< i32 > for Coordinate< Connectivity >
{
type Output = Self;
fn mul( self, rhs : i32 ) -> Self::Output
{
Self::new( self.x * rhs, self.y * rhs )
}
}
impl< Connectivity > std::ops::Div< i32 > for Coordinate< Connectivity >
{
type Output = Self;
fn div( self, rhs : i32 ) -> Self::Output
{
Self::new( self.x / rhs, self.y / rhs )
}
}
impl Distance for Coordinate< FourConnected >
{
fn distance( &self, other : &Self ) -> u32
{
( ( self.x - other.x ).abs() + ( self.y - other.y ).abs() ) as u32
}
}
impl Distance for Coordinate< EightConnected >
{
fn distance( &self, other : &Self ) -> u32
{
( ( self.x - other.x ).abs().max( ( self.y - other.y ).abs() ) ) as u32
}
}
impl Neighbors for Coordinate< FourConnected >
{
fn neighbors( &self ) -> Vec< Self >
{
vec!
[
Self::new( self.x + 1, self.y ), Self::new( self.x - 1, self.y ), Self::new( self.x, self.y + 1 ), Self::new( self.x, self.y - 1 ), ]
}
}
impl Neighbors for Coordinate< EightConnected >
{
fn neighbors( &self ) -> Vec< Self >
{
vec!
[
Self::new( self.x + 1, self.y ), Self::new( self.x - 1, self.y ), Self::new( self.x, self.y + 1 ), Self::new( self.x, self.y - 1 ), Self::new( self.x + 1, self.y + 1 ), Self::new( self.x - 1, self.y + 1 ), Self::new( self.x + 1, self.y - 1 ), Self::new( self.x - 1, self.y - 1 ), ]
}
}
pub type SquareCoord4 = Coordinate< FourConnected >;
pub type SquareCoord8 = Coordinate< EightConnected >;