use alloc::vec::Vec;
use geometry_coords::CoordinateScalar;
use geometry_cs::{Cartesian, CoordinateSystem};
use geometry_tag::DynamicGeometryTag;
use geometry_trait::Geometry;
use crate::{Linestring, MultiLinestring, MultiPoint, MultiPolygon, Point, Polygon};
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serde",
serde(bound(
serialize = "Scalar: serde::Serialize",
deserialize = "Scalar: serde::Deserialize<'de>"
))
)]
pub enum DynGeometry<Scalar: CoordinateScalar, Cs: CoordinateSystem = Cartesian> {
Point(Point<Scalar, 2, Cs>),
LineString(Linestring<Point<Scalar, 2, Cs>>),
Polygon(Polygon<Point<Scalar, 2, Cs>>),
MultiPoint(MultiPoint<Point<Scalar, 2, Cs>>),
MultiLineString(MultiLinestring<Linestring<Point<Scalar, 2, Cs>>>),
MultiPolygon(MultiPolygon<Polygon<Point<Scalar, 2, Cs>>>),
GeometryCollection(Vec<DynGeometry<Scalar, Cs>>),
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DynKind {
Point,
LineString,
Polygon,
MultiPoint,
MultiLineString,
MultiPolygon,
GeometryCollection,
PolyhedralSurface,
}
impl<Scalar: CoordinateScalar, Cs: CoordinateSystem> Geometry for DynGeometry<Scalar, Cs> {
type Kind = DynamicGeometryTag;
type Point = Point<Scalar, 2, Cs>;
}
impl<Scalar: CoordinateScalar, Cs: CoordinateSystem> DynGeometry<Scalar, Cs> {
#[must_use]
pub fn kind(&self) -> DynKind {
match self {
DynGeometry::Point(_) => DynKind::Point,
DynGeometry::LineString(_) => DynKind::LineString,
DynGeometry::Polygon(_) => DynKind::Polygon,
DynGeometry::MultiPoint(_) => DynKind::MultiPoint,
DynGeometry::MultiLineString(_) => DynKind::MultiLineString,
DynGeometry::MultiPolygon(_) => DynKind::MultiPolygon,
DynGeometry::GeometryCollection(_) => DynKind::GeometryCollection,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Point2D, linestring, polygon};
use alloc::vec;
use geometry_cs::Cartesian;
type S = f64;
type Pt = Point2D<S, Cartesian>;
#[test]
fn kind_round_trip_every_variant() {
let cases: Vec<(DynGeometry<S, Cartesian>, DynKind)> = vec![
(DynGeometry::Point(Pt::new(1.0, 2.0)), DynKind::Point),
(
DynGeometry::LineString(linestring![(0.0, 0.0), (1.0, 1.0)]),
DynKind::LineString,
),
(
DynGeometry::Polygon(polygon![[
(0.0, 0.0),
(1.0, 0.0),
(1.0, 1.0),
(0.0, 1.0),
(0.0, 0.0)
]]),
DynKind::Polygon,
),
(
DynGeometry::MultiPoint(crate::MultiPoint(vec![Pt::new(0.0, 0.0)])),
DynKind::MultiPoint,
),
(
DynGeometry::GeometryCollection(vec![]),
DynKind::GeometryCollection,
),
];
for (g, expected) in cases {
assert_eq!(g.kind(), expected);
}
}
#[test]
fn geometry_collection_can_nest() {
let nested = DynGeometry::<S, Cartesian>::GeometryCollection(vec![
DynGeometry::Point(Pt::new(1.0, 2.0)),
DynGeometry::GeometryCollection(vec![DynGeometry::Point(Pt::new(3.0, 4.0))]),
]);
assert_eq!(
nested,
DynGeometry::GeometryCollection(vec![
DynGeometry::Point(Pt::new(1.0, 2.0)),
DynGeometry::GeometryCollection(vec![DynGeometry::Point(Pt::new(3.0, 4.0))]),
])
);
}
}