Last active
February 21, 2022 22:56
-
-
Save nyurik/cc47c629ead68a46ae1072149f060495 to your computer and use it in GitHub Desktop.
Multidimensional Geo-types with separate Metadata
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use num_traits::{Float, Num, NumCast}; | |
use std::fmt::Debug; | |
trait CoordinateType: Default + Num + Copy + NumCast + PartialOrd + Debug {} | |
impl<T: Default + Num + Copy + NumCast + PartialOrd + Debug> CoordinateType for T {} | |
trait CoordNum: CoordinateType {} | |
impl<T: CoordinateType + Debug> CoordNum for T {} | |
trait CoordFloat: CoordNum + Float {} | |
impl<T: CoordNum + Float> CoordFloat for T {} | |
trait Metadata: Default + Copy + PartialEq + Debug {} | |
impl<M: Default + Copy + PartialEq + Debug> Metadata for M {} | |
#[derive(Clone, Copy, Debug)] | |
struct Coordinate<T: CoordNum, M: Metadata, const D: usize> { | |
coord: [T; D], | |
meta: M, | |
} | |
impl<T: CoordNum, M: Metadata, const D: usize> Coordinate<T, M, D> { | |
pub fn new(coord: [T; D], meta: M) -> Self { | |
Self { coord, meta } | |
} | |
} | |
impl<T: CoordNum, M: Metadata> Coordinate<T, M, 2> { | |
pub fn get_x(&self) -> T { | |
self.coord[0] | |
} | |
pub fn get_y(&self) -> T { | |
self.coord[1] | |
} | |
} | |
impl<T: CoordNum, M: Metadata> Coordinate<T, M, 3> { | |
pub fn get_x(&self) -> T { | |
self.coord[0] | |
} | |
pub fn get_y(&self) -> T { | |
self.coord[1] | |
} | |
pub fn get_z(&self) -> T { | |
self.coord[2] | |
} | |
} | |
impl<T: CoordNum, M: Metadata, const D: usize> Coordinate<T, M, D> { | |
pub fn get_metadata(&self) -> M { | |
self.meta | |
} | |
} | |
impl<T: CoordNum, M: Metadata, const D: usize> Default for Coordinate<T, M, D> { | |
fn default() -> Self { | |
Self { | |
coord: [T::default(); D], | |
meta: M::default(), | |
} | |
} | |
} | |
#[derive(Clone, Copy, Debug)] | |
struct SizedMultipoint<T: CoordNum, M: Metadata, const D: usize, const P: usize> { | |
coords: [Coordinate<T, M, D>; P], | |
} | |
impl<T: CoordNum, M: Metadata, const D: usize, const P: usize> Default | |
for SizedMultipoint<T, M, D, P> | |
{ | |
fn default() -> Self { | |
Self { | |
coords: [Coordinate::<T, M, D>::default(); P], | |
} | |
} | |
} | |
#[derive(Default, Clone, Debug)] | |
struct Multipoint<T: CoordNum, M: Metadata, const D: usize> { | |
coords: Vec<Coordinate<T, M, D>>, | |
} | |
type Point<T, M, const D: usize> = SizedMultipoint<T, M, D, 1>; | |
type Point2D<T> = Point<T, (), 2>; | |
type Point2DM<T, M> = Point<T, M, 2>; | |
type Point3D<T> = Point<T, (), 3>; | |
type Point3DM<T, M> = Point<T, M, 3>; | |
type Line<T, M, const D: usize> = SizedMultipoint<T, M, D, 2>; | |
type Line2D<T> = Line<T, (), 2>; | |
type Line2DM<T, M> = Line<T, M, 2>; | |
type Line3D<T> = Line<T, (), 3>; | |
type Line3DM<T, M> = Line<T, M, 3>; | |
type Triangle<T, M, const D: usize> = SizedMultipoint<T, M, D, 3>; | |
type Triangle2D<T> = Triangle<T, (), 2>; | |
type Triangle2DM<T, M> = Triangle<T, M, 2>; | |
type Triangle3D<T> = Triangle<T, (), 3>; | |
type Triangle3DM<T, M> = Triangle<T, M, 3>; | |
impl<T: CoordNum, M: Metadata, const D: usize> Point<T, M, D> { | |
pub fn get_coord(self) -> Coordinate<T, M, D> { | |
self.coords[0] | |
} | |
} | |
impl<T: CoordNum, M: Metadata, const D: usize> Line<T, M, D> { | |
pub fn get_start(self) -> Coordinate<T, M, D> { | |
self.coords[0] | |
} | |
pub fn get_end(self) -> Coordinate<T, M, D> { | |
self.coords[1] | |
} | |
} | |
impl<T: CoordNum> Point2D<T> { | |
pub fn new(x: T, y: T) -> Self { | |
Self { | |
coords: [Coordinate::new([x, y], ())], | |
} | |
} | |
} | |
impl<T: CoordNum> Line2D<T> { | |
pub fn get_x(self) -> T { | |
self.coords[0].coord[2] | |
} | |
} | |
impl<T: CoordNum> Point3D<T> { | |
pub fn new(x: T, y: T, z: T) -> Self { | |
Self { | |
coords: [Coordinate::new([x, y, z], ())], | |
} | |
} | |
} | |
fn test() { | |
// Create a 2D point | |
let p = Point2D::<i64>::default(); | |
// Create a 3D point with i64 coordinates, and a char metadata | |
let p = Point3DM::<i64, char>::default(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment