use crate::*;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
pub enum VectorGeometryType {
#[default]
Point,
MultiPoint,
LineString,
MultiLineString,
Polygon,
MultiPolygon,
}
impl From<&str> for VectorGeometryType {
fn from(s: &str) -> Self {
match s {
"Point" => VectorGeometryType::Point,
"MultiPoint" => VectorGeometryType::MultiPoint,
"LineString" => VectorGeometryType::LineString,
"MultiLineString" => VectorGeometryType::MultiLineString,
"Polygon" => VectorGeometryType::Polygon,
"MultiPolygon" => VectorGeometryType::MultiPolygon,
_ => panic!("Invalid vector geometry type: {}", s),
}
}
}
pub type VectorMultiPoint<M = MValue> = Vec<VectorPoint<M>>;
pub type VectorLineString<M = MValue> = Vec<VectorPoint<M>>;
pub type VectorMultiLineString<M = MValue> = Vec<VectorLineString<M>>;
pub type VectorPolygon<M = MValue> = Vec<VectorLineString<M>>;
pub type VectorMultiPolygon<M = MValue> = Vec<VectorPolygon<M>>;
#[derive(Clone, Serialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum VectorGeometry<M: Clone + Default = MValue> {
Point(VectorPointGeometry<M>),
MultiPoint(VectorMultiPointGeometry<M>),
LineString(VectorLineStringGeometry<M>),
MultiLineString(VectorMultiLineStringGeometry<M>),
Polygon(VectorPolygonGeometry<M>),
MultiPolygon(VectorMultiPolygonGeometry<M>),
}
impl<M: Clone + Default> VectorGeometry<M> {
pub fn bbox(&self) -> &Option<BBox3D> {
match self {
VectorGeometry::Point(g) => &g.bbox,
VectorGeometry::MultiPoint(g) => &g.bbox,
VectorGeometry::LineString(g) => &g.bbox,
VectorGeometry::MultiLineString(g) => &g.bbox,
VectorGeometry::Polygon(g) => &g.bbox,
VectorGeometry::MultiPolygon(g) => &g.bbox,
}
}
pub fn vec_bbox(&self) -> &Option<BBox3D> {
match self {
VectorGeometry::Point(g) => &g.vec_bbox,
VectorGeometry::MultiPoint(g) => &g.vec_bbox,
VectorGeometry::LineString(g) => &g.vec_bbox,
VectorGeometry::MultiLineString(g) => &g.vec_bbox,
VectorGeometry::Polygon(g) => &g.vec_bbox,
VectorGeometry::MultiPolygon(g) => &g.vec_bbox,
}
}
pub fn point(&self) -> Option<&VectorPoint<M>> {
match self {
VectorGeometry::Point(g) => Some(&g.coordinates),
_ => None,
}
}
pub fn new_point(coordinates: VectorPoint<M>, bbox: Option<BBox3D>) -> Self {
VectorGeometry::Point(VectorPointGeometry {
_type: VectorGeometryType::Point,
is_3d: coordinates.z.is_some(),
coordinates,
bbox,
..Default::default()
})
}
pub fn multipoint(&self) -> Option<&VectorMultiPoint<M>> {
match self {
VectorGeometry::MultiPoint(g) => Some(&g.coordinates),
_ => None,
}
}
pub fn new_multipoint(coordinates: VectorMultiPoint<M>, bbox: Option<BBox3D>) -> Self {
VectorGeometry::MultiPoint(VectorMultiPointGeometry {
_type: VectorGeometryType::MultiPoint,
is_3d: coordinates.iter().any(|point| point.z.is_some()),
coordinates,
bbox,
..Default::default()
})
}
pub fn linestring(&self) -> Option<&VectorLineString<M>> {
match self {
VectorGeometry::LineString(g) => Some(&g.coordinates),
_ => None,
}
}
pub fn new_linestring(coordinates: VectorLineString<M>, bbox: Option<BBox3D>) -> Self {
VectorGeometry::LineString(VectorLineStringGeometry {
_type: VectorGeometryType::LineString,
is_3d: coordinates.iter().any(|point| point.z.is_some()),
coordinates,
bbox,
..Default::default()
})
}
pub fn multilinestring(&self) -> Option<&VectorMultiLineString<M>> {
match self {
VectorGeometry::MultiLineString(g) => Some(&g.coordinates),
_ => None,
}
}
pub fn new_multilinestring(
coordinates: VectorMultiLineString<M>,
bbox: Option<BBox3D>,
) -> Self {
VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
_type: VectorGeometryType::MultiLineString,
is_3d: coordinates.iter().any(|line| line.iter().any(|point| point.z.is_some())),
coordinates,
bbox,
..Default::default()
})
}
pub fn polygon(&self) -> Option<&VectorPolygon<M>> {
match self {
VectorGeometry::Polygon(g) => Some(&g.coordinates),
_ => None,
}
}
pub fn new_polygon(coordinates: VectorPolygon<M>, bbox: Option<BBox3D>) -> Self {
VectorGeometry::Polygon(VectorPolygonGeometry {
_type: VectorGeometryType::Polygon,
is_3d: coordinates.iter().any(|ring| ring.iter().any(|point| point.z.is_some())),
coordinates,
bbox,
..Default::default()
})
}
pub fn multipolygon(&self) -> Option<&VectorMultiPolygon<M>> {
match self {
VectorGeometry::MultiPolygon(g) => Some(&g.coordinates),
_ => None,
}
}
pub fn new_multipolygon(coordinates: VectorMultiPolygon<M>, bbox: Option<BBox3D>) -> Self {
VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
_type: VectorGeometryType::MultiPolygon,
is_3d: coordinates.iter().any(|polygon| {
polygon.iter().any(|ring| ring.iter().any(|point| point.z.is_some()))
}),
coordinates,
bbox,
..Default::default()
})
}
pub fn set_tess(&mut self, tessellation: Vec<f64>) {
match self {
VectorGeometry::Polygon(g) => g.tessellation = Some(tessellation),
VectorGeometry::MultiPolygon(g) => g.tessellation = Some(tessellation),
_ => {}
}
}
pub fn set_indices(&mut self, indices: Vec<u32>) {
match self {
VectorGeometry::Polygon(g) => g.indices = Some(indices),
VectorGeometry::MultiPolygon(g) => g.indices = Some(indices),
_ => {}
}
}
pub fn to_m_geometry(&self) -> VectorGeometry<MValue>
where
M: MValueCompatible,
{
match self {
VectorGeometry::Point(g) => VectorGeometry::Point(VectorPointGeometry {
_type: g._type,
is_3d: g.is_3d,
coordinates: g.coordinates.to_m_value(),
offset: g.offset.clone(),
bbox: g.bbox,
vec_bbox: g.vec_bbox,
..Default::default()
}),
VectorGeometry::MultiPoint(g) => VectorGeometry::MultiPoint(VectorMultiPointGeometry {
_type: g._type,
is_3d: g.is_3d,
coordinates: g.coordinates.iter().map(|point| point.to_m_value()).collect(),
offset: g.offset,
bbox: g.bbox,
vec_bbox: g.vec_bbox,
..Default::default()
}),
VectorGeometry::LineString(g) => VectorGeometry::LineString(VectorLineStringGeometry {
_type: g._type,
is_3d: g.is_3d,
coordinates: g.coordinates.iter().map(|point| point.to_m_value()).collect(),
offset: g.offset,
bbox: g.bbox,
vec_bbox: g.vec_bbox,
..Default::default()
}),
VectorGeometry::MultiLineString(g) => {
VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
_type: g._type,
is_3d: g.is_3d,
coordinates: g
.coordinates
.iter()
.map(|line| line.iter().map(|point| point.to_m_value()).collect())
.collect(),
offset: g.offset.clone(),
bbox: g.bbox,
vec_bbox: g.vec_bbox,
..Default::default()
})
}
VectorGeometry::Polygon(g) => VectorGeometry::Polygon(VectorPolygonGeometry {
_type: g._type,
is_3d: g.is_3d,
coordinates: g
.coordinates
.iter()
.map(|ring| ring.iter().map(|point| point.to_m_value()).collect())
.collect(),
offset: g.offset.clone(),
bbox: g.bbox,
vec_bbox: g.vec_bbox,
..Default::default()
}),
VectorGeometry::MultiPolygon(g) => {
VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
_type: g._type,
is_3d: g.is_3d,
coordinates: g
.coordinates
.iter()
.map(|polygon| {
polygon
.iter()
.map(|ring| ring.iter().map(|point| point.to_m_value()).collect())
.collect()
})
.collect(),
offset: g.offset.clone(),
bbox: g.bbox,
vec_bbox: g.vec_bbox,
..Default::default()
})
}
}
}
}
impl<M: Clone + Default> Default for VectorGeometry<M> {
fn default() -> Self {
VectorGeometry::Point(VectorPointGeometry::default())
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
pub struct VectorBaseGeometry<G = VectorGeometry, O = VectorOffsets> {
#[serde(rename = "type")]
pub _type: VectorGeometryType,
#[serde(rename = "is3D", default)]
pub is_3d: bool,
pub coordinates: G,
#[serde(skip_serializing_if = "Option::is_none")]
pub offset: Option<O>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bbox: Option<BBox3D>,
#[serde(skip)]
pub vec_bbox: Option<BBox3D>,
#[serde(skip_serializing_if = "Option::is_none")]
pub indices: Option<Vec<u32>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tessellation: Option<Vec<f64>>,
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub enum VectorOffsets {
LineOffset(VectorLineOffset),
MultiLineOffset(VectorMultiLineOffset),
PolygonOffset(VectorPolygonOffset),
MultiPolygonOffset(VectorMultiPolygonOffset),
}
impl Default for VectorOffsets {
fn default() -> Self {
VectorOffsets::LineOffset(0.0)
}
}
pub type VectorLineOffset = f64;
pub type VectorMultiLineOffset = Vec<VectorLineOffset>;
pub type VectorPolygonOffset = VectorMultiLineOffset;
pub type VectorMultiPolygonOffset = Vec<VectorPolygonOffset>;
pub type VectorPointGeometry<M = MValue> = VectorBaseGeometry<VectorPoint<M>>;
pub type VectorMultiPointGeometry<M = MValue> =
VectorBaseGeometry<VectorMultiPoint<M>, VectorLineOffset>;
pub type VectorLineStringGeometry<M = MValue> =
VectorBaseGeometry<VectorLineString<M>, VectorLineOffset>;
pub type VectorMultiLineStringGeometry<M = MValue> =
VectorBaseGeometry<VectorMultiLineString<M>, VectorMultiLineOffset>;
pub type VectorPolygonGeometry<M = MValue> =
VectorBaseGeometry<VectorPolygon<M>, VectorPolygonOffset>;
pub type VectorMultiPolygonGeometry<M = MValue> =
VectorBaseGeometry<VectorMultiPolygon<M>, VectorMultiPolygonOffset>;