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