proj_core/transform/
geo_adapters.rs1use super::{Transform, TransformableGeometry};
2use crate::error::Result;
3
4#[cfg(feature = "geo-types")]
5fn transform_geo_coord(
6 transform: &Transform,
7 coord: geo_types::Coord<f64>,
8) -> Result<geo_types::Coord<f64>> {
9 transform.convert(coord)
10}
11
12#[cfg(feature = "geo-types")]
13fn transform_geo_coords(
14 transform: &Transform,
15 coords: Vec<geo_types::Coord<f64>>,
16) -> Result<Vec<geo_types::Coord<f64>>> {
17 coords
18 .into_iter()
19 .map(|coord| transform_geo_coord(transform, coord))
20 .collect()
21}
22
23#[cfg(feature = "geo-types")]
24fn transform_geo_rect(
25 transform: &Transform,
26 rect: geo_types::Rect<f64>,
27) -> Result<geo_types::Rect<f64>> {
28 let min = rect.min();
29 let max = rect.max();
30 let corners = [
31 geo_types::Coord { x: min.x, y: min.y },
32 geo_types::Coord { x: max.x, y: min.y },
33 geo_types::Coord { x: max.x, y: max.y },
34 geo_types::Coord { x: min.x, y: max.y },
35 ];
36
37 let mut transformed = corners
38 .into_iter()
39 .map(|coord| transform_geo_coord(transform, coord));
40 let first = transformed.next().expect("rect has four corners")?;
41 let mut min_x = first.x;
42 let mut min_y = first.y;
43 let mut max_x = first.x;
44 let mut max_y = first.y;
45 for coord in transformed {
46 let coord = coord?;
47 min_x = min_x.min(coord.x);
48 min_y = min_y.min(coord.y);
49 max_x = max_x.max(coord.x);
50 max_y = max_y.max(coord.y);
51 }
52
53 Ok(geo_types::Rect::new(
54 geo_types::Coord { x: min_x, y: min_y },
55 geo_types::Coord { x: max_x, y: max_y },
56 ))
57}
58
59#[cfg(feature = "geo-types")]
60impl TransformableGeometry for geo_types::Coord<f64> {
61 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
62 transform_geo_coord(transform, self)
63 }
64}
65
66#[cfg(feature = "geo-types")]
67impl TransformableGeometry for geo_types::Point<f64> {
68 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
69 Ok(geo_types::Point::from(transform_geo_coord(
70 transform, self.0,
71 )?))
72 }
73}
74
75#[cfg(feature = "geo-types")]
76impl TransformableGeometry for geo_types::Line<f64> {
77 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
78 Ok(geo_types::Line::new(
79 transform_geo_coord(transform, self.start)?,
80 transform_geo_coord(transform, self.end)?,
81 ))
82 }
83}
84
85#[cfg(feature = "geo-types")]
86impl TransformableGeometry for geo_types::LineString<f64> {
87 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
88 Ok(geo_types::LineString::new(transform_geo_coords(
89 transform,
90 self.into_inner(),
91 )?))
92 }
93}
94
95#[cfg(feature = "geo-types")]
96impl TransformableGeometry for geo_types::Polygon<f64> {
97 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
98 let (exterior, interiors) = self.into_inner();
99 let exterior = exterior.transform_geometry(transform)?;
100 let interiors = interiors
101 .into_iter()
102 .map(|ring| ring.transform_geometry(transform))
103 .collect::<Result<Vec<_>>>()?;
104 Ok(geo_types::Polygon::new(exterior, interiors))
105 }
106}
107
108#[cfg(feature = "geo-types")]
109impl TransformableGeometry for geo_types::MultiPoint<f64> {
110 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
111 Ok(geo_types::MultiPoint(
112 self.0
113 .into_iter()
114 .map(|point| point.transform_geometry(transform))
115 .collect::<Result<Vec<_>>>()?,
116 ))
117 }
118}
119
120#[cfg(feature = "geo-types")]
121impl TransformableGeometry for geo_types::MultiLineString<f64> {
122 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
123 Ok(geo_types::MultiLineString(
124 self.0
125 .into_iter()
126 .map(|line| line.transform_geometry(transform))
127 .collect::<Result<Vec<_>>>()?,
128 ))
129 }
130}
131
132#[cfg(feature = "geo-types")]
133impl TransformableGeometry for geo_types::MultiPolygon<f64> {
134 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
135 Ok(geo_types::MultiPolygon(
136 self.0
137 .into_iter()
138 .map(|polygon| polygon.transform_geometry(transform))
139 .collect::<Result<Vec<_>>>()?,
140 ))
141 }
142}
143
144#[cfg(feature = "geo-types")]
145impl TransformableGeometry for geo_types::GeometryCollection<f64> {
146 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
147 Ok(geo_types::GeometryCollection(
148 self.0
149 .into_iter()
150 .map(|geometry| geometry.transform_geometry(transform))
151 .collect::<Result<Vec<_>>>()?,
152 ))
153 }
154}
155
156#[cfg(feature = "geo-types")]
157impl TransformableGeometry for geo_types::Rect<f64> {
158 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
159 transform_geo_rect(transform, self)
160 }
161}
162
163#[cfg(feature = "geo-types")]
164impl TransformableGeometry for geo_types::Triangle<f64> {
165 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
166 let [v1, v2, v3] = self.to_array();
167 Ok(geo_types::Triangle(
168 transform_geo_coord(transform, v1)?,
169 transform_geo_coord(transform, v2)?,
170 transform_geo_coord(transform, v3)?,
171 ))
172 }
173}
174
175#[cfg(feature = "geo-types")]
176impl TransformableGeometry for geo_types::Geometry<f64> {
177 fn transform_geometry(self, transform: &Transform) -> Result<Self> {
178 Ok(match self {
179 geo_types::Geometry::Point(geometry) => {
180 geo_types::Geometry::Point(geometry.transform_geometry(transform)?)
181 }
182 geo_types::Geometry::Line(geometry) => {
183 geo_types::Geometry::Line(geometry.transform_geometry(transform)?)
184 }
185 geo_types::Geometry::LineString(geometry) => {
186 geo_types::Geometry::LineString(geometry.transform_geometry(transform)?)
187 }
188 geo_types::Geometry::Polygon(geometry) => {
189 geo_types::Geometry::Polygon(geometry.transform_geometry(transform)?)
190 }
191 geo_types::Geometry::MultiPoint(geometry) => {
192 geo_types::Geometry::MultiPoint(geometry.transform_geometry(transform)?)
193 }
194 geo_types::Geometry::MultiLineString(geometry) => {
195 geo_types::Geometry::MultiLineString(geometry.transform_geometry(transform)?)
196 }
197 geo_types::Geometry::MultiPolygon(geometry) => {
198 geo_types::Geometry::MultiPolygon(geometry.transform_geometry(transform)?)
199 }
200 geo_types::Geometry::GeometryCollection(geometry) => {
201 geo_types::Geometry::GeometryCollection(geometry.transform_geometry(transform)?)
202 }
203 geo_types::Geometry::Rect(geometry) => {
204 geo_types::Geometry::Rect(geometry.transform_geometry(transform)?)
205 }
206 geo_types::Geometry::Triangle(geometry) => {
207 geo_types::Geometry::Triangle(geometry.transform_geometry(transform)?)
208 }
209 })
210 }
211}