use crate::{
error::InvalidGeometry, geom::ToCells, CellIndex, Resolution, TWO_PI,
};
use std::{boxed::Box, f64::consts::PI};
mod bbox;
mod geometrycollection;
mod line;
mod linestring;
mod multilinestring;
mod multipoint;
mod multipolygon;
mod point;
mod polygon;
mod rect;
mod ring;
mod triangle;
use ring::Ring;
pub use geometrycollection::GeometryCollection;
pub use line::Line;
pub use linestring::LineString;
pub use multilinestring::MultiLineString;
pub use multipoint::MultiPoint;
pub use multipolygon::MultiPolygon;
pub use point::Point;
pub use polygon::Polygon;
pub use rect::Rect;
pub use triangle::Triangle;
#[derive(Clone, Debug, PartialEq)]
#[non_exhaustive]
pub enum Geometry<'a> {
Point(Point),
Line(Line),
LineString(LineString<'a>),
Polygon(Polygon<'a>),
MultiPoint(MultiPoint),
MultiLineString(MultiLineString<'a>),
MultiPolygon(MultiPolygon<'a>),
GeometryCollection(GeometryCollection<'a>),
Rect(Rect<'a>),
Triangle(Triangle<'a>),
}
impl<'a> Geometry<'a> {
pub fn from_radians(
geometry: &'a geo::Geometry<f64>,
) -> Result<Self, InvalidGeometry> {
Ok(match *geometry {
geo::Geometry::Point(point) => {
Self::Point(Point::from_radians(point)?)
}
geo::Geometry::Line(line) => Self::Line(Line::from_radians(line)?),
geo::Geometry::LineString(ref line) => {
Self::LineString(LineString::from_radians(line)?)
}
geo::Geometry::Polygon(ref polygon) => {
Self::Polygon(Polygon::from_radians(polygon)?)
}
geo::Geometry::MultiPoint(ref points) => {
Self::MultiPoint(MultiPoint::from_radians(points)?)
}
geo::Geometry::MultiLineString(ref lines) => {
Self::MultiLineString(MultiLineString::from_radians(lines)?)
}
geo::Geometry::MultiPolygon(ref polygons) => {
Self::MultiPolygon(MultiPolygon::from_radians(polygons)?)
}
geo::Geometry::GeometryCollection(ref geometries) => {
Self::GeometryCollection(GeometryCollection::from_radians(
geometries,
)?)
}
geo::Geometry::Rect(rect) => Self::Rect(Rect::from_radians(rect)?),
geo::Geometry::Triangle(triangle) => {
Self::Triangle(Triangle::from_radians(triangle)?)
}
})
}
pub fn from_degrees(
geometry: geo::Geometry<f64>,
) -> Result<Self, InvalidGeometry> {
Ok(match geometry {
geo::Geometry::Point(point) => {
Self::Point(Point::from_degrees(point)?)
}
geo::Geometry::Line(line) => Self::Line(Line::from_degrees(line)?),
geo::Geometry::LineString(line) => {
Self::LineString(LineString::from_degrees(line)?)
}
geo::Geometry::Polygon(polygon) => {
Self::Polygon(Polygon::from_degrees(polygon)?)
}
geo::Geometry::MultiPoint(points) => {
Self::MultiPoint(MultiPoint::from_degrees(&points)?)
}
geo::Geometry::MultiLineString(lines) => {
Self::MultiLineString(MultiLineString::from_degrees(lines)?)
}
geo::Geometry::MultiPolygon(polygons) => {
Self::MultiPolygon(MultiPolygon::from_degrees(polygons)?)
}
geo::Geometry::GeometryCollection(geometries) => {
Self::GeometryCollection(GeometryCollection::from_degrees(
geometries,
)?)
}
geo::Geometry::Rect(rect) => Self::Rect(Rect::from_degrees(rect)?),
geo::Geometry::Triangle(triangle) => {
Self::Triangle(Triangle::from_degrees(triangle)?)
}
})
}
}
impl From<Geometry<'_>> for geo::Geometry<f64> {
fn from(value: Geometry<'_>) -> Self {
match value {
Geometry::Point(point) => Self::Point(point.into()),
Geometry::Line(line) => Self::Line(line.into()),
Geometry::LineString(line) => Self::LineString(line.into()),
Geometry::Polygon(polygon) => Self::Polygon(polygon.into()),
Geometry::MultiPoint(points) => Self::MultiPoint(points.into()),
Geometry::MultiLineString(lines) => {
Self::MultiLineString(lines.into())
}
Geometry::MultiPolygon(polygons) => {
Self::MultiPolygon(polygons.into())
}
Geometry::GeometryCollection(geometries) => {
Self::GeometryCollection(geometries.into())
}
Geometry::Rect(rect) => Self::Rect(rect.into()),
Geometry::Triangle(triangle) => Self::Triangle(triangle.into()),
}
}
}
impl ToCells for Geometry<'_> {
fn max_cells_count(&self, resolution: Resolution) -> usize {
match *self {
Self::Point(ref point) => point.max_cells_count(resolution),
Self::Line(ref line) => line.max_cells_count(resolution),
Self::LineString(ref line) => line.max_cells_count(resolution),
Self::Polygon(ref polygon) => polygon.max_cells_count(resolution),
Self::MultiPoint(ref points) => points.max_cells_count(resolution),
Self::MultiLineString(ref lines) => {
lines.max_cells_count(resolution)
}
Self::MultiPolygon(ref polygons) => {
polygons.max_cells_count(resolution)
}
Self::GeometryCollection(ref geometries) => {
geometries.max_cells_count(resolution)
}
Self::Rect(ref rect) => rect.max_cells_count(resolution),
Self::Triangle(ref triangle) => {
triangle.max_cells_count(resolution)
}
}
}
fn to_cells(
&self,
resolution: Resolution,
) -> Box<dyn Iterator<Item = CellIndex> + '_> {
match *self {
Self::Point(ref point) => Box::new(point.to_cells(resolution)),
Self::Line(ref line) => Box::new(line.to_cells(resolution)),
Self::LineString(ref line) => Box::new(line.to_cells(resolution)),
Self::Polygon(ref polygon) => {
Box::new(polygon.to_cells(resolution))
}
Self::MultiPoint(ref points) => {
Box::new(points.to_cells(resolution))
}
Self::MultiLineString(ref lines) => {
Box::new(lines.to_cells(resolution))
}
Self::MultiPolygon(ref polygons) => {
Box::new(polygons.to_cells(resolution))
}
Self::GeometryCollection(ref geometries) => {
Box::new(geometries.to_cells(resolution))
}
Self::Rect(ref rect) => Box::new(rect.to_cells(resolution)),
Self::Triangle(ref triangle) => {
Box::new(triangle.to_cells(resolution))
}
}
}
}
fn coord_is_valid(coord: geo::Coord) -> bool {
coord.x.is_finite()
&& coord.y.is_finite()
&& coord.x >= -TWO_PI
&& coord.x <= TWO_PI
&& coord.y >= -PI
&& coord.y <= PI
}