1use core::fmt::{Debug, Formatter};
2
3use crate::geometry::*;
4use crate::CoordNum;
5
6impl<T: CoordNum> Debug for Coord<T> {
7 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
8 write!(f, "COORD({x:?} {y:?})", x = self.x, y = self.y)
9 }
10}
11
12impl<T: CoordNum> Debug for Point<T> {
13 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
14 write!(f, "POINT({x:?} {y:?})", x = self.x(), y = self.y())
15 }
16}
17
18impl<T: CoordNum> Debug for Line<T> {
19 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
20 write!(f, "LINE")?;
21 write_coord_seq(f, [self.start, self.end].iter())
22 }
23}
24
25impl<T: CoordNum> Debug for LineString<T> {
26 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
27 write!(f, "LINESTRING")?;
28 if self.0.is_empty() {
29 write!(f, " ")?;
30 }
31 write_coord_seq(f, self.0.iter())?;
32 Ok(())
33 }
34}
35
36impl<T: CoordNum> Debug for Polygon<T> {
37 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
38 write!(f, "POLYGON")?;
39 if self.exterior().0.is_empty() && self.interiors().is_empty() {
40 write!(f, " ")?;
41 }
42 write_polygon_inner(f, self)
43 }
44}
45
46impl<T: CoordNum> Debug for MultiPoint<T> {
47 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
48 write!(f, "MULTIPOINT")?;
49 if self.0.is_empty() {
50 write!(f, " ")?;
51 }
52 write_coord_seq(f, self.0.iter().map(|p| &p.0))
53 }
54}
55
56impl<T: CoordNum> Debug for MultiLineString<T> {
57 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
58 write!(f, "MULTILINESTRING")?;
59 let mut line_strings = self.0.iter();
60 let Some(first) = line_strings.next() else {
61 return write!(f, " EMPTY");
62 };
63 write!(f, "(")?;
64 write_coord_seq(f, first.0.iter())?;
65 for line_string in line_strings {
66 write!(f, ",")?;
67 write_coord_seq(f, line_string.0.iter())?;
68 }
69 write!(f, ")")
70 }
71}
72impl<T: CoordNum> Debug for MultiPolygon<T> {
73 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
74 write!(f, "MULTIPOLYGON")?;
75 let mut polygons = self.0.iter();
76 let Some(first) = polygons.next() else {
77 return write!(f, " EMPTY");
78 };
79 write!(f, "(")?;
80 write_polygon_inner(f, first)?;
81 for polygon in polygons {
82 write!(f, ",")?;
83 write_polygon_inner(f, polygon)?;
84 }
85 write!(f, ")")
86 }
87}
88
89impl<T: CoordNum> Debug for Rect<T> {
90 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
91 write!(f, "RECT")?;
92 write_coord_seq(f, [self.min(), self.max()].iter())
93 }
94}
95
96impl<T: CoordNum> Debug for Triangle<T> {
97 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
98 write!(f, "TRIANGLE")?;
99 write_coord_seq(f, [self.0, self.1, self.2].iter())
100 }
101}
102
103impl<T: CoordNum> Debug for Geometry<T> {
104 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
105 match self {
106 Geometry::Point(inner) => inner.fmt(f),
107 Geometry::Line(inner) => inner.fmt(f),
108 Geometry::LineString(inner) => inner.fmt(f),
109 Geometry::Polygon(inner) => inner.fmt(f),
110 Geometry::MultiPoint(inner) => inner.fmt(f),
111 Geometry::MultiLineString(inner) => inner.fmt(f),
112 Geometry::MultiPolygon(inner) => inner.fmt(f),
113 Geometry::GeometryCollection(inner) => inner.fmt(f),
114 Geometry::Rect(inner) => inner.fmt(f),
115 Geometry::Triangle(inner) => inner.fmt(f),
116 }
117 }
118}
119
120impl<T: CoordNum> Debug for GeometryCollection<T> {
121 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
122 write!(f, "GEOMETRYCOLLECTION")?;
123 let mut geometries = self.0.iter();
124 let Some(first) = geometries.next() else {
125 return write!(f, " EMPTY");
126 };
127 write!(f, "({first:?}")?;
128 for geometry in geometries {
129 write!(f, ",{geometry:?}")?;
130 }
131 write!(f, ")")
132 }
133}
134
135fn write_coord_seq<'a, T: CoordNum + 'a>(
136 f: &mut Formatter<'_>,
137 mut coords: impl Iterator<Item = &'a Coord<T>>,
138) -> core::fmt::Result {
139 let Some(coord) = coords.next() else {
140 write!(f, "EMPTY")?;
141 return Ok(());
142 };
143 write!(f, "({x:?} {y:?}", x = coord.x, y = coord.y)?;
144 for coord in coords {
145 write!(f, ",{x:?} {y:?}", x = coord.x, y = coord.y)?;
146 }
147 write!(f, ")")
148}
149
150fn write_polygon_inner<T: CoordNum>(
151 f: &mut Formatter<'_>,
152 polygon: &Polygon<T>,
153) -> core::fmt::Result {
154 if polygon.exterior().0.is_empty() {
155 let mut interiors = polygon.interiors().iter();
156 let Some(interior) = interiors.next() else {
157 write!(f, "EMPTY")?;
158 return Ok(());
159 };
160
161 write!(f, "(EMPTY,")?;
164 write_coord_seq(f, interior.0.iter())?;
165 for interior in interiors {
166 write!(f, ",")?;
167 write_coord_seq(f, interior.0.iter())?;
168 }
169 write!(f, ")")?;
170 } else {
171 write!(f, "(")?;
172 write_coord_seq(f, polygon.exterior().0.iter())?;
173 for interior in polygon.interiors().iter() {
174 write!(f, ",")?;
175 write_coord_seq(f, interior.0.iter())?;
176 }
177 write!(f, ")")?;
178 }
179 Ok(())
180}
181
182#[cfg(feature = "std")]
183#[cfg(test)]
184mod tests {
185 use super::*;
186
187 #[test]
188 fn float_coord() {
189 let coord = Coord { x: 1.0, y: 2.0 };
190 assert_eq!("COORD(1.0 2.0)", format!("{coord:?}"));
191 }
192 #[test]
193 fn int_coord() {
194 let coord = Coord { x: 1, y: 2 };
195 assert_eq!("COORD(1 2)", format!("{coord:?}"));
196 }
197 #[test]
198 fn float_point() {
199 let point = Point::new(1.0, 2.0);
200 assert_eq!("POINT(1.0 2.0)", format!("{point:?}"));
201 }
202 #[test]
203 fn int_point() {
204 let point = Point::new(1, 2);
205 assert_eq!("POINT(1 2)", format!("{point:?}"));
206 }
207 #[test]
208 fn line() {
209 let line_string = Line::new((1, 2), (3, 4));
210 assert_eq!("LINE(1 2,3 4)", format!("{line_string:?}"));
211 }
212 #[test]
213 fn line_string() {
214 let line_string = LineString::new(vec![(1, 2).into(), (3, 4).into()]);
215 assert_eq!("LINESTRING(1 2,3 4)", format!("{line_string:?}"));
216 }
217 #[test]
218 fn line_string_with_single_element() {
219 let line_string = LineString::new(vec![(1, 2).into()]);
220 assert_eq!("LINESTRING(1 2)", format!("{line_string:?}"));
221 }
222 #[test]
223 fn empty_line_string() {
224 let line_string = LineString::<i32>::new(vec![]);
225 assert_eq!("LINESTRING EMPTY", format!("{line_string:?}"));
226 }
227 #[test]
228 fn polygon_no_holes() {
229 let polygon = wkt!(POLYGON((1 2,3 4,5 6)));
230 assert_eq!("POLYGON((1 2,3 4,5 6,1 2))", format!("{polygon:?}"));
231 }
232 #[test]
233 fn polygon_with_hole() {
234 let polygon = wkt!(POLYGON(
235 (1 1,10 1,10 10,1 10,1 1),
236 (3 3,7 3,7 7,3 7,3 3)
237 ));
238 assert_eq!(
239 "POLYGON((1 1,10 1,10 10,1 10,1 1),(3 3,7 3,7 7,3 7,3 3))",
240 format!("{polygon:?}")
241 );
242 }
243 #[test]
244 fn polygon_with_multiple_holes() {
245 let polygon = wkt!(POLYGON(
246 (0 0,10 0,10 10,0 10,0 0),
247 (2 2,4 2,4 4,2 4,2 2),
248 (6 6,8 6,8 8,6 8,6 6)
249 ));
250 assert_eq!(
251 "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))",
252 format!("{polygon:?}")
253 );
254 }
255 #[test]
256 fn invalid_polygon_interior_but_no_exterior() {
257 let interior = LineString::new(vec![(1, 2).into()]);
259 let polygon = Polygon::new(LineString::new(vec![]), vec![interior]);
260 assert_eq!("POLYGON(EMPTY,(1 2))", format!("{polygon:?}"));
261 }
262 #[test]
263 fn empty_polygon() {
264 let polygon: Polygon = wkt!(POLYGON EMPTY);
265 assert_eq!("POLYGON EMPTY", format!("{polygon:?}"));
266 }
267 #[test]
268 fn multi_point_empty() {
269 let multi_point: MultiPoint = wkt!(MULTIPOINT EMPTY);
270 assert_eq!("MULTIPOINT EMPTY", format!("{multi_point:?}"));
271 }
272 #[test]
273 fn multi_point_one_point() {
274 let multi_point = wkt!(MULTIPOINT(1 2));
275 assert_eq!("MULTIPOINT(1 2)", format!("{multi_point:?}"));
276 }
277 #[test]
278 fn multi_point_three_points() {
279 let multi_point = wkt!(MULTIPOINT(1 2,3 4,5 6));
280 assert_eq!("MULTIPOINT(1 2,3 4,5 6)", format!("{multi_point:?}"));
281 }
282 #[test]
283 fn multilinestring_empty() {
284 let multi_line_string: MultiLineString = wkt!(MULTILINESTRING EMPTY);
285 assert_eq!("MULTILINESTRING EMPTY", format!("{multi_line_string:?}"));
286 }
287
288 #[test]
289 fn multi_line_string_one_line() {
290 let multi_line_string = wkt!(MULTILINESTRING((1 2, 3 4, 5 6)));
291 assert_eq!(
292 "MULTILINESTRING((1 2,3 4,5 6))",
293 format!("{multi_line_string:?}")
294 );
295 }
296
297 #[test]
298 fn multi_line_string_multiple_lines() {
299 let multi_line_string = wkt!(MULTILINESTRING(
300 (1 2, 3 4, 5 6),
301 (7 8, 9 10, 11 12)
302 ));
303 assert_eq!(
304 "MULTILINESTRING((1 2,3 4,5 6),(7 8,9 10,11 12))",
305 format!("{multi_line_string:?}")
306 );
307 }
308
309 #[test]
310 fn multi_line_string_multiple_lines_with_empty() {
311 let multi_line_string = wkt!(MULTILINESTRING(
312 (1 2, 3 4, 5 6),
313 EMPTY,
314 (7 8, 9 10, 11 12)
315 ));
316 assert_eq!(
317 "MULTILINESTRING((1 2,3 4,5 6),EMPTY,(7 8,9 10,11 12))",
318 format!("{multi_line_string:?}")
319 );
320 }
321 #[test]
322 fn multi_polygon_empty() {
323 let multi_polygon: MultiPolygon = wkt!(MULTIPOLYGON EMPTY);
324 assert_eq!("MULTIPOLYGON EMPTY", format!("{multi_polygon:?}"));
325 }
326
327 #[test]
328 fn multi_polygon_one_polygon() {
329 let multi_polygon = wkt!(MULTIPOLYGON(
330 ((1 2, 3 4, 5 6, 1 2))
331 ));
332 assert_eq!(
333 "MULTIPOLYGON(((1 2,3 4,5 6,1 2)))",
334 format!("{multi_polygon:?}")
335 );
336 }
337
338 #[test]
339 fn multi_polygon_multiple_polygons() {
340 let multi_polygon = wkt!(MULTIPOLYGON(
341 ((1 2, 3 4, 5 6, 1 2)),
342 ((7 8, 9 10, 11 12, 7 8))
343 ));
344 assert_eq!(
345 "MULTIPOLYGON(((1 2,3 4,5 6,1 2)),((7 8,9 10,11 12,7 8)))",
346 format!("{multi_polygon:?}")
347 );
348 }
349
350 #[test]
351 fn multi_polygon_with_holes() {
352 let multi_polygon = wkt!(MULTIPOLYGON(
353 (
354 (1 1, 10 1, 10 10, 1 10, 1 1)
355 ),
356 (
357 (20 20, 30 20, 30 30, 20 30, 20 20),
358 (22 22, 28 22, 28 28, 22 28, 22 22)
359 )
360 ));
361 assert_eq!(
362 "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)))",
363 format!("{multi_polygon:?}")
364 );
365 }
366 #[test]
367 fn multi_polygon_with_holes_and_empty_polygon() {
368 let multi_polygon = wkt!(MULTIPOLYGON(
369 (
370 (1 1, 10 1, 10 10, 1 10, 1 1)
371 ),
372 EMPTY,
373 (
374 (20 20, 30 20, 30 30, 20 30, 20 20),
375 (22 22, 28 22, 28 28, 22 28, 22 22)
376 )
377 ));
378 assert_eq!(
379 "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)))",
380 format!("{multi_polygon:?}")
381 );
382 }
383 #[test]
384 fn rect() {
385 let rect = Rect::new((1, 2), (3, 4));
386 assert_eq!("RECT(1 2,3 4)", format!("{rect:?}"));
387
388 let rect = Rect::new((3, 4), (1, 2));
389 assert_eq!("RECT(1 2,3 4)", format!("{rect:?}"));
391 }
392 #[test]
393 fn triangle() {
394 let rect = Triangle::new((1, 2).into(), (3, 4).into(), (5, 6).into());
395 assert_eq!("TRIANGLE(1 2,3 4,5 6)", format!("{rect:?}"));
396 }
397
398 #[test]
399 fn geometry() {
400 let rect = Geometry::Triangle(Triangle::new((1, 2).into(), (3, 4).into(), (5, 6).into()));
401 assert_eq!("TRIANGLE(1 2,3 4,5 6)", format!("{rect:?}"));
402 }
403
404 #[test]
405 fn geometry_collection() {
406 let rect = Geometry::Triangle(Triangle::new((1, 2).into(), (3, 4).into(), (5, 6).into()));
407 assert_eq!("TRIANGLE(1 2,3 4,5 6)", format!("{rect:?}"));
408 }
409
410 #[test]
411 fn empty_geometry_collection() {
412 let geometry_collection: GeometryCollection = GeometryCollection::default();
413 assert_eq!(
414 "GEOMETRYCOLLECTION EMPTY",
415 format!("{geometry_collection:?}")
416 );
417 }
418
419 #[test]
420 fn geometry_collection_with_mixed_geometries() {
421 let geometry_collection: GeometryCollection<i32> = GeometryCollection::from(vec![
422 Geometry::Point(Point::new(1, 2)),
423 Geometry::Line(Line::new((1, 2), (3, 4))),
424 Geometry::Polygon(Polygon::new(
425 LineString::from(vec![(0, 0), (1, 0), (1, 1), (0, 0)]),
426 vec![],
427 )),
428 ]);
429
430 assert_eq!(
431 "GEOMETRYCOLLECTION(POINT(1 2),LINE(1 2,3 4),POLYGON((0 0,1 0,1 1,0 0)))",
432 format!("{geometry_collection:?}")
433 );
434 }
435
436 #[test]
437 fn nested_geometry_collection() {
438 let inner_collection: GeometryCollection<i32> = GeometryCollection::from(vec![
439 Geometry::Point(Point::new(5, 6)),
440 Geometry::LineString(LineString::from(vec![(1, 2), (3, 4)])),
441 ]);
442
443 let outer_collection: GeometryCollection<i32> = GeometryCollection::from(vec![
444 Geometry::Point(Point::new(1, 2)),
445 Geometry::GeometryCollection(inner_collection),
446 ]);
447
448 assert_eq!(
449 "GEOMETRYCOLLECTION(POINT(1 2),GEOMETRYCOLLECTION(POINT(5 6),LINESTRING(1 2,3 4)))",
450 format!("{outer_collection:?}")
451 );
452 }
453
454 #[test]
455 fn geometry_collection_with_no_coordinates() {
456 let geometry_collection: GeometryCollection<f64> = GeometryCollection::from(vec![
457 Geometry::Point(Point::new(0.0, 0.0)),
458 Geometry::Polygon(Polygon::new(LineString::new(vec![]), vec![])),
459 ]);
460
461 assert_eq!(
462 "GEOMETRYCOLLECTION(POINT(0.0 0.0),POLYGON EMPTY)",
463 format!("{geometry_collection:?}")
464 );
465 }
466}