From 135b570d80e85cd29194a7d21f88287e4478a1ec Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Thu, 16 Jan 2025 12:42:53 -0800 Subject: [PATCH] more legible geo-types debug output (WKT-ish) FIXES #564 Note: Most of the output is valid WKT, but not all of it is. For example, there is no RECT or TRIANGLE type in standard WKT. And there are certain invalid representations you can make in geo that are not valid WKT, but for a debug output format we still need to print *something* e.g. a polygon with interiors but no exterior: `POLYGON(EMPTY,(1 2,2 4))` --- geo-types/CHANGES.md | 5 + geo-types/src/debug.rs | 466 ++++++++++++++++++ geo-types/src/geometry/coord.rs | 2 +- geo-types/src/geometry/geometry_collection.rs | 2 +- geo-types/src/geometry/line.rs | 2 +- geo-types/src/geometry/line_string.rs | 2 +- geo-types/src/geometry/mod.rs | 2 +- geo-types/src/geometry/multi_line_string.rs | 2 +- geo-types/src/geometry/multi_point.rs | 2 +- geo-types/src/geometry/multi_polygon.rs | 2 +- geo-types/src/geometry/point.rs | 2 +- geo-types/src/geometry/polygon.rs | 2 +- geo-types/src/geometry/rect.rs | 2 +- geo-types/src/geometry/triangle.rs | 2 +- geo-types/src/lib.rs | 2 + 15 files changed, 485 insertions(+), 12 deletions(-) create mode 100644 geo-types/src/debug.rs diff --git a/geo-types/CHANGES.md b/geo-types/CHANGES.md index d2b73a308b..9c25479a30 100644 --- a/geo-types/CHANGES.md +++ b/geo-types/CHANGES.md @@ -1,5 +1,10 @@ # Changes +## UNRELEASED + +- Add more concise Debug output for geometries (like WKT). + NOTE: because geo-types allows some representations which are not supported by standard WKT, not all debug output is valid WKT. Do not attempt to treat debug as a stable format - it's unsuitable for interacting with programmatically. See the [`wkt` crate](https://crates.io/crates/wkt) for that. + ## 0.7.15 - 2025-01-14 - Implement `RTreeObject` for `Triangle`. diff --git a/geo-types/src/debug.rs b/geo-types/src/debug.rs new file mode 100644 index 0000000000..ef42fb977b --- /dev/null +++ b/geo-types/src/debug.rs @@ -0,0 +1,466 @@ +use core::fmt::{Debug, Formatter}; + +use crate::geometry::*; +use crate::CoordNum; + +impl Debug for Coord { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "COORD({x:?} {y:?})", x = self.x, y = self.y) + } +} + +impl Debug for Point { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "POINT({x:?} {y:?})", x = self.x(), y = self.y()) + } +} + +impl Debug for Line { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "LINE")?; + write_coord_seq(f, [self.start, self.end].iter()) + } +} + +impl Debug for LineString { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "LINESTRING")?; + if self.0.is_empty() { + write!(f, " ")?; + } + write_coord_seq(f, self.0.iter())?; + Ok(()) + } +} + +impl Debug for Polygon { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "POLYGON")?; + if self.exterior().0.is_empty() && self.interiors().is_empty() { + write!(f, " ")?; + } + write_polygon_inner(f, self) + } +} + +impl Debug for MultiPoint { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "MULTIPOINT")?; + if self.0.is_empty() { + write!(f, " ")?; + } + write_coord_seq(f, self.0.iter().map(|p| &p.0)) + } +} + +impl Debug for MultiLineString { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "MULTILINESTRING")?; + let mut line_strings = self.0.iter(); + let Some(first) = line_strings.next() else { + return write!(f, " EMPTY"); + }; + write!(f, "(")?; + write_coord_seq(f, first.0.iter())?; + for line_string in line_strings { + write!(f, ",")?; + write_coord_seq(f, line_string.0.iter())?; + } + write!(f, ")") + } +} +impl Debug for MultiPolygon { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "MULTIPOLYGON")?; + let mut polygons = self.0.iter(); + let Some(first) = polygons.next() else { + return write!(f, " EMPTY"); + }; + write!(f, "(")?; + write_polygon_inner(f, first)?; + for polygon in polygons { + write!(f, ",")?; + write_polygon_inner(f, polygon)?; + } + write!(f, ")") + } +} + +impl Debug for Rect { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "RECT")?; + write_coord_seq(f, [self.min(), self.max()].iter()) + } +} + +impl Debug for Triangle { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "TRIANGLE")?; + write_coord_seq(f, [self.0, self.1, self.2].iter()) + } +} + +impl Debug for Geometry { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Geometry::Point(inner) => inner.fmt(f), + Geometry::Line(inner) => inner.fmt(f), + Geometry::LineString(inner) => inner.fmt(f), + Geometry::Polygon(inner) => inner.fmt(f), + Geometry::MultiPoint(inner) => inner.fmt(f), + Geometry::MultiLineString(inner) => inner.fmt(f), + Geometry::MultiPolygon(inner) => inner.fmt(f), + Geometry::GeometryCollection(inner) => inner.fmt(f), + Geometry::Rect(inner) => inner.fmt(f), + Geometry::Triangle(inner) => inner.fmt(f), + } + } +} + +impl Debug for GeometryCollection { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + write!(f, "GEOMETRYCOLLECTION")?; + let mut geometries = self.0.iter(); + let Some(first) = geometries.next() else { + return write!(f, " EMPTY"); + }; + write!(f, "({first:?}")?; + for geometry in geometries { + write!(f, ",{geometry:?}")?; + } + write!(f, ")") + } +} + +fn write_coord_seq<'a, T: CoordNum + 'a>( + f: &mut Formatter<'_>, + mut coords: impl Iterator>, +) -> core::fmt::Result { + let Some(coord) = coords.next() else { + write!(f, "EMPTY")?; + return Ok(()); + }; + write!(f, "({x:?} {y:?}", x = coord.x, y = coord.y)?; + for coord in coords { + write!(f, ",{x:?} {y:?}", x = coord.x, y = coord.y)?; + } + write!(f, ")") +} + +fn write_polygon_inner( + f: &mut Formatter<'_>, + polygon: &Polygon, +) -> core::fmt::Result { + if polygon.exterior().0.is_empty() { + let mut interiors = polygon.interiors().iter(); + let Some(interior) = interiors.next() else { + write!(f, "EMPTY")?; + return Ok(()); + }; + + // Invalid polygon - having interiors but no exterior! + // Still, we should try to print something meaningful. + write!(f, "(EMPTY,")?; + write_coord_seq(f, interior.0.iter())?; + for interior in interiors { + write!(f, ",")?; + write_coord_seq(f, interior.0.iter())?; + } + write!(f, ")")?; + } else { + write!(f, "(")?; + write_coord_seq(f, polygon.exterior().0.iter())?; + for interior in polygon.interiors().iter() { + write!(f, ",")?; + write_coord_seq(f, interior.0.iter())?; + } + write!(f, ")")?; + } + Ok(()) +} + +#[cfg(feature = "std")] +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn float_coord() { + let coord = Coord { x: 1.0, y: 2.0 }; + assert_eq!("COORD(1.0 2.0)", format!("{coord:?}")); + } + #[test] + fn int_coord() { + let coord = Coord { x: 1, y: 2 }; + assert_eq!("COORD(1 2)", format!("{coord:?}")); + } + #[test] + fn float_point() { + let point = Point::new(1.0, 2.0); + assert_eq!("POINT(1.0 2.0)", format!("{point:?}")); + } + #[test] + fn int_point() { + let point = Point::new(1, 2); + assert_eq!("POINT(1 2)", format!("{point:?}")); + } + #[test] + fn line() { + let line_string = Line::new((1, 2), (3, 4)); + assert_eq!("LINE(1 2,3 4)", format!("{line_string:?}")); + } + #[test] + fn line_string() { + let line_string = LineString::new(vec![(1, 2).into(), (3, 4).into()]); + assert_eq!("LINESTRING(1 2,3 4)", format!("{line_string:?}")); + } + #[test] + fn line_string_with_single_element() { + let line_string = LineString::new(vec![(1, 2).into()]); + assert_eq!("LINESTRING(1 2)", format!("{line_string:?}")); + } + #[test] + fn empty_line_string() { + let line_string = LineString::::new(vec![]); + assert_eq!("LINESTRING EMPTY", format!("{line_string:?}")); + } + #[test] + fn polygon_no_holes() { + let polygon = wkt!(POLYGON((1 2,3 4,5 6))); + assert_eq!("POLYGON((1 2,3 4,5 6,1 2))", format!("{polygon:?}")); + } + #[test] + fn polygon_with_hole() { + let polygon = wkt!(POLYGON( + (1 1,10 1,10 10,1 10,1 1), + (3 3,7 3,7 7,3 7,3 3) + )); + assert_eq!( + "POLYGON((1 1,10 1,10 10,1 10,1 1),(3 3,7 3,7 7,3 7,3 3))", + format!("{polygon:?}") + ); + } + #[test] + fn polygon_with_multiple_holes() { + let polygon = wkt!(POLYGON( + (0 0,10 0,10 10,0 10,0 0), + (2 2,4 2,4 4,2 4,2 2), + (6 6,8 6,8 8,6 8,6 6) + )); + assert_eq!( + "POLYGON((0 0,10 0,10 10,0 10,0 0),(2 2,4 2,4 4,2 4,2 2),(6 6,8 6,8 8,6 8,6 6))", + format!("{polygon:?}") + ); + } + #[test] + fn invalid_polygon_interior_but_no_exterior() { + // Not a valid polygon, but we should still have reasonable debug output - note this is *not* valid WKT + let interior = LineString::new(vec![(1, 2).into()]); + let polygon = Polygon::new(LineString::new(vec![]), vec![interior]); + assert_eq!("POLYGON(EMPTY,(1 2))", format!("{polygon:?}")); + } + #[test] + fn empty_polygon() { + let polygon: Polygon = wkt!(POLYGON EMPTY); + assert_eq!("POLYGON EMPTY", format!("{polygon:?}")); + } + #[test] + fn multi_point_empty() { + let multi_point: MultiPoint = wkt!(MULTIPOINT EMPTY); + assert_eq!("MULTIPOINT EMPTY", format!("{multi_point:?}")); + } + #[test] + fn multi_point_one_point() { + let multi_point = wkt!(MULTIPOINT(1 2)); + assert_eq!("MULTIPOINT(1 2)", format!("{multi_point:?}")); + } + #[test] + fn multi_point_three_points() { + let multi_point = wkt!(MULTIPOINT(1 2,3 4,5 6)); + assert_eq!("MULTIPOINT(1 2,3 4,5 6)", format!("{multi_point:?}")); + } + #[test] + fn multilinestring_empty() { + let multi_line_string: MultiLineString = wkt!(MULTILINESTRING EMPTY); + assert_eq!("MULTILINESTRING EMPTY", format!("{multi_line_string:?}")); + } + + #[test] + fn multi_line_string_one_line() { + let multi_line_string = wkt!(MULTILINESTRING((1 2, 3 4, 5 6))); + assert_eq!( + "MULTILINESTRING((1 2,3 4,5 6))", + format!("{multi_line_string:?}") + ); + } + + #[test] + fn multi_line_string_multiple_lines() { + let multi_line_string = wkt!(MULTILINESTRING( + (1 2, 3 4, 5 6), + (7 8, 9 10, 11 12) + )); + assert_eq!( + "MULTILINESTRING((1 2,3 4,5 6),(7 8,9 10,11 12))", + format!("{multi_line_string:?}") + ); + } + + #[test] + fn multi_line_string_multiple_lines_with_empty() { + let multi_line_string = wkt!(MULTILINESTRING( + (1 2, 3 4, 5 6), + EMPTY, + (7 8, 9 10, 11 12) + )); + assert_eq!( + "MULTILINESTRING((1 2,3 4,5 6),EMPTY,(7 8,9 10,11 12))", + format!("{multi_line_string:?}") + ); + } + #[test] + fn multi_polygon_empty() { + let multi_polygon: MultiPolygon = wkt!(MULTIPOLYGON EMPTY); + assert_eq!("MULTIPOLYGON EMPTY", format!("{multi_polygon:?}")); + } + + #[test] + fn multi_polygon_one_polygon() { + let multi_polygon = wkt!(MULTIPOLYGON( + ((1 2, 3 4, 5 6, 1 2)) + )); + assert_eq!( + "MULTIPOLYGON(((1 2,3 4,5 6,1 2)))", + format!("{multi_polygon:?}") + ); + } + + #[test] + fn multi_polygon_multiple_polygons() { + let multi_polygon = wkt!(MULTIPOLYGON( + ((1 2, 3 4, 5 6, 1 2)), + ((7 8, 9 10, 11 12, 7 8)) + )); + assert_eq!( + "MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)))", + format!("{multi_polygon:?}") + ); + } + + #[test] + fn multi_polygon_with_holes() { + let multi_polygon = wkt!(MULTIPOLYGON( + ( + (1 1, 10 1, 10 10, 1 10, 1 1) + ), + ( + (20 20, 30 20, 30 30, 20 30, 20 20), + (22 22, 28 22, 28 28, 22 28, 22 22) + ) + )); + assert_eq!( + "MULTIPOLYGON(((1 1,10 1,10 10,1 10,1 1)),((20 20,30 20,30 30,20 30,20 20),(22 22,28 22,28 28,22 28,22 22)))", + format!("{multi_polygon:?}") + ); + } + #[test] + fn multi_polygon_with_holes_and_empty_polygon() { + let multi_polygon = wkt!(MULTIPOLYGON( + ( + (1 1, 10 1, 10 10, 1 10, 1 1) + ), + EMPTY, + ( + (20 20, 30 20, 30 30, 20 30, 20 20), + (22 22, 28 22, 28 28, 22 28, 22 22) + ) + )); + assert_eq!( + "MULTIPOLYGON(((1 1,10 1,10 10,1 10,1 1)),EMPTY,((20 20,30 20,30 30,20 30,20 20),(22 22,28 22,28 28,22 28,22 22)))", + format!("{multi_polygon:?}") + ); + } + #[test] + fn rect() { + let rect = Rect::new((1, 2), (3, 4)); + assert_eq!("RECT(1 2,3 4)", format!("{rect:?}")); + + let rect = Rect::new((3, 4), (1, 2)); + // output is always (min, max) + assert_eq!("RECT(1 2,3 4)", format!("{rect:?}")); + } + #[test] + fn triangle() { + let rect = Triangle::new((1, 2).into(), (3, 4).into(), (5, 6).into()); + assert_eq!("TRIANGLE(1 2,3 4,5 6)", format!("{rect:?}")); + } + + #[test] + fn geometry() { + let rect = Geometry::Triangle(Triangle::new((1, 2).into(), (3, 4).into(), (5, 6).into())); + assert_eq!("TRIANGLE(1 2,3 4,5 6)", format!("{rect:?}")); + } + + #[test] + fn geometry_collection() { + let rect = Geometry::Triangle(Triangle::new((1, 2).into(), (3, 4).into(), (5, 6).into())); + assert_eq!("TRIANGLE(1 2,3 4,5 6)", format!("{rect:?}")); + } + + #[test] + fn empty_geometry_collection() { + let geometry_collection: GeometryCollection = GeometryCollection::default(); + assert_eq!( + "GEOMETRYCOLLECTION EMPTY", + format!("{geometry_collection:?}") + ); + } + + #[test] + fn geometry_collection_with_mixed_geometries() { + let geometry_collection: GeometryCollection = GeometryCollection::from(vec![ + Geometry::Point(Point::new(1, 2)), + Geometry::Line(Line::new((1, 2), (3, 4))), + Geometry::Polygon(Polygon::new( + LineString::from(vec![(0, 0), (1, 0), (1, 1), (0, 0)]), + vec![], + )), + ]); + + assert_eq!( + "GEOMETRYCOLLECTION(POINT(1 2),LINE(1 2,3 4),POLYGON((0 0,1 0,1 1,0 0)))", + format!("{geometry_collection:?}") + ); + } + + #[test] + fn nested_geometry_collection() { + let inner_collection: GeometryCollection = GeometryCollection::from(vec![ + Geometry::Point(Point::new(5, 6)), + Geometry::LineString(LineString::from(vec![(1, 2), (3, 4)])), + ]); + + let outer_collection: GeometryCollection = GeometryCollection::from(vec![ + Geometry::Point(Point::new(1, 2)), + Geometry::GeometryCollection(inner_collection), + ]); + + assert_eq!( + "GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(POINT(5 6),LINESTRING(1 2,3 4)))", + format!("{outer_collection:?}") + ); + } + + #[test] + fn geometry_collection_with_no_coordinates() { + let geometry_collection: GeometryCollection = GeometryCollection::from(vec![ + Geometry::Point(Point::new(0.0, 0.0)), + Geometry::Polygon(Polygon::new(LineString::new(vec![]), vec![])), + ]); + + assert_eq!( + "GEOMETRYCOLLECTION(POINT(0.0 0.0),POLYGON EMPTY)", + format!("{geometry_collection:?}") + ); + } +} diff --git a/geo-types/src/geometry/coord.rs b/geo-types/src/geometry/coord.rs index d34ece5389..e1c7903c66 100644 --- a/geo-types/src/geometry/coord.rs +++ b/geo-types/src/geometry/coord.rs @@ -23,7 +23,7 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq}; /// (for eg. not `f64::NAN`). /// /// [vector space]: //en.wikipedia.org/wiki/Vector_space -#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash, Default)] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Coord { pub x: T, diff --git a/geo-types/src/geometry/geometry_collection.rs b/geo-types/src/geometry/geometry_collection.rs index a870f1ff70..35ad979a08 100644 --- a/geo-types/src/geometry/geometry_collection.rs +++ b/geo-types/src/geometry/geometry_collection.rs @@ -71,7 +71,7 @@ use core::ops::{Index, IndexMut}; /// println!("{:?}", gc[0]); /// ``` /// -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct GeometryCollection(pub Vec>); diff --git a/geo-types/src/geometry/line.rs b/geo-types/src/geometry/line.rs index 9cbed404fa..799fee2095 100644 --- a/geo-types/src/geometry/line.rs +++ b/geo-types/src/geometry/line.rs @@ -9,7 +9,7 @@ use approx::{AbsDiffEq, RelativeEq}; /// /// The _interior_ and _boundary_ are defined as with a /// `LineString` with the two end points. -#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Copy, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Line { pub start: Coord, diff --git a/geo-types/src/geometry/line_string.rs b/geo-types/src/geometry/line_string.rs index 6a623e3340..85c22ae036 100644 --- a/geo-types/src/geometry/line_string.rs +++ b/geo-types/src/geometry/line_string.rs @@ -132,7 +132,7 @@ use core::ops::{Index, IndexMut}; /// /// ``` -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct LineString(pub Vec>); diff --git a/geo-types/src/geometry/mod.rs b/geo-types/src/geometry/mod.rs index 4faf01753a..53ff3252ae 100644 --- a/geo-types/src/geometry/mod.rs +++ b/geo-types/src/geometry/mod.rs @@ -47,7 +47,7 @@ use core::convert::TryFrom; /// let pn = Point::try_from(pe).unwrap(); /// ``` /// -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum Geometry { Point(Point), diff --git a/geo-types/src/geometry/multi_line_string.rs b/geo-types/src/geometry/multi_line_string.rs index ff19a7c3d4..a12cd2f2cc 100644 --- a/geo-types/src/geometry/multi_line_string.rs +++ b/geo-types/src/geometry/multi_line_string.rs @@ -35,7 +35,7 @@ use rayon::prelude::*; /// the boundaries of both elements. A `MultiLineString` is /// _closed_ if all of its elements are closed. The boundary /// of a closed `MultiLineString` is always empty. -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct MultiLineString(pub Vec>); diff --git a/geo-types/src/geometry/multi_point.rs b/geo-types/src/geometry/multi_point.rs index c596333daf..8ae7e97268 100644 --- a/geo-types/src/geometry/multi_point.rs +++ b/geo-types/src/geometry/multi_point.rs @@ -32,7 +32,7 @@ use rayon::prelude::*; /// println!("Point x = {}, y = {}", point.x(), point.y()); /// } /// ``` -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct MultiPoint(pub Vec>); diff --git a/geo-types/src/geometry/multi_polygon.rs b/geo-types/src/geometry/multi_polygon.rs index 0a68333b13..d23299f732 100644 --- a/geo-types/src/geometry/multi_polygon.rs +++ b/geo-types/src/geometry/multi_polygon.rs @@ -29,7 +29,7 @@ use rayon::prelude::*; /// definition of validity. Note that the validity is not /// enforced, but expected by the operations and /// predicates that operate on it. -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct MultiPolygon(pub Vec>); diff --git a/geo-types/src/geometry/point.rs b/geo-types/src/geometry/point.rs index aa22a33cbb..ae48d7c314 100644 --- a/geo-types/src/geometry/point.rs +++ b/geo-types/src/geometry/point.rs @@ -26,7 +26,7 @@ use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAss /// let c = coord! { x: 10., y: 20. }; /// let p2: Point = c.into(); /// ``` -#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash, Default)] +#[derive(Eq, PartialEq, Clone, Copy, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Point(pub Coord); diff --git a/geo-types/src/geometry/polygon.rs b/geo-types/src/geometry/polygon.rs index 053a0ffa25..8cd4552fc9 100644 --- a/geo-types/src/geometry/polygon.rs +++ b/geo-types/src/geometry/polygon.rs @@ -66,7 +66,7 @@ use approx::{AbsDiffEq, RelativeEq}; /// the first `Coord`. /// /// [`LineString`]: line_string/struct.LineString.html -#[derive(Eq, PartialEq, Clone, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Polygon { exterior: LineString, diff --git a/geo-types/src/geometry/rect.rs b/geo-types/src/geometry/rect.rs index 9d8a7b77de..228fccb213 100644 --- a/geo-types/src/geometry/rect.rs +++ b/geo-types/src/geometry/rect.rs @@ -37,7 +37,7 @@ use approx::{AbsDiffEq, RelativeEq}; /// rect.center() /// ); /// ``` -#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)] +#[derive(Eq, PartialEq, Clone, Copy, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Rect { min: Coord, diff --git a/geo-types/src/geometry/triangle.rs b/geo-types/src/geometry/triangle.rs index d93c48515b..23e0c703f4 100644 --- a/geo-types/src/geometry/triangle.rs +++ b/geo-types/src/geometry/triangle.rs @@ -7,7 +7,7 @@ use approx::{AbsDiffEq, RelativeEq}; /// `Coord`s. The semantics and validity are that of /// the equivalent [`Polygon`]; in addition, the three /// vertices must not be collinear and they must be distinct. -#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] +#[derive(Copy, Clone, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Triangle(pub Coord, pub Coord, pub Coord); diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index a4d12ccc30..7e295ba249 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -149,6 +149,8 @@ mod arbitrary; #[doc(hidden)] pub mod private_utils; +mod debug; + #[doc(hidden)] pub mod _alloc { //! Needed to access these types from `alloc` in macros when the std feature is