pub(crate) mod coord;
pub(crate) mod geometry_collection;
pub(crate) mod line;
pub(crate) mod line_string;
pub(crate) mod multi_line_string;
pub(crate) mod multi_point;
pub(crate) mod multi_polygon;
pub(crate) mod point;
pub(crate) mod polygon;
pub(crate) mod rect;
pub(crate) mod triangle;
#[allow(deprecated)]
pub use coord::{Coord, Coordinate};
pub use geometry_collection::GeometryCollection;
pub use line::Line;
pub use line_string::LineString;
pub use multi_line_string::MultiLineString;
pub use multi_point::MultiPoint;
pub use multi_polygon::MultiPolygon;
pub use point::Point;
pub use polygon::Polygon;
pub use rect::Rect;
pub use triangle::Triangle;
use crate::{CoordNum, Error};
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};
use core::any::type_name;
use core::convert::TryFrom;
#[derive(Eq, PartialEq, Clone, Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Geometry<T: CoordNum = f64> {
Point(Point<T>),
Line(Line<T>),
LineString(LineString<T>),
Polygon(Polygon<T>),
MultiPoint(MultiPoint<T>),
MultiLineString(MultiLineString<T>),
MultiPolygon(MultiPolygon<T>),
GeometryCollection(GeometryCollection<T>),
Rect(Rect<T>),
Triangle(Triangle<T>),
}
impl<T: CoordNum> From<Point<T>> for Geometry<T> {
fn from(x: Point<T>) -> Self {
Self::Point(x)
}
}
impl<T: CoordNum> From<Line<T>> for Geometry<T> {
fn from(x: Line<T>) -> Self {
Self::Line(x)
}
}
impl<T: CoordNum> From<LineString<T>> for Geometry<T> {
fn from(x: LineString<T>) -> Self {
Self::LineString(x)
}
}
impl<T: CoordNum> From<Polygon<T>> for Geometry<T> {
fn from(x: Polygon<T>) -> Self {
Self::Polygon(x)
}
}
impl<T: CoordNum> From<MultiPoint<T>> for Geometry<T> {
fn from(x: MultiPoint<T>) -> Self {
Self::MultiPoint(x)
}
}
impl<T: CoordNum> From<MultiLineString<T>> for Geometry<T> {
fn from(x: MultiLineString<T>) -> Self {
Self::MultiLineString(x)
}
}
impl<T: CoordNum> From<MultiPolygon<T>> for Geometry<T> {
fn from(x: MultiPolygon<T>) -> Self {
Self::MultiPolygon(x)
}
}
impl<T: CoordNum> From<Rect<T>> for Geometry<T> {
fn from(x: Rect<T>) -> Self {
Self::Rect(x)
}
}
impl<T: CoordNum> From<Triangle<T>> for Geometry<T> {
fn from(x: Triangle<T>) -> Self {
Self::Triangle(x)
}
}
impl<T: CoordNum> Geometry<T> {
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<Point>"
)]
pub fn into_point(self) -> Option<Point<T>> {
if let Geometry::Point(x) = self {
Some(x)
} else {
None
}
}
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<LineString>"
)]
pub fn into_line_string(self) -> Option<LineString<T>> {
if let Geometry::LineString(x) = self {
Some(x)
} else {
None
}
}
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<Line>"
)]
pub fn into_line(self) -> Option<Line<T>> {
if let Geometry::Line(x) = self {
Some(x)
} else {
None
}
}
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<Polygon>"
)]
pub fn into_polygon(self) -> Option<Polygon<T>> {
if let Geometry::Polygon(x) = self {
Some(x)
} else {
None
}
}
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<MultiPoint>"
)]
pub fn into_multi_point(self) -> Option<MultiPoint<T>> {
if let Geometry::MultiPoint(x) = self {
Some(x)
} else {
None
}
}
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<MultiLineString>"
)]
pub fn into_multi_line_string(self) -> Option<MultiLineString<T>> {
if let Geometry::MultiLineString(x) = self {
Some(x)
} else {
None
}
}
#[deprecated(
note = "Will be removed in an upcoming version. Switch to std::convert::TryInto<MultiPolygon>"
)]
pub fn into_multi_polygon(self) -> Option<MultiPolygon<T>> {
if let Geometry::MultiPolygon(x) = self {
Some(x)
} else {
None
}
}
}
macro_rules! try_from_geometry_impl {
($($type: ident),+) => {
$(
impl <T: CoordNum> TryFrom<Geometry<T>> for $type<T> {
type Error = Error;
fn try_from(geom: Geometry<T>) -> Result<Self, Self::Error> {
match geom {
Geometry::$type(g) => Ok(g),
other => Err(Error::MismatchedGeometry {
expected: type_name::<$type<T>>(),
found: inner_type_name(other)
})
}
}
}
)+
}
}
try_from_geometry_impl!(
Point,
Line,
LineString,
Polygon,
MultiPoint,
MultiLineString,
MultiPolygon,
Rect,
Triangle
);
fn inner_type_name<T>(geometry: Geometry<T>) -> &'static str
where
T: CoordNum,
{
match geometry {
Geometry::Point(_) => type_name::<Point<T>>(),
Geometry::Line(_) => type_name::<Line<T>>(),
Geometry::LineString(_) => type_name::<LineString<T>>(),
Geometry::Polygon(_) => type_name::<Polygon<T>>(),
Geometry::MultiPoint(_) => type_name::<MultiPoint<T>>(),
Geometry::MultiLineString(_) => type_name::<MultiLineString<T>>(),
Geometry::MultiPolygon(_) => type_name::<MultiPolygon<T>>(),
Geometry::GeometryCollection(_) => type_name::<GeometryCollection<T>>(),
Geometry::Rect(_) => type_name::<Rect<T>>(),
Geometry::Triangle(_) => type_name::<Triangle<T>>(),
}
}
#[cfg(any(feature = "approx", test))]
impl<T> RelativeEq for Geometry<T>
where
T: AbsDiffEq<Epsilon = T> + CoordNum + RelativeEq,
{
#[inline]
fn default_max_relative() -> Self::Epsilon {
T::default_max_relative()
}
fn relative_eq(
&self,
other: &Self,
epsilon: Self::Epsilon,
max_relative: Self::Epsilon,
) -> bool {
match (self, other) {
(Geometry::Point(g1), Geometry::Point(g2)) => g1.relative_eq(g2, epsilon, max_relative),
(Geometry::Line(g1), Geometry::Line(g2)) => g1.relative_eq(g2, epsilon, max_relative),
(Geometry::LineString(g1), Geometry::LineString(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(Geometry::Polygon(g1), Geometry::Polygon(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(Geometry::MultiPoint(g1), Geometry::MultiPoint(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(Geometry::MultiLineString(g1), Geometry::MultiLineString(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(Geometry::MultiPolygon(g1), Geometry::MultiPolygon(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(Geometry::GeometryCollection(g1), Geometry::GeometryCollection(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(Geometry::Rect(g1), Geometry::Rect(g2)) => g1.relative_eq(g2, epsilon, max_relative),
(Geometry::Triangle(g1), Geometry::Triangle(g2)) => {
g1.relative_eq(g2, epsilon, max_relative)
}
(_, _) => false,
}
}
}
#[cfg(any(feature = "approx", test))]
impl<T: AbsDiffEq<Epsilon = T> + CoordNum> AbsDiffEq for Geometry<T> {
type Epsilon = T;
#[inline]
fn default_epsilon() -> Self::Epsilon {
T::default_epsilon()
}
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool {
match (self, other) {
(Geometry::Point(g1), Geometry::Point(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::Line(g1), Geometry::Line(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::LineString(g1), Geometry::LineString(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::Polygon(g1), Geometry::Polygon(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::MultiPoint(g1), Geometry::MultiPoint(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::MultiLineString(g1), Geometry::MultiLineString(g2)) => {
g1.abs_diff_eq(g2, epsilon)
}
(Geometry::MultiPolygon(g1), Geometry::MultiPolygon(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::GeometryCollection(g1), Geometry::GeometryCollection(g2)) => {
g1.abs_diff_eq(g2, epsilon)
}
(Geometry::Rect(g1), Geometry::Rect(g2)) => g1.abs_diff_eq(g2, epsilon),
(Geometry::Triangle(g1), Geometry::Triangle(g2)) => g1.abs_diff_eq(g2, epsilon),
(_, _) => false,
}
}
}