LineString(vec![
Coord { x: 1, y: 1, None, None },
Coord { x: 1, y: 1, Some(1), None },
])
LINESTRING ( 1 1, 1 1 1 )
...which doesn't make any sense since the first item has two dimensions but the second item has three dimensions.
We can change the core structures to a different design to enforce all items having the same dimensions:
pub trait Dimension {
fn from_quad(x: f64, y: f64, z: Option<f64>, m: Option<f64>) -> Self;
fn to_quad(&self) -> (f64, f64, Option<f64>, Option<f64>);
}
pub struct Xy(f64, f64);
impl Dimension for Xy {
fn from_quad(x: f64, y: f64, _: Option<f64>, _: Option<f64>) -> Self {
Xy(x, y)
}
fn to_quad(&self) -> (f64, f64, Option<f64>, Option<f64>) {
(self.0, self.1, None, None)
}
}
pub struct Xyz(f64, f64, f64);
impl Dimension for Xyz {
fn from_quad(x: f64, y: f64, z: Option<f64>, _: Option<f64>) -> Self {
Xyz(x, y, z.unwrap())
}
fn to_quad(&self) -> (f64, f64, Option<f64>, Option<f64>) {
(self.0, self.1, Some(self.2), None)
}
}
pub struct Xym(f64, f64, f64);
impl Dimension for Xym {
fn from_quad(x: f64, y: f64, _: Option<f64>, m: Option<f64>) -> Self {
Xym(x, y, m.unwrap())
}
fn to_quad(&self) -> (f64, f64, Option<f64>, Option<f64>) {
(self.0, self.1, None, Some(self.2))
}
}
pub struct Xyzm(f64, f64, f64, f64);
impl Dimension for Xyzm {
fn from_quad(x: f64, y: f64, z: Option<f64>, m: Option<f64>) -> Self {
Xyzm(x, y, z.unwrap(), m.unwrap())
}
fn to_quad(&self) -> (f64, f64, Option<f64>, Option<f64>) {
(self.0, self.1, Some(self.2), Some(self.3))
}
}
// Concrete types
pub enum Point<D: Dimension> {
Empty,
Value(D),
}
pub enum LineString<D: Dimension> {
Empty,
Value(Vec<D>),
}
pub enum Geometry<D: Dimension> {
Empty,
Point(Point<D>),
LineString(LineString<D>),
// ...
GeometryCollection(Vec<Geometry<D>>),
}