1use crate::{
2 mapbox::MapboxVectorFeature,
3 open::{encode_value, ColumnCacheWriter, FeatureType},
4 weave_2d, weave_3d, zigzag, Point, Point3D, VectorFeatureMethods, VectorGeometry,
5 VectorLines3DWithOffset, VectorLinesWithOffset, VectorPoints, VectorPoints3D,
6};
7use alloc::vec::Vec;
8use libm::round;
9use s2json::{BBox, BBox3D, LineStringMValues, Properties, Shape, Value, BBOX};
10
11pub trait VectorFeature {
13 fn get_type(&self) -> FeatureType;
15 fn properties(&self) -> &Properties;
17 fn has_bbox(&self) -> bool;
19 fn has_offsets(&self) -> bool;
21 fn has_m_values(&self) -> bool;
23 fn load_geometry(&self) -> VectorGeometry;
25 fn m_values(&self) -> Option<LineStringMValues>;
27 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize;
29}
30
31#[derive(Default, Debug, Clone, PartialEq)]
35pub struct BaseVectorPointsFeature {
36 pub id: Option<u64>,
38 pub geometry: VectorPoints,
40 pub properties: Properties,
42 pub bbox: Option<BBox>,
44}
45impl BaseVectorPointsFeature {
46 pub fn new(
48 id: Option<u64>,
49 geometry: VectorPoints,
50 properties: Properties,
51 bbox: Option<BBox>,
52 ) -> Self {
53 Self { id, geometry, properties, bbox }
54 }
55}
56impl VectorFeature for BaseVectorPointsFeature {
57 fn get_type(&self) -> FeatureType {
59 FeatureType::Points
60 }
61
62 fn properties(&self) -> &Properties {
64 &self.properties
65 }
66
67 fn has_bbox(&self) -> bool {
69 self.bbox.is_some()
70 }
71
72 fn has_offsets(&self) -> bool {
74 false
75 }
76
77 fn has_m_values(&self) -> bool {
79 self.geometry.iter().any(|g| g.m.is_some())
80 }
81
82 fn load_geometry(&self) -> VectorGeometry {
83 VectorGeometry::VectorPoints(self.geometry.clone())
84 }
85
86 fn m_values(&self) -> Option<LineStringMValues> {
87 if !self.has_m_values() {
88 return None;
89 }
90 Some(
91 self.geometry
92 .iter()
93 .map(|g| {
94 g.m.clone().unwrap_or_default()
96 })
97 .collect(),
98 )
99 }
100
101 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
102 let geometry = &self.geometry;
103 if geometry.len() == 1 {
104 let point = &geometry[0];
105 weave_2d(zigzag(point.x) as u16, zigzag(point.y) as u16) as usize
106 } else {
107 let mut indices: Vec<u32> = Vec::new();
108 indices.push(cache.add_points(geometry.to_vec()) as u32);
109 if let (Some(m_values), Some(shape)) = (self.m_values(), m_shape) {
111 for m in m_values {
112 indices.push(encode_value(&m, shape, cache) as u32);
113 }
114 }
115 cache.add_indices(indices)
116 }
117 }
118}
119#[derive(Default, Debug, Clone, PartialEq)]
121pub struct BaseVectorPoints3DFeature {
122 pub id: Option<u64>,
124 pub geometry: VectorPoints3D,
126 pub properties: Properties,
128 pub bbox: Option<BBox3D>,
130}
131impl BaseVectorPoints3DFeature {
132 pub fn new(
134 id: Option<u64>,
135 geometry: VectorPoints3D,
136 properties: Properties,
137 bbox: Option<BBox3D>,
138 ) -> Self {
139 Self { id, geometry, properties, bbox }
140 }
141}
142impl VectorFeature for BaseVectorPoints3DFeature {
143 fn get_type(&self) -> FeatureType {
145 FeatureType::Points3D
146 }
147
148 fn properties(&self) -> &Properties {
150 &self.properties
151 }
152
153 fn has_bbox(&self) -> bool {
155 self.bbox.is_some()
156 }
157
158 fn has_offsets(&self) -> bool {
160 false
161 }
162
163 fn has_m_values(&self) -> bool {
165 self.geometry.iter().any(|g| g.m.is_some())
166 }
167
168 fn load_geometry(&self) -> VectorGeometry {
169 VectorGeometry::VectorPoints3D(self.geometry.clone())
170 }
171
172 fn m_values(&self) -> Option<LineStringMValues> {
173 if !self.has_m_values() {
174 return None;
175 }
176 Some(self.geometry.iter().map(|g| g.m.clone().unwrap_or_default()).collect())
177 }
178
179 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
180 let geometry = &self.geometry;
181 if geometry.len() == 1 {
182 let point = &geometry[0];
183 weave_3d(zigzag(point.x) as u16, zigzag(point.y) as u16, zigzag(point.z) as u16)
184 as usize
185 } else {
186 let mut indices: Vec<u32> = Vec::new();
187 indices.push(cache.add_points_3d(geometry.to_vec()) as u32);
188 if let (Some(m_values), Some(shape)) = (self.m_values(), m_shape) {
190 for m in m_values {
191 indices.push(encode_value(&m, shape, cache) as u32);
192 }
193 }
194 cache.add_indices(indices)
195 }
196 }
197}
198
199#[derive(Default, Debug, Clone, PartialEq)]
203pub struct BaseVectorLinesFeature {
204 pub id: Option<u64>,
206 pub geometry: VectorLinesWithOffset,
208 pub properties: Properties,
210 pub bbox: Option<BBox>,
212}
213impl BaseVectorLinesFeature {
214 pub fn new(
216 id: Option<u64>,
217 geometry: VectorLinesWithOffset,
218 properties: Properties,
219 bbox: Option<BBox>,
220 ) -> Self {
221 Self { id, geometry, properties, bbox }
222 }
223}
224impl VectorFeature for BaseVectorLinesFeature {
225 fn get_type(&self) -> FeatureType {
227 FeatureType::Lines
228 }
229
230 fn properties(&self) -> &Properties {
232 &self.properties
233 }
234
235 fn has_bbox(&self) -> bool {
237 self.bbox.is_some()
238 }
239
240 fn has_offsets(&self) -> bool {
242 self.geometry.iter().any(|g| g.has_offset())
243 }
244
245 fn has_m_values(&self) -> bool {
247 self.geometry.iter().any(|g| g.has_m_values())
248 }
249
250 fn load_geometry(&self) -> VectorGeometry {
251 VectorGeometry::VectorLines(self.geometry.to_vec())
252 }
253
254 fn m_values(&self) -> Option<LineStringMValues> {
255 if !self.has_m_values() {
256 return None;
257 }
258 Some(self.geometry.iter().flat_map(|g| g.m_values().unwrap_or_default()).collect())
259 }
260
261 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
262 let geometry = &self.geometry;
263 let mut indices: Vec<u32> = Vec::new();
264 if geometry.len() != 1 {
265 indices.push(geometry.len() as u32)
266 }
267 for line in geometry {
268 if line.has_offset() {
269 indices.push(encode_offset(line.offset));
270 }
271 indices.push(cache.add_points(line.geometry.clone()) as u32);
272 if self.has_m_values() {
274 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
275 for m in m_values {
276 indices.push(encode_value(&m, shape, cache) as u32);
277 }
278 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
279 for _ in 0..line.geometry.len() {
280 indices.push(encode_value(&Value::default(), shape, cache) as u32);
281 }
282 }
283 }
284 }
285 cache.add_indices(indices)
286 }
287}
288
289#[derive(Default, Debug, Clone, PartialEq)]
291pub struct BaseVectorLines3DFeature {
292 pub id: Option<u64>,
294 pub geometry: VectorLines3DWithOffset,
296 pub properties: Properties,
298 pub bbox: Option<BBox3D>,
300}
301impl BaseVectorLines3DFeature {
302 pub fn new(
304 id: Option<u64>,
305 geometry: VectorLines3DWithOffset,
306 properties: Properties,
307 bbox: Option<BBox3D>,
308 ) -> Self {
309 Self { id, geometry, properties, bbox }
310 }
311}
312impl VectorFeature for BaseVectorLines3DFeature {
313 fn get_type(&self) -> FeatureType {
315 FeatureType::Lines3D
316 }
317
318 fn properties(&self) -> &Properties {
320 &self.properties
321 }
322
323 fn has_bbox(&self) -> bool {
325 self.bbox.is_some()
326 }
327
328 fn has_offsets(&self) -> bool {
330 self.geometry.iter().any(|g| g.has_offset())
331 }
332
333 fn has_m_values(&self) -> bool {
335 self.geometry.iter().any(|g| g.has_m_values())
336 }
337
338 fn load_geometry(&self) -> VectorGeometry {
339 VectorGeometry::VectorLines3D(self.geometry.to_vec())
340 }
341
342 fn m_values(&self) -> Option<LineStringMValues> {
343 if !self.has_m_values() {
344 return None;
345 }
346 Some(self.geometry.iter().flat_map(|g| g.m_values().unwrap_or_default()).collect())
347 }
348
349 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
350 let geometry = &self.geometry;
351 let mut indices: Vec<u32> = Vec::new();
352 if geometry.len() != 1 {
353 indices.push(geometry.len() as u32)
354 }
355 for line in geometry {
356 if line.has_offset() {
357 indices.push(encode_offset(line.offset));
358 }
359 indices.push(cache.add_points_3d(line.geometry.clone()) as u32);
360 if self.has_m_values() {
362 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
363 for m in m_values {
364 indices.push(encode_value(&m, shape, cache) as u32);
365 }
366 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
367 for _ in 0..line.geometry.len() {
368 indices.push(encode_value(&Value::default(), shape, cache) as u32);
369 }
370 }
371 }
372 }
373 cache.add_indices(indices)
374 }
375}
376
377#[derive(Default, Debug, Clone, PartialEq)]
381pub struct BaseVectorPolysFeature {
382 pub id: Option<u64>,
384 pub geometry: Vec<VectorLinesWithOffset>,
386 pub properties: Properties,
388 pub bbox: Option<BBox>,
390 pub tessellation: Vec<Point>,
392 pub indices: Vec<u32>,
394}
395impl BaseVectorPolysFeature {
396 pub fn new(
398 id: Option<u64>,
399 geometry: Vec<VectorLinesWithOffset>,
400 properties: Properties,
401 bbox: Option<BBox>,
402 indices: Vec<u32>,
403 tessellation: Vec<Point>,
404 ) -> Self {
405 Self { id, geometry, properties, bbox, indices, tessellation }
406 }
407}
408impl VectorFeature for BaseVectorPolysFeature {
409 fn get_type(&self) -> FeatureType {
411 FeatureType::Polygons
412 }
413
414 fn properties(&self) -> &Properties {
416 &self.properties
417 }
418
419 fn has_bbox(&self) -> bool {
421 self.bbox.is_some()
422 }
423
424 fn has_offsets(&self) -> bool {
426 self.geometry.iter().any(|g| g.iter().any(|l| l.has_offset()))
427 }
428
429 fn has_m_values(&self) -> bool {
431 self.geometry.iter().any(|g| g.iter().any(|l| l.has_m_values()))
432 }
433
434 fn load_geometry(&self) -> VectorGeometry {
435 VectorGeometry::VectorPolys(self.geometry.iter().map(|line| line.to_vec()).collect())
436 }
437
438 fn m_values(&self) -> Option<LineStringMValues> {
439 if !self.has_m_values() {
440 return None;
441 }
442 Some(
443 self.geometry
444 .iter()
445 .flat_map(|g| g.iter().flat_map(|l| l.m_values().unwrap_or_default()))
446 .collect(),
447 )
448 }
449
450 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
451 let geometry = &self.geometry;
452 let mut indices: Vec<u32> = Vec::new();
453 if geometry.len() != 1 {
454 indices.push(geometry.len() as u32)
455 }
456 for poly in geometry {
457 indices.push(poly.len() as u32);
458 for line in poly {
459 if line.has_offset() {
460 indices.push(encode_offset(line.offset));
461 }
462 indices.push(cache.add_points(line.geometry.clone()) as u32);
463 if self.has_m_values() {
465 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
466 for m in m_values {
467 indices.push(encode_value(&m, shape, cache) as u32);
468 }
469 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
470 for _ in 0..line.geometry.len() {
471 indices.push(encode_value(&Value::default(), shape, cache) as u32);
472 }
473 }
474 }
475 }
476 }
477 cache.add_indices(indices)
478 }
479}
480
481#[derive(Default, Debug, Clone, PartialEq)]
483pub struct BaseVectorPolys3DFeature {
484 pub id: Option<u64>,
486 pub geometry: Vec<VectorLines3DWithOffset>,
488 pub properties: Properties,
490 pub bbox: Option<BBox3D>,
492 pub tessellation: Vec<Point3D>,
494 pub indices: Vec<u32>,
496}
497impl BaseVectorPolys3DFeature {
498 pub fn new(
500 id: Option<u64>,
501 geometry: Vec<VectorLines3DWithOffset>,
502 properties: Properties,
503 bbox: Option<BBox3D>,
504 indices: Vec<u32>,
505 tessellation: Vec<Point3D>,
506 ) -> Self {
507 Self { id, geometry, properties, bbox, indices, tessellation }
508 }
509}
510impl VectorFeature for BaseVectorPolys3DFeature {
511 fn get_type(&self) -> FeatureType {
513 FeatureType::Polygons3D
514 }
515
516 fn properties(&self) -> &Properties {
518 &self.properties
519 }
520
521 fn has_bbox(&self) -> bool {
523 self.bbox.is_some()
524 }
525
526 fn has_offsets(&self) -> bool {
528 self.geometry.iter().any(|g| g.iter().any(|l| l.has_offset()))
529 }
530
531 fn has_m_values(&self) -> bool {
533 self.geometry.iter().any(|g| g.iter().any(|l| l.has_m_values()))
534 }
535
536 fn load_geometry(&self) -> VectorGeometry {
537 VectorGeometry::VectorPolys3D(self.geometry.iter().map(|line| line.to_vec()).collect())
538 }
539
540 fn m_values(&self) -> Option<LineStringMValues> {
541 if !self.has_m_values() {
542 return None;
543 }
544 Some(
545 self.geometry
546 .iter()
547 .flat_map(|g| g.iter().flat_map(|l| l.m_values().unwrap_or_default()))
548 .collect(),
549 )
550 }
551
552 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
553 let geometry = &self.geometry;
554 let mut indices: Vec<u32> = Vec::new();
555 if geometry.len() != 1 {
556 indices.push(geometry.len() as u32)
557 }
558 for poly in geometry {
559 indices.push(poly.len() as u32);
560 for line in poly {
561 if line.has_offset() {
562 indices.push(encode_offset(line.offset));
563 }
564 indices.push(cache.add_points_3d(line.geometry.clone()) as u32);
565 if self.has_m_values() {
567 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
568 for m in m_values {
569 indices.push(encode_value(&m, shape, cache) as u32);
570 }
571 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
572 for _ in 0..line.geometry.len() {
573 indices.push(encode_value(&Value::default(), shape, cache) as u32);
574 }
575 }
576 }
577 }
578 }
579 cache.add_indices(indices)
580 }
581}
582
583#[derive(Debug, Clone, PartialEq)]
585pub enum TessellationWrapper {
586 Tessellation(Vec<Point>),
588 Tessellation3D(Vec<Point3D>),
590}
591impl TessellationWrapper {
592 pub fn len(&self) -> usize {
594 match self {
595 TessellationWrapper::Tessellation(points) => points.len(),
596 TessellationWrapper::Tessellation3D(points) => points.len(),
597 }
598 }
599
600 pub fn is_empty(&self) -> bool {
602 match self {
603 TessellationWrapper::Tessellation(points) => points.is_empty(),
604 TessellationWrapper::Tessellation3D(points) => points.is_empty(),
605 }
606 }
607}
608
609#[derive(Debug, Clone, PartialEq)]
611pub enum BaseVectorFeature {
612 BaseVectorPointsFeature(BaseVectorPointsFeature),
614 BaseVectorLinesFeature(BaseVectorLinesFeature),
616 BaseVectorPolysFeature(BaseVectorPolysFeature),
618 BaseVectorPoints3DFeature(BaseVectorPoints3DFeature),
620 BaseVectorLines3DFeature(BaseVectorLines3DFeature),
622 BaseVectorPolys3DFeature(BaseVectorPolys3DFeature),
624}
625impl BaseVectorFeature {
626 pub fn single(&self) -> bool {
628 match self {
629 BaseVectorFeature::BaseVectorPointsFeature(f) => f.geometry.len() == 1,
630 BaseVectorFeature::BaseVectorLinesFeature(f) => f.geometry.len() == 1,
631 BaseVectorFeature::BaseVectorPolysFeature(f) => f.geometry.len() == 1,
632 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.geometry.len() == 1,
633 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.geometry.len() == 1,
634 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.geometry.len() == 1,
635 }
636 }
637
638 pub fn properties(&self) -> &Properties {
640 match self {
641 BaseVectorFeature::BaseVectorPointsFeature(f) => f.properties(),
642 BaseVectorFeature::BaseVectorLinesFeature(f) => f.properties(),
643 BaseVectorFeature::BaseVectorPolysFeature(f) => f.properties(),
644 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.properties(),
645 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.properties(),
646 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.properties(),
647 }
648 }
649
650 pub fn has_m_values(&self) -> bool {
652 match self {
653 BaseVectorFeature::BaseVectorPointsFeature(f) => f.has_m_values(),
654 BaseVectorFeature::BaseVectorLinesFeature(f) => f.has_m_values(),
655 BaseVectorFeature::BaseVectorPolysFeature(f) => f.has_m_values(),
656 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.has_m_values(),
657 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.has_m_values(),
658 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.has_m_values(),
659 }
660 }
661
662 pub fn m_values(&self) -> Option<LineStringMValues> {
664 match self {
665 BaseVectorFeature::BaseVectorPointsFeature(f) => f.m_values(),
666 BaseVectorFeature::BaseVectorLinesFeature(f) => f.m_values(),
667 BaseVectorFeature::BaseVectorPolysFeature(f) => f.m_values(),
668 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.m_values(),
669 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.m_values(),
670 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.m_values(),
671 }
672 }
673
674 pub fn get_type(&self) -> FeatureType {
676 match self {
677 BaseVectorFeature::BaseVectorPointsFeature(f) => f.get_type(),
678 BaseVectorFeature::BaseVectorLinesFeature(f) => f.get_type(),
679 BaseVectorFeature::BaseVectorPolysFeature(f) => f.get_type(),
680 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.get_type(),
681 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.get_type(),
682 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.get_type(),
683 }
684 }
685
686 pub fn id(&self) -> Option<u64> {
688 match self {
689 BaseVectorFeature::BaseVectorPointsFeature(f) => f.id,
690 BaseVectorFeature::BaseVectorLinesFeature(f) => f.id,
691 BaseVectorFeature::BaseVectorPolysFeature(f) => f.id,
692 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.id,
693 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.id,
694 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.id,
695 }
696 }
697
698 pub fn indices(&self) -> Option<Vec<u32>> {
700 match self {
701 BaseVectorFeature::BaseVectorPolysFeature(f) => Some(f.indices.clone()),
702 BaseVectorFeature::BaseVectorPolys3DFeature(f) => Some(f.indices.clone()),
703 _ => None,
704 }
705 }
706
707 pub fn tessellation(&self) -> Option<TessellationWrapper> {
709 match self {
710 BaseVectorFeature::BaseVectorPolysFeature(f) => {
711 Some(TessellationWrapper::Tessellation(f.tessellation.clone()))
712 }
713 BaseVectorFeature::BaseVectorPolys3DFeature(f) => {
714 Some(TessellationWrapper::Tessellation3D(f.tessellation.clone()))
715 }
716 _ => None,
717 }
718 }
719
720 pub fn bbox(&self) -> Option<BBOX> {
722 match self {
723 BaseVectorFeature::BaseVectorPointsFeature(f) => f.bbox.map(BBOX::BBox),
724 BaseVectorFeature::BaseVectorLinesFeature(f) => f.bbox.map(BBOX::BBox),
725 BaseVectorFeature::BaseVectorPolysFeature(f) => f.bbox.map(BBOX::BBox),
726 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.bbox.map(BBOX::BBox3D),
727 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.bbox.map(BBOX::BBox3D),
728 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.bbox.map(BBOX::BBox3D),
729 }
730 }
731
732 pub fn has_offsets(&self) -> bool {
734 match self {
735 BaseVectorFeature::BaseVectorLinesFeature(f) => f.has_offsets(),
736 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.has_offsets(),
737 BaseVectorFeature::BaseVectorPolysFeature(f) => f.has_offsets(),
738 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.has_offsets(),
739 _ => false,
740 }
741 }
742
743 pub fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
745 match self {
746 BaseVectorFeature::BaseVectorPointsFeature(f) => f.encode_to_cache(cache, m_shape),
747 BaseVectorFeature::BaseVectorLinesFeature(f) => f.encode_to_cache(cache, m_shape),
748 BaseVectorFeature::BaseVectorPolysFeature(f) => f.encode_to_cache(cache, m_shape),
749 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.encode_to_cache(cache, m_shape),
750 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.encode_to_cache(cache, m_shape),
751 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.encode_to_cache(cache, m_shape),
752 }
753 }
754}
755impl From<&mut MapboxVectorFeature> for BaseVectorFeature {
756 fn from(mvt: &mut MapboxVectorFeature) -> Self {
757 let id = mvt.id;
758 let properties: Properties = (&mvt.properties).into();
759 let indices = mvt.read_indices();
760 let mut tessellation_floats: Vec<f64> = Vec::new();
761 mvt.add_tessellation(&mut tessellation_floats, 1.0);
762 let tessellation = tess_to_points(tessellation_floats);
764
765 match mvt.load_geometry() {
766 VectorGeometry::VectorPoints(geo) => BaseVectorFeature::BaseVectorPointsFeature(
767 BaseVectorPointsFeature::new(id, geo, properties, None),
768 ),
769 VectorGeometry::VectorLines(geo) => BaseVectorFeature::BaseVectorLinesFeature(
770 BaseVectorLinesFeature::new(id, geo, properties, None),
771 ),
772 VectorGeometry::VectorPolys(geo) => BaseVectorFeature::BaseVectorPolysFeature(
773 BaseVectorPolysFeature::new(id, geo, properties, None, indices, tessellation),
774 ),
775 #[tarpaulin::skip]
776 _ => panic!("unexpected geometry type"),
777 }
778 }
779}
780
781pub fn tess_to_points(tess: Vec<f64>) -> Vec<Point> {
783 tess.chunks(2).map(|chunk| Point::new(round(chunk[0]) as i32, round(chunk[1]) as i32)).collect()
784}
785
786pub fn tess_to_points_3d(tess: Vec<f64>) -> Vec<Point3D> {
788 tess.chunks(3)
789 .map(|chunk| {
790 Point3D::new(round(chunk[0]) as i32, round(chunk[1]) as i32, round(chunk[2]) as i32)
791 })
792 .collect()
793}
794
795pub fn encode_offset(offset: f64) -> u32 {
797 round(offset * 1_000.0) as u32
798}
799
800pub fn decode_offset(offset: u32) -> f64 {
802 (offset as f64) / 1_000.0
803}