geo/algorithm/validation/
multi_point.rs

1use super::{GeometryIndex, InvalidPoint, Validation};
2use crate::{GeoFloat, MultiPoint};
3
4use std::fmt;
5
6/// A [`MultiPoint`] is valid if each [`Point`](crate::Point) in it is valid.
7#[derive(Debug, Clone, PartialEq)]
8pub enum InvalidMultiPoint {
9    /// Which element is invalid, and what was invalid about it.
10    InvalidPoint(GeometryIndex, InvalidPoint),
11}
12
13impl fmt::Display for InvalidMultiPoint {
14    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
15        match self {
16            InvalidMultiPoint::InvalidPoint(idx, err) => {
17                write!(f, "point at index {} is invalid: {}", idx.0, err)
18            }
19        }
20    }
21}
22
23impl std::error::Error for InvalidMultiPoint {}
24
25impl<F: GeoFloat> Validation for MultiPoint<F> {
26    type Error = InvalidMultiPoint;
27
28    fn visit_validation<T>(
29        &self,
30        mut handle_validation_error: Box<dyn FnMut(Self::Error) -> Result<(), T> + '_>,
31    ) -> Result<(), T> {
32        for (i, point) in self.0.iter().enumerate() {
33            point.visit_validation(Box::new(&mut |invalid_point| {
34                let err = InvalidMultiPoint::InvalidPoint(GeometryIndex(i), invalid_point);
35                handle_validation_error(err)
36            }))?;
37        }
38        Ok(())
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use crate::algorithm::validation::{assert_valid, assert_validation_errors};
46    use crate::{geometry::*, wkt};
47
48    #[test]
49    fn test_multipoint_valid() {
50        let mp = wkt!(MULTIPOINT(0. 0.,1. 1.));
51        assert_valid!(&mp);
52    }
53
54    #[test]
55    fn test_multipoint_invalid() {
56        let mp = MultiPoint(vec![
57            Point::new(0., f64::INFINITY),
58            Point::new(f64::NAN, 1.),
59        ]);
60        assert_validation_errors!(
61            &mp,
62            vec![
63                InvalidMultiPoint::InvalidPoint(GeometryIndex(0), InvalidPoint::NonFiniteCoord),
64                InvalidMultiPoint::InvalidPoint(GeometryIndex(1), InvalidPoint::NonFiniteCoord)
65            ]
66        );
67    }
68}