1use crate::{
2 Point, Point3D, VectorFeatureMethods, VectorGeometry, VectorLines3DWithOffset,
3 VectorLinesWithOffset, VectorPoints, VectorPoints3D,
4 mapbox::MapboxVectorFeature,
5 open::{ColumnCacheWriter, FeatureType, encode_value},
6 weave_2d, weave_3d, zigzag,
7};
8use alloc::vec::Vec;
9use libm::round;
10use s2json::{BBOX, BBox, BBox3D, LineStringMValues, Properties, Shape, Value};
11
12pub trait VectorFeature {
14 fn get_type(&self) -> FeatureType;
16 fn properties(&self) -> &Properties;
18 fn has_bbox(&self) -> bool;
20 fn has_offsets(&self) -> bool;
22 fn has_m_values(&self) -> bool;
24 fn load_geometry(&self) -> VectorGeometry;
26 fn m_values(&self) -> Option<LineStringMValues>;
28 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize;
30}
31
32#[derive(Default, Debug, Clone, PartialEq)]
36pub struct BaseVectorPointsFeature {
37 pub id: Option<u64>,
39 pub geometry: VectorPoints,
41 pub properties: Properties,
43 pub bbox: Option<BBox>,
45}
46impl BaseVectorPointsFeature {
47 pub fn new(
49 id: Option<u64>,
50 geometry: VectorPoints,
51 properties: Properties,
52 bbox: Option<BBox>,
53 ) -> Self {
54 Self { id, geometry, properties, bbox }
55 }
56}
57impl VectorFeature for BaseVectorPointsFeature {
58 fn get_type(&self) -> FeatureType {
60 FeatureType::Points
61 }
62
63 fn properties(&self) -> &Properties {
65 &self.properties
66 }
67
68 fn has_bbox(&self) -> bool {
70 self.bbox.is_some()
71 }
72
73 fn has_offsets(&self) -> bool {
75 false
76 }
77
78 fn has_m_values(&self) -> bool {
80 self.geometry.iter().any(|g| g.m.is_some())
81 }
82
83 fn load_geometry(&self) -> VectorGeometry {
84 VectorGeometry::VectorPoints(self.geometry.clone())
85 }
86
87 fn m_values(&self) -> Option<LineStringMValues> {
88 if !self.has_m_values() {
89 return None;
90 }
91 Some(
92 self.geometry
93 .iter()
94 .map(|g| {
95 g.m.clone().unwrap_or_default()
97 })
98 .collect(),
99 )
100 }
101
102 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
103 let geometry = &self.geometry;
104 if geometry.len() == 1 {
105 let point = &geometry[0];
106 weave_2d(zigzag(point.x) as u16, zigzag(point.y) as u16) as usize
107 } else {
108 let mut indices: Vec<u32> = Vec::new();
109 indices.push(cache.add_points(geometry.to_vec()) as u32);
110 if let (Some(m_values), Some(shape)) = (self.m_values(), m_shape) {
112 for m in m_values {
113 indices.push(encode_value(&m, shape, cache) as u32);
114 }
115 }
116 cache.add_indices(indices)
117 }
118 }
119}
120#[derive(Default, Debug, Clone, PartialEq)]
122pub struct BaseVectorPoints3DFeature {
123 pub id: Option<u64>,
125 pub geometry: VectorPoints3D,
127 pub properties: Properties,
129 pub bbox: Option<BBox3D>,
131}
132impl BaseVectorPoints3DFeature {
133 pub fn new(
135 id: Option<u64>,
136 geometry: VectorPoints3D,
137 properties: Properties,
138 bbox: Option<BBox3D>,
139 ) -> Self {
140 Self { id, geometry, properties, bbox }
141 }
142}
143impl VectorFeature for BaseVectorPoints3DFeature {
144 fn get_type(&self) -> FeatureType {
146 FeatureType::Points3D
147 }
148
149 fn properties(&self) -> &Properties {
151 &self.properties
152 }
153
154 fn has_bbox(&self) -> bool {
156 self.bbox.is_some()
157 }
158
159 fn has_offsets(&self) -> bool {
161 false
162 }
163
164 fn has_m_values(&self) -> bool {
166 self.geometry.iter().any(|g| g.m.is_some())
167 }
168
169 fn load_geometry(&self) -> VectorGeometry {
170 VectorGeometry::VectorPoints3D(self.geometry.clone())
171 }
172
173 fn m_values(&self) -> Option<LineStringMValues> {
174 if !self.has_m_values() {
175 return None;
176 }
177 Some(self.geometry.iter().map(|g| g.m.clone().unwrap_or_default()).collect())
178 }
179
180 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
181 let geometry = &self.geometry;
182 if geometry.len() == 1 {
183 let point = &geometry[0];
184 weave_3d(zigzag(point.x) as u16, zigzag(point.y) as u16, zigzag(point.z) as u16)
185 as usize
186 } else {
187 let mut indices: Vec<u32> = Vec::new();
188 indices.push(cache.add_points_3d(geometry.to_vec()) as u32);
189 if let (Some(m_values), Some(shape)) = (self.m_values(), m_shape) {
191 for m in m_values {
192 indices.push(encode_value(&m, shape, cache) as u32);
193 }
194 }
195 cache.add_indices(indices)
196 }
197 }
198}
199
200#[derive(Default, Debug, Clone, PartialEq)]
204pub struct BaseVectorLinesFeature {
205 pub id: Option<u64>,
207 pub geometry: VectorLinesWithOffset,
209 pub properties: Properties,
211 pub bbox: Option<BBox>,
213}
214impl BaseVectorLinesFeature {
215 pub fn new(
217 id: Option<u64>,
218 geometry: VectorLinesWithOffset,
219 properties: Properties,
220 bbox: Option<BBox>,
221 ) -> Self {
222 Self { id, geometry, properties, bbox }
223 }
224}
225impl VectorFeature for BaseVectorLinesFeature {
226 fn get_type(&self) -> FeatureType {
228 FeatureType::Lines
229 }
230
231 fn properties(&self) -> &Properties {
233 &self.properties
234 }
235
236 fn has_bbox(&self) -> bool {
238 self.bbox.is_some()
239 }
240
241 fn has_offsets(&self) -> bool {
243 self.geometry.iter().any(|g| g.has_offset())
244 }
245
246 fn has_m_values(&self) -> bool {
248 self.geometry.iter().any(|g| g.has_m_values())
249 }
250
251 fn load_geometry(&self) -> VectorGeometry {
252 VectorGeometry::VectorLines(self.geometry.to_vec())
253 }
254
255 fn m_values(&self) -> Option<LineStringMValues> {
256 if !self.has_m_values() {
257 return None;
258 }
259 Some(self.geometry.iter().flat_map(|g| g.m_values().unwrap_or_default()).collect())
260 }
261
262 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
263 let geometry = &self.geometry;
264 let mut indices: Vec<u32> = Vec::new();
265 if geometry.len() != 1 {
266 indices.push(geometry.len() as u32)
267 }
268 for line in geometry {
269 if line.has_offset() {
270 indices.push(encode_offset(line.offset));
271 }
272 indices.push(cache.add_points(line.geometry.clone()) as u32);
273 if self.has_m_values() {
275 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
276 for m in m_values {
277 indices.push(encode_value(&m, shape, cache) as u32);
278 }
279 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
280 for _ in 0..line.geometry.len() {
281 indices.push(encode_value(&Value::default(), shape, cache) as u32);
282 }
283 }
284 }
285 }
286 cache.add_indices(indices)
287 }
288}
289
290#[derive(Default, Debug, Clone, PartialEq)]
292pub struct BaseVectorLines3DFeature {
293 pub id: Option<u64>,
295 pub geometry: VectorLines3DWithOffset,
297 pub properties: Properties,
299 pub bbox: Option<BBox3D>,
301}
302impl BaseVectorLines3DFeature {
303 pub fn new(
305 id: Option<u64>,
306 geometry: VectorLines3DWithOffset,
307 properties: Properties,
308 bbox: Option<BBox3D>,
309 ) -> Self {
310 Self { id, geometry, properties, bbox }
311 }
312}
313impl VectorFeature for BaseVectorLines3DFeature {
314 fn get_type(&self) -> FeatureType {
316 FeatureType::Lines3D
317 }
318
319 fn properties(&self) -> &Properties {
321 &self.properties
322 }
323
324 fn has_bbox(&self) -> bool {
326 self.bbox.is_some()
327 }
328
329 fn has_offsets(&self) -> bool {
331 self.geometry.iter().any(|g| g.has_offset())
332 }
333
334 fn has_m_values(&self) -> bool {
336 self.geometry.iter().any(|g| g.has_m_values())
337 }
338
339 fn load_geometry(&self) -> VectorGeometry {
340 VectorGeometry::VectorLines3D(self.geometry.to_vec())
341 }
342
343 fn m_values(&self) -> Option<LineStringMValues> {
344 if !self.has_m_values() {
345 return None;
346 }
347 Some(self.geometry.iter().flat_map(|g| g.m_values().unwrap_or_default()).collect())
348 }
349
350 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
351 let geometry = &self.geometry;
352 let mut indices: Vec<u32> = Vec::new();
353 if geometry.len() != 1 {
354 indices.push(geometry.len() as u32)
355 }
356 for line in geometry {
357 if line.has_offset() {
358 indices.push(encode_offset(line.offset));
359 }
360 indices.push(cache.add_points_3d(line.geometry.clone()) as u32);
361 if self.has_m_values() {
363 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
364 for m in m_values {
365 indices.push(encode_value(&m, shape, cache) as u32);
366 }
367 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
368 for _ in 0..line.geometry.len() {
369 indices.push(encode_value(&Value::default(), shape, cache) as u32);
370 }
371 }
372 }
373 }
374 cache.add_indices(indices)
375 }
376}
377
378#[derive(Default, Debug, Clone, PartialEq)]
382pub struct BaseVectorPolysFeature {
383 pub id: Option<u64>,
385 pub geometry: Vec<VectorLinesWithOffset>,
387 pub properties: Properties,
389 pub bbox: Option<BBox>,
391 pub tessellation: Vec<Point>,
393 pub indices: Vec<u32>,
395}
396impl BaseVectorPolysFeature {
397 pub fn new(
399 id: Option<u64>,
400 geometry: Vec<VectorLinesWithOffset>,
401 properties: Properties,
402 bbox: Option<BBox>,
403 indices: Vec<u32>,
404 tessellation: Vec<Point>,
405 ) -> Self {
406 Self { id, geometry, properties, bbox, indices, tessellation }
407 }
408}
409impl VectorFeature for BaseVectorPolysFeature {
410 fn get_type(&self) -> FeatureType {
412 FeatureType::Polygons
413 }
414
415 fn properties(&self) -> &Properties {
417 &self.properties
418 }
419
420 fn has_bbox(&self) -> bool {
422 self.bbox.is_some()
423 }
424
425 fn has_offsets(&self) -> bool {
427 self.geometry.iter().any(|g| g.iter().any(|l| l.has_offset()))
428 }
429
430 fn has_m_values(&self) -> bool {
432 self.geometry.iter().any(|g| g.iter().any(|l| l.has_m_values()))
433 }
434
435 fn load_geometry(&self) -> VectorGeometry {
436 VectorGeometry::VectorPolys(self.geometry.iter().map(|line| line.to_vec()).collect())
437 }
438
439 fn m_values(&self) -> Option<LineStringMValues> {
440 if !self.has_m_values() {
441 return None;
442 }
443 Some(
444 self.geometry
445 .iter()
446 .flat_map(|g| g.iter().flat_map(|l| l.m_values().unwrap_or_default()))
447 .collect(),
448 )
449 }
450
451 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
452 let geometry = &self.geometry;
453 let mut indices: Vec<u32> = Vec::new();
454 if geometry.len() != 1 {
455 indices.push(geometry.len() as u32)
456 }
457 for poly in geometry {
458 indices.push(poly.len() as u32);
459 for line in poly {
460 if line.has_offset() {
461 indices.push(encode_offset(line.offset));
462 }
463 indices.push(cache.add_points(line.geometry.clone()) as u32);
464 if self.has_m_values() {
466 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
467 for m in m_values {
468 indices.push(encode_value(&m, shape, cache) as u32);
469 }
470 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
471 for _ in 0..line.geometry.len() {
472 indices.push(encode_value(&Value::default(), shape, cache) as u32);
473 }
474 }
475 }
476 }
477 }
478 cache.add_indices(indices)
479 }
480}
481
482#[derive(Default, Debug, Clone, PartialEq)]
484pub struct BaseVectorPolys3DFeature {
485 pub id: Option<u64>,
487 pub geometry: Vec<VectorLines3DWithOffset>,
489 pub properties: Properties,
491 pub bbox: Option<BBox3D>,
493 pub tessellation: Vec<Point3D>,
495 pub indices: Vec<u32>,
497}
498impl BaseVectorPolys3DFeature {
499 pub fn new(
501 id: Option<u64>,
502 geometry: Vec<VectorLines3DWithOffset>,
503 properties: Properties,
504 bbox: Option<BBox3D>,
505 indices: Vec<u32>,
506 tessellation: Vec<Point3D>,
507 ) -> Self {
508 Self { id, geometry, properties, bbox, indices, tessellation }
509 }
510}
511impl VectorFeature for BaseVectorPolys3DFeature {
512 fn get_type(&self) -> FeatureType {
514 FeatureType::Polygons3D
515 }
516
517 fn properties(&self) -> &Properties {
519 &self.properties
520 }
521
522 fn has_bbox(&self) -> bool {
524 self.bbox.is_some()
525 }
526
527 fn has_offsets(&self) -> bool {
529 self.geometry.iter().any(|g| g.iter().any(|l| l.has_offset()))
530 }
531
532 fn has_m_values(&self) -> bool {
534 self.geometry.iter().any(|g| g.iter().any(|l| l.has_m_values()))
535 }
536
537 fn load_geometry(&self) -> VectorGeometry {
538 VectorGeometry::VectorPolys3D(self.geometry.iter().map(|line| line.to_vec()).collect())
539 }
540
541 fn m_values(&self) -> Option<LineStringMValues> {
542 if !self.has_m_values() {
543 return None;
544 }
545 Some(
546 self.geometry
547 .iter()
548 .flat_map(|g| g.iter().flat_map(|l| l.m_values().unwrap_or_default()))
549 .collect(),
550 )
551 }
552
553 fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
554 let geometry = &self.geometry;
555 let mut indices: Vec<u32> = Vec::new();
556 if geometry.len() != 1 {
557 indices.push(geometry.len() as u32)
558 }
559 for poly in geometry {
560 indices.push(poly.len() as u32);
561 for line in poly {
562 if line.has_offset() {
563 indices.push(encode_offset(line.offset));
564 }
565 indices.push(cache.add_points_3d(line.geometry.clone()) as u32);
566 if self.has_m_values() {
568 if let (Some(m_values), Some(shape)) = (line.m_values(), m_shape) {
569 for m in m_values {
570 indices.push(encode_value(&m, shape, cache) as u32);
571 }
572 } else if let (None, Some(shape)) = (line.m_values(), m_shape) {
573 for _ in 0..line.geometry.len() {
574 indices.push(encode_value(&Value::default(), shape, cache) as u32);
575 }
576 }
577 }
578 }
579 }
580 cache.add_indices(indices)
581 }
582}
583
584#[derive(Debug, Clone, PartialEq)]
586pub enum TessellationWrapper {
587 Tessellation(Vec<Point>),
589 Tessellation3D(Vec<Point3D>),
591}
592impl TessellationWrapper {
593 pub fn len(&self) -> usize {
595 match self {
596 TessellationWrapper::Tessellation(points) => points.len(),
597 TessellationWrapper::Tessellation3D(points) => points.len(),
598 }
599 }
600
601 pub fn is_empty(&self) -> bool {
603 match self {
604 TessellationWrapper::Tessellation(points) => points.is_empty(),
605 TessellationWrapper::Tessellation3D(points) => points.is_empty(),
606 }
607 }
608}
609
610#[derive(Debug, Clone, PartialEq)]
612pub enum BaseVectorFeature {
613 BaseVectorPointsFeature(BaseVectorPointsFeature),
615 BaseVectorLinesFeature(BaseVectorLinesFeature),
617 BaseVectorPolysFeature(BaseVectorPolysFeature),
619 BaseVectorPoints3DFeature(BaseVectorPoints3DFeature),
621 BaseVectorLines3DFeature(BaseVectorLines3DFeature),
623 BaseVectorPolys3DFeature(BaseVectorPolys3DFeature),
625}
626impl BaseVectorFeature {
627 pub fn single(&self) -> bool {
629 match self {
630 BaseVectorFeature::BaseVectorPointsFeature(f) => f.geometry.len() == 1,
631 BaseVectorFeature::BaseVectorLinesFeature(f) => f.geometry.len() == 1,
632 BaseVectorFeature::BaseVectorPolysFeature(f) => f.geometry.len() == 1,
633 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.geometry.len() == 1,
634 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.geometry.len() == 1,
635 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.geometry.len() == 1,
636 }
637 }
638
639 pub fn properties(&self) -> &Properties {
641 match self {
642 BaseVectorFeature::BaseVectorPointsFeature(f) => f.properties(),
643 BaseVectorFeature::BaseVectorLinesFeature(f) => f.properties(),
644 BaseVectorFeature::BaseVectorPolysFeature(f) => f.properties(),
645 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.properties(),
646 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.properties(),
647 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.properties(),
648 }
649 }
650
651 pub fn has_m_values(&self) -> bool {
653 match self {
654 BaseVectorFeature::BaseVectorPointsFeature(f) => f.has_m_values(),
655 BaseVectorFeature::BaseVectorLinesFeature(f) => f.has_m_values(),
656 BaseVectorFeature::BaseVectorPolysFeature(f) => f.has_m_values(),
657 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.has_m_values(),
658 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.has_m_values(),
659 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.has_m_values(),
660 }
661 }
662
663 pub fn m_values(&self) -> Option<LineStringMValues> {
665 match self {
666 BaseVectorFeature::BaseVectorPointsFeature(f) => f.m_values(),
667 BaseVectorFeature::BaseVectorLinesFeature(f) => f.m_values(),
668 BaseVectorFeature::BaseVectorPolysFeature(f) => f.m_values(),
669 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.m_values(),
670 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.m_values(),
671 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.m_values(),
672 }
673 }
674
675 pub fn get_type(&self) -> FeatureType {
677 match self {
678 BaseVectorFeature::BaseVectorPointsFeature(f) => f.get_type(),
679 BaseVectorFeature::BaseVectorLinesFeature(f) => f.get_type(),
680 BaseVectorFeature::BaseVectorPolysFeature(f) => f.get_type(),
681 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.get_type(),
682 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.get_type(),
683 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.get_type(),
684 }
685 }
686
687 pub fn id(&self) -> Option<u64> {
689 match self {
690 BaseVectorFeature::BaseVectorPointsFeature(f) => f.id,
691 BaseVectorFeature::BaseVectorLinesFeature(f) => f.id,
692 BaseVectorFeature::BaseVectorPolysFeature(f) => f.id,
693 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.id,
694 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.id,
695 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.id,
696 }
697 }
698
699 pub fn indices(&self) -> Option<Vec<u32>> {
701 match self {
702 BaseVectorFeature::BaseVectorPolysFeature(f) => Some(f.indices.clone()),
703 BaseVectorFeature::BaseVectorPolys3DFeature(f) => Some(f.indices.clone()),
704 _ => None,
705 }
706 }
707
708 pub fn tessellation(&self) -> Option<TessellationWrapper> {
710 match self {
711 BaseVectorFeature::BaseVectorPolysFeature(f) => {
712 Some(TessellationWrapper::Tessellation(f.tessellation.clone()))
713 }
714 BaseVectorFeature::BaseVectorPolys3DFeature(f) => {
715 Some(TessellationWrapper::Tessellation3D(f.tessellation.clone()))
716 }
717 _ => None,
718 }
719 }
720
721 pub fn bbox(&self) -> Option<BBOX> {
723 match self {
724 BaseVectorFeature::BaseVectorPointsFeature(f) => f.bbox.map(BBOX::BBox),
725 BaseVectorFeature::BaseVectorLinesFeature(f) => f.bbox.map(BBOX::BBox),
726 BaseVectorFeature::BaseVectorPolysFeature(f) => f.bbox.map(BBOX::BBox),
727 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.bbox.map(BBOX::BBox3D),
728 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.bbox.map(BBOX::BBox3D),
729 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.bbox.map(BBOX::BBox3D),
730 }
731 }
732
733 pub fn has_offsets(&self) -> bool {
735 match self {
736 BaseVectorFeature::BaseVectorLinesFeature(f) => f.has_offsets(),
737 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.has_offsets(),
738 BaseVectorFeature::BaseVectorPolysFeature(f) => f.has_offsets(),
739 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.has_offsets(),
740 _ => false,
741 }
742 }
743
744 pub fn encode_to_cache(&self, cache: &mut ColumnCacheWriter, m_shape: Option<&Shape>) -> usize {
746 match self {
747 BaseVectorFeature::BaseVectorPointsFeature(f) => f.encode_to_cache(cache, m_shape),
748 BaseVectorFeature::BaseVectorLinesFeature(f) => f.encode_to_cache(cache, m_shape),
749 BaseVectorFeature::BaseVectorPolysFeature(f) => f.encode_to_cache(cache, m_shape),
750 BaseVectorFeature::BaseVectorPoints3DFeature(f) => f.encode_to_cache(cache, m_shape),
751 BaseVectorFeature::BaseVectorLines3DFeature(f) => f.encode_to_cache(cache, m_shape),
752 BaseVectorFeature::BaseVectorPolys3DFeature(f) => f.encode_to_cache(cache, m_shape),
753 }
754 }
755}
756impl From<&mut MapboxVectorFeature> for BaseVectorFeature {
757 fn from(mvt: &mut MapboxVectorFeature) -> Self {
758 let id = mvt.id;
759 let properties: Properties = (&mvt.properties).into();
760 let indices = mvt.read_indices();
761 let mut tessellation_floats: Vec<f64> = Vec::new();
762 mvt.add_tessellation(&mut tessellation_floats, 1.0);
763 let tessellation = tess_to_points(tessellation_floats);
765
766 match mvt.load_geometry() {
767 VectorGeometry::VectorPoints(geo) => BaseVectorFeature::BaseVectorPointsFeature(
768 BaseVectorPointsFeature::new(id, geo, properties, None),
769 ),
770 VectorGeometry::VectorLines(geo) => BaseVectorFeature::BaseVectorLinesFeature(
771 BaseVectorLinesFeature::new(id, geo, properties, None),
772 ),
773 VectorGeometry::VectorPolys(geo) => BaseVectorFeature::BaseVectorPolysFeature(
774 BaseVectorPolysFeature::new(id, geo, properties, None, indices, tessellation),
775 ),
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}