1use std::convert::TryFrom;
14
15use crate::errors::Error;
16use crate::types::{
17 Coord, CoordType, Geometry, Kml, LineString, LinearRing, MultiGeometry, Point, Polygon,
18};
19
20#[allow(deprecated)]
21#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
22impl<T> From<geo_types::Coordinate<T>> for Coord<T>
23where
24 T: CoordType,
25{
26 fn from(val: geo_types::Coordinate<T>) -> Coord<T> {
27 Coord::from((val.x, val.y))
28 }
29}
30
31#[allow(deprecated)]
32#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
33impl<T> From<Coord<T>> for geo_types::Coordinate<T>
34where
35 T: CoordType,
36{
37 fn from(val: Coord<T>) -> geo_types::Coordinate<T> {
38 geo_types::Coordinate::from((val.x, val.y))
39 }
40}
41
42#[allow(deprecated)]
43#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
44impl<T> From<geo_types::Point<T>> for Point<T>
45where
46 T: CoordType + Default,
47{
48 fn from(val: geo_types::Point<T>) -> Point<T> {
49 Point::from(Coord::from(val.0))
50 }
51}
52
53#[allow(deprecated)]
54#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
55impl<T> From<Point<T>> for geo_types::Point<T>
56where
57 T: CoordType,
58{
59 fn from(val: Point<T>) -> geo_types::Point<T> {
60 geo_types::Point::from(geo_types::Coordinate::from(val.coord))
61 }
62}
63
64#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
65impl<T> From<geo_types::Line<T>> for LineString<T>
66where
67 T: CoordType + Default,
68{
69 fn from(val: geo_types::Line<T>) -> LineString<T> {
70 LineString::from(vec![Coord::from(val.start), Coord::from(val.end)])
71 }
72}
73
74#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
75impl<T> From<geo_types::LineString<T>> for LineString<T>
76where
77 T: CoordType + Default,
78{
79 fn from(val: geo_types::LineString<T>) -> LineString<T> {
80 LineString::from(
81 val.0
82 .into_iter()
83 .map(Coord::from)
84 .collect::<Vec<Coord<T>>>(),
85 )
86 }
87}
88
89#[allow(deprecated)]
90#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
91impl<T> From<LineString<T>> for geo_types::LineString<T>
92where
93 T: CoordType,
94{
95 fn from(val: LineString<T>) -> geo_types::LineString<T> {
96 geo_types::LineString(
97 val.coords
98 .into_iter()
99 .map(geo_types::Coordinate::from)
100 .collect(),
101 )
102 }
103}
104
105#[allow(deprecated)]
106#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
107impl<T> From<geo_types::LineString<T>> for LinearRing<T>
108where
109 T: CoordType + Default,
110{
111 fn from(val: geo_types::LineString<T>) -> LinearRing<T> {
112 LinearRing::from(
113 val.0
114 .into_iter()
115 .map(Coord::from)
116 .collect::<Vec<Coord<T>>>(),
117 )
118 }
119}
120
121#[allow(deprecated)]
122#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
123impl<T> From<LinearRing<T>> for geo_types::LineString<T>
124where
125 T: CoordType,
126{
127 fn from(val: LinearRing<T>) -> geo_types::LineString<T> {
128 geo_types::LineString(
129 val.coords
130 .into_iter()
131 .map(geo_types::Coordinate::from)
132 .collect(),
133 )
134 }
135}
136
137#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
138impl<T> From<geo_types::Polygon<T>> for Polygon<T>
139where
140 T: CoordType + Default,
141{
142 fn from(val: geo_types::Polygon<T>) -> Polygon<T> {
143 let (outer, inner) = val.into_inner();
144 Polygon::new(
145 LinearRing::from(outer),
146 inner
147 .into_iter()
148 .map(LinearRing::from)
149 .collect::<Vec<LinearRing<T>>>(),
150 )
151 }
152}
153
154#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
155impl<T> From<geo_types::Rect<T>> for Polygon<T>
156where
157 T: CoordType + Default,
158{
159 fn from(val: geo_types::Rect<T>) -> Polygon<T> {
160 Polygon::from(val.to_polygon())
161 }
162}
163
164#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
165impl<T> From<geo_types::Triangle<T>> for Polygon<T>
166where
167 T: CoordType + Default,
168{
169 fn from(val: geo_types::Triangle<T>) -> Polygon<T> {
170 Polygon::from(val.to_polygon())
171 }
172}
173
174#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
175impl<T> From<Polygon<T>> for geo_types::Polygon<T>
176where
177 T: CoordType,
178{
179 fn from(val: Polygon<T>) -> geo_types::Polygon<T> {
180 geo_types::Polygon::new(
181 geo_types::LineString::from(val.outer),
182 val.inner
183 .into_iter()
184 .map(geo_types::LineString::from)
185 .collect::<Vec<geo_types::LineString<T>>>(),
186 )
187 }
188}
189
190#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
191impl<T> From<geo_types::MultiPoint<T>> for MultiGeometry<T>
192where
193 T: CoordType + Default,
194{
195 fn from(val: geo_types::MultiPoint<T>) -> MultiGeometry<T> {
196 MultiGeometry::new(
197 val.into_iter()
198 .map(|p| Geometry::Point(Point::from(p)))
199 .collect::<Vec<Geometry<T>>>(),
200 )
201 }
202}
203
204#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
205impl<T> From<geo_types::MultiLineString<T>> for MultiGeometry<T>
206where
207 T: CoordType + Default,
208{
209 fn from(val: geo_types::MultiLineString<T>) -> MultiGeometry<T> {
210 MultiGeometry::new(
211 val.into_iter()
212 .map(|l| Geometry::LineString(LineString::from(l)))
213 .collect::<Vec<Geometry<T>>>(),
214 )
215 }
216}
217
218#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
219impl<T> From<geo_types::MultiPolygon<T>> for MultiGeometry<T>
220where
221 T: CoordType + Default,
222{
223 fn from(val: geo_types::MultiPolygon<T>) -> MultiGeometry<T> {
224 MultiGeometry::new(
225 val.into_iter()
226 .map(|p| Geometry::Polygon(Polygon::from(p)))
227 .collect::<Vec<Geometry<T>>>(),
228 )
229 }
230}
231
232#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
233impl<T> From<geo_types::GeometryCollection<T>> for MultiGeometry<T>
234where
235 T: CoordType + Default,
236{
237 fn from(val: geo_types::GeometryCollection<T>) -> MultiGeometry<T> {
238 MultiGeometry::new(
239 val.into_iter()
240 .map(Geometry::from)
241 .collect::<Vec<Geometry<T>>>(),
242 )
243 }
244}
245
246#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
247impl<T> TryFrom<MultiGeometry<T>> for geo_types::GeometryCollection<T>
248where
249 T: CoordType,
250{
251 type Error = Error;
252
253 fn try_from(val: MultiGeometry<T>) -> Result<geo_types::GeometryCollection<T>, Self::Error> {
254 Ok(geo_types::GeometryCollection(
255 val.geometries
256 .into_iter()
257 .map(geo_types::Geometry::try_from)
258 .collect::<Result<Vec<geo_types::Geometry<T>>, _>>()?,
259 ))
260 }
261}
262
263#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
264impl<T> From<geo_types::Geometry<T>> for Geometry<T>
265where
266 T: CoordType + Default,
267{
268 fn from(val: geo_types::Geometry<T>) -> Geometry<T> {
269 match val {
270 geo_types::Geometry::Point(p) => Geometry::Point(Point::from(p)),
271 geo_types::Geometry::Line(l) => Geometry::LineString(LineString::from(l)),
272 geo_types::Geometry::LineString(l) => Geometry::LineString(LineString::from(l)),
273 geo_types::Geometry::Polygon(p) => Geometry::Polygon(Polygon::from(p)),
274 geo_types::Geometry::MultiPoint(p) => Geometry::MultiGeometry(MultiGeometry::from(p)),
275 geo_types::Geometry::MultiLineString(l) => {
276 Geometry::MultiGeometry(MultiGeometry::from(l))
277 }
278 geo_types::Geometry::MultiPolygon(p) => Geometry::MultiGeometry(MultiGeometry::from(p)),
279 geo_types::Geometry::GeometryCollection(g) => {
280 Geometry::MultiGeometry(MultiGeometry::from(g))
281 }
282 geo_types::Geometry::Rect(r) => Geometry::Polygon(Polygon::from(r)),
283 geo_types::Geometry::Triangle(t) => Geometry::Polygon(Polygon::from(t)),
284 }
285 }
286}
287
288#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
289impl<T> TryFrom<Geometry<T>> for geo_types::Geometry<T>
290where
291 T: CoordType,
292{
293 type Error = Error;
294
295 fn try_from(val: Geometry<T>) -> Result<geo_types::Geometry<T>, Self::Error> {
296 match val {
297 Geometry::Point(p) => Ok(geo_types::Geometry::Point(geo_types::Point::from(p))),
298 Geometry::LineString(l) => Ok(geo_types::Geometry::LineString(
299 geo_types::LineString::from(l),
300 )),
301 Geometry::LinearRing(l) => Ok(geo_types::Geometry::LineString(
302 geo_types::LineString::from(l),
303 )),
304 Geometry::Polygon(p) => Ok(geo_types::Geometry::Polygon(geo_types::Polygon::from(p))),
305 Geometry::MultiGeometry(g) => Ok(geo_types::Geometry::GeometryCollection(
306 geo_types::GeometryCollection::try_from(g)?,
307 )),
308 _ => Err(Error::InvalidGeometry("Can't convert geometry".to_string())),
309 }
310 }
311}
312
313#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
314impl<T> TryFrom<Kml<T>> for Vec<geo_types::Geometry<T>>
315where
316 T: CoordType,
317{
318 type Error = Error;
319
320 fn try_from(k: Kml<T>) -> Result<Vec<geo_types::Geometry<T>>, Self::Error> {
321 match k {
322 Kml::KmlDocument(d) => Ok(d
323 .elements
324 .into_iter()
325 .flat_map(Vec::<geo_types::Geometry<T>>::try_from)
326 .flatten()
327 .collect::<Vec<geo_types::Geometry<T>>>()),
328 Kml::Point(p) => Ok(vec![
329 geo_types::Geometry::Point(geo_types::Point::from(p));
330 1
331 ]),
332 Kml::LineString(l) => Ok(vec![
333 geo_types::Geometry::LineString(
334 geo_types::LineString::from(l),
335 );
336 1
337 ]),
338 Kml::LinearRing(l) => Ok(vec![
339 geo_types::Geometry::LineString(
340 geo_types::LineString::from(l),
341 );
342 1
343 ]),
344 Kml::Polygon(p) => Ok(vec![
345 geo_types::Geometry::Polygon(geo_types::Polygon::from(
346 p
347 ));
348 1
349 ]),
350 Kml::MultiGeometry(g) => Ok(geo_types::GeometryCollection::try_from(g)?.0),
351 Kml::Placemark(p) => Ok(if let Some(g) = p.geometry {
352 vec![geo_types::Geometry::try_from(g)?; 1]
353 } else {
354 vec![]
355 }),
356 Kml::Document { elements, .. } => Ok(elements
357 .into_iter()
358 .flat_map(Vec::<geo_types::Geometry<T>>::try_from)
359 .flatten()
360 .collect()),
361 Kml::Folder(f) => Ok(f
362 .elements
363 .into_iter()
364 .flat_map(Vec::<geo_types::Geometry<T>>::try_from)
365 .flatten()
366 .collect()),
367 _ => Ok(vec![]),
368 }
369 }
370}
371
372#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
373impl<T> TryFrom<Kml<T>> for geo_types::GeometryCollection<T>
374where
375 T: CoordType,
376{
377 type Error = Error;
378
379 fn try_from(k: Kml<T>) -> Result<geo_types::GeometryCollection<T>, Self::Error> {
380 Ok(geo_types::GeometryCollection(
381 Vec::<geo_types::Geometry<T>>::try_from(k)?,
382 ))
383 }
384}
385
386#[deprecated(
411 since = "0.8.7",
412 note = "use `geo_types::GeometryCollection::try_from(&k)` instead"
413)]
414#[cfg_attr(docsrs, doc(cfg(feature = "geo-types")))]
415pub fn quick_collection<T>(k: Kml<T>) -> Result<geo_types::GeometryCollection<T>, Error>
416where
417 T: CoordType,
418{
419 geo_types::GeometryCollection::try_from(k)
420}
421
422#[cfg(test)]
423mod tests {
424 use super::*;
425 use crate::types::Folder;
426 use crate::KmlDocument;
427
428 #[test]
429 fn test_try_from_collection() {
430 let k = KmlDocument {
431 elements: vec![
432 Kml::Point(Point::from(Coord::from((1., 1.)))),
433 Kml::Folder(Folder {
434 elements: vec![
435 Kml::LineString(LineString::from(vec![
436 Coord::from((1., 1.)),
437 Coord::from((2., 2.)),
438 ])),
439 Kml::Point(Point::from(Coord::from((3., 3.)))),
440 ],
441 ..Default::default()
442 }),
443 ],
444 ..Default::default()
445 };
446
447 let gc = geo_types::GeometryCollection(vec![
448 geo_types::Geometry::Point(geo_types::Point::from((1., 1.))),
449 geo_types::Geometry::LineString(geo_types::LineString::from(vec![(1., 1.), (2., 2.)])),
450 geo_types::Geometry::Point(geo_types::Point::from((3., 3.))),
451 ]);
452 assert_eq!(
453 geo_types::GeometryCollection::try_from(Kml::KmlDocument(k)).unwrap(),
454 gc
455 );
456 }
457}