Skip to content

Instantly share code, notes, and snippets.

@nyurik
Last active February 21, 2022 16:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nyurik/d0e3fe5d5d3b6446d524130081eb7edb to your computer and use it in GitHub Desktop.
Save nyurik/d0e3fe5d5d3b6446d524130081eb7edb to your computer and use it in GitHub Desktop.
Multidimensional Geo-types
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 {}
#[derive(Clone, Copy, Debug)]
struct Coordinate<T: CoordNum, const D: usize> {
coord: [T; D],
}
impl<T: CoordNum, const D: usize> Coordinate<T, D> {
pub fn new(coord: [T; D]) -> Self {
Self { coord }
}
}
impl<T: CoordNum, const D: usize> Default for Coordinate<T, D> {
fn default() -> Self {
Self {
coord: [T::default(); D],
}
}
}
#[derive(Clone, Copy, Debug)]
struct SizedMultipoint<T: CoordNum, const D: usize, const P: usize> {
coords: [Coordinate<T, D>; P],
}
impl<T: CoordNum, const D: usize, const P: usize> Default for SizedMultipoint<T, D, P> {
fn default() -> Self {
Self {
coords: [Coordinate::<T, D>::default(); P],
}
}
}
#[derive(Default, Clone, Debug)]
struct Multipoint<T: CoordNum, const D: usize> {
coords: Vec<Coordinate<T, D>>,
}
type Point<T, const D: usize> = SizedMultipoint<T, D, 1>;
impl<T: CoordNum, const D: usize> Point<T, D> {
pub fn get_vertex(self) -> Coordinate<T, D> {
self.coords[0]
}
}
type Point2D<T> = Point<T, 2>;
impl<T: CoordNum> Point2D<T> {
pub fn get_x(self) -> T {
self.get_vertex().coord[0]
}
pub fn get_y(self) -> T {
self.get_vertex().coord[1]
}
}
type Point3D<T> = Point<T, 3>;
impl<T: CoordNum> Point3D<T> {
pub fn get_z(self) -> T {
self.get_vertex().coord[2]
}
}
type Line<T, const D: usize> = SizedMultipoint<T, D, 2>;
type Line2D<T> = Line<T, 2>;
type Line3D<T> = Line<T, 3>;
type Line3DM<T> = Line<T, 4>;
type Triangle<T, const D: usize> = SizedMultipoint<T, D, 3>;
type Triangle2D<T> = Triangle<T, 2>;
type Triangle3D<T> = Triangle<T, 3>;
type Triangle3DM<T> = Triangle<T, 4>;
impl<T: CoordNum> Line2D<T> {
pub fn get_x(self) -> T {
self.coords[0].coord[2]
}
}
impl<T: CoordNum> Point2D<T> {
pub fn new(x: T, y: T) -> Self {
Self {
coords: [Coordinate::new([x, y])],
}
}
}
impl<T: CoordNum> Point3D<T> {
pub fn new(x: T, y: T, z: T) -> Self {
Self {
coords: [Coordinate::new([x, y, z])],
}
}
}
fn test() {
let p = Line3DM::<i64>::default();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment