use core::f64;
use serde::de::{self, SeqAccess, Visitor};
use serde::ser::SerializeTuple;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use alloc::fmt;
use alloc::vec::Vec;
use crate::*;
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Axis {
X = 0,
Y = 1,
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct BBox<T = f64> {
pub left: T,
pub bottom: T,
pub right: T,
pub top: T,
}
impl<T> BBox<T> {
pub fn new(left: T, bottom: T, right: T, top: T) -> Self
where
T: Copy,
{
BBox { left, bottom, right, top }
}
pub fn point_overlap<M: MValueCompatible>(&self, point: VectorPoint<M>) -> bool
where
T: Into<f64> + Copy, {
point.x >= self.left.into()
&& point.x <= self.right.into()
&& point.y >= self.bottom.into()
&& point.y <= self.top.into()
}
pub fn merge(&self, other: &BBox<T>) -> BBox<T>
where
T: PartialOrd + Copy,
{
let mut new_bbox = *self;
new_bbox.left = if new_bbox.left < other.left { new_bbox.left } else { other.left };
new_bbox.bottom =
if new_bbox.bottom < other.bottom { new_bbox.bottom } else { other.bottom };
new_bbox.right = if new_bbox.right > other.right { new_bbox.right } else { other.right };
new_bbox.top = if new_bbox.top > other.top { new_bbox.top } else { other.top };
new_bbox
}
pub fn overlap(&self, other: &BBox<T>) -> Option<BBox<T>>
where
T: PartialOrd + Copy,
{
if self.left > other.right
|| self.right < other.left
|| self.bottom > other.top
|| self.top < other.bottom
{
None
} else {
let left = if self.left > other.left { self.left } else { other.left };
let bottom = if self.bottom > other.bottom { self.bottom } else { other.bottom };
let right = if self.right < other.right { self.right } else { other.right };
let top = if self.top < other.top { self.top } else { other.top };
Some(BBox { left, bottom, right, top })
}
}
pub fn clip(&self, axis: Axis, k1: T, k2: T) -> BBox<T>
where
T: PartialOrd + Copy,
{
let mut new_bbox = *self;
if axis == Axis::X {
new_bbox.left = if new_bbox.left > k1 { new_bbox.left } else { k1 };
new_bbox.right = if new_bbox.right < k2 { new_bbox.right } else { k2 };
} else {
new_bbox.bottom = if new_bbox.bottom > k1 { new_bbox.bottom } else { k1 };
new_bbox.top = if new_bbox.top < k2 { new_bbox.top } else { k2 };
}
new_bbox
}
}
impl Default for BBox<f64> {
fn default() -> Self {
BBox::new(f64::INFINITY, f64::INFINITY, -f64::INFINITY, -f64::INFINITY)
}
}
impl BBox<f64> {
pub fn from_point<M: MValueCompatible>(point: &VectorPoint<M>) -> Self {
BBox::new(point.x, point.y, point.x, point.y)
}
pub fn from_linestring<M: MValueCompatible>(line: &VectorLineString<M>) -> Self {
let mut bbox = BBox::from_point(&line[0]);
for point in line {
bbox.extend_from_point(point);
}
bbox
}
pub fn from_multi_linestring<M: MValueCompatible>(lines: &VectorMultiLineString<M>) -> Self {
let mut bbox = BBox::from_point(&lines[0][0]);
for line in lines {
for point in line {
bbox.extend_from_point(point);
}
}
bbox
}
pub fn from_polygon<M: MValueCompatible>(polygon: &VectorPolygon<M>) -> Self {
BBox::<f64>::from_multi_linestring(polygon)
}
pub fn from_multi_polygon<M: MValueCompatible>(polygons: &VectorMultiPolygon<M>) -> Self {
let mut bbox = BBox::from_point(&polygons[0][0][0]);
for polygon in polygons {
for line in polygon {
for point in line {
bbox.extend_from_point(point);
}
}
}
bbox
}
pub fn extend_from_point<M: MValueCompatible>(&mut self, point: &VectorPoint<M>) {
*self = self.merge(&BBox::from_point(point));
}
pub fn from_uv_zoom(u: f64, v: f64, zoom: u8) -> Self {
let division_factor = 2. / (1 << zoom) as f64;
BBox {
left: division_factor * u - 1.0,
bottom: division_factor * v - 1.0,
right: division_factor * (u + 1.0) - 1.0,
top: division_factor * (v + 1.0) - 1.0,
}
}
pub fn from_st_zoom(s: f64, t: f64, zoom: u8) -> Self {
let division_factor = (2. / (1 << zoom) as f64) * 0.5;
BBox {
left: division_factor * s,
bottom: division_factor * t,
right: division_factor * (s + 1.),
top: division_factor * (t + 1.),
}
}
}
impl<T> Serialize for BBox<T>
where
T: Serialize + Copy,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_tuple(4)?;
seq.serialize_element(&self.left)?;
seq.serialize_element(&self.bottom)?;
seq.serialize_element(&self.right)?;
seq.serialize_element(&self.top)?;
seq.end()
}
}
impl<'de, T> Deserialize<'de> for BBox<T>
where
T: Deserialize<'de> + Copy,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct BBoxVisitor<T> {
marker: core::marker::PhantomData<T>,
}
impl<'de, T> Visitor<'de> for BBoxVisitor<T>
where
T: Deserialize<'de> + Copy,
{
type Value = BBox<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence of four numbers")
}
fn visit_seq<V>(self, mut seq: V) -> Result<BBox<T>, V::Error>
where
V: SeqAccess<'de>,
{
let left =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let bottom =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(1, &self))?;
let right =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?;
let top = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(3, &self))?;
Ok(BBox { left, bottom, right, top })
}
}
deserializer.deserialize_tuple(4, BBoxVisitor { marker: core::marker::PhantomData })
}
}
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
pub struct BBox3D<T = f64> {
pub left: T,
pub bottom: T,
pub right: T,
pub top: T,
pub near: T,
pub far: T,
}
impl<T> BBox3D<T> {
pub fn new(left: T, bottom: T, right: T, top: T, near: T, far: T) -> Self
where
T: Copy,
{
BBox3D { left, bottom, right, top, near, far }
}
pub fn point_overlap<M: MValueCompatible>(&self, point: VectorPoint<M>) -> bool
where
T: Into<f64> + Copy, {
let z = point.z.unwrap_or_default();
point.x >= self.left.into()
&& point.x <= self.right.into()
&& point.y >= self.bottom.into()
&& point.y <= self.top.into()
&& z >= self.near.into()
&& z <= self.far.into()
}
pub fn merge(&self, other: &BBox3D<T>) -> BBox3D<T>
where
T: PartialOrd + Copy,
{
let mut new_bbox = *self;
new_bbox.left = if new_bbox.left < other.left { new_bbox.left } else { other.left };
new_bbox.bottom =
if new_bbox.bottom < other.bottom { new_bbox.bottom } else { other.bottom };
new_bbox.right = if new_bbox.right > other.right { new_bbox.right } else { other.right };
new_bbox.top = if new_bbox.top > other.top { new_bbox.top } else { other.top };
new_bbox.near = if new_bbox.near < other.near { new_bbox.near } else { other.near };
new_bbox.far = if new_bbox.far > other.far { new_bbox.far } else { other.far };
new_bbox
}
pub fn overlap(&self, other: &BBox3D<T>) -> Option<BBox3D<T>>
where
T: PartialOrd + Copy,
{
if self.left > other.right
|| self.right < other.left
|| self.bottom > other.top
|| self.top < other.bottom
|| self.near > other.far
|| self.far < other.near
{
None
} else {
let left = if self.left > other.left { self.left } else { other.left };
let bottom = if self.bottom > other.bottom { self.bottom } else { other.bottom };
let right = if self.right < other.right { self.right } else { other.right };
let top = if self.top < other.top { self.top } else { other.top };
let near = if self.near > other.near { self.near } else { other.near };
let far = if self.far < other.far { self.far } else { other.far };
Some(BBox3D { left, bottom, right, top, near, far })
}
}
pub fn clip(&self, axis: Axis, k1: T, k2: T) -> BBox3D<T>
where
T: PartialOrd + Copy,
{
let mut new_bbox = *self;
if axis == Axis::X {
new_bbox.left = if new_bbox.left > k1 { new_bbox.left } else { k1 };
new_bbox.right = if new_bbox.right < k2 { new_bbox.right } else { k2 };
} else {
new_bbox.bottom = if new_bbox.bottom > k1 { new_bbox.bottom } else { k1 };
new_bbox.top = if new_bbox.top < k2 { new_bbox.top } else { k2 };
}
new_bbox
}
}
impl<T> Serialize for BBox3D<T>
where
T: Serialize + Copy,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_tuple(6)?;
seq.serialize_element(&self.left)?;
seq.serialize_element(&self.bottom)?;
seq.serialize_element(&self.right)?;
seq.serialize_element(&self.top)?;
seq.serialize_element(&self.near)?;
seq.serialize_element(&self.far)?;
seq.end()
}
}
impl Default for BBox3D<f64> {
fn default() -> Self {
BBox3D::new(
f64::INFINITY,
f64::INFINITY,
-f64::INFINITY,
-f64::INFINITY,
f64::INFINITY,
-f64::INFINITY,
)
}
}
impl BBox3D<f64> {
pub fn from_point<M: MValueCompatible>(point: &VectorPoint<M>) -> Self {
BBox3D::new(
point.x,
point.y,
point.x,
point.y,
point.z.unwrap_or(f64::INFINITY),
point.z.unwrap_or(-f64::INFINITY),
)
}
pub fn from_linestring<M: MValueCompatible>(line: &VectorLineString<M>) -> Self {
let mut bbox = BBox3D::from_point(&line[0]);
for point in line {
bbox.extend_from_point(point);
}
bbox
}
pub fn from_multi_linestring<M: MValueCompatible>(lines: &VectorMultiLineString<M>) -> Self {
let mut bbox = BBox3D::from_point(&lines[0][0]);
for line in lines {
for point in line {
bbox.extend_from_point(point);
}
}
bbox
}
pub fn from_polygon<M: MValueCompatible>(polygon: &VectorPolygon<M>) -> Self {
BBox3D::<f64>::from_multi_linestring(polygon)
}
pub fn from_multi_polygon<M: MValueCompatible>(polygons: &VectorMultiPolygon<M>) -> Self {
let mut bbox = BBox3D::from_point(&polygons[0][0][0]);
for polygon in polygons {
for line in polygon {
for point in line {
bbox.extend_from_point(point);
}
}
}
bbox
}
pub fn from_bbox(bbox: &BBox) -> Self {
BBox3D::new(bbox.left, bbox.bottom, bbox.right, bbox.top, 0., 0.)
}
pub fn extend_from_point<M: MValueCompatible>(&mut self, point: &VectorPoint<M>) {
*self = self.merge(&BBox3D::from_point(point));
}
pub fn from_uv_zoom(u: f64, v: f64, zoom: u8) -> Self {
let division_factor = 2. / (1 << zoom) as f64;
BBox3D {
left: division_factor * u - 1.0,
bottom: division_factor * v - 1.0,
right: division_factor * (u + 1.0) - 1.0,
top: division_factor * (v + 1.0) - 1.0,
near: f64::INFINITY,
far: -f64::INFINITY,
}
}
pub fn from_st_zoom(s: f64, t: f64, zoom: u8) -> Self {
let division_factor = (2. / (1 << zoom) as f64) * 0.5;
BBox3D {
left: division_factor * s,
bottom: division_factor * t,
right: division_factor * (s + 1.),
top: division_factor * (t + 1.),
near: f64::INFINITY,
far: -f64::INFINITY,
}
}
}
impl From<BBox> for BBox3D<f64> {
fn from(bbox: BBox) -> Self {
BBox3D::from_bbox(&bbox)
}
}
impl<'de, T> Deserialize<'de> for BBox3D<T>
where
T: Deserialize<'de> + Copy,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct BBox3DVisitor<T> {
marker: core::marker::PhantomData<T>,
}
impl<'de, T> Visitor<'de> for BBox3DVisitor<T>
where
T: Deserialize<'de> + Copy,
{
type Value = BBox3D<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence of six numbers")
}
fn visit_seq<V>(self, mut seq: V) -> Result<BBox3D<T>, V::Error>
where
V: SeqAccess<'de>,
{
let left =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(0, &self))?;
let bottom =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(1, &self))?;
let right =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(2, &self))?;
let top = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(3, &self))?;
let near =
seq.next_element()?.ok_or_else(|| de::Error::invalid_length(4, &self))?;
let far = seq.next_element()?.ok_or_else(|| de::Error::invalid_length(5, &self))?;
Ok(BBox3D { left, bottom, right, top, near, far })
}
}
deserializer.deserialize_tuple(6, BBox3DVisitor { marker: core::marker::PhantomData })
}
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq)]
pub enum BBOX {
BBox(BBox),
BBox3D(BBox3D),
}
impl Default for BBOX {
fn default() -> Self {
BBOX::BBox(BBox::default())
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Default)]
pub struct STPoint<M: MValueCompatible = MValue> {
pub face: Face,
pub s: f64,
pub t: f64,
pub z: Option<f64>,
pub m: Option<M>,
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
pub enum GeometryType {
#[default]
Point,
MultiPoint,
LineString,
MultiLineString,
Polygon,
MultiPolygon,
Point3D,
MultiPoint3D,
LineString3D,
MultiLineString3D,
Polygon3D,
MultiPolygon3D,
}
impl From<&str> for GeometryType {
fn from(s: &str) -> Self {
match s {
"Point" => GeometryType::Point,
"MultiPoint" => GeometryType::MultiPoint,
"LineString" => GeometryType::LineString,
"MultiLineString" => GeometryType::MultiLineString,
"Polygon" => GeometryType::Polygon,
"MultiPolygon" => GeometryType::MultiPolygon,
"Point3D" => GeometryType::Point3D,
"MultiPoint3D" => GeometryType::MultiPoint3D,
"LineString3D" => GeometryType::LineString3D,
"MultiLineString3D" => GeometryType::MultiLineString3D,
"Polygon3D" => GeometryType::Polygon3D,
"MultiPolygon3D" => GeometryType::MultiPolygon3D,
_ => unreachable!(),
}
}
}
pub type Point = (f64, f64);
pub type MultiPoint = Vec<Point>;
pub type LineString = Vec<Point>;
pub type MultiLineString = Vec<LineString>;
pub type Polygon = Vec<Vec<Point>>;
pub type MultiPolygon = Vec<Polygon>;
pub type Point3D = (f64, f64, f64);
pub type MultiPoint3D = Vec<Point3D>;
pub type LineString3D = Vec<Point3D>;
pub type MultiLineString3D = Vec<LineString3D>;
pub type Polygon3D = Vec<Vec<Point3D>>;
pub type MultiPolygon3D = Vec<Polygon3D>;
#[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum Geometry<M: MValueCompatible = MValue> {
Point(PointGeometry<M>),
MultiPoint(MultiPointGeometry<M>),
LineString(LineStringGeometry<M>),
MultiLineString(MultiLineStringGeometry<M>),
Polygon(PolygonGeometry<M>),
MultiPolygon(MultiPolygonGeometry<M>),
Point3D(Point3DGeometry<M>),
MultiPoint3D(MultiPoint3DGeometry<M>),
LineString3D(LineString3DGeometry<M>),
MultiLineString3D(MultiLineString3DGeometry<M>),
Polygon3D(Polygon3DGeometry<M>),
MultiPolygon3D(MultiPolygon3DGeometry<M>),
}
impl<M: MValueCompatible> Default for Geometry<M> {
fn default() -> Self {
Geometry::Point(PointGeometry::<M>::default())
}
}
#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Default)]
pub struct BaseGeometry<M = MValue, G = Geometry<M>, B = BBOX> {
#[serde(rename = "type")]
pub _type: GeometryType,
pub coordinates: G,
#[serde(rename = "mValues", skip_serializing_if = "Option::is_none")]
pub m_values: Option<M>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bbox: Option<B>,
}
pub type PointGeometry<M = MValue> = BaseGeometry<M, Point, BBox>;
pub type MultiPointGeometry<M = MValue> = BaseGeometry<LineStringMValues<M>, MultiPoint, BBox>;
pub type LineStringGeometry<M = MValue> = BaseGeometry<LineStringMValues<M>, LineString, BBox>;
pub type MultiLineStringGeometry<M = MValue> =
BaseGeometry<MultiLineStringMValues<M>, MultiLineString, BBox>;
pub type PolygonGeometry<M = MValue> = BaseGeometry<PolygonMValues<M>, Polygon, BBox>;
pub type MultiPolygonGeometry<M = MValue> =
BaseGeometry<MultiPolygonMValues<M>, MultiPolygon, BBox>;
pub type Point3DGeometry<M = MValue> = BaseGeometry<M, Point3D, BBox3D>;
pub type MultiPoint3DGeometry<M = MValue> =
BaseGeometry<LineStringMValues<M>, MultiPoint3D, BBox3D>;
pub type LineString3DGeometry<M = MValue> =
BaseGeometry<LineStringMValues<M>, LineString3D, BBox3D>;
pub type MultiLineString3DGeometry<M = MValue> =
BaseGeometry<MultiLineStringMValues<M>, MultiLineString3D, BBox3D>;
pub type Polygon3DGeometry<M = MValue> = BaseGeometry<PolygonMValues<M>, Polygon3D, BBox3D>;
pub type MultiPolygon3DGeometry<M = MValue> =
BaseGeometry<MultiPolygonMValues<M>, MultiPolygon3D, BBox3D>;
#[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, Deserialize, Debug, PartialEq)]
pub enum VectorGeometry<M: MValueCompatible = MValue> {
Point(VectorPointGeometry<M>),
MultiPoint(VectorMultiPointGeometry<M>),
LineString(VectorLineStringGeometry<M>),
MultiLineString(VectorMultiLineStringGeometry<M>),
Polygon(VectorPolygonGeometry<M>),
MultiPolygon(VectorMultiPolygonGeometry<M>),
}
impl<M: MValueCompatible> VectorGeometry<M> {
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,
}
}
}
impl Default for VectorGeometry {
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")]
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>,
pub indices: Option<Vec<u32>>,
pub tesselation: Option<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>;
#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;
use serde_json::json;
#[test]
fn test_vector_offset() {
let offset = VectorOffsets::default();
assert_eq!(offset, VectorOffsets::LineOffset(0.0));
let offset: VectorOffsets = Default::default();
assert_eq!(offset, VectorOffsets::LineOffset(0.0));
}
#[test]
fn test_bbox() {
let bbox = BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0 };
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0 });
let bbox_str = serde_json::to_string(&bbox).unwrap();
assert_eq!(bbox_str, "[0.0,0.0,1.0,1.0]");
let str_bbox: BBox = serde_json::from_str(&bbox_str).unwrap();
assert_eq!(str_bbox, bbox);
let default_bbox = BBox::default();
assert_eq!(
default_bbox,
BBox {
left: f64::INFINITY,
bottom: f64::INFINITY,
right: -f64::INFINITY,
top: -f64::INFINITY
}
);
let default_bbox_2 = BBOX::default();
assert_eq!(
default_bbox_2,
BBOX::BBox(BBox {
left: f64::INFINITY,
bottom: f64::INFINITY,
right: -f64::INFINITY,
top: -f64::INFINITY
})
);
}
#[test]
fn test_bbox_serialize() {
let bbox = BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0 };
let bbox_str = serde_json::to_string(&bbox).unwrap();
assert_eq!(bbox_str, "[0.0,0.0,1.0,1.0]");
}
#[test]
fn test_bbox_deserialize() {
let bbox_str = "[0.0,0.0,1.0,1.0]";
let bbox: BBox = serde_json::from_str(bbox_str).unwrap();
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0 });
}
#[test]
fn test_bbox_clip() {
let bbox = BBox::new(0., 0., 1., 1.);
let bbox2 = BBox { left: 0.5, bottom: 0., right: 0.75, top: 1. };
assert_eq!(bbox.clip(Axis::X, 0.5, 0.75), bbox2);
let bbox2 = BBox { left: 0., bottom: 0.5, right: 1., top: 0.75 };
assert_eq!(bbox.clip(Axis::Y, 0.5, 0.75), bbox2);
}
#[test]
fn test_bbox_overlap() {
let bbox = BBox::new(0., 0., 1., 1.);
assert!(bbox.point_overlap(VectorPoint::<MValue>::new(0.5, 0.5, None, None)));
assert!(!bbox.point_overlap(VectorPoint::<MValue>::new(2.0, 2.0, None, None)));
let bbox2 = BBox { left: 0.5, bottom: 0.5, right: 1.5, top: 1.5 };
assert_eq!(
bbox.overlap(&bbox2),
Some(BBox { left: 0.5, bottom: 0.5, right: 1.0, top: 1.0 })
);
let bbox3 = BBox { left: 2.0, bottom: 2.0, right: 3.0, top: 3.0 };
assert_eq!(bbox3.overlap(&bbox), None);
}
#[test]
fn test_bbox_merge() {
let bbox = BBox::new(0., 0., 1., 1.);
let bbox2 = BBox { left: 0.5, bottom: 0.5, right: 1.5, top: 1.5 };
assert_eq!(bbox.merge(&bbox2), BBox { left: 0.0, bottom: 0.0, right: 1.5, top: 1.5 });
assert_eq!(bbox2.merge(&bbox), BBox { left: 0.0, bottom: 0.0, right: 1.5, top: 1.5 });
let bbox3 = BBox { left: 2.0, bottom: 2.0, right: 3.0, top: 3.0 };
assert_eq!(bbox.merge(&bbox3), BBox { left: 0.0, bottom: 0.0, right: 3.0, top: 3.0 });
}
#[test]
fn test_bbox_from_st_uv() {
let bbox = BBox::from_st_zoom(0., 0., 0);
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1., top: 1. });
let bbox = BBox::from_st_zoom(1., 0., 1);
assert_eq!(bbox, BBox { left: 0.5, bottom: 0.0, right: 1., top: 0.5 });
let bbox = BBox::from_st_zoom(2., 0., 2);
assert_eq!(bbox, BBox { left: 0.5, bottom: 0.0, right: 0.75, top: 0.25 });
let bbox = BBox::from_uv_zoom(0., 0., 0);
assert_eq!(bbox, BBox { left: -1.0, bottom: -1.0, right: 1., top: 1. });
let bbox = BBox::from_uv_zoom(1., 0., 1);
assert_eq!(bbox, BBox { left: 0., bottom: -1.0, right: 1., top: 0. });
let bbox = BBox::from_uv_zoom(2., 0., 2);
assert_eq!(bbox, BBox { left: 0., bottom: -1.0, right: 0.5, top: -0.5 });
}
#[test]
fn test_bbox_from_point() {
let bbox = BBox::from_point(&VectorPoint::<MValue>::new(0., 0., None, None));
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 0.0, top: 0.0 });
}
#[test]
fn test_bbox_from_linestring() {
let bbox = BBox::from_linestring(&vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(1., 1.5, None, None),
]);
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.5 });
}
#[test]
fn test_bbox_from_multilinestring() {
let bbox = BBox::from_multi_linestring(&vec![vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(1., 1.5, None, None),
]]);
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 1.0, top: 1.5 });
}
#[test]
fn test_bbox_from_polygon() {
let bbox = BBox::from_polygon(&vec![vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(2., 1.5, None, None),
]]);
assert_eq!(bbox, BBox { left: 0.0, bottom: 0.0, right: 2.0, top: 1.5 });
}
#[test]
fn test_bbox_from_multipolygon() {
let bbox = BBox::from_multi_polygon(&vec![
vec![vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(2., 1.5, None, None),
]],
vec![vec![
VectorPoint::new(0., 0., None, None),
VectorPoint::new(-1., 3.5, None, None),
]],
]);
assert_eq!(bbox, BBox { left: -1.0, bottom: 0.0, right: 2.0, top: 3.5 });
}
#[test]
fn test_bbox3d() {
let bbox = BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 1.0 };
assert_eq!(
bbox,
BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 1.0 }
);
let bbox_str = serde_json::to_string(&bbox).unwrap();
assert_eq!(bbox_str, "[0.0,0.0,1.0,1.0,0.0,1.0]");
let str_bbox: BBox3D = serde_json::from_str(&bbox_str).unwrap();
assert_eq!(str_bbox, bbox);
let default_bbox = BBox3D::default();
assert_eq!(
default_bbox,
BBox3D {
left: f64::INFINITY,
bottom: f64::INFINITY,
right: -f64::INFINITY,
top: -f64::INFINITY,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3d_serialize() {
let bbox = BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 1.0 };
let bbox_str = serde_json::to_string(&bbox).unwrap();
assert_eq!(bbox_str, "[0.0,0.0,1.0,1.0,0.0,1.0]");
}
#[test]
fn test_bbox_3_d_deserialize() {
let bbox_str = "[0.0,0.0,1.0,1.0,0.0,1.0]";
let bbox: BBox3D = serde_json::from_str(bbox_str).unwrap();
assert_eq!(
bbox,
BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 1.0 }
);
}
#[test]
fn test_bbox_3_d_overlap() {
let bbox = BBox3D::new(0., 0., 1., 1., 0., 1.);
assert!(bbox.point_overlap(VectorPoint::<MValue>::new(0.5, 0.5, None, None)));
assert!(!bbox.point_overlap(VectorPoint::<MValue>::new(2.0, 2.0, None, None)));
let bbox2 = BBox3D { left: 0.5, bottom: 0.5, right: 1.5, top: 1.5, near: 0.5, far: 1.5 };
assert_eq!(
bbox.overlap(&bbox2),
Some(BBox3D { left: 0.5, bottom: 0.5, right: 1.0, top: 1.0, near: 0.5, far: 1.0 })
);
let bbox3 = BBox3D { left: 2.0, bottom: 2.0, right: 3.0, top: 3.0, near: 2.0, far: 3.0 };
assert_eq!(bbox3.overlap(&bbox), None);
}
#[test]
fn test_bbox_3_d_clip() {
let bbox = BBox3D::new(0., 0., 1., 1., -1., 5.);
let bbox2 = BBox3D { left: 0.5, bottom: 0., right: 0.75, top: 1., near: -1., far: 5. };
assert_eq!(bbox.clip(Axis::X, 0.5, 0.75), bbox2);
let bbox2 = BBox3D { left: 0., bottom: 0.5, right: 1., top: 0.75, near: -1., far: 5. };
assert_eq!(bbox.clip(Axis::Y, 0.5, 0.75), bbox2);
}
#[test]
fn test_bbox_3_d_merge() {
let bbox = BBox3D::new(0., 0., 1., 1., 0., 1.);
let bbox2 = BBox3D { left: 0.5, bottom: 0.5, right: 1.5, top: 1.5, near: 0.5, far: 1.5 };
assert_eq!(
bbox.merge(&bbox2),
BBox3D { left: 0.0, bottom: 0.0, right: 1.5, top: 1.5, near: 0.0, far: 1.5 }
);
assert_eq!(
bbox2.merge(&bbox),
BBox3D { left: 0.0, bottom: 0.0, right: 1.5, top: 1.5, near: 0.0, far: 1.5 }
);
let bbox3 = BBox3D { left: 2.0, bottom: 2.0, right: 3.0, top: 3.0, near: 2.0, far: 3.0 };
assert_eq!(
bbox.merge(&bbox3),
BBox3D { left: 0.0, bottom: 0.0, right: 3.0, top: 3.0, near: 0.0, far: 3.0 }
);
}
#[test]
fn test_bbox_3_d_from_point() {
let bbox = BBox3D::from_point(&VectorPoint::<MValue>::new(0., 0., None, None));
assert_eq!(
bbox,
BBox3D {
left: 0.0,
bottom: 0.0,
right: 0.0,
top: 0.0,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_from_linestring() {
let bbox = BBox3D::from_linestring(&vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(1., 1.5, None, None),
]);
assert_eq!(
bbox,
BBox3D {
left: 0.0,
bottom: 0.0,
right: 1.0,
top: 1.5,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_from_multilinestring() {
let bbox = BBox3D::from_multi_linestring(&vec![vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(1., 1.5, None, None),
]]);
assert_eq!(
bbox,
BBox3D {
left: 0.0,
bottom: 0.0,
right: 1.0,
top: 1.5,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_from_polygon() {
let bbox = BBox3D::from_polygon(&vec![vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(2., 1.5, None, None),
]]);
assert_eq!(
bbox,
BBox3D {
left: 0.0,
bottom: 0.0,
right: 2.0,
top: 1.5,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_from_multipolygon() {
let bbox = BBox3D::from_multi_polygon(&vec![
vec![vec![
VectorPoint::<MValue>::new(0., 0., None, None),
VectorPoint::new(2., 1.5, None, None),
]],
vec![vec![
VectorPoint::new(0., 0., None, None),
VectorPoint::new(-1., 3.5, None, None),
]],
]);
assert_eq!(
bbox,
BBox3D {
left: -1.0,
bottom: 0.0,
right: 2.0,
top: 3.5,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_extend_from_point() {
let mut bbox = BBox3D::default();
bbox.extend_from_point(&VectorPoint::<MValue>::new(20., -4., None, None));
assert_eq!(
bbox,
BBox3D {
left: 20.0,
bottom: -4.0,
right: 20.0,
top: -4.0,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_from_st_uv() {
let bbox = BBox3D::from_st_zoom(0., 0., 0);
assert_eq!(
bbox,
BBox3D {
left: 0.0,
bottom: 0.0,
right: 1.,
top: 1.,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
let bbox = BBox3D::from_st_zoom(1., 0., 1);
assert_eq!(
bbox,
BBox3D {
left: 0.5,
bottom: 0.0,
right: 1.,
top: 0.5,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
let bbox = BBox3D::from_st_zoom(2., 0., 2);
assert_eq!(
bbox,
BBox3D {
left: 0.5,
bottom: 0.0,
right: 0.75,
top: 0.25,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
let bbox = BBox3D::from_uv_zoom(0., 0., 0);
assert_eq!(
bbox,
BBox3D {
left: -1.0,
bottom: -1.0,
right: 1.,
top: 1.,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
let bbox = BBox3D::from_uv_zoom(1., 0., 1);
assert_eq!(
bbox,
BBox3D {
left: 0.,
bottom: -1.0,
right: 1.,
top: 0.,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
let bbox = BBox3D::from_uv_zoom(2., 0., 2);
assert_eq!(
bbox,
BBox3D {
left: 0.,
bottom: -1.0,
right: 0.5,
top: -0.5,
near: f64::INFINITY,
far: -f64::INFINITY
}
);
}
#[test]
fn test_bbox_3_d_from_bbox() {
let bbox: BBox3D = BBox::new(0., 0., 1., 1.).into();
assert_eq!(
bbox,
BBox3D { left: 0.0, bottom: 0.0, right: 1.0, top: 1.0, near: 0.0, far: 0.0 }
);
}
#[test]
fn test_point_geometry() {
let point = PointGeometry {
_type: "Point".into(),
coordinates: (0.0, 0.0),
m_values: None,
bbox: None,
};
assert_eq!(
point,
PointGeometry {
_type: "Point".into(),
coordinates: (0.0, 0.0),
m_values: None,
bbox: None
}
);
let point_str = serde_json::to_string(&point).unwrap();
assert_eq!(point_str, "{\"type\":\"Point\",\"coordinates\":[0.0,0.0]}");
let str_point: PointGeometry = serde_json::from_str(&point_str).unwrap();
assert_eq!(str_point, point);
}
#[test]
fn test_geometry_default() {
let geo = Geometry::default();
assert_eq!(geo, Geometry::Point(PointGeometry::default()));
let default_instance: Geometry = Default::default();
assert_eq!(geo, default_instance);
}
#[test]
fn test_point3d_geometry() {
let point = Point3DGeometry {
_type: "Point3D".into(),
coordinates: (0.0, 0.0, 0.0),
m_values: None,
bbox: Some(BBox3D {
left: 0.0,
bottom: 0.0,
right: 1.0,
top: 1.0,
near: 0.0,
far: 1.0,
}),
};
assert_eq!(
point,
Point3DGeometry {
_type: "Point3D".into(),
coordinates: (0.0, 0.0, 0.0),
m_values: None,
bbox: Some(BBox3D {
left: 0.0,
bottom: 0.0,
right: 1.0,
top: 1.0,
near: 0.0,
far: 1.0
})
}
);
let point_str = serde_json::to_string(&point).unwrap();
assert_eq!(
point_str,
"{\"type\":\"Point3D\",\"coordinates\":[0.0,0.0,0.0],\"bbox\":[0.0,0.0,1.0,1.0,0.0,1.\
0]}"
);
let str_point: Point3DGeometry = serde_json::from_str(&point_str).unwrap();
assert_eq!(str_point, point);
}
#[test]
fn test_line_string_geometry() {
let line = LineStringGeometry {
_type: "LineString".into(),
coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
m_values: None,
bbox: None,
};
assert_eq!(
line,
LineStringGeometry {
_type: "LineString".into(),
coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
m_values: None,
bbox: None
}
);
let line_str = serde_json::to_string(&line).unwrap();
assert_eq!(line_str, "{\"type\":\"LineString\",\"coordinates\":[[0.0,0.0],[1.0,1.0]]}");
let str_line: LineStringGeometry = serde_json::from_str(&line_str).unwrap();
assert_eq!(str_line, line);
}
#[test]
fn test_line_string3d_geometry() {
let line = LineString3DGeometry::<MValue> {
_type: "LineString3D".into(),
coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
m_values: None,
bbox: None,
};
assert_eq!(
line,
LineString3DGeometry {
_type: "LineString3D".into(),
coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
m_values: None,
bbox: None
}
);
let line_str = serde_json::to_string(&line).unwrap();
assert_eq!(
line_str,
"{\"type\":\"LineString3D\",\"coordinates\":[[0.0,0.0,0.0],[1.0,1.0,1.0]]}"
);
let str_line: LineString3DGeometry = serde_json::from_str(&line_str).unwrap();
assert_eq!(str_line, line);
}
#[test]
fn test_multi_point_geometry() {
let multi_point = MultiPointGeometry {
_type: "MultiPoint".into(),
coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
m_values: None,
bbox: None,
};
assert_eq!(
multi_point,
MultiPointGeometry {
_type: "MultiPoint".into(),
coordinates: vec![(0.0, 0.0), (1.0, 1.0)],
m_values: None,
bbox: None
}
);
let multi_point_str = serde_json::to_string(&multi_point).unwrap();
assert_eq!(
multi_point_str,
"{\"type\":\"MultiPoint\",\"coordinates\":[[0.0,0.0],[1.0,1.0]]}"
);
let str_multi_point: MultiPointGeometry = serde_json::from_str(&multi_point_str).unwrap();
assert_eq!(str_multi_point, multi_point);
}
#[test]
fn test_multi_point3d_geometry() {
let multi_point = MultiPoint3DGeometry {
_type: "MultiPoint3D".into(),
coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
m_values: None,
bbox: None,
};
assert_eq!(
multi_point,
MultiPoint3DGeometry {
_type: "MultiPoint3D".into(),
coordinates: vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0)],
m_values: None,
bbox: None
}
);
let multi_point_str = serde_json::to_string(&multi_point).unwrap();
assert_eq!(
multi_point_str,
"{\"type\":\"MultiPoint3D\",\"coordinates\":[[0.0,0.0,0.0],[1.0,1.0,1.0]]}"
);
let str_multi_point: MultiPoint3DGeometry = serde_json::from_str(&multi_point_str).unwrap();
assert_eq!(str_multi_point, multi_point);
}
#[test]
fn test_polygon_geometry() {
let polygon = PolygonGeometry {
_type: "Polygon".into(),
coordinates: vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]],
m_values: None,
bbox: None,
};
assert_eq!(
polygon,
PolygonGeometry {
_type: "Polygon".into(),
coordinates: vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]],
m_values: None,
bbox: None
}
);
let polygon_str = serde_json::to_string(&polygon).unwrap();
assert_eq!(
polygon_str,
"{\"type\":\"Polygon\",\"coordinates\":[[[0.0,0.0],[1.0,1.0],[0.0,1.0]]]}"
);
let str_polygon: PolygonGeometry = serde_json::from_str(&polygon_str).unwrap();
assert_eq!(str_polygon, polygon);
}
#[test]
fn test_polygon3d_geometry() {
let polygon = Polygon3DGeometry {
_type: "Polygon3D".into(),
coordinates: vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]],
m_values: None,
bbox: None,
};
assert_eq!(
polygon,
Polygon3DGeometry {
_type: "Polygon3D".into(),
coordinates: vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]],
m_values: None,
bbox: None
}
);
let polygon_str = serde_json::to_string(&polygon).unwrap();
assert_eq!(
polygon_str,
"{\"type\":\"Polygon3D\",\"coordinates\":[[[0.0,0.0,0.0],[1.0,1.0,1.0],[0.0,1.0,1.\
0]]]}"
);
let str_polygon: Polygon3DGeometry = serde_json::from_str(&polygon_str).unwrap();
assert_eq!(str_polygon, polygon);
}
#[test]
fn test_multi_polygon_geometry() {
let multi_polygon = MultiPolygonGeometry {
_type: "MultiPolygon".into(),
coordinates: vec![vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]]],
m_values: None,
bbox: None,
};
assert_eq!(
multi_polygon,
MultiPolygonGeometry {
_type: "MultiPolygon".into(),
coordinates: vec![vec![vec![(0.0, 0.0), (1.0, 1.0), (0.0, 1.0)]]],
m_values: None,
bbox: None
}
);
let multi_polygon_str = serde_json::to_string(&multi_polygon).unwrap();
assert_eq!(
multi_polygon_str,
"{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0.0,0.0],[1.0,1.0],[0.0,1.0]]]]}"
);
let str_multi_polygon: MultiPolygonGeometry =
serde_json::from_str(&multi_polygon_str).unwrap();
assert_eq!(str_multi_polygon, multi_polygon);
}
#[test]
fn test_multi_polygon3d_geometry() {
let multi_polygon = MultiPolygon3DGeometry {
_type: "MultiPolygon3D".into(),
coordinates: vec![vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]]],
m_values: None,
bbox: None,
};
assert_eq!(
multi_polygon,
MultiPolygon3DGeometry {
_type: "MultiPolygon3D".into(),
coordinates: vec![vec![vec![(0.0, 0.0, 0.0), (1.0, 1.0, 1.0), (0.0, 1.0, 1.0)]]],
m_values: None,
bbox: None
}
);
let multi_polygon_str = serde_json::to_string(&multi_polygon).unwrap();
assert_eq!(
multi_polygon_str,
"{\"type\":\"MultiPolygon3D\",\"coordinates\":[[[[0.0,0.0,0.0],[1.0,1.0,1.0],[0.0,1.0,\
1.0]]]]}"
);
let str_multi_polygon: MultiPolygon3DGeometry =
serde_json::from_str(&multi_polygon_str).unwrap();
assert_eq!(str_multi_polygon, multi_polygon);
}
#[test]
fn test_vector_geometry_default() {
let default = VectorGeometry::default();
assert_eq!(default, VectorGeometry::Point(VectorPointGeometry::default()));
let default_instance: VectorGeometry = Default::default();
assert_eq!(default, default_instance);
}
#[test]
fn test_vector_geometry_type() {
let vgt_point: VectorGeometryType = "Point".into();
assert_eq!(vgt_point, VectorGeometryType::Point);
let vgt_line_string: VectorGeometryType = "LineString".into();
assert_eq!(vgt_line_string, VectorGeometryType::LineString);
let vgt_polygon: VectorGeometryType = "Polygon".into();
assert_eq!(vgt_polygon, VectorGeometryType::Polygon);
let vgt_multi_point: VectorGeometryType = "MultiPoint".into();
assert_eq!(vgt_multi_point, VectorGeometryType::MultiPoint);
let vgt_multi_line_string: VectorGeometryType = "MultiLineString".into();
assert_eq!(vgt_multi_line_string, VectorGeometryType::MultiLineString);
let vgt_multi_polygon: VectorGeometryType = "MultiPolygon".into();
assert_eq!(vgt_multi_polygon, VectorGeometryType::MultiPolygon);
let default = VectorGeometryType::default();
assert_eq!(default, VectorGeometryType::Point);
let default_instance: VectorGeometryType = Default::default();
assert_eq!(default, default_instance);
}
#[test]
#[should_panic(expected = "Invalid vector geometry type")]
fn test_invalid_vector_geometry_type() {
let _ = VectorGeometryType::from("Pant");
}
#[test]
fn test_vector_geometry_bbox() {
let vgt_point: VectorGeometry = VectorGeometry::Point(VectorPointGeometry {
_type: "Point".into(),
coordinates: VectorPoint { x: 0.0, y: 1.0, z: Some(2.0), m: None, t: None },
bbox: None,
is_3d: true,
offset: None,
vec_bbox: Some(BBox3D {
left: 0.0,
bottom: 1.0,
right: 0.0,
top: 1.0,
near: 2.0,
far: 2.0,
}),
indices: None,
tesselation: None,
});
assert_eq!(vgt_point.vec_bbox().unwrap(), BBox3D::new(0.0, 1.0, 0.0, 1.0, 2.0, 2.0));
let vgt_multi_point: VectorGeometry =
VectorGeometry::MultiPoint(VectorMultiPointGeometry {
_type: "MultiPoint".into(),
coordinates: vec![VectorPoint { x: 0.0, y: 1.0, z: Some(2.0), m: None, t: None }],
bbox: None,
is_3d: true,
offset: None,
vec_bbox: Some(BBox3D {
left: 0.0,
bottom: 1.0,
right: 0.0,
top: 1.0,
near: 2.0,
far: 2.0,
}),
indices: None,
tesselation: None,
});
assert_eq!(vgt_multi_point.vec_bbox().unwrap(), BBox3D::new(0.0, 1.0, 0.0, 1.0, 2.0, 2.0));
let vgt_line_string: VectorGeometry =
VectorGeometry::LineString(VectorLineStringGeometry {
_type: "LineString".into(),
coordinates: vec![VectorPoint { x: 0.0, y: 1.0, z: Some(2.0), m: None, t: None }],
bbox: None,
is_3d: true,
offset: None,
vec_bbox: Some(BBox3D {
left: 0.0,
bottom: 1.0,
right: 0.0,
top: 1.0,
near: 2.0,
far: 2.0,
}),
indices: None,
tesselation: None,
});
assert_eq!(vgt_line_string.vec_bbox().unwrap(), BBox3D::new(0.0, 1.0, 0.0, 1.0, 2.0, 2.0));
let vgt_multi_line_string: VectorGeometry =
VectorGeometry::MultiLineString(VectorMultiLineStringGeometry {
_type: "MultiLineString".into(),
coordinates: vec![vec![VectorPoint {
x: 0.0,
y: 1.0,
z: Some(2.0),
m: None,
t: None,
}]],
bbox: None,
is_3d: true,
offset: None,
vec_bbox: Some(BBox3D {
left: 0.0,
bottom: 1.0,
right: 0.0,
top: 1.0,
near: 2.0,
far: 2.0,
}),
indices: None,
tesselation: None,
});
assert_eq!(
vgt_multi_line_string.vec_bbox().unwrap(),
BBox3D::new(0.0, 1.0, 0.0, 1.0, 2.0, 2.0)
);
let vgt_polygon: VectorGeometry = VectorGeometry::Polygon(VectorPolygonGeometry {
_type: "Polygon".into(),
coordinates: vec![vec![VectorPoint { x: 0.0, y: 1.0, z: Some(2.0), m: None, t: None }]],
bbox: None,
is_3d: true,
offset: None,
vec_bbox: Some(BBox3D {
left: 0.0,
bottom: 1.0,
right: 0.0,
top: 1.0,
near: 2.0,
far: 2.0,
}),
indices: None,
tesselation: None,
});
assert_eq!(vgt_polygon.vec_bbox().unwrap(), BBox3D::new(0.0, 1.0, 0.0, 1.0, 2.0, 2.0));
let vgt_multi_polygon: VectorGeometry =
VectorGeometry::MultiPolygon(VectorMultiPolygonGeometry {
_type: "MultiPolygon".into(),
coordinates: vec![vec![vec![VectorPoint {
x: 0.0,
y: 1.0,
z: Some(2.0),
m: None,
t: None,
}]]],
bbox: None,
is_3d: true,
offset: None,
vec_bbox: Some(BBox3D {
left: 0.0,
bottom: 1.0,
right: 0.0,
top: 1.0,
near: 2.0,
far: 2.0,
}),
indices: None,
tesselation: None,
});
assert_eq!(
vgt_multi_polygon.vec_bbox().unwrap(),
BBox3D::new(0.0, 1.0, 0.0, 1.0, 2.0, 2.0)
);
}
#[test]
fn from_string() {
let geo_str = json!({
"type": "Point",
"coordinates": [0, 0],
})
.to_string();
let _feature: Geometry = serde_json::from_str(&geo_str).unwrap();
let feature_str = json!({
"type": "Feature",
"properties": { "a": 1 },
"geometry": {
"type": "Point",
"coordinates": [0, 0],
}
})
.to_string();
let _feature: Feature = serde_json::from_str(&feature_str).unwrap();
let json_string = r#"{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "a": 1 },
"geometry": {
"type": "Point",
"coordinates": [0, 0]
}
},
{
"type": "Feature",
"properties": { "b": 2 },
"geometry": {
"type": "Point3D",
"coordinates": [45, 45, 1]
}
},
{
"type": "Feature",
"properties": { "c": 3 },
"geometry": {
"type": "MultiPoint",
"coordinates": [
[-45, -45],
[-45, 45]
]
}
},
{
"type": "Feature",
"properties": { "d": 4 },
"geometry": {
"type": "MultiPoint3D",
"coordinates": [
[45, -45, 1],
[-180, 20, 2]
]
}
}
]
}"#;
let data: FeatureCollection = serde_json::from_str(json_string).unwrap();
assert_eq!(data.features.len(), 4);
let data2: JSONCollection = serde_json::from_str(json_string).unwrap();
if let JSONCollection::FeatureCollection(fc) = data2 {
assert_eq!(fc.features.len(), 4);
if let WMFeature::Feature(first_feature) = &fc.features[0] {
assert_eq!(first_feature.id, None);
assert_eq!(first_feature._type, "Feature");
assert_eq!(
first_feature.geometry,
Geometry::Point(PointGeometry {
_type: "Point".into(),
coordinates: (0.0, 0.0),
..Default::default()
})
);
} else {
panic!("Expected Feature");
}
} else {
panic!("Expected FeatureCollection");
}
}
}