shapefile/
geo_traits_impl.rs1use std::hint::unreachable_unchecked;
2
3use crate::{
4 Multipoint, MultipointM, MultipointZ, Point, PointM, PointZ, PolygonRing, Polyline, PolylineM,
5 PolylineZ, NO_DATA,
6};
7use geo_traits::{
8 CoordTrait, LineStringTrait, MultiLineStringTrait, MultiPointTrait, MultiPolygonTrait,
9 PointTrait, PolygonTrait,
10};
11
12impl CoordTrait for Point {
14 type T = f64;
15
16 fn dim(&self) -> geo_traits::Dimensions {
17 geo_traits::Dimensions::Xy
18 }
19
20 fn nth_or_panic(&self, n: usize) -> Self::T {
21 match n {
22 0 => self.x(),
23 1 => self.y(),
24 _ => panic!("invalid dimension index"),
25 }
26 }
27
28 unsafe fn nth_unchecked(&self, n: usize) -> Self::T {
29 match n {
30 0 => self.x(),
31 1 => self.y(),
32 _ => unreachable_unchecked(),
33 }
34 }
35
36 fn x(&self) -> Self::T {
37 self.x
38 }
39
40 fn y(&self) -> Self::T {
41 self.y
42 }
43}
44
45impl CoordTrait for &Point {
46 type T = f64;
47
48 fn dim(&self) -> geo_traits::Dimensions {
49 geo_traits::Dimensions::Xy
50 }
51
52 fn nth_or_panic(&self, n: usize) -> Self::T {
53 match n {
54 0 => self.x(),
55 1 => self.y(),
56 _ => panic!("invalid dimension index"),
57 }
58 }
59
60 unsafe fn nth_unchecked(&self, n: usize) -> Self::T {
61 match n {
62 0 => self.x(),
63 1 => self.y(),
64 _ => unreachable_unchecked(),
65 }
66 }
67
68 fn x(&self) -> Self::T {
69 self.x
70 }
71
72 fn y(&self) -> Self::T {
73 self.y
74 }
75}
76
77impl PointTrait for Point {
78 type T = f64;
79 type CoordType<'a>
80 = &'a Point
81 where
82 Self: 'a;
83
84 fn dim(&self) -> geo_traits::Dimensions {
85 geo_traits::Dimensions::Xy
86 }
87
88 fn coord(&self) -> Option<Self::CoordType<'_>> {
89 Some(self)
90 }
91}
92
93impl PointTrait for &Point {
94 type T = f64;
95 type CoordType<'a>
96 = &'a Point
97 where
98 Self: 'a;
99
100 fn dim(&self) -> geo_traits::Dimensions {
101 geo_traits::Dimensions::Xy
102 }
103
104 fn coord(&self) -> Option<Self::CoordType<'_>> {
105 Some(self)
106 }
107}
108
109impl CoordTrait for PointM {
111 type T = f64;
112
113 fn dim(&self) -> geo_traits::Dimensions {
114 if self.m <= NO_DATA {
115 geo_traits::Dimensions::Xy
116 } else {
117 geo_traits::Dimensions::Xym
118 }
119 }
120
121 fn nth_or_panic(&self, n: usize) -> Self::T {
122 match n {
123 0 => self.x(),
124 1 => self.y(),
125 2 => self.m,
126 _ => panic!("invalid dimension index"),
127 }
128 }
129
130 fn x(&self) -> Self::T {
131 self.x
132 }
133
134 fn y(&self) -> Self::T {
135 self.y
136 }
137}
138
139impl CoordTrait for &PointM {
140 type T = f64;
141
142 fn dim(&self) -> geo_traits::Dimensions {
143 if self.m <= NO_DATA {
144 geo_traits::Dimensions::Xy
145 } else {
146 geo_traits::Dimensions::Xym
147 }
148 }
149
150 fn nth_or_panic(&self, n: usize) -> Self::T {
151 match n {
152 0 => self.x(),
153 1 => self.y(),
154 2 => self.m,
155 _ => panic!("invalid dimension index"),
156 }
157 }
158
159 fn x(&self) -> Self::T {
160 self.x
161 }
162
163 fn y(&self) -> Self::T {
164 self.y
165 }
166}
167
168impl PointTrait for PointM {
169 type T = f64;
170 type CoordType<'a>
171 = &'a PointM
172 where
173 Self: 'a;
174
175 fn dim(&self) -> geo_traits::Dimensions {
176 if self.m <= NO_DATA {
177 geo_traits::Dimensions::Xy
178 } else {
179 geo_traits::Dimensions::Xym
180 }
181 }
182
183 fn coord(&self) -> Option<Self::CoordType<'_>> {
184 Some(self)
185 }
186}
187
188impl PointTrait for &PointM {
189 type T = f64;
190 type CoordType<'a>
191 = &'a PointM
192 where
193 Self: 'a;
194
195 fn dim(&self) -> geo_traits::Dimensions {
196 if self.m <= NO_DATA {
197 geo_traits::Dimensions::Xy
198 } else {
199 geo_traits::Dimensions::Xym
200 }
201 }
202
203 fn coord(&self) -> Option<Self::CoordType<'_>> {
204 Some(self)
205 }
206}
207
208impl CoordTrait for PointZ {
210 type T = f64;
211
212 fn dim(&self) -> geo_traits::Dimensions {
213 if self.m <= NO_DATA {
214 geo_traits::Dimensions::Xyz
215 } else {
216 geo_traits::Dimensions::Xyzm
217 }
218 }
219
220 fn nth_or_panic(&self, n: usize) -> Self::T {
221 match n {
222 0 => self.x(),
223 1 => self.y(),
224 2 => self.z,
225 3 => {
226 if self.m > NO_DATA {
227 self.m
228 } else {
229 panic!("asked for 4th item from coordinate but this coordinate does not have 4 dimensions.")
230 }
231 }
232 _ => panic!("invalid dimension index"),
233 }
234 }
235
236 fn x(&self) -> Self::T {
237 self.x
238 }
239
240 fn y(&self) -> Self::T {
241 self.y
242 }
243}
244
245impl CoordTrait for &PointZ {
246 type T = f64;
247
248 fn dim(&self) -> geo_traits::Dimensions {
249 if self.m <= NO_DATA {
250 geo_traits::Dimensions::Xyz
251 } else {
252 geo_traits::Dimensions::Xyzm
253 }
254 }
255
256 fn nth_or_panic(&self, n: usize) -> Self::T {
257 match n {
258 0 => self.x(),
259 1 => self.y(),
260 2 => self.z,
261 3 => {
262 if self.m > NO_DATA {
263 self.m
264 } else {
265 panic!("asked for 4th item from coordinate but this coordinate does not have 4 dimensions.")
266 }
267 }
268 _ => panic!("invalid dimension index"),
269 }
270 }
271
272 fn x(&self) -> Self::T {
273 self.x
274 }
275
276 fn y(&self) -> Self::T {
277 self.y
278 }
279}
280
281impl PointTrait for PointZ {
282 type T = f64;
283 type CoordType<'a>
284 = &'a PointZ
285 where
286 Self: 'a;
287
288 fn dim(&self) -> geo_traits::Dimensions {
289 if self.m <= NO_DATA {
290 geo_traits::Dimensions::Xyz
291 } else {
292 geo_traits::Dimensions::Xyzm
293 }
294 }
295
296 fn coord(&self) -> Option<Self::CoordType<'_>> {
297 Some(self)
298 }
299}
300
301impl PointTrait for &PointZ {
302 type T = f64;
303 type CoordType<'a>
304 = &'a PointZ
305 where
306 Self: 'a;
307
308 fn dim(&self) -> geo_traits::Dimensions {
309 if self.m <= NO_DATA {
310 geo_traits::Dimensions::Xyz
311 } else {
312 geo_traits::Dimensions::Xyzm
313 }
314 }
315
316 fn coord(&self) -> Option<Self::CoordType<'_>> {
317 Some(self)
318 }
319}
320
321pub struct LineString<'a>(&'a [Point]);
322
323impl LineStringTrait for LineString<'_> {
324 type T = f64;
325 type CoordType<'b>
326 = &'b Point
327 where
328 Self: 'b;
329
330 fn dim(&self) -> geo_traits::Dimensions {
331 geo_traits::Dimensions::Xy
332 }
333
334 fn num_coords(&self) -> usize {
335 self.0.len()
336 }
337
338 unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> {
339 self.0.get_unchecked(i)
340 }
341}
342
343pub struct LineStringM<'a>(&'a [PointM]);
344
345impl LineStringTrait for LineStringM<'_> {
346 type T = f64;
347 type CoordType<'b>
348 = &'b PointM
349 where
350 Self: 'b;
351
352 fn dim(&self) -> geo_traits::Dimensions {
353 geo_traits::Dimensions::Xym
354 }
355
356 fn num_coords(&self) -> usize {
357 self.0.len()
358 }
359
360 unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> {
361 self.0.get_unchecked(i)
362 }
363}
364
365pub struct LineStringZ<'a>(&'a [PointZ]);
366
367impl LineStringTrait for LineStringZ<'_> {
368 type T = f64;
369 type CoordType<'b>
370 = &'b PointZ
371 where
372 Self: 'b;
373
374 fn dim(&self) -> geo_traits::Dimensions {
375 self.0
377 .first()
378 .map(CoordTrait::dim)
379 .unwrap_or(geo_traits::Dimensions::Xyz)
380 }
381
382 fn num_coords(&self) -> usize {
383 self.0.len()
384 }
385
386 unsafe fn coord_unchecked(&self, i: usize) -> Self::CoordType<'_> {
387 self.0.get_unchecked(i)
388 }
389}
390
391pub struct Polygon {
392 outer: Vec<Point>,
393 inner: Vec<Vec<Point>>,
394}
395
396impl<'a> PolygonTrait for &'a Polygon {
397 type T = f64;
398 type RingType<'b>
399 = LineString<'a>
400 where
401 Self: 'b;
402
403 fn dim(&self) -> geo_traits::Dimensions {
404 geo_traits::Dimensions::Xy
405 }
406
407 fn num_interiors(&self) -> usize {
408 self.inner.len()
409 }
410
411 fn exterior(&self) -> Option<Self::RingType<'_>> {
412 Some(LineString(&self.outer))
413 }
414
415 unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> {
416 LineString(&self.inner[i])
417 }
418}
419
420pub struct PolygonM {
421 outer: Vec<PointM>,
422 inner: Vec<Vec<PointM>>,
423}
424
425impl<'a> PolygonTrait for &'a PolygonM {
426 type T = f64;
427 type RingType<'b>
428 = LineStringM<'a>
429 where
430 Self: 'b;
431
432 fn dim(&self) -> geo_traits::Dimensions {
433 geo_traits::Dimensions::Xym
434 }
435
436 fn num_interiors(&self) -> usize {
437 self.inner.len()
438 }
439
440 fn exterior(&self) -> Option<Self::RingType<'_>> {
441 Some(LineStringM(&self.outer))
442 }
443
444 unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> {
445 LineStringM(&self.inner[i])
446 }
447}
448
449pub struct PolygonZ {
450 outer: Vec<PointZ>,
451 inner: Vec<Vec<PointZ>>,
452}
453
454impl<'a> PolygonTrait for &'a PolygonZ {
455 type T = f64;
456 type RingType<'b>
457 = LineStringZ<'a>
458 where
459 Self: 'b;
460
461 fn dim(&self) -> geo_traits::Dimensions {
462 self.outer
464 .first()
465 .map(CoordTrait::dim)
466 .unwrap_or(geo_traits::Dimensions::Xyz)
467 }
468
469 fn num_interiors(&self) -> usize {
470 self.inner.len()
471 }
472
473 fn exterior(&self) -> Option<Self::RingType<'_>> {
474 Some(LineStringZ(&self.outer))
475 }
476
477 unsafe fn interior_unchecked(&self, i: usize) -> Self::RingType<'_> {
478 LineStringZ(&self.inner[i])
479 }
480}
481
482impl MultiPointTrait for Multipoint {
483 type T = f64;
484 type PointType<'b>
485 = &'b Point
486 where
487 Self: 'b;
488
489 fn dim(&self) -> geo_traits::Dimensions {
490 geo_traits::Dimensions::Xy
491 }
492
493 fn num_points(&self) -> usize {
494 self.points().len()
495 }
496
497 unsafe fn point_unchecked(&self, i: usize) -> Self::PointType<'_> {
498 self.point(i).unwrap()
499 }
500}
501
502impl MultiPointTrait for MultipointM {
503 type T = f64;
504 type PointType<'b>
505 = &'b PointM
506 where
507 Self: 'b;
508
509 fn dim(&self) -> geo_traits::Dimensions {
510 geo_traits::Dimensions::Xym
511 }
512
513 fn num_points(&self) -> usize {
514 self.points().len()
515 }
516
517 unsafe fn point_unchecked(&self, i: usize) -> Self::PointType<'_> {
518 self.point(i).unwrap()
519 }
520}
521
522impl MultiPointTrait for MultipointZ {
523 type T = f64;
524 type PointType<'b>
525 = &'b PointZ
526 where
527 Self: 'b;
528
529 fn dim(&self) -> geo_traits::Dimensions {
530 self.points
532 .first()
533 .map(CoordTrait::dim)
534 .unwrap_or(geo_traits::Dimensions::Xyz)
535 }
536
537 fn num_points(&self) -> usize {
538 self.points().len()
539 }
540
541 unsafe fn point_unchecked(&self, i: usize) -> Self::PointType<'_> {
542 self.point(i).unwrap()
543 }
544}
545
546impl MultiLineStringTrait for Polyline {
547 type T = f64;
548 type LineStringType<'a>
549 = LineString<'a>
550 where
551 Self: 'a;
552
553 fn dim(&self) -> geo_traits::Dimensions {
554 geo_traits::Dimensions::Xy
555 }
556
557 fn num_line_strings(&self) -> usize {
558 self.parts().len()
559 }
560
561 unsafe fn line_string_unchecked(&self, i: usize) -> Self::LineStringType<'_> {
562 LineString(self.part(i).unwrap())
563 }
564}
565
566impl MultiLineStringTrait for PolylineM {
567 type T = f64;
568 type LineStringType<'a>
569 = LineStringM<'a>
570 where
571 Self: 'a;
572
573 fn dim(&self) -> geo_traits::Dimensions {
574 geo_traits::Dimensions::Xym
575 }
576
577 fn num_line_strings(&self) -> usize {
578 self.parts().len()
579 }
580
581 unsafe fn line_string_unchecked(&self, i: usize) -> Self::LineStringType<'_> {
582 LineStringM(self.part(i).unwrap())
583 }
584}
585
586impl MultiLineStringTrait for PolylineZ {
587 type T = f64;
588 type LineStringType<'a>
589 = LineStringZ<'a>
590 where
591 Self: 'a;
592
593 fn dim(&self) -> geo_traits::Dimensions {
594 self.parts
596 .first()
597 .and_then(|line_string| line_string.first().map(CoordTrait::dim))
598 .unwrap_or(geo_traits::Dimensions::Xyz)
599 }
600
601 fn num_line_strings(&self) -> usize {
602 self.parts().len()
603 }
604
605 unsafe fn line_string_unchecked(&self, i: usize) -> Self::LineStringType<'_> {
606 LineStringZ(self.part(i).unwrap())
607 }
608}
609
610pub struct MultiPolygon(Vec<Polygon>);
611
612impl From<crate::Polygon> for MultiPolygon {
613 fn from(geom: crate::Polygon) -> Self {
614 let mut last_poly = None;
615 let mut polygons = Vec::new();
616 for ring in geom.into_inner() {
617 match ring {
618 PolygonRing::Outer(points) => {
619 if let Some(poly) = last_poly.take() {
620 polygons.push(poly);
621 }
622 last_poly = Some(Polygon {
623 outer: points,
624 inner: vec![],
625 });
626 }
627 PolygonRing::Inner(points) => {
628 if let Some(poly) = last_poly.as_mut() {
629 poly.inner.push(points);
630 } else {
631 panic!("inner ring without a previous outer ring");
632 }
638 }
639 }
640 }
641
642 if let Some(poly) = last_poly.take() {
643 polygons.push(poly);
644 }
645
646 Self(polygons)
647 }
648}
649
650impl MultiPolygonTrait for MultiPolygon {
651 type T = f64;
652 type PolygonType<'a> = &'a Polygon;
653
654 fn dim(&self) -> geo_traits::Dimensions {
655 geo_traits::Dimensions::Xy
656 }
657
658 fn num_polygons(&self) -> usize {
659 self.0.len()
660 }
661
662 unsafe fn polygon_unchecked(&self, i: usize) -> Self::PolygonType<'_> {
663 &self.0[i]
664 }
665}
666
667pub struct MultiPolygonM(Vec<Polygon>);
668
669impl From<crate::Polygon> for MultiPolygonM {
670 fn from(geom: crate::Polygon) -> Self {
671 let mut last_poly = None;
672 let mut polygons = Vec::new();
673 for ring in geom.into_inner() {
674 match ring {
675 PolygonRing::Outer(points) => {
676 if let Some(poly) = last_poly.take() {
677 polygons.push(poly);
678 }
679 last_poly = Some(Polygon {
680 outer: points,
681 inner: vec![],
682 });
683 }
684 PolygonRing::Inner(points) => {
685 if let Some(poly) = last_poly.as_mut() {
686 poly.inner.push(points);
687 } else {
688 panic!("inner ring without a previous outer ring");
689 }
695 }
696 }
697 }
698
699 if let Some(poly) = last_poly.take() {
700 polygons.push(poly);
701 }
702
703 Self(polygons)
704 }
705}
706
707impl MultiPolygonTrait for MultiPolygonM {
708 type T = f64;
709 type PolygonType<'a> = &'a Polygon;
710
711 fn dim(&self) -> geo_traits::Dimensions {
712 geo_traits::Dimensions::Xym
713 }
714
715 fn num_polygons(&self) -> usize {
716 self.0.len()
717 }
718
719 unsafe fn polygon_unchecked(&self, i: usize) -> Self::PolygonType<'_> {
720 &self.0[i]
721 }
722}
723
724pub struct MultiPolygonZ(Vec<PolygonZ>);
725
726impl From<crate::PolygonZ> for MultiPolygonZ {
727 fn from(geom: crate::PolygonZ) -> Self {
728 let mut last_poly = None;
729 let mut polygons = Vec::new();
730 for ring in geom.into_inner() {
731 match ring {
732 PolygonRing::Outer(points) => {
733 if let Some(poly) = last_poly.take() {
734 polygons.push(poly);
735 }
736 last_poly = Some(PolygonZ {
737 outer: points,
738 inner: vec![],
739 });
740 }
741 PolygonRing::Inner(points) => {
742 if let Some(poly) = last_poly.as_mut() {
743 poly.inner.push(points);
744 } else {
745 panic!("inner ring without a previous outer ring");
746 }
752 }
753 }
754 }
755
756 if let Some(poly) = last_poly.take() {
757 polygons.push(poly);
758 }
759
760 Self(polygons)
761 }
762}
763
764impl MultiPolygonTrait for MultiPolygonZ {
765 type T = f64;
766 type PolygonType<'a> = &'a PolygonZ;
767
768 fn dim(&self) -> geo_traits::Dimensions {
769 self.0
771 .first()
772 .map(|polygon| polygon.dim())
773 .unwrap_or(geo_traits::Dimensions::Xyz)
774 }
775
776 fn num_polygons(&self) -> usize {
777 self.0.len()
778 }
779
780 unsafe fn polygon_unchecked(&self, i: usize) -> Self::PolygonType<'_> {
781 &self.0[i]
782 }
783}