1use super::decode_value;
2use crate::{
3 Point, Point3D, VectorFeatureMethods, VectorGeometry, VectorLine3DWithOffset,
4 VectorLineWithOffset, VectorLines3DWithOffset, VectorLinesWithOffset, VectorPoints,
5 VectorPoints3D,
6 base::{BaseVectorFeature, TessellationWrapper, decode_offset},
7 mapbox::FeatureType as MapboxFeatureType,
8 open::{ColumnCacheReader, ColumnCacheWriter, encode_value},
9 unweave_2d, unweave_3d, zagzig,
10};
11use alloc::{rc::Rc, vec, vec::Vec};
12use core::cell::RefCell;
13use pbf::{BitCast, Protobuf};
14use s2json::{BBOX, Properties, Shape};
15use serde::{Deserialize, Serialize};
16
17#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
19pub enum Extent {
20 Extent512 = 512,
22 Extent1024 = 1_024,
24 Extent2048 = 2_048,
26 #[default]
28 Extent4096 = 4_096,
29 Extent8192 = 8_192,
31 Extent16384 = 16_384,
33}
34impl BitCast for Extent {
35 fn to_u64(&self) -> u64 {
36 match self {
37 Extent::Extent512 => 0,
38 Extent::Extent1024 => 1,
39 Extent::Extent2048 => 2,
40 Extent::Extent4096 => 3,
41 Extent::Extent8192 => 4,
42 Extent::Extent16384 => 5,
43 }
44 }
45
46 fn from_u64(value: u64) -> Self {
47 match value {
48 1 => Extent::Extent1024,
49 2 => Extent::Extent2048,
50 3 => Extent::Extent4096,
51 4 => Extent::Extent8192,
52 5 => Extent::Extent16384,
53 _ => Extent::Extent512,
54 }
55 }
56}
57impl From<usize> for Extent {
58 fn from(extent: usize) -> Self {
59 match extent {
60 512 => Extent::Extent512,
61 1_024 => Extent::Extent1024,
62 2_048 => Extent::Extent2048,
63 4_096 => Extent::Extent4096,
64 8_192 => Extent::Extent8192,
65 16_384 => Extent::Extent16384,
66 _ => Extent::Extent512,
67 }
68 }
69}
70impl From<Extent> for usize {
71 fn from(extent: Extent) -> Self {
72 extent as i32 as usize
73 }
74}
75impl From<Extent> for f64 {
76 fn from(extent: Extent) -> Self {
77 extent as i32 as f64
78 }
79}
80
81#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
83pub enum FeatureType {
84 #[default]
86 Points = 1,
87 Lines = 2,
89 Polygons = 3,
91 Points3D = 4,
93 Lines3D = 5,
95 Polygons3D = 6,
97}
98impl BitCast for FeatureType {
99 fn to_u64(&self) -> u64 {
100 (*self) as u64
101 }
102 fn from_u64(value: u64) -> Self {
103 match value {
104 1 => FeatureType::Points,
105 2 => FeatureType::Lines,
106 3 => FeatureType::Polygons,
107 4 => FeatureType::Points3D,
108 5 => FeatureType::Lines3D,
109 6 => FeatureType::Polygons3D,
110 _ => panic!("unknown value: {}", value),
111 }
112 }
113}
114impl From<&MapboxFeatureType> for FeatureType {
115 fn from(mft: &MapboxFeatureType) -> Self {
116 match mft {
117 MapboxFeatureType::Point => FeatureType::Points,
118 MapboxFeatureType::Line => FeatureType::Lines,
119 MapboxFeatureType::Polygon => FeatureType::Polygons,
120 MapboxFeatureType::MultiPolygon => FeatureType::Polygons,
121 }
122 }
123}
124
125#[derive(Debug)]
127pub struct OpenVectorFeature {
128 pub id: Option<u64>,
130 pub properties: Properties,
132 pub r#type: FeatureType,
134 cache: Rc<RefCell<ColumnCacheReader>>,
135 m_shape: Shape,
136 extent: Extent,
137 geometry_indices: Vec<u32>,
138 geometry: Option<VectorGeometry>,
139 single: bool,
140 bbox_index: Option<usize>,
141 has_offsets: bool,
142 has_m_values: bool,
143 indices_index: Option<usize>,
144 tessellation_index: Option<usize>,
145}
146impl OpenVectorFeature {
147 fn _load_geometry_points(&mut self) -> VectorPoints {
148 let mut cache = self.cache.borrow_mut();
149
150 let mut index_pos = 0;
151 let geometry_index = self.geometry_indices[index_pos];
152 index_pos += 1;
153 if self.single {
154 let (a, b) = unweave_2d(geometry_index);
155 vec![Point::new(zagzig(a as u32), zagzig(b as u32))]
156 } else {
157 let mut geometry = cache.get_points(geometry_index as usize);
158
159 if self.has_m_values {
160 let length = geometry.len();
161 geometry.iter_mut().take(length).for_each(|p| {
162 let value_index = self.geometry_indices[index_pos];
163 p.m = Some(decode_value(value_index as usize, &self.m_shape, &mut cache));
164 index_pos += 1;
165 });
166 }
167
168 geometry
169 }
170 }
171
172 fn _load_geometry_points_3d(&mut self) -> VectorPoints3D {
173 let mut cache = self.cache.borrow_mut();
174
175 let mut index_pos = 0;
176 let geometry_index = self.geometry_indices[index_pos];
177 index_pos += 1;
178 if self.single {
179 let (a, b, c) = unweave_3d(geometry_index as u64);
180 vec![Point3D::new(zagzig(a), zagzig(b), zagzig(c))]
181 } else {
182 let mut geometry = cache.get_points_3d(geometry_index as usize);
183
184 if self.has_m_values {
185 let length = geometry.len();
186 geometry.iter_mut().take(length).for_each(|p| {
187 let value_index = self.geometry_indices[index_pos];
188 p.m = Some(decode_value(value_index as usize, &self.m_shape, &mut cache));
189 index_pos += 1;
190 });
191 }
192
193 geometry
194 }
195 }
196
197 fn _load_geometry_lines(&mut self) -> VectorLinesWithOffset {
198 let mut cache = self.cache.borrow_mut();
199
200 let mut res: VectorLinesWithOffset = vec![];
201
202 let mut index_pos = 0;
203 let mut line_count = 1;
204 if !self.single {
205 line_count = self.geometry_indices[index_pos];
206 index_pos += 1;
207 };
208 for _ in 0..line_count {
209 let mut offset = 0.0;
211 if self.has_offsets {
212 offset = decode_offset(self.geometry_indices[index_pos]);
213 index_pos += 1;
214 }
215 let mut geometry = cache.get_points(self.geometry_indices[index_pos] as usize);
217 index_pos += 1;
218 if self.has_m_values {
220 let length = geometry.len();
221 geometry.iter_mut().take(length).for_each(|p| {
222 let value_index = self.geometry_indices[index_pos];
223 p.m = Some(decode_value(value_index as usize, &self.m_shape, &mut cache));
224 index_pos += 1;
225 });
226 }
227 res.push(VectorLineWithOffset::new(offset, geometry));
228 }
229
230 res
231 }
232
233 fn _load_geometry_lines_3d(&mut self) -> VectorLines3DWithOffset {
234 let mut cache = self.cache.borrow_mut();
235
236 let mut res: VectorLines3DWithOffset = vec![];
237
238 let mut index_pos = 0;
239 let mut line_count = 1;
240 if !self.single {
241 line_count = self.geometry_indices[index_pos];
242 index_pos += 1;
243 };
244 for _ in 0..line_count {
245 let mut offset = 0.0;
247 if self.has_offsets {
248 offset = decode_offset(self.geometry_indices[index_pos]);
249 index_pos += 1;
250 }
251 let mut geometry = cache.get_points_3d(self.geometry_indices[index_pos] as usize);
253 index_pos += 1;
254 if self.has_m_values {
256 let length = geometry.len();
257 geometry.iter_mut().take(length).for_each(|p| {
258 let value_index = self.geometry_indices[index_pos];
259 p.m = Some(decode_value(value_index as usize, &self.m_shape, &mut cache));
260 index_pos += 1;
261 });
262 }
263 res.push(VectorLine3DWithOffset::new(offset, geometry));
264 }
265
266 res
267 }
268
269 fn _load_geometry_polys(&mut self) -> Vec<VectorLinesWithOffset> {
270 let mut cache = self.cache.borrow_mut();
271
272 let mut res: Vec<VectorLinesWithOffset> = vec![];
273
274 let mut index_pos = 0;
275 let mut poly_count = 1;
276 if !self.single {
277 poly_count = self.geometry_indices[index_pos];
278 index_pos += 1;
279 };
280 for _ in 0..poly_count {
281 let line_count = self.geometry_indices[index_pos];
282 index_pos += 1;
283 let mut lines: VectorLinesWithOffset = vec![];
284 for _ in 0..line_count {
285 let mut offset = 0.0;
287 if self.has_offsets {
288 offset = decode_offset(self.geometry_indices[index_pos]);
289 index_pos += 1;
290 }
291 let mut geometry = cache.get_points(self.geometry_indices[index_pos] as usize);
293 index_pos += 1;
294 if self.has_m_values {
296 let length = geometry.len();
297 geometry.iter_mut().take(length).for_each(|p| {
298 let value_index = self.geometry_indices[index_pos];
299 p.m = Some(decode_value(value_index as usize, &self.m_shape, &mut cache));
300 index_pos += 1;
301 });
302 }
303 lines.push(VectorLineWithOffset::new(offset, geometry));
304 }
305 res.push(lines);
306 }
307
308 res
309 }
310
311 fn _load_geometry_polys_3d(&mut self) -> Vec<VectorLines3DWithOffset> {
312 let mut cache = self.cache.borrow_mut();
313
314 let mut res: Vec<VectorLines3DWithOffset> = vec![];
315
316 let mut index_pos = 0;
317 let mut poly_count = 1;
318 if !self.single {
319 poly_count = self.geometry_indices[index_pos];
320 index_pos += 1;
321 };
322 for _ in 0..poly_count {
323 let line_count = self.geometry_indices[index_pos];
324 index_pos += 1;
325 let mut lines: VectorLines3DWithOffset = vec![];
326 for _ in 0..line_count {
327 let mut offset = 0.0;
329 if self.has_offsets {
330 offset = decode_offset(self.geometry_indices[index_pos]);
331 index_pos += 1;
332 }
333 let mut geometry = cache.get_points_3d(self.geometry_indices[index_pos] as usize);
335 index_pos += 1;
336 if self.has_m_values {
338 let length = geometry.len();
339 geometry.iter_mut().take(length).for_each(|p| {
340 let value_index = self.geometry_indices[index_pos];
341 p.m = Some(decode_value(value_index as usize, &self.m_shape, &mut cache));
342 index_pos += 1;
343 });
344 }
345 lines.push(VectorLine3DWithOffset::new(offset, geometry));
346 }
347 res.push(lines);
348 }
349
350 res
351 }
352}
353impl VectorFeatureMethods for OpenVectorFeature {
354 fn id(&self) -> Option<u64> {
356 self.id
357 }
358
359 fn version(&self) -> u16 {
361 1
362 }
363
364 fn extent(&self) -> usize {
366 self.extent.into()
367 }
368
369 fn properties(&self) -> Properties {
370 self.properties.clone()
371 }
372
373 fn get_type(&self) -> FeatureType {
375 self.r#type
376 }
377
378 fn bbox(&self) -> Option<BBOX> {
380 if let Some(index) = self.bbox_index {
381 let mut cache = self.cache.borrow_mut();
382 Some(cache.get_bbox(index))
383 } else {
384 None
385 }
386 }
387
388 fn has_m_values(&self) -> bool {
390 self.has_m_values
391 }
392
393 fn is_points(&self) -> bool {
395 self.r#type == FeatureType::Points
396 }
397
398 fn is_lines(&self) -> bool {
400 self.r#type == FeatureType::Lines
401 }
402
403 fn is_polygons(&self) -> bool {
405 self.r#type == FeatureType::Polygons
406 }
407
408 fn is_points_3d(&self) -> bool {
410 self.r#type == FeatureType::Points3D
411 }
412
413 fn is_lines_3d(&self) -> bool {
415 self.r#type == FeatureType::Lines3D
416 }
417
418 fn is_polygons_3d(&self) -> bool {
420 self.r#type == FeatureType::Polygons3D
421 }
422
423 fn load_points(&mut self) -> VectorPoints {
425 match self.load_geometry() {
426 VectorGeometry::VectorPoints(p) => p,
427 VectorGeometry::VectorLines(lines) => {
428 lines.iter().flat_map(|p| p.geometry.clone()).collect()
429 }
430 VectorGeometry::VectorPolys(polys) => polys
431 .iter()
432 .flat_map(|p| p.iter().flat_map(|p| p.geometry[..p.geometry.len() - 1].to_vec()))
433 .collect(),
434 _ => {
435 panic!("unexpected geometry type")
436 }
437 }
438 }
439
440 fn load_points_3d(&mut self) -> VectorPoints3D {
442 match self.load_geometry() {
443 VectorGeometry::VectorPoints3D(p) => p,
444 VectorGeometry::VectorLines3D(lines) => {
445 lines.iter().flat_map(|p| p.geometry.clone()).collect()
446 }
447 VectorGeometry::VectorPolys3D(polys) => polys
448 .iter()
449 .flat_map(|p| p.iter().flat_map(|p| p.geometry[..p.geometry.len() - 1].to_vec()))
450 .collect(),
451 _ => {
452 panic!("unexpected geometry type")
453 }
454 }
455 }
456
457 fn load_lines(&mut self) -> VectorLinesWithOffset {
459 match self.load_geometry() {
460 VectorGeometry::VectorLines(lines) => lines,
461 VectorGeometry::VectorPolys(polys) => polys.iter().flat_map(|p| p.clone()).collect(),
462 _ => {
463 panic!("unexpected geometry type")
464 }
465 }
466 }
467
468 fn load_lines_3d(&mut self) -> VectorLines3DWithOffset {
470 match self.load_geometry() {
471 VectorGeometry::VectorLines3D(lines) => lines,
472 VectorGeometry::VectorPolys3D(polys) => polys.iter().flat_map(|p| p.clone()).collect(),
473 _ => {
474 panic!("unexpected geometry type")
475 }
476 }
477 }
478
479 fn load_polys(&mut self) -> Vec<VectorLinesWithOffset> {
481 match self.load_geometry() {
482 VectorGeometry::VectorPolys(polys) => polys,
483 _ => {
484 panic!("unexpected geometry type")
485 }
486 }
487 }
488
489 fn load_polys_3d(&mut self) -> Vec<VectorLines3DWithOffset> {
491 match self.load_geometry() {
492 VectorGeometry::VectorPolys3D(polys) => polys,
493 _ => {
494 panic!("unexpected geometry type")
495 }
496 }
497 }
498
499 fn read_indices(&mut self) -> Vec<u32> {
501 if self.indices_index.is_none() {
502 return vec![];
503 }
504 let mut cache = self.cache.borrow_mut();
505 cache.get_indices(self.indices_index.unwrap())
506 }
507
508 fn add_tessellation(&mut self, geometry: &mut Vec<f64>, multiplier: f64) {
510 let Some(tessellation_index) = self.tessellation_index else {
511 return;
512 };
513 let mut cache = self.cache.borrow_mut();
514 let data = cache.get_points(tessellation_index);
515 for point in data {
516 geometry.push(point.x as f64 * multiplier);
517 geometry.push(point.y as f64 * multiplier);
518 }
519 }
520
521 fn add_tessellation_3d(&mut self, geometry: &mut Vec<f64>, multiplier: f64) {
523 let Some(tessellation_index) = self.tessellation_index else {
524 return;
525 };
526 let mut cache = self.cache.borrow_mut();
527 let data = cache.get_points_3d(tessellation_index);
528 for point in data {
529 geometry.push(point.x as f64 * multiplier);
530 geometry.push(point.y as f64 * multiplier);
531 geometry.push(point.z as f64 * multiplier);
532 }
533 }
534
535 fn load_geometry_flat(&mut self) -> (Vec<f64>, Vec<u32>) {
537 let multiplier: f64 = 1.0 / f64::from(self.extent);
539 let geometry: Vec<f64> = match self.load_geometry() {
541 VectorGeometry::VectorPolys(polys) => {
542 let mut geo = polys
543 .iter()
544 .flat_map(|p| {
545 p.iter().flat_map(|p| {
546 p.geometry.clone().into_iter().flat_map(|p| {
547 vec![p.x as f64 * multiplier, p.y as f64 * multiplier]
548 })
549 })
550 })
551 .collect();
552 self.add_tessellation(&mut geo, multiplier);
553 geo
554 }
555 VectorGeometry::VectorPolys3D(polys) => {
556 let mut geo = polys
557 .iter()
558 .flat_map(|p| {
559 p.iter().flat_map(|p| {
560 p.geometry.clone().into_iter().flat_map(|p| {
561 vec![p.x as f64 * multiplier, p.y as f64 * multiplier]
562 })
563 })
564 })
565 .collect();
566 self.add_tessellation_3d(&mut geo, multiplier);
567 geo
568 }
569 _ => {
570 panic!("unexpected geometry type")
571 }
572 };
573 let indices = self.read_indices();
575
576 (geometry, indices)
577 }
578
579 fn load_geometry(&mut self) -> VectorGeometry {
581 if let Some(geometry) = &self.geometry {
582 return geometry.clone();
583 }
584
585 self.geometry = Some(match self.r#type {
586 FeatureType::Points => VectorGeometry::VectorPoints(self._load_geometry_points()),
587 FeatureType::Points3D => {
588 VectorGeometry::VectorPoints3D(self._load_geometry_points_3d())
589 }
590 FeatureType::Lines => VectorGeometry::VectorLines(self._load_geometry_lines()),
591 FeatureType::Lines3D => VectorGeometry::VectorLines3D(self._load_geometry_lines_3d()),
592 FeatureType::Polygons => VectorGeometry::VectorPolys(self._load_geometry_polys()),
593 FeatureType::Polygons3D => {
594 VectorGeometry::VectorPolys3D(self._load_geometry_polys_3d())
595 }
596 });
597
598 self.load_geometry()
599 }
600}
601
602pub fn read_feature(
604 data: Vec<u8>,
605 extent: Extent,
606 cache: Rc<RefCell<ColumnCacheReader>>,
607 shape: &Shape,
608 m_shape: Shape,
609) -> OpenVectorFeature {
610 let mut pbf = Protobuf::from_input(data);
611 let r#type: FeatureType = pbf.read_varint();
613 let flags: u8 = pbf.read_varint();
615 let id: Option<u64> = if flags & 1 > 0 { Some(pbf.read_varint()) } else { None };
617 let has_bbox = flags & (1 << 1) > 0;
618 let has_offsets = (flags & (1 << 2)) > 0;
619 let has_indices = flags & (1 << 3) > 0;
620 let has_tessellation = flags & (1 << 4) > 0;
621 let has_m_values = flags & (1 << 5) > 0;
622 let single = flags & (1 << 6) > 0;
623 let value_index: usize = pbf.read_varint();
625 let properties = decode_value(value_index, shape, &mut cache.borrow_mut());
626 let mut geometry_indices: Vec<u32> = vec![];
628 let mut indices_index: Option<usize> = None;
629 let mut tessellation_index: Option<usize> = None;
630 if r#type == FeatureType::Points || r#type == FeatureType::Points3D {
631 if single {
632 geometry_indices.push(pbf.read_varint())
633 } else {
634 geometry_indices = cache.borrow_mut().get_indices(pbf.read_varint());
635 }
636 } else {
637 geometry_indices = cache.borrow_mut().get_indices(pbf.read_varint());
638 }
639 if r#type == FeatureType::Polygons || r#type == FeatureType::Polygons3D {
641 if has_indices {
642 indices_index = Some(pbf.read_varint());
643 }
644 if has_tessellation {
645 tessellation_index = Some(pbf.read_varint());
646 }
647 }
648 let bbox_index = if has_bbox { Some(pbf.read_varint()) } else { None };
649
650 OpenVectorFeature {
651 id,
652 properties,
653 r#type,
654 cache,
655 m_shape,
656 extent,
657 geometry_indices,
658 geometry: None,
659 single,
660 bbox_index,
661 has_offsets,
662 has_m_values,
663 indices_index,
664 tessellation_index,
665 }
666}
667
668pub fn write_feature(
670 feature: &BaseVectorFeature,
671 shape: &Shape,
672 m_shape: Option<&Shape>,
673 cache: &mut ColumnCacheWriter,
674) -> Vec<u8> {
675 let mut pbf = Protobuf::new();
677 pbf.write_varint(feature.get_type());
679 let id = feature.id();
681 let has_id: bool = id.is_some();
682 let indices = feature.indices();
683 let has_indices = indices.is_some() && !indices.unwrap().is_empty();
684 let tessellation = feature.tessellation();
685 let has_tessellation = tessellation.is_some() && !tessellation.as_ref().unwrap().is_empty();
686 let has_offsets = feature.has_offsets();
687 let bbox = feature.bbox();
688 let has_bbox = bbox.is_some();
689 let has_m_values = feature.has_m_values();
690 let single = feature.single();
691 let mut flags: u8 = 0;
692 if has_id {
693 flags += 1;
694 }
695 if has_bbox {
696 flags += 1 << 1;
697 }
698 if has_offsets {
699 flags += 1 << 2;
700 }
701 if has_indices {
702 flags += 1 << 3;
703 }
704 if has_tessellation {
705 flags += 1 << 4;
706 }
707 if has_m_values {
708 flags += 1 << 5;
709 }
710 if single {
711 flags += 1 << 6;
712 }
713 pbf.write_varint(flags);
714 if has_id {
716 pbf.write_varint(id.unwrap());
717 }
718 let value_index = encode_value(feature.properties(), shape, cache);
720 pbf.write_varint(value_index);
721 let stored_geo = feature.encode_to_cache(cache, m_shape);
723 pbf.write_varint(stored_geo);
724 if has_indices {
726 pbf.write_varint(cache.add_indices(feature.indices().unwrap()));
727 }
728 if has_tessellation {
730 match tessellation.unwrap() {
731 TessellationWrapper::Tessellation(t) => pbf.write_varint(cache.add_points(t)),
732 TessellationWrapper::Tessellation3D(t) => pbf.write_varint(cache.add_points_3d(t)),
733 }
734 }
735 if has_bbox {
737 pbf.write_varint(cache.add_bbox(bbox.unwrap()));
738 }
739
740 pbf.take()
741}