1use crate::{
2 mapbox::MapboxVectorFeature,
3 open::{
4 encode_value, ColumnCacheWriter, FeatureType, LineStringMValues, Properties, Shape, Value,
5 },
6 weave_2d, weave_3d, zigzag, BBox, BBox3D, Point, Point3D, VectorFeatureMethods, VectorGeometry,
7 VectorLines3DWithOffset, VectorLinesWithOffset, VectorPoints, VectorPoints3D, BBOX,
8};
9
10use alloc::vec::Vec;
11
12use libm::round;
13
14pub trait VectorFeature {
16 fn get_type(&self) -> FeatureType;
18 fn properties(&self) -> &Properties;
20 fn has_bbox(&self) -> bool;
22 fn has_offsets(&self) -> bool;
24 fn has_m_values(&self) -> bool;
26 fn load_geometry(&self) -> VectorGeometry;
28 fn m_values(&self) -> Option<LineStringMValues>;
30 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize;
32}
33
34#[derive(Default, Debug, Clone, PartialEq)]
38pub struct BaseVectorPointsFeature {
39 pub id: Option<u64>,
41 pub geometry: VectorPoints,
43 pub properties: Properties,
45 pub bbox: Option<BBox>,
47}
48impl BaseVectorPointsFeature {
49 pub fn new(
51 id: Option<u64>,
52 geometry: VectorPoints,
53 properties: Properties,
54 bbox: Option<BBox>,
55 ) -> Self {
56 Self { id, geometry, properties, bbox }
57 }
58}
59impl VectorFeature for BaseVectorPointsFeature {
60 fn get_type(&self) -> FeatureType {
62 FeatureType::Points
63 }
64
65 fn properties(&self) -> &Properties {
67 &self.properties
68 }
69
70 fn has_bbox(&self) -> bool {
72 self.bbox.is_some()
73 }
74
75 fn has_offsets(&self) -> bool {
77 false
78 }
79
80 fn has_m_values(&self) -> bool {
82 self.geometry.iter().any(|g| g.m.is_some())
83 }
84
85 fn load_geometry(&self) -> VectorGeometry {
86 VectorGeometry::VectorPoints(self.geometry.clone())
87 }
88
89 fn m_values(&self) -> Option<LineStringMValues> {
90 if !self.has_m_values() {
91 return None;
92 }
93 Some(
94 self.geometry
95 .iter()
96 .map(|g| {
97 g.m.clone().unwrap_or_default()
99 })
100 .collect(),
101 )
102 }
103
104 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
105 let geometry = &self.geometry;
106 if geometry.len() == 1 {
107 let point = &geometry[0];
108 weave_2d(zigzag(point.x) as u16, zigzag(point.y) as u16) as usize
109 } else {
110 let mut indices: Vec<u32> = Vec::new();
111 indices.push(cache.add_points(geometry.to_vec()) as u32);
112 if let (Some(m_values), Some(shape)) = (self.m_values(), m_shape) {
114 for m in m_values {
115 indices.push(encode_value(&m, shape, cache) as u32);
116 }
117 }
118 cache.add_indices(indices)
119 }
120 }
121}
122#[derive(Default, Debug, Clone, PartialEq)]
124pub struct BaseVectorPoints3DFeature {
125 pub id: Option<u64>,
127 pub geometry: VectorPoints3D,
129 pub properties: Properties,
131 pub bbox: Option<BBox3D>,
133}
134impl BaseVectorPoints3DFeature {
135 pub fn new(
137 id: Option<u64>,
138 geometry: VectorPoints3D,
139 properties: Properties,
140 bbox: Option<BBox3D>,
141 ) -> Self {
142 Self { id, geometry, properties, bbox }
143 }
144}
145impl VectorFeature for BaseVectorPoints3DFeature {
146 fn get_type(&self) -> FeatureType {
148 FeatureType::Points3D
149 }
150
151 fn properties(&self) -> &Properties {
153 &self.properties
154 }
155
156 fn has_bbox(&self) -> bool {
158 self.bbox.is_some()
159 }
160
161 fn has_offsets(&self) -> bool {
163 false
164 }
165
166 fn has_m_values(&self) -> bool {
168 self.geometry.iter().any(|g| g.m.is_some())
169 }
170
171 fn load_geometry(&self) -> VectorGeometry {
172 VectorGeometry::VectorPoints3D(self.geometry.clone())
173 }
174
175 fn m_values(&self) -> Option<LineStringMValues> {
176 if !self.has_m_values() {
177 return None;
178 }
179 Some(self.geometry.iter().map(|g| g.m.clone().unwrap_or_default()).collect())
180 }
181
182 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
183 let geometry = &self.geometry;
184 if geometry.len() == 1 {
185 let point = &geometry[0];
186 weave_3d(zigzag(point.x) as u16, zigzag(point.y) as u16, zigzag(point.z) as u16)
187 as usize
188 } else {
189 let mut indices: Vec<u32> = Vec::new();
190 indices.push(cache.add_points_3d(geometry.to_vec()) as u32);
191 if let (Some(m_values), Some(shape)) = (self.m_values(), m_shape) {
193 for m in m_values {
194 indices.push(encode_value(&m, shape, cache) as u32);
195 }
196 }
197 cache.add_indices(indices)
198 }
199 }
200}
201
202#[derive(Default, Debug, Clone, PartialEq)]
206pub struct BaseVectorLinesFeature {
207 pub id: Option<u64>,
209 pub geometry: VectorLinesWithOffset,
211 pub properties: Properties,
213 pub bbox: Option<BBox>,
215}
216impl BaseVectorLinesFeature {
217 pub fn new(
219 id: Option<u64>,
220 geometry: VectorLinesWithOffset,
221 properties: Properties,
222 bbox: Option<BBox>,
223 ) -> Self {
224 Self { id, geometry, properties, bbox }
225 }
226}
227impl VectorFeature for BaseVectorLinesFeature {
228 fn get_type(&self) -> FeatureType {
230 FeatureType::Lines
231 }
232
233 fn properties(&self) -> &Properties {
235 &self.properties
236 }
237
238 fn has_bbox(&self) -> bool {
240 self.bbox.is_some()
241 }
242
243 fn has_offsets(&self) -> bool {
245 self.geometry.iter().any(|g| g.has_offset())
246 }
247
248 fn has_m_values(&self) -> bool {
250 self.geometry.iter().any(|g| g.has_m_values())
251 }
252
253 fn load_geometry(&self) -> VectorGeometry {
254 VectorGeometry::VectorLines(self.geometry.to_vec())
255 }
256
257 fn m_values(&self) -> Option<LineStringMValues> {
258 if !self.has_m_values() {
259 return None;
260 }
261 Some(self.geometry.iter().flat_map(|g| g.m_values().unwrap_or_default()).collect())
262 }
263
264 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
265 let geometry = &self.geometry;
266 let mut indices: Vec<u32> = Vec::new();
267 if geometry.len() != 1 {
268 indices.push(geometry.len() as u32)
269 }
270 for line in geometry {
271 if line.has_offset() {
272 indices.push(encode_offset(line.offset));
273 }
274 indices.push(cache.add_points(line.geometry.clone()) as u32);
275 if self.has_m_values() {
277 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
278 for m in m_values {
279 indices.push(encode_value(&m, shape, cache) as u32);
280 }
281 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
282 for _ in 0..line.geometry.len() {
283 indices.push(encode_value(&Value::default(), shape, cache) as u32);
284 }
285 }
286 }
287 }
288 cache.add_indices(indices)
289 }
290}
291
292#[derive(Default, Debug, Clone, PartialEq)]
294pub struct BaseVectorLines3DFeature {
295 pub id: Option<u64>,
297 pub geometry: VectorLines3DWithOffset,
299 pub properties: Properties,
301 pub bbox: Option<BBox3D>,
303}
304impl BaseVectorLines3DFeature {
305 pub fn new(
307 id: Option<u64>,
308 geometry: VectorLines3DWithOffset,
309 properties: Properties,
310 bbox: Option<BBox3D>,
311 ) -> Self {
312 Self { id, geometry, properties, bbox }
313 }
314}
315impl VectorFeature for BaseVectorLines3DFeature {
316 fn get_type(&self) -> FeatureType {
318 FeatureType::Lines3D
319 }
320
321 fn properties(&self) -> &Properties {
323 &self.properties
324 }
325
326 fn has_bbox(&self) -> bool {
328 self.bbox.is_some()
329 }
330
331 fn has_offsets(&self) -> bool {
333 self.geometry.iter().any(|g| g.has_offset())
334 }
335
336 fn has_m_values(&self) -> bool {
338 self.geometry.iter().any(|g| g.has_m_values())
339 }
340
341 fn load_geometry(&self) -> VectorGeometry {
342 VectorGeometry::VectorLines3D(self.geometry.to_vec())
343 }
344
345 fn m_values(&self) -> Option<LineStringMValues> {
346 if !self.has_m_values() {
347 return None;
348 }
349 Some(self.geometry.iter().flat_map(|g| g.m_values().unwrap_or_default()).collect())
350 }
351
352 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
353 let geometry = &self.geometry;
354 let mut indices: Vec<u32> = Vec::new();
355 if geometry.len() != 1 {
356 indices.push(geometry.len() as u32)
357 }
358 for line in geometry {
359 if line.has_offset() {
360 indices.push(encode_offset(line.offset));
361 }
362 indices.push(cache.add_points_3d(line.geometry.clone()) as u32);
363 if self.has_m_values() {
365 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
366 for m in m_values {
367 indices.push(encode_value(&m, shape, cache) as u32);
368 }
369 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
370 for _ in 0..line.geometry.len() {
371 indices.push(encode_value(&Value::default(), shape, cache) as u32);
372 }
373 }
374 }
375 }
376 cache.add_indices(indices)
377 }
378}
379
380#[derive(Default, Debug, Clone, PartialEq)]
384pub struct BaseVectorPolysFeature {
385 pub id: Option<u64>,
387 pub geometry: Vec<VectorLinesWithOffset>,
389 pub properties: Properties,
391 pub bbox: Option<BBox>,
393 pub tesselation: Vec<Point>,
395 pub indices: Vec<u32>,
397}
398impl BaseVectorPolysFeature {
399 pub fn new(
401 id: Option<u64>,
402 geometry: Vec<VectorLinesWithOffset>,
403 properties: Properties,
404 bbox: Option<BBox>,
405 indices: Vec<u32>,
406 tesselation: Vec<Point>,
407 ) -> Self {
408 Self { id, geometry, properties, bbox, indices, tesselation }
409 }
410}
411impl VectorFeature for BaseVectorPolysFeature {
412 fn get_type(&self) -> FeatureType {
414 FeatureType::Polygons
415 }
416
417 fn properties(&self) -> &Properties {
419 &self.properties
420 }
421
422 fn has_bbox(&self) -> bool {
424 self.bbox.is_some()
425 }
426
427 fn has_offsets(&self) -> bool {
429 self.geometry.iter().any(|g| g.iter().any(|l| l.has_offset()))
430 }
431
432 fn has_m_values(&self) -> bool {
434 self.geometry.iter().any(|g| g.iter().any(|l| l.has_m_values()))
435 }
436
437 fn load_geometry(&self) -> VectorGeometry {
438 VectorGeometry::VectorPolys(self.geometry.iter().map(|line| line.to_vec()).collect())
439 }
440
441 fn m_values(&self) -> Option<LineStringMValues> {
442 if !self.has_m_values() {
443 return None;
444 }
445 Some(
446 self.geometry
447 .iter()
448 .flat_map(|g| g.iter().flat_map(|l| l.m_values().unwrap_or_default()))
449 .collect(),
450 )
451 }
452
453 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
454 let geometry = &self.geometry;
455 let mut indices: Vec<u32> = Vec::new();
456 if geometry.len() != 1 {
457 indices.push(geometry.len() as u32)
458 }
459 for poly in geometry {
460 indices.push(poly.len() as u32);
461 for line in poly {
462 if line.has_offset() {
463 indices.push(encode_offset(line.offset));
464 }
465 indices.push(cache.add_points(line.geometry.clone()) as u32);
466 if self.has_m_values() {
468 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
469 for m in m_values {
470 indices.push(encode_value(&m, shape, cache) as u32);
471 }
472 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
473 for _ in 0..line.geometry.len() {
474 indices.push(encode_value(&Value::default(), shape, cache) as u32);
475 }
476 }
477 }
478 }
479 }
480 cache.add_indices(indices)
481 }
482}
483
484#[derive(Default, Debug, Clone, PartialEq)]
486pub struct BaseVectorPolys3DFeature {
487 pub id: Option<u64>,
489 pub geometry: Vec<VectorLines3DWithOffset>,
491 pub properties: Properties,
493 pub bbox: Option<BBox3D>,
495 pub tesselation: Vec<Point3D>,
497 pub indices: Vec<u32>,
499}
500impl BaseVectorPolys3DFeature {
501 pub fn new(
503 id: Option<u64>,
504 geometry: Vec<VectorLines3DWithOffset>,
505 properties: Properties,
506 bbox: Option<BBox3D>,
507 indices: Vec<u32>,
508 tesselation: Vec<Point3D>,
509 ) -> Self {
510 Self { id, geometry, properties, bbox, indices, tesselation }
511 }
512}
513impl VectorFeature for BaseVectorPolys3DFeature {
514 fn get_type(&self) -> FeatureType {
516 FeatureType::Polygons3D
517 }
518
519 fn properties(&self) -> &Properties {
521 &self.properties
522 }
523
524 fn has_bbox(&self) -> bool {
526 self.bbox.is_some()
527 }
528
529 fn has_offsets(&self) -> bool {
531 self.geometry.iter().any(|g| g.iter().any(|l| l.has_offset()))
532 }
533
534 fn has_m_values(&self) -> bool {
536 self.geometry.iter().any(|g| g.iter().any(|l| l.has_m_values()))
537 }
538
539 fn load_geometry(&self) -> VectorGeometry {
540 VectorGeometry::VectorPolys3D(self.geometry.iter().map(|line| line.to_vec()).collect())
541 }
542
543 fn m_values(&self) -> Option<LineStringMValues> {
544 if !self.has_m_values() {
545 return None;
546 }
547 Some(
548 self.geometry
549 .iter()
550 .flat_map(|g| g.iter().flat_map(|l| l.m_values().unwrap_or_default()))
551 .collect(),
552 )
553 }
554
555 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
556 let geometry = &self.geometry;
557 let mut indices: Vec<u32> = Vec::new();
558 if geometry.len() != 1 {
559 indices.push(geometry.len() as u32)
560 }
561 for poly in geometry {
562 indices.push(poly.len() as u32);
563 for line in poly {
564 if line.has_offset() {
565 indices.push(encode_offset(line.offset));
566 }
567 indices.push(cache.add_points_3d(line.geometry.clone()) as u32);
568 if self.has_m_values() {
570 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
571 for m in m_values {
572 indices.push(encode_value(&m, shape, cache) as u32);
573 }
574 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
575 for _ in 0..line.geometry.len() {
576 indices.push(encode_value(&Value::default(), shape, cache) as u32);
577 }
578 }
579 }
580 }
581 }
582 cache.add_indices(indices)
583 }
584}
585
586#[derive(Debug, Clone, PartialEq)]
588pub enum TesselationWrapper {
589 Tesselation(Vec<Point>),
591 Tesselation3D(Vec<Point3D>),
593}
594impl TesselationWrapper {
595 pub fn len(&self) -> usize {
597 match self {
598 TesselationWrapper::Tesselation(points) => points.len(),
599 TesselationWrapper::Tesselation3D(points) => points.len(),
600 }
601 }
602
603 pub fn is_empty(&self) -> bool {
605 match self {
606 TesselationWrapper::Tesselation(points) => points.is_empty(),
607 TesselationWrapper::Tesselation3D(points) => points.is_empty(),
608 }
609 }
610}
611
612#[derive(Debug, Clone, PartialEq)]
614pub enum BaseVectorFeature {
615 BaseVectorPointsFeature(BaseVectorPointsFeature),
617 BaseVectorLinesFeature(BaseVectorLinesFeature),
619 BaseVectorPolysFeature(BaseVectorPolysFeature),
621 BaseVectorPoints3DFeature(BaseVectorPoints3DFeature),
623 BaseVectorLines3DFeature(BaseVectorLines3DFeature),
625 BaseVectorPolys3DFeature(BaseVectorPolys3DFeature),
627}
628impl BaseVectorFeature {
629 pub fn single(&self) -> bool {
631 match self {
632 BaseVectorFeature::BaseVectorPointsFeature(f) => f.geometry.len() == 1,
633 BaseVectorFeature::BaseVectorLinesFeature(f) => f.geometry.len() == 1,
634 BaseVectorFeature::BaseVectorPolysFeature(f) => f.geometry.len() == 1,
635 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.geometry.len() == 1,
636 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.geometry.len() == 1,
637 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.geometry.len() == 1,
638 }
639 }
640
641 pub fn properties(&self) -> &Properties {
643 match self {
644 BaseVectorFeature::BaseVectorPointsFeature(f) => f.properties(),
645 BaseVectorFeature::BaseVectorLinesFeature(f) => f.properties(),
646 BaseVectorFeature::BaseVectorPolysFeature(f) => f.properties(),
647 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.properties(),
648 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.properties(),
649 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.properties(),
650 }
651 }
652
653 pub fn has_m_values(&self) -> bool {
655 match self {
656 BaseVectorFeature::BaseVectorPointsFeature(f) => f.has_m_values(),
657 BaseVectorFeature::BaseVectorLinesFeature(f) => f.has_m_values(),
658 BaseVectorFeature::BaseVectorPolysFeature(f) => f.has_m_values(),
659 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.has_m_values(),
660 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.has_m_values(),
661 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.has_m_values(),
662 }
663 }
664
665 pub fn m_values(&self) -> Option<LineStringMValues> {
667 match self {
668 BaseVectorFeature::BaseVectorPointsFeature(f) => f.m_values(),
669 BaseVectorFeature::BaseVectorLinesFeature(f) => f.m_values(),
670 BaseVectorFeature::BaseVectorPolysFeature(f) => f.m_values(),
671 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.m_values(),
672 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.m_values(),
673 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.m_values(),
674 }
675 }
676
677 pub fn get_type(&self) -> FeatureType {
679 match self {
680 BaseVectorFeature::BaseVectorPointsFeature(f) => f.get_type(),
681 BaseVectorFeature::BaseVectorLinesFeature(f) => f.get_type(),
682 BaseVectorFeature::BaseVectorPolysFeature(f) => f.get_type(),
683 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.get_type(),
684 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.get_type(),
685 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.get_type(),
686 }
687 }
688
689 pub fn id(&self) -> Option<u64> {
691 match self {
692 BaseVectorFeature::BaseVectorPointsFeature(f) => f.id,
693 BaseVectorFeature::BaseVectorLinesFeature(f) => f.id,
694 BaseVectorFeature::BaseVectorPolysFeature(f) => f.id,
695 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.id,
696 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.id,
697 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.id,
698 }
699 }
700
701 pub fn indices(&self) -> Option<Vec<u32>> {
703 match self {
704 BaseVectorFeature::BaseVectorPolysFeature(f) => Some(f.indices.clone()),
705 BaseVectorFeature::BaseVectorPolys3DFeature(f) => Some(f.indices.clone()),
706 _ => None,
707 }
708 }
709
710 pub fn tesselation(&self) -> Option<TesselationWrapper> {
712 match self {
713 BaseVectorFeature::BaseVectorPolysFeature(f) => {
714 Some(TesselationWrapper::Tesselation(f.tesselation.clone()))
715 }
716 BaseVectorFeature::BaseVectorPolys3DFeature(f) => {
717 Some(TesselationWrapper::Tesselation3D(f.tesselation.clone()))
718 }
719 _ => None,
720 }
721 }
722
723 pub fn bbox(&self) -> Option<BBOX> {
725 match self {
726 BaseVectorFeature::BaseVectorPointsFeature(f) => f.bbox.map(BBOX::BBox),
727 BaseVectorFeature::BaseVectorLinesFeature(f) => f.bbox.map(BBOX::BBox),
728 BaseVectorFeature::BaseVectorPolysFeature(f) => f.bbox.map(BBOX::BBox),
729 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.bbox.map(BBOX::BBox3D),
730 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.bbox.map(BBOX::BBox3D),
731 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.bbox.map(BBOX::BBox3D),
732 }
733 }
734
735 pub fn has_offsets(&self) -> bool {
737 match self {
738 BaseVectorFeature::BaseVectorLinesFeature(f) => f.has_offsets(),
739 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.has_offsets(),
740 BaseVectorFeature::BaseVectorPolysFeature(f) => f.has_offsets(),
741 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.has_offsets(),
742 _ => false,
743 }
744 }
745
746 pub fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
748 match self {
749 BaseVectorFeature::BaseVectorPointsFeature(f) => f.encode_to_cache(cache, m_shape),
750 BaseVectorFeature::BaseVectorLinesFeature(f) => f.encode_to_cache(cache, m_shape),
751 BaseVectorFeature::BaseVectorPolysFeature(f) => f.encode_to_cache(cache, m_shape),
752 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.encode_to_cache(cache, m_shape),
753 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.encode_to_cache(cache, m_shape),
754 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.encode_to_cache(cache, m_shape),
755 }
756 }
757}
758impl From<&mut MapboxVectorFeature> for BaseVectorFeature {
759 fn from(mvt: &mut MapboxVectorFeature) -> Self {
760 let id = mvt.id;
761 let properties: Properties = (&mvt.properties).into();
762 let indices = mvt.read_indices();
763 let mut tesselation_floats: Vec<f64> = Vec::new();
764 mvt.add_tesselation(&mut tesselation_floats, 1.0);
765 let tesselation = tesselation_floats
767 .chunks(2)
768 .map(|chunk| Point::new(chunk[0] as i32, chunk[1] as i32))
769 .collect();
770
771 match mvt.load_geometry() {
772 VectorGeometry::VectorPoints(geo) => BaseVectorFeature::BaseVectorPointsFeature(
773 BaseVectorPointsFeature::new(id, geo, properties, None),
774 ),
775 VectorGeometry::VectorLines(geo) => BaseVectorFeature::BaseVectorLinesFeature(
776 BaseVectorLinesFeature::new(id, geo, properties, None),
777 ),
778 VectorGeometry::VectorPolys(geo) => BaseVectorFeature::BaseVectorPolysFeature(
779 BaseVectorPolysFeature::new(id, geo, properties, None, indices, tesselation),
780 ),
781 #[tarpaulin::skip]
782 _ => panic!("unexpected geometry type"),
783 }
784 }
785}
786
787pub fn encode_offset(offset: f64) -> u32 {
789 round(offset * 1_000.0) as u32
790}
791
792pub fn decode_offset(offset: u32) -> f64 {
794 (offset as f64) / 1_000.0
795}