geo/algorithm/
coords_iter.rs

1use std::fmt::Debug;
2
3use crate::geometry::*;
4use crate::{coord, CoordNum};
5
6use std::{fmt, iter, marker, slice};
7
8type CoordinateChainOnce<T> = iter::Chain<iter::Once<Coord<T>>, iter::Once<Coord<T>>>;
9
10/// Iterate over geometry coordinates.
11pub trait CoordsIter<'a> {
12    type Iter: Iterator<Item = Coord<Self::Scalar>>;
13    type ExteriorIter: Iterator<Item = Coord<Self::Scalar>>;
14    type Scalar: CoordNum;
15
16    /// Iterate over all exterior and (if any) interior coordinates of a geometry.
17    ///
18    /// # Examples
19    ///
20    /// ```
21    /// use geo::coords_iter::CoordsIter;
22    ///
23    /// let multi_point = geo::MultiPoint::new(vec![
24    ///     geo::point!(x: -10., y: 0.),
25    ///     geo::point!(x: 20., y: 20.),
26    ///     geo::point!(x: 30., y: 40.),
27    /// ]);
28    ///
29    /// let mut iter = multi_point.coords_iter();
30    /// assert_eq!(Some(geo::coord! { x: -10., y: 0. }), iter.next());
31    /// assert_eq!(Some(geo::coord! { x: 20., y: 20. }), iter.next());
32    /// assert_eq!(Some(geo::coord! { x: 30., y: 40. }), iter.next());
33    /// assert_eq!(None, iter.next());
34    /// ```
35    fn coords_iter(&'a self) -> Self::Iter;
36
37    /// Return the number of coordinates in a geometry.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use geo::coords_iter::CoordsIter;
43    /// use geo::line_string;
44    ///
45    /// let ls = line_string![
46    ///     (x: 1., y: 2.),
47    ///     (x: 23., y: 82.),
48    ///     (x: -1., y: 0.),
49    /// ];
50    ///
51    /// assert_eq!(3, ls.coords_count());
52    /// ```
53    fn coords_count(&'a self) -> usize;
54
55    /// Iterate over all exterior coordinates of a geometry.
56    ///
57    /// # Examples
58    ///
59    /// ```
60    /// use geo::coords_iter::CoordsIter;
61    /// use geo::polygon;
62    ///
63    /// // a diamond shape
64    /// let polygon = polygon![
65    ///     exterior: [
66    ///         (x: 1.0, y: 0.0),
67    ///         (x: 2.0, y: 1.0),
68    ///         (x: 1.0, y: 2.0),
69    ///         (x: 0.0, y: 1.0),
70    ///         (x: 1.0, y: 0.0),
71    ///     ],
72    ///     interiors: [
73    ///         [
74    ///             (x: 1.0, y: 0.5),
75    ///             (x: 0.5, y: 1.0),
76    ///             (x: 1.0, y: 1.5),
77    ///             (x: 1.5, y: 1.0),
78    ///             (x: 1.0, y: 0.5),
79    ///         ],
80    ///     ],
81    /// ];
82    ///
83    /// let mut iter = polygon.exterior_coords_iter();
84    /// assert_eq!(Some(geo::coord! { x: 1., y: 0. }), iter.next());
85    /// assert_eq!(Some(geo::coord! { x: 2., y: 1. }), iter.next());
86    /// assert_eq!(Some(geo::coord! { x: 1., y: 2. }), iter.next());
87    /// assert_eq!(Some(geo::coord! { x: 0., y: 1. }), iter.next());
88    /// assert_eq!(Some(geo::coord! { x: 1., y: 0. }), iter.next());
89    /// assert_eq!(None, iter.next());
90    /// ```
91    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter;
92}
93
94// ┌──────────────────────────┐
95// │ Implementation for Point │
96// └──────────────────────────┘
97
98impl<'a, T: CoordNum> CoordsIter<'a> for Point<T> {
99    type Iter = iter::Once<Coord<T>>;
100    type ExteriorIter = Self::Iter;
101    type Scalar = T;
102
103    fn coords_iter(&'a self) -> Self::Iter {
104        iter::once(self.0)
105    }
106
107    /// Return the number of coordinates in the `Point`.
108    fn coords_count(&'a self) -> usize {
109        1
110    }
111
112    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
113        self.coords_iter()
114    }
115}
116
117// ┌─────────────────────────┐
118// │ Implementation for Line │
119// └─────────────────────────┘
120
121impl<'a, T: CoordNum> CoordsIter<'a> for Line<T> {
122    type Iter = iter::Chain<iter::Once<Coord<T>>, iter::Once<Coord<T>>>;
123    type ExteriorIter = Self::Iter;
124    type Scalar = T;
125
126    fn coords_iter(&'a self) -> Self::Iter {
127        iter::once(self.start).chain(iter::once(self.end))
128    }
129
130    /// Return the number of coordinates in the `Line`.
131    fn coords_count(&'a self) -> usize {
132        2
133    }
134
135    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
136        self.coords_iter()
137    }
138}
139
140// ┌───────────────────────────────┐
141// │ Implementation for LineString │
142// └───────────────────────────────┘
143
144type LineStringIter<'a, T> = iter::Copied<slice::Iter<'a, Coord<T>>>;
145
146impl<'a, T: CoordNum + 'a> CoordsIter<'a> for LineString<T> {
147    type Iter = LineStringIter<'a, T>;
148    type ExteriorIter = Self::Iter;
149    type Scalar = T;
150
151    fn coords_iter(&'a self) -> Self::Iter {
152        self.0.iter().copied()
153    }
154
155    /// Return the number of coordinates in the `LineString`.
156    fn coords_count(&'a self) -> usize {
157        self.0.len()
158    }
159
160    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
161        self.coords_iter()
162    }
163}
164
165// ┌────────────────────────────┐
166// │ Implementation for Polygon │
167// └────────────────────────────┘
168
169type PolygonIter<'a, T> = iter::Chain<
170    LineStringIter<'a, T>,
171    iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, LineString<T>>, LineString<T>>>,
172>;
173
174impl<'a, T: CoordNum + 'a> CoordsIter<'a> for Polygon<T> {
175    type Iter = PolygonIter<'a, T>;
176    type ExteriorIter = LineStringIter<'a, T>;
177    type Scalar = T;
178
179    fn coords_iter(&'a self) -> Self::Iter {
180        self.exterior()
181            .coords_iter()
182            .chain(MapCoordsIter(self.interiors().iter(), marker::PhantomData).flatten())
183    }
184
185    /// Return the number of coordinates in the `Polygon`.
186    fn coords_count(&'a self) -> usize {
187        self.exterior().coords_count()
188            + self
189                .interiors()
190                .iter()
191                .map(|i| i.coords_count())
192                .sum::<usize>()
193    }
194
195    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
196        self.exterior().coords_iter()
197    }
198}
199
200// ┌───────────────────────────────┐
201// │ Implementation for MultiPoint │
202// └───────────────────────────────┘
203
204impl<'a, T: CoordNum + 'a> CoordsIter<'a> for MultiPoint<T> {
205    type Iter = iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, Point<T>>, Point<T>>>;
206    type ExteriorIter = Self::Iter;
207    type Scalar = T;
208
209    fn coords_iter(&'a self) -> Self::Iter {
210        MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
211    }
212
213    /// Return the number of coordinates in the `MultiPoint`.
214    fn coords_count(&'a self) -> usize {
215        self.0.len()
216    }
217
218    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
219        self.coords_iter()
220    }
221}
222
223// ┌────────────────────────────────────┐
224// │ Implementation for MultiLineString │
225// └────────────────────────────────────┘
226
227impl<'a, T: CoordNum + 'a> CoordsIter<'a> for MultiLineString<T> {
228    type Iter = iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, LineString<T>>, LineString<T>>>;
229    type ExteriorIter = Self::Iter;
230    type Scalar = T;
231
232    fn coords_iter(&'a self) -> Self::Iter {
233        MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
234    }
235
236    /// Return the number of coordinates in the `MultiLineString`.
237    fn coords_count(&'a self) -> usize {
238        self.0
239            .iter()
240            .map(|line_string| line_string.coords_count())
241            .sum()
242    }
243
244    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
245        self.coords_iter()
246    }
247}
248
249// ┌─────────────────────────────────┐
250// │ Implementation for MultiPolygon │
251// └─────────────────────────────────┘
252
253impl<'a, T: CoordNum + 'a> CoordsIter<'a> for MultiPolygon<T> {
254    type Iter = iter::Flatten<MapCoordsIter<'a, T, slice::Iter<'a, Polygon<T>>, Polygon<T>>>;
255    type ExteriorIter =
256        iter::Flatten<MapExteriorCoordsIter<'a, T, slice::Iter<'a, Polygon<T>>, Polygon<T>>>;
257    type Scalar = T;
258
259    fn coords_iter(&'a self) -> Self::Iter {
260        MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
261    }
262
263    /// Return the number of coordinates in the `MultiPolygon`.
264    fn coords_count(&'a self) -> usize {
265        self.0.iter().map(|polygon| polygon.coords_count()).sum()
266    }
267
268    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
269        MapExteriorCoordsIter(self.0.iter(), marker::PhantomData).flatten()
270    }
271}
272
273// ┌───────────────────────────────────────┐
274// │ Implementation for GeometryCollection │
275// └───────────────────────────────────────┘
276
277impl<'a, T: CoordNum + 'a> CoordsIter<'a> for GeometryCollection<T> {
278    type Iter = Box<dyn Iterator<Item = Coord<T>> + 'a>;
279    type ExteriorIter = Box<dyn Iterator<Item = Coord<T>> + 'a>;
280    type Scalar = T;
281
282    fn coords_iter(&'a self) -> Self::Iter {
283        Box::new(self.0.iter().flat_map(|geometry| geometry.coords_iter()))
284    }
285
286    /// Return the number of coordinates in the `GeometryCollection`.
287    fn coords_count(&'a self) -> usize {
288        self.0.iter().map(|geometry| geometry.coords_count()).sum()
289    }
290
291    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
292        Box::new(
293            self.0
294                .iter()
295                .flat_map(|geometry| geometry.exterior_coords_iter()),
296        )
297    }
298}
299
300// ┌─────────────────────────┐
301// │ Implementation for Rect │
302// └─────────────────────────┘
303
304type RectIter<T> =
305    iter::Chain<iter::Chain<CoordinateChainOnce<T>, iter::Once<Coord<T>>>, iter::Once<Coord<T>>>;
306
307impl<'a, T: CoordNum + 'a> CoordsIter<'a> for Rect<T> {
308    type Iter = RectIter<T>;
309    type ExteriorIter = Self::Iter;
310    type Scalar = T;
311
312    fn coords_iter(&'a self) -> Self::Iter {
313        iter::once(coord! {
314            x: self.min().x,
315            y: self.min().y,
316        })
317        .chain(iter::once(coord! {
318            x: self.min().x,
319            y: self.max().y,
320        }))
321        .chain(iter::once(coord! {
322            x: self.max().x,
323            y: self.max().y,
324        }))
325        .chain(iter::once(coord! {
326            x: self.max().x,
327            y: self.min().y,
328        }))
329    }
330
331    /// Return the number of coordinates in the `Rect`.
332    ///
333    /// Note: Although a `Rect` is represented by two coordinates, it is
334    /// spatially represented by four, so this method returns `4`.
335    fn coords_count(&'a self) -> usize {
336        4
337    }
338
339    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
340        self.coords_iter()
341    }
342}
343
344// ┌─────────────────────────────┐
345// │ Implementation for Triangle │
346// └─────────────────────────────┘
347
348impl<'a, T: CoordNum + 'a> CoordsIter<'a> for Triangle<T> {
349    type Iter = iter::Chain<CoordinateChainOnce<T>, iter::Once<Coord<T>>>;
350    type ExteriorIter = Self::Iter;
351    type Scalar = T;
352
353    fn coords_iter(&'a self) -> Self::Iter {
354        iter::once(self.0)
355            .chain(iter::once(self.1))
356            .chain(iter::once(self.2))
357    }
358
359    /// Return the number of coordinates in the `Triangle`.
360    fn coords_count(&'a self) -> usize {
361        3
362    }
363
364    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
365        self.coords_iter()
366    }
367}
368
369// ┌─────────────────────────────┐
370// │ Implementation for Geometry │
371// └─────────────────────────────┘
372
373impl<'a, T: CoordNum + 'a> CoordsIter<'a> for Geometry<T> {
374    type Iter = GeometryCoordsIter<'a, T>;
375    type ExteriorIter = GeometryExteriorCoordsIter<'a, T>;
376    type Scalar = T;
377
378    fn coords_iter(&'a self) -> Self::Iter {
379        match self {
380            Geometry::Point(g) => GeometryCoordsIter::Point(g.coords_iter()),
381            Geometry::Line(g) => GeometryCoordsIter::Line(g.coords_iter()),
382            Geometry::LineString(g) => GeometryCoordsIter::LineString(g.coords_iter()),
383            Geometry::Polygon(g) => GeometryCoordsIter::Polygon(g.coords_iter()),
384            Geometry::MultiPoint(g) => GeometryCoordsIter::MultiPoint(g.coords_iter()),
385            Geometry::MultiLineString(g) => GeometryCoordsIter::MultiLineString(g.coords_iter()),
386            Geometry::MultiPolygon(g) => GeometryCoordsIter::MultiPolygon(g.coords_iter()),
387            Geometry::GeometryCollection(g) => {
388                GeometryCoordsIter::GeometryCollection(g.coords_iter())
389            }
390            Geometry::Rect(g) => GeometryCoordsIter::Rect(g.coords_iter()),
391            Geometry::Triangle(g) => GeometryCoordsIter::Triangle(g.coords_iter()),
392        }
393    }
394    crate::geometry_delegate_impl! {
395        /// Return the number of coordinates in the `Geometry`.
396        fn coords_count(&'a self) -> usize;
397    }
398
399    fn exterior_coords_iter(&'a self) -> Self::ExteriorIter {
400        match self {
401            Geometry::Point(g) => GeometryExteriorCoordsIter::Point(g.exterior_coords_iter()),
402            Geometry::Line(g) => GeometryExteriorCoordsIter::Line(g.exterior_coords_iter()),
403            Geometry::LineString(g) => {
404                GeometryExteriorCoordsIter::LineString(g.exterior_coords_iter())
405            }
406            Geometry::Polygon(g) => GeometryExteriorCoordsIter::Polygon(g.exterior_coords_iter()),
407            Geometry::MultiPoint(g) => {
408                GeometryExteriorCoordsIter::MultiPoint(g.exterior_coords_iter())
409            }
410            Geometry::MultiLineString(g) => {
411                GeometryExteriorCoordsIter::MultiLineString(g.exterior_coords_iter())
412            }
413            Geometry::MultiPolygon(g) => {
414                GeometryExteriorCoordsIter::MultiPolygon(g.exterior_coords_iter())
415            }
416            Geometry::GeometryCollection(g) => {
417                GeometryExteriorCoordsIter::GeometryCollection(g.exterior_coords_iter())
418            }
419            Geometry::Rect(g) => GeometryExteriorCoordsIter::Rect(g.exterior_coords_iter()),
420            Geometry::Triangle(g) => GeometryExteriorCoordsIter::Triangle(g.exterior_coords_iter()),
421        }
422    }
423}
424
425// ┌───────────┐
426// │ Utilities │
427// └───────────┘
428
429// Utility to transform Iterator<CoordsIter> into Iterator<Iterator<Coord>>
430#[doc(hidden)]
431#[derive(Debug)]
432pub struct MapCoordsIter<
433    'a,
434    T: 'a + CoordNum,
435    Iter1: Iterator<Item = &'a Iter2>,
436    Iter2: 'a + CoordsIter<'a>,
437>(Iter1, marker::PhantomData<T>);
438
439impl<'a, T: 'a + CoordNum, Iter1: Iterator<Item = &'a Iter2>, Iter2: CoordsIter<'a>> Iterator
440    for MapCoordsIter<'a, T, Iter1, Iter2>
441{
442    type Item = Iter2::Iter;
443
444    fn next(&mut self) -> Option<Self::Item> {
445        self.0.next().map(|g| g.coords_iter())
446    }
447
448    fn size_hint(&self) -> (usize, Option<usize>) {
449        self.0.size_hint()
450    }
451}
452
453// Utility to transform Iterator<CoordsIter> into Iterator<Iterator<Coord>>
454#[doc(hidden)]
455#[derive(Debug)]
456pub struct MapExteriorCoordsIter<
457    'a,
458    T: 'a + CoordNum,
459    Iter1: Iterator<Item = &'a Iter2>,
460    Iter2: 'a + CoordsIter<'a>,
461>(Iter1, marker::PhantomData<T>);
462
463impl<'a, T: 'a + CoordNum, Iter1: Iterator<Item = &'a Iter2>, Iter2: CoordsIter<'a>> Iterator
464    for MapExteriorCoordsIter<'a, T, Iter1, Iter2>
465{
466    type Item = Iter2::ExteriorIter;
467
468    fn next(&mut self) -> Option<Self::Item> {
469        self.0.next().map(|g| g.exterior_coords_iter())
470    }
471
472    fn size_hint(&self) -> (usize, Option<usize>) {
473        self.0.size_hint()
474    }
475}
476
477// Utility to transform Geometry into Iterator<Coord>
478#[doc(hidden)]
479pub enum GeometryCoordsIter<'a, T: CoordNum + 'a> {
480    Point(<Point<T> as CoordsIter<'a>>::Iter),
481    Line(<Line<T> as CoordsIter<'a>>::Iter),
482    LineString(<LineString<T> as CoordsIter<'a>>::Iter),
483    Polygon(<Polygon<T> as CoordsIter<'a>>::Iter),
484    MultiPoint(<MultiPoint<T> as CoordsIter<'a>>::Iter),
485    MultiLineString(<MultiLineString<T> as CoordsIter<'a>>::Iter),
486    MultiPolygon(<MultiPolygon<T> as CoordsIter<'a>>::Iter),
487    GeometryCollection(<GeometryCollection<T> as CoordsIter<'a>>::Iter),
488    Rect(<Rect<T> as CoordsIter<'a>>::Iter),
489    Triangle(<Triangle<T> as CoordsIter<'a>>::Iter),
490}
491
492impl<'a, T: CoordNum> Iterator for GeometryCoordsIter<'a, T> {
493    type Item = Coord<T>;
494
495    fn next(&mut self) -> Option<Self::Item> {
496        match self {
497            GeometryCoordsIter::Point(g) => g.next(),
498            GeometryCoordsIter::Line(g) => g.next(),
499            GeometryCoordsIter::LineString(g) => g.next(),
500            GeometryCoordsIter::Polygon(g) => g.next(),
501            GeometryCoordsIter::MultiPoint(g) => g.next(),
502            GeometryCoordsIter::MultiLineString(g) => g.next(),
503            GeometryCoordsIter::MultiPolygon(g) => g.next(),
504            GeometryCoordsIter::GeometryCollection(g) => g.next(),
505            GeometryCoordsIter::Rect(g) => g.next(),
506            GeometryCoordsIter::Triangle(g) => g.next(),
507        }
508    }
509
510    fn size_hint(&self) -> (usize, Option<usize>) {
511        match self {
512            GeometryCoordsIter::Point(g) => g.size_hint(),
513            GeometryCoordsIter::Line(g) => g.size_hint(),
514            GeometryCoordsIter::LineString(g) => g.size_hint(),
515            GeometryCoordsIter::Polygon(g) => g.size_hint(),
516            GeometryCoordsIter::MultiPoint(g) => g.size_hint(),
517            GeometryCoordsIter::MultiLineString(g) => g.size_hint(),
518            GeometryCoordsIter::MultiPolygon(g) => g.size_hint(),
519            GeometryCoordsIter::GeometryCollection(g) => g.size_hint(),
520            GeometryCoordsIter::Rect(g) => g.size_hint(),
521            GeometryCoordsIter::Triangle(g) => g.size_hint(),
522        }
523    }
524}
525
526impl<'a, T: CoordNum + Debug> fmt::Debug for GeometryCoordsIter<'a, T> {
527    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
528        match self {
529            GeometryCoordsIter::Point(i) => fmt.debug_tuple("Point").field(i).finish(),
530            GeometryCoordsIter::Line(i) => fmt.debug_tuple("Line").field(i).finish(),
531            GeometryCoordsIter::LineString(i) => fmt.debug_tuple("LineString").field(i).finish(),
532            GeometryCoordsIter::Polygon(i) => fmt.debug_tuple("Polygon").field(i).finish(),
533            GeometryCoordsIter::MultiPoint(i) => fmt.debug_tuple("MultiPoint").field(i).finish(),
534            GeometryCoordsIter::MultiLineString(i) => {
535                fmt.debug_tuple("MultiLineString").field(i).finish()
536            }
537            GeometryCoordsIter::MultiPolygon(i) => {
538                fmt.debug_tuple("MultiPolygon").field(i).finish()
539            }
540            GeometryCoordsIter::GeometryCollection(_) => fmt
541                .debug_tuple("GeometryCollection")
542                .field(&String::from("..."))
543                .finish(),
544            GeometryCoordsIter::Rect(i) => fmt.debug_tuple("Rect").field(i).finish(),
545            GeometryCoordsIter::Triangle(i) => fmt.debug_tuple("Triangle").field(i).finish(),
546        }
547    }
548}
549
550// Utility to transform Geometry into Iterator<Coord>
551#[doc(hidden)]
552pub enum GeometryExteriorCoordsIter<'a, T: CoordNum + 'a> {
553    Point(<Point<T> as CoordsIter<'a>>::ExteriorIter),
554    Line(<Line<T> as CoordsIter<'a>>::ExteriorIter),
555    LineString(<LineString<T> as CoordsIter<'a>>::ExteriorIter),
556    Polygon(<Polygon<T> as CoordsIter<'a>>::ExteriorIter),
557    MultiPoint(<MultiPoint<T> as CoordsIter<'a>>::ExteriorIter),
558    MultiLineString(<MultiLineString<T> as CoordsIter<'a>>::ExteriorIter),
559    MultiPolygon(<MultiPolygon<T> as CoordsIter<'a>>::ExteriorIter),
560    GeometryCollection(<GeometryCollection<T> as CoordsIter<'a>>::ExteriorIter),
561    Rect(<Rect<T> as CoordsIter<'a>>::ExteriorIter),
562    Triangle(<Triangle<T> as CoordsIter<'a>>::ExteriorIter),
563}
564
565impl<'a, T: CoordNum> Iterator for GeometryExteriorCoordsIter<'a, T> {
566    type Item = Coord<T>;
567
568    fn next(&mut self) -> Option<Self::Item> {
569        match self {
570            GeometryExteriorCoordsIter::Point(g) => g.next(),
571            GeometryExteriorCoordsIter::Line(g) => g.next(),
572            GeometryExteriorCoordsIter::LineString(g) => g.next(),
573            GeometryExteriorCoordsIter::Polygon(g) => g.next(),
574            GeometryExteriorCoordsIter::MultiPoint(g) => g.next(),
575            GeometryExteriorCoordsIter::MultiLineString(g) => g.next(),
576            GeometryExteriorCoordsIter::MultiPolygon(g) => g.next(),
577            GeometryExteriorCoordsIter::GeometryCollection(g) => g.next(),
578            GeometryExteriorCoordsIter::Rect(g) => g.next(),
579            GeometryExteriorCoordsIter::Triangle(g) => g.next(),
580        }
581    }
582
583    fn size_hint(&self) -> (usize, Option<usize>) {
584        match self {
585            GeometryExteriorCoordsIter::Point(g) => g.size_hint(),
586            GeometryExteriorCoordsIter::Line(g) => g.size_hint(),
587            GeometryExteriorCoordsIter::LineString(g) => g.size_hint(),
588            GeometryExteriorCoordsIter::Polygon(g) => g.size_hint(),
589            GeometryExteriorCoordsIter::MultiPoint(g) => g.size_hint(),
590            GeometryExteriorCoordsIter::MultiLineString(g) => g.size_hint(),
591            GeometryExteriorCoordsIter::MultiPolygon(g) => g.size_hint(),
592            GeometryExteriorCoordsIter::GeometryCollection(g) => g.size_hint(),
593            GeometryExteriorCoordsIter::Rect(g) => g.size_hint(),
594            GeometryExteriorCoordsIter::Triangle(g) => g.size_hint(),
595        }
596    }
597}
598
599impl<'a, T: CoordNum + Debug> fmt::Debug for GeometryExteriorCoordsIter<'a, T> {
600    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
601        match self {
602            GeometryExteriorCoordsIter::Point(i) => fmt.debug_tuple("Point").field(i).finish(),
603            GeometryExteriorCoordsIter::Line(i) => fmt.debug_tuple("Line").field(i).finish(),
604            GeometryExteriorCoordsIter::LineString(i) => {
605                fmt.debug_tuple("LineString").field(i).finish()
606            }
607            GeometryExteriorCoordsIter::Polygon(i) => fmt.debug_tuple("Polygon").field(i).finish(),
608            GeometryExteriorCoordsIter::MultiPoint(i) => {
609                fmt.debug_tuple("MultiPoint").field(i).finish()
610            }
611            GeometryExteriorCoordsIter::MultiLineString(i) => {
612                fmt.debug_tuple("MultiLineString").field(i).finish()
613            }
614            GeometryExteriorCoordsIter::MultiPolygon(i) => {
615                fmt.debug_tuple("MultiPolygon").field(i).finish()
616            }
617            GeometryExteriorCoordsIter::GeometryCollection(_) => fmt
618                .debug_tuple("GeometryCollection")
619                .field(&String::from("..."))
620                .finish(),
621            GeometryExteriorCoordsIter::Rect(i) => fmt.debug_tuple("Rect").field(i).finish(),
622            GeometryExteriorCoordsIter::Triangle(i) => {
623                fmt.debug_tuple("Triangle").field(i).finish()
624            }
625        }
626    }
627}
628
629#[cfg(test)]
630mod test {
631    use super::CoordsIter;
632    use crate::{
633        coord, line_string, point, polygon, Coord, Geometry, GeometryCollection, Line, LineString,
634        MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle,
635    };
636
637    #[test]
638    fn test_point() {
639        let (point, expected_coords) = create_point();
640
641        let actual_coords = point.coords_iter().collect::<Vec<_>>();
642
643        assert_eq!(expected_coords, actual_coords);
644    }
645
646    #[test]
647    fn test_line() {
648        let line = Line::new(coord! { x: 1., y: 2. }, coord! { x: 2., y: 3. });
649
650        let coords = line.coords_iter().collect::<Vec<_>>();
651
652        assert_eq!(
653            vec![coord! { x: 1., y: 2. }, coord! { x: 2., y: 3. },],
654            coords
655        );
656    }
657
658    #[test]
659    fn test_line_string() {
660        let (line_string, expected_coords) = create_line_string();
661
662        let actual_coords = line_string.coords_iter().collect::<Vec<_>>();
663
664        assert_eq!(expected_coords, actual_coords);
665    }
666
667    #[test]
668    fn test_polygon() {
669        let (polygon, expected_coords) = create_polygon();
670
671        let actual_coords = polygon.coords_iter().collect::<Vec<_>>();
672
673        assert_eq!(expected_coords, actual_coords);
674    }
675
676    #[test]
677    fn test_multi_point() {
678        let mut expected_coords = vec![];
679        let (point, mut coords) = create_point();
680        expected_coords.append(&mut coords.clone());
681        expected_coords.append(&mut coords);
682
683        let actual_coords = MultiPoint::new(vec![point, point])
684            .coords_iter()
685            .collect::<Vec<_>>();
686
687        assert_eq!(expected_coords, actual_coords);
688    }
689
690    #[test]
691    fn test_multi_line_string() {
692        let mut expected_coords = vec![];
693        let (line_string, mut coords) = create_line_string();
694        expected_coords.append(&mut coords.clone());
695        expected_coords.append(&mut coords);
696
697        let actual_coords = MultiLineString::new(vec![line_string.clone(), line_string])
698            .coords_iter()
699            .collect::<Vec<_>>();
700
701        assert_eq!(expected_coords, actual_coords);
702    }
703
704    #[test]
705    fn test_multi_polygon() {
706        let mut expected_coords = vec![];
707        let (polygon, mut coords) = create_polygon();
708        expected_coords.append(&mut coords.clone());
709        expected_coords.append(&mut coords);
710
711        let actual_coords = MultiPolygon::new(vec![polygon.clone(), polygon])
712            .coords_iter()
713            .collect::<Vec<_>>();
714
715        assert_eq!(expected_coords, actual_coords);
716    }
717
718    #[test]
719    fn test_geometry() {
720        let (line_string, expected_coords) = create_line_string();
721
722        let actual_coords = Geometry::LineString(line_string)
723            .coords_iter()
724            .collect::<Vec<_>>();
725
726        assert_eq!(expected_coords, actual_coords);
727    }
728
729    #[test]
730    fn test_rect() {
731        let (rect, expected_coords) = create_rect();
732
733        let actual_coords = rect.coords_iter().collect::<Vec<_>>();
734
735        assert_eq!(expected_coords, actual_coords);
736    }
737
738    #[test]
739    fn test_triangle() {
740        let (triangle, expected_coords) = create_triangle();
741
742        let actual_coords = triangle.coords_iter().collect::<Vec<_>>();
743
744        assert_eq!(expected_coords, actual_coords);
745    }
746
747    #[test]
748    fn test_geometry_collection() {
749        let mut expected_coords = vec![];
750        let (line_string, mut coords) = create_line_string();
751        expected_coords.append(&mut coords);
752        let (polygon, mut coords) = create_polygon();
753        expected_coords.append(&mut coords);
754
755        let actual_coords = GeometryCollection::new_from(vec![
756            Geometry::LineString(line_string),
757            Geometry::Polygon(polygon),
758        ])
759        .coords_iter()
760        .collect::<Vec<_>>();
761
762        assert_eq!(expected_coords, actual_coords);
763    }
764
765    fn create_point() -> (Point, Vec<Coord>) {
766        (point!(x: 1., y: 2.), vec![coord! { x: 1., y: 2. }])
767    }
768
769    fn create_triangle() -> (Triangle, Vec<Coord>) {
770        (
771            Triangle::new(
772                coord! { x: 1., y: 2. },
773                coord! { x: 3., y: 4. },
774                coord! { x: 5., y: 6. },
775            ),
776            vec![
777                coord! { x: 1., y: 2. },
778                coord! { x: 3., y: 4. },
779                coord! { x: 5., y: 6. },
780            ],
781        )
782    }
783
784    fn create_rect() -> (Rect, Vec<Coord>) {
785        (
786            Rect::new(coord! { x: 1., y: 2. }, coord! { x: 3., y: 4. }),
787            vec![
788                coord! { x: 1., y: 2. },
789                coord! { x: 1., y: 4. },
790                coord! { x: 3., y: 4. },
791                coord! { x: 3., y: 2. },
792            ],
793        )
794    }
795
796    fn create_line_string() -> (LineString, Vec<Coord>) {
797        (
798            line_string![
799                (x: 1., y: 2.),
800                (x: 2., y: 3.),
801            ],
802            vec![coord! { x: 1., y: 2. }, coord! { x: 2., y: 3. }],
803        )
804    }
805
806    fn create_polygon() -> (Polygon<f64>, Vec<Coord>) {
807        (
808            polygon!(
809                exterior: [(x: 0., y: 0.), (x: 5., y: 10.), (x: 10., y: 0.), (x: 0., y: 0.)],
810                interiors: [[(x: 1., y: 1.), (x: 9., y: 1.), (x: 5., y: 9.), (x: 1., y: 1.)]],
811            ),
812            vec![
813                coord! { x: 0.0, y: 0.0 },
814                coord! { x: 5.0, y: 10.0 },
815                coord! { x: 10.0, y: 0.0 },
816                coord! { x: 0.0, y: 0.0 },
817                coord! { x: 1.0, y: 1.0 },
818                coord! { x: 9.0, y: 1.0 },
819                coord! { x: 5.0, y: 9.0 },
820                coord! { x: 1.0, y: 1.0 },
821            ],
822        )
823    }
824}