1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use geo::{Geometry, Line, LineString, Point, Polygon, Rect, Triangle};
use crate::Error;
pub(crate) trait IsSafe {
fn is_safe(&self, position: usize) -> Result<(), Error>;
}
impl IsSafe for Point<f64> {
fn is_safe(&self, position: usize) -> Result<(), Error> {
if self.x().is_finite() && self.y().is_finite() {
Ok(())
} else {
Err(Error::BadCoordinateValue(position, Geometry::Point(*self)))
}
}
}
impl IsSafe for Line<f64> {
fn is_safe(&self, position: usize) -> Result<(), Error> {
let r = self
.start_point()
.is_safe(position)
.and(self.end_point().is_safe(position));
if r.is_err() {
Err(Error::BadCoordinateValue(position, Geometry::Line(*self)))
} else {
Ok(())
}
}
}
impl IsSafe for LineString<f64> {
fn is_safe(&self, position: usize) -> Result<(), Error> {
if self.0.len() < 2 {
return Err(Error::LineStringTooSmall(position));
}
for pt in self.points_iter() {
if pt.is_safe(position).is_err() {
return Err(Error::BadCoordinateValue(
position,
Geometry::LineString(self.clone()),
));
}
}
Ok(())
}
}
impl IsSafe for Rect<f64> {
fn is_safe(&self, position: usize) -> Result<(), Error> {
let min: Point<f64> = self.min().into();
let max: Point<f64> = self.max().into();
let r = min.is_safe(position).and(max.is_safe(position));
if r.is_err() {
Err(Error::BadCoordinateValue(position, Geometry::Rect(*self)))
} else {
Ok(())
}
}
}
impl IsSafe for Triangle<f64> {
fn is_safe(&self, position: usize) -> Result<(), Error> {
let [a, b, c] = self.to_array();
let a: Point<f64> = a.into();
let b: Point<f64> = b.into();
let c: Point<f64> = c.into();
let r = a
.is_safe(position)
.and(b.is_safe(position))
.and(c.is_safe(position));
if r.is_err() {
Err(Error::BadCoordinateValue(
position,
Geometry::Triangle(*self),
))
} else {
Ok(())
}
}
}
impl IsSafe for Polygon<f64> {
fn is_safe(&self, position: usize) -> Result<(), Error> {
if self.exterior().num_coords() < 3 {
return Err(Error::PolygonExteriorTooSmall(position));
}
for line_string in std::iter::once(self.exterior()).chain(self.interiors().iter()) {
if line_string.is_safe(position).is_err() {
return Err(Error::BadCoordinateValue(
position,
Geometry::Polygon(self.clone()),
));
}
}
Ok(())
}
}