1use std::marker::PhantomData;
2
3#[cfg(feature = "geo-types")]
4use geo_types::{
5 CoordNum, Geometry, GeometryCollection, Line, LineString, MultiLineString, MultiPoint,
6 MultiPolygon, Point, Polygon, Rect, Triangle,
7};
8
9use crate::{
10 Dimensions, GeometryCollectionTrait, LineStringTrait, LineTrait, MultiLineStringTrait,
11 MultiPointTrait, MultiPolygonTrait, PointTrait, PolygonTrait, RectTrait, TriangleTrait,
12 UnimplementedGeometryCollection, UnimplementedLine, UnimplementedLineString,
13 UnimplementedMultiLineString, UnimplementedMultiPoint, UnimplementedMultiPolygon,
14 UnimplementedPoint, UnimplementedPolygon, UnimplementedRect, UnimplementedTriangle,
15};
16
17#[allow(clippy::type_complexity)]
19pub trait GeometryTrait {
20 type T;
22
23 type PointType<'a>: 'a + PointTrait<T = Self::T>
25 where
26 Self: 'a;
27
28 type LineStringType<'a>: 'a + LineStringTrait<T = Self::T>
30 where
31 Self: 'a;
32
33 type PolygonType<'a>: 'a + PolygonTrait<T = Self::T>
35 where
36 Self: 'a;
37
38 type MultiPointType<'a>: 'a + MultiPointTrait<T = Self::T>
40 where
41 Self: 'a;
42
43 type MultiLineStringType<'a>: 'a + MultiLineStringTrait<T = Self::T>
45 where
46 Self: 'a;
47
48 type MultiPolygonType<'a>: 'a + MultiPolygonTrait<T = Self::T>
50 where
51 Self: 'a;
52
53 type GeometryCollectionType<'a>: 'a + GeometryCollectionTrait<T = Self::T>
55 where
56 Self: 'a;
57
58 type RectType<'a>: 'a + RectTrait<T = Self::T>
60 where
61 Self: 'a;
62
63 type TriangleType<'a>: 'a + TriangleTrait<T = Self::T>
65 where
66 Self: 'a;
67
68 type LineType<'a>: 'a + LineTrait<T = Self::T>
70 where
71 Self: 'a;
72
73 fn dim(&self) -> Dimensions;
75
76 fn as_type(
79 &self,
80 ) -> GeometryType<
81 '_,
82 Self::PointType<'_>,
83 Self::LineStringType<'_>,
84 Self::PolygonType<'_>,
85 Self::MultiPointType<'_>,
86 Self::MultiLineStringType<'_>,
87 Self::MultiPolygonType<'_>,
88 Self::GeometryCollectionType<'_>,
89 Self::RectType<'_>,
90 Self::TriangleType<'_>,
91 Self::LineType<'_>,
92 >;
93}
94
95#[derive(Debug)]
98pub enum GeometryType<'a, P, LS, Y, MP, ML, MY, GC, R, T, L>
99where
100 P: PointTrait,
101 LS: LineStringTrait,
102 Y: PolygonTrait,
103 MP: MultiPointTrait,
104 ML: MultiLineStringTrait,
105 MY: MultiPolygonTrait,
106 GC: GeometryCollectionTrait,
107 R: RectTrait,
108 T: TriangleTrait,
109 L: LineTrait,
110{
111 Point(&'a P),
113 LineString(&'a LS),
115 Polygon(&'a Y),
117 MultiPoint(&'a MP),
119 MultiLineString(&'a ML),
121 MultiPolygon(&'a MY),
123 GeometryCollection(&'a GC),
125 Rect(&'a R),
127 Triangle(&'a T),
129 Line(&'a L),
131}
132
133#[cfg(feature = "geo-types")]
134impl<T: CoordNum> GeometryTrait for Geometry<T> {
135 type T = T;
136 type PointType<'b>
137 = Point<Self::T>
138 where
139 Self: 'b;
140 type LineStringType<'b>
141 = LineString<Self::T>
142 where
143 Self: 'b;
144 type PolygonType<'b>
145 = Polygon<Self::T>
146 where
147 Self: 'b;
148 type MultiPointType<'b>
149 = MultiPoint<Self::T>
150 where
151 Self: 'b;
152 type MultiLineStringType<'b>
153 = MultiLineString<Self::T>
154 where
155 Self: 'b;
156 type MultiPolygonType<'b>
157 = MultiPolygon<Self::T>
158 where
159 Self: 'b;
160 type GeometryCollectionType<'b>
161 = GeometryCollection<Self::T>
162 where
163 Self: 'b;
164 type RectType<'b>
165 = Rect<Self::T>
166 where
167 Self: 'b;
168 type TriangleType<'b>
169 = Triangle<Self::T>
170 where
171 Self: 'b;
172 type LineType<'b>
173 = Line<Self::T>
174 where
175 Self: 'b;
176
177 fn dim(&self) -> Dimensions {
178 Dimensions::Xy
179 }
180
181 fn as_type(
182 &self,
183 ) -> GeometryType<
184 '_,
185 Point<T>,
186 LineString<T>,
187 Polygon<T>,
188 MultiPoint<T>,
189 MultiLineString<T>,
190 MultiPolygon<T>,
191 GeometryCollection<T>,
192 Rect<T>,
193 Triangle<T>,
194 Line<T>,
195 > {
196 match self {
197 Geometry::Point(p) => GeometryType::Point(p),
198 Geometry::LineString(p) => GeometryType::LineString(p),
199 Geometry::Polygon(p) => GeometryType::Polygon(p),
200 Geometry::MultiPoint(p) => GeometryType::MultiPoint(p),
201 Geometry::MultiLineString(p) => GeometryType::MultiLineString(p),
202 Geometry::MultiPolygon(p) => GeometryType::MultiPolygon(p),
203 Geometry::GeometryCollection(p) => GeometryType::GeometryCollection(p),
204 Geometry::Rect(p) => GeometryType::Rect(p),
205 Geometry::Triangle(p) => GeometryType::Triangle(p),
206 Geometry::Line(p) => GeometryType::Line(p),
207 }
208 }
209}
210
211#[cfg(feature = "geo-types")]
212impl<'a, T: CoordNum + 'a> GeometryTrait for &'a Geometry<T> {
213 type T = T;
214 type PointType<'b>
215 = Point<Self::T>
216 where
217 Self: 'b;
218 type LineStringType<'b>
219 = LineString<Self::T>
220 where
221 Self: 'b;
222 type PolygonType<'b>
223 = Polygon<Self::T>
224 where
225 Self: 'b;
226 type MultiPointType<'b>
227 = MultiPoint<Self::T>
228 where
229 Self: 'b;
230 type MultiLineStringType<'b>
231 = MultiLineString<Self::T>
232 where
233 Self: 'b;
234 type MultiPolygonType<'b>
235 = MultiPolygon<Self::T>
236 where
237 Self: 'b;
238 type GeometryCollectionType<'b>
239 = GeometryCollection<Self::T>
240 where
241 Self: 'b;
242 type RectType<'b>
243 = Rect<Self::T>
244 where
245 Self: 'b;
246 type TriangleType<'b>
247 = Triangle<Self::T>
248 where
249 Self: 'b;
250 type LineType<'b>
251 = Line<Self::T>
252 where
253 Self: 'b;
254
255 fn dim(&self) -> Dimensions {
256 Dimensions::Xy
257 }
258
259 fn as_type(
260 &self,
261 ) -> GeometryType<
262 '_,
263 Point<T>,
264 LineString<T>,
265 Polygon<T>,
266 MultiPoint<T>,
267 MultiLineString<T>,
268 MultiPolygon<T>,
269 GeometryCollection<T>,
270 Rect<T>,
271 Triangle<T>,
272 Line<T>,
273 > {
274 match self {
275 Geometry::Point(p) => GeometryType::Point(p),
276 Geometry::LineString(p) => GeometryType::LineString(p),
277 Geometry::Polygon(p) => GeometryType::Polygon(p),
278 Geometry::MultiPoint(p) => GeometryType::MultiPoint(p),
279 Geometry::MultiLineString(p) => GeometryType::MultiLineString(p),
280 Geometry::MultiPolygon(p) => GeometryType::MultiPolygon(p),
281 Geometry::GeometryCollection(p) => GeometryType::GeometryCollection(p),
282 Geometry::Rect(p) => GeometryType::Rect(p),
283 Geometry::Triangle(p) => GeometryType::Triangle(p),
284 Geometry::Line(p) => GeometryType::Line(p),
285 }
286 }
287}
288
289macro_rules! impl_specialization {
292 ($geometry_type:ident) => {
293 #[cfg(feature = "geo-types")]
294 impl<T: CoordNum> GeometryTrait for $geometry_type<T> {
295 type T = T;
296 type PointType<'b>
297 = Point<Self::T>
298 where
299 Self: 'b;
300 type LineStringType<'b>
301 = LineString<Self::T>
302 where
303 Self: 'b;
304 type PolygonType<'b>
305 = Polygon<Self::T>
306 where
307 Self: 'b;
308 type MultiPointType<'b>
309 = MultiPoint<Self::T>
310 where
311 Self: 'b;
312 type MultiLineStringType<'b>
313 = MultiLineString<Self::T>
314 where
315 Self: 'b;
316 type MultiPolygonType<'b>
317 = MultiPolygon<Self::T>
318 where
319 Self: 'b;
320 type GeometryCollectionType<'b>
321 = GeometryCollection<Self::T>
322 where
323 Self: 'b;
324 type RectType<'b>
325 = Rect<Self::T>
326 where
327 Self: 'b;
328 type TriangleType<'b>
329 = Triangle<Self::T>
330 where
331 Self: 'b;
332 type LineType<'b>
333 = Line<Self::T>
334 where
335 Self: 'b;
336
337 fn dim(&self) -> Dimensions {
338 Dimensions::Xy
339 }
340
341 fn as_type(
342 &self,
343 ) -> GeometryType<
344 '_,
345 Point<T>,
346 LineString<T>,
347 Polygon<T>,
348 MultiPoint<T>,
349 MultiLineString<T>,
350 MultiPolygon<T>,
351 GeometryCollection<T>,
352 Rect<T>,
353 Triangle<T>,
354 Line<T>,
355 > {
356 GeometryType::$geometry_type(self)
357 }
358 }
359
360 #[cfg(feature = "geo-types")]
361 impl<'a, T: CoordNum + 'a> GeometryTrait for &'a $geometry_type<T> {
362 type T = T;
363 type PointType<'b>
364 = Point<Self::T>
365 where
366 Self: 'b;
367 type LineStringType<'b>
368 = LineString<Self::T>
369 where
370 Self: 'b;
371 type PolygonType<'b>
372 = Polygon<Self::T>
373 where
374 Self: 'b;
375 type MultiPointType<'b>
376 = MultiPoint<Self::T>
377 where
378 Self: 'b;
379 type MultiLineStringType<'b>
380 = MultiLineString<Self::T>
381 where
382 Self: 'b;
383 type MultiPolygonType<'b>
384 = MultiPolygon<Self::T>
385 where
386 Self: 'b;
387 type GeometryCollectionType<'b>
388 = GeometryCollection<Self::T>
389 where
390 Self: 'b;
391 type RectType<'b>
392 = Rect<Self::T>
393 where
394 Self: 'b;
395 type TriangleType<'b>
396 = Triangle<Self::T>
397 where
398 Self: 'b;
399 type LineType<'b>
400 = Line<Self::T>
401 where
402 Self: 'b;
403
404 fn dim(&self) -> Dimensions {
405 Dimensions::Xy
406 }
407
408 fn as_type(
409 &self,
410 ) -> GeometryType<
411 '_,
412 Point<T>,
413 LineString<T>,
414 Polygon<T>,
415 MultiPoint<T>,
416 MultiLineString<T>,
417 MultiPolygon<T>,
418 GeometryCollection<T>,
419 Rect<T>,
420 Triangle<T>,
421 Line<T>,
422 > {
423 GeometryType::$geometry_type(self)
424 }
425 }
426 };
427}
428
429impl_specialization!(Point);
430impl_specialization!(LineString);
431impl_specialization!(Polygon);
432impl_specialization!(MultiPoint);
433impl_specialization!(MultiLineString);
434impl_specialization!(MultiPolygon);
435impl_specialization!(GeometryCollection);
436impl_specialization!(Rect);
437impl_specialization!(Triangle);
438impl_specialization!(Line);
439
440pub struct UnimplementedGeometry<T>(PhantomData<T>);
446
447impl<T> GeometryTrait for UnimplementedGeometry<T> {
448 type T = T;
449 type PointType<'b>
450 = UnimplementedPoint<T>
451 where
452 Self: 'b;
453 type LineStringType<'b>
454 = UnimplementedLineString<Self::T>
455 where
456 Self: 'b;
457 type PolygonType<'b>
458 = UnimplementedPolygon<Self::T>
459 where
460 Self: 'b;
461 type MultiPointType<'b>
462 = UnimplementedMultiPoint<Self::T>
463 where
464 Self: 'b;
465 type MultiLineStringType<'b>
466 = UnimplementedMultiLineString<Self::T>
467 where
468 Self: 'b;
469 type MultiPolygonType<'b>
470 = UnimplementedMultiPolygon<Self::T>
471 where
472 Self: 'b;
473 type GeometryCollectionType<'b>
474 = UnimplementedGeometryCollection<Self::T>
475 where
476 Self: 'b;
477 type RectType<'b>
478 = UnimplementedRect<Self::T>
479 where
480 Self: 'b;
481 type TriangleType<'b>
482 = UnimplementedTriangle<Self::T>
483 where
484 Self: 'b;
485 type LineType<'b>
486 = UnimplementedLine<Self::T>
487 where
488 Self: 'b;
489
490 fn dim(&self) -> Dimensions {
491 unimplemented!()
492 }
493
494 fn as_type(
495 &self,
496 ) -> GeometryType<
497 '_,
498 Self::PointType<'_>,
499 Self::LineStringType<'_>,
500 Self::PolygonType<'_>,
501 Self::MultiPointType<'_>,
502 Self::MultiLineStringType<'_>,
503 Self::MultiPolygonType<'_>,
504 Self::GeometryCollectionType<'_>,
505 Self::RectType<'_>,
506 Self::TriangleType<'_>,
507 Self::LineType<'_>,
508 > {
509 unimplemented!()
510 }
511}
512
513macro_rules! impl_unimplemented_specialization {
516 ($geometry_type:ident, $variant:expr) => {
517 impl<T> GeometryTrait for $geometry_type<T> {
518 type T = T;
519 type PointType<'b>
520 = UnimplementedPoint<Self::T>
521 where
522 Self: 'b;
523 type LineStringType<'b>
524 = UnimplementedLineString<Self::T>
525 where
526 Self: 'b;
527 type PolygonType<'b>
528 = UnimplementedPolygon<Self::T>
529 where
530 Self: 'b;
531 type MultiPointType<'b>
532 = UnimplementedMultiPoint<Self::T>
533 where
534 Self: 'b;
535 type MultiLineStringType<'b>
536 = UnimplementedMultiLineString<Self::T>
537 where
538 Self: 'b;
539 type MultiPolygonType<'b>
540 = UnimplementedMultiPolygon<Self::T>
541 where
542 Self: 'b;
543 type GeometryCollectionType<'b>
544 = UnimplementedGeometryCollection<Self::T>
545 where
546 Self: 'b;
547 type RectType<'b>
548 = UnimplementedRect<Self::T>
549 where
550 Self: 'b;
551 type TriangleType<'b>
552 = UnimplementedTriangle<Self::T>
553 where
554 Self: 'b;
555 type LineType<'b>
556 = UnimplementedLine<Self::T>
557 where
558 Self: 'b;
559
560 fn dim(&self) -> Dimensions {
561 unimplemented!()
562 }
563
564 fn as_type(
565 &self,
566 ) -> GeometryType<
567 '_,
568 Self::PointType<'_>,
569 Self::LineStringType<'_>,
570 Self::PolygonType<'_>,
571 Self::MultiPointType<'_>,
572 Self::MultiLineStringType<'_>,
573 Self::MultiPolygonType<'_>,
574 Self::GeometryCollectionType<'_>,
575 Self::RectType<'_>,
576 Self::TriangleType<'_>,
577 Self::LineType<'_>,
578 > {
579 $variant(self)
580 }
581 }
582
583 impl<'a, T> GeometryTrait for &'a $geometry_type<T> {
584 type T = T;
585 type PointType<'b>
586 = UnimplementedPoint<Self::T>
587 where
588 Self: 'b;
589 type LineStringType<'b>
590 = UnimplementedLineString<Self::T>
591 where
592 Self: 'b;
593 type PolygonType<'b>
594 = UnimplementedPolygon<Self::T>
595 where
596 Self: 'b;
597 type MultiPointType<'b>
598 = UnimplementedMultiPoint<Self::T>
599 where
600 Self: 'b;
601 type MultiLineStringType<'b>
602 = UnimplementedMultiLineString<Self::T>
603 where
604 Self: 'b;
605 type MultiPolygonType<'b>
606 = UnimplementedMultiPolygon<Self::T>
607 where
608 Self: 'b;
609 type GeometryCollectionType<'b>
610 = UnimplementedGeometryCollection<Self::T>
611 where
612 Self: 'b;
613 type RectType<'b>
614 = UnimplementedRect<Self::T>
615 where
616 Self: 'b;
617 type TriangleType<'b>
618 = UnimplementedTriangle<Self::T>
619 where
620 Self: 'b;
621 type LineType<'b>
622 = UnimplementedLine<Self::T>
623 where
624 Self: 'b;
625
626 fn dim(&self) -> Dimensions {
627 unimplemented!()
628 }
629
630 fn as_type(
631 &self,
632 ) -> GeometryType<
633 '_,
634 Self::PointType<'_>,
635 Self::LineStringType<'_>,
636 Self::PolygonType<'_>,
637 Self::MultiPointType<'_>,
638 Self::MultiLineStringType<'_>,
639 Self::MultiPolygonType<'_>,
640 Self::GeometryCollectionType<'_>,
641 Self::RectType<'_>,
642 Self::TriangleType<'_>,
643 Self::LineType<'_>,
644 > {
645 $variant(self)
646 }
647 }
648 };
649}
650
651impl_unimplemented_specialization!(UnimplementedPoint, GeometryType::Point);
652impl_unimplemented_specialization!(UnimplementedLineString, GeometryType::LineString);
653impl_unimplemented_specialization!(UnimplementedPolygon, GeometryType::Polygon);
654impl_unimplemented_specialization!(UnimplementedMultiPoint, GeometryType::MultiPoint);
655impl_unimplemented_specialization!(UnimplementedMultiLineString, GeometryType::MultiLineString);
656impl_unimplemented_specialization!(UnimplementedMultiPolygon, GeometryType::MultiPolygon);
657impl_unimplemented_specialization!(
658 UnimplementedGeometryCollection,
659 GeometryType::GeometryCollection
660);
661impl_unimplemented_specialization!(UnimplementedRect, GeometryType::Rect);
662impl_unimplemented_specialization!(UnimplementedTriangle, GeometryType::Triangle);
663impl_unimplemented_specialization!(UnimplementedLine, GeometryType::Line);
664
665#[cfg(test)]
666mod test {
667 #[test]
669 #[cfg(feature = "geo-types")]
670 fn geo_types_implement_geometry_trait() {
671 use geo_types::{
672 coord, Geometry, GeometryCollection, Line, LineString, MultiLineString, MultiPoint,
673 MultiPolygon, Point, Polygon, Rect, Triangle,
674 };
675
676 use crate::GeometryTrait;
677
678 fn requires_geometry_trait<G: GeometryTrait>(_geometry: &G) {}
679
680 let point: Point = Point::new(0.0, 0.0);
681 requires_geometry_trait(&point);
682
683 let line: Line = Line::new(coord! { x: 0.0, y: 0.0 }, coord! { x: 1.0, y: 1.0 });
684 requires_geometry_trait(&line);
685
686 let line_string: LineString =
687 LineString::from(vec![coord! { x: 0.0, y: 0.0 }, coord! { x: 1.0, y: 1.0 }]);
688 requires_geometry_trait(&line_string);
689
690 let polygon: Polygon = Polygon::new(line_string.clone(), vec![]);
691 requires_geometry_trait(&polygon);
692
693 let multi_point: MultiPoint = MultiPoint::from(vec![point]);
694 requires_geometry_trait(&multi_point);
695
696 let multi_line_string: MultiLineString = MultiLineString(vec![line_string.clone()]);
697 requires_geometry_trait(&multi_line_string);
698
699 let multi_polygon: MultiPolygon = MultiPolygon::from(vec![polygon.clone()]);
700 requires_geometry_trait(&multi_polygon);
701
702 let geometry_collection: GeometryCollection =
703 GeometryCollection::from(vec![Geometry::Point(point)]);
704 requires_geometry_trait(&geometry_collection);
705
706 let rect: Rect = Rect::new(coord! { x: 0.0, y: 0.0 }, coord! { x: 1.0, y: 1.0 });
707 requires_geometry_trait(&rect);
708
709 let triangle: Triangle = Triangle::new(
710 coord! { x: 0.0, y: 0.0 },
711 coord! { x: 1.0, y: 0.0 },
712 coord! { x: 0.0, y: 1.0 },
713 );
714 requires_geometry_trait(&triangle);
715
716 let geometry: Geometry = Geometry::Point(point);
717 requires_geometry_trait(&geometry);
718 }
719}