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 read_indices(&mut self) -> Vec<u32> {
481 if self.indices_index.is_none() {
482 return vec![];
483 }
484 let mut cache = self.cache.borrow_mut();
485 cache.get_indices(self.indices_index.unwrap())
486 }
487
488 fn add_tessellation(&mut self, geometry: &mut Vec<f64>, multiplier: f64) {
490 let Some(tessellation_index) = self.tessellation_index else {
491 return;
492 };
493 let mut cache = self.cache.borrow_mut();
494 let data = cache.get_points(tessellation_index);
495 for point in data {
496 geometry.push(point.x as f64 * multiplier);
497 geometry.push(point.y as f64 * multiplier);
498 }
499 }
500
501 fn add_tessellation_3d(&mut self, geometry: &mut Vec<f64>, multiplier: f64) {
503 let Some(tessellation_index) = self.tessellation_index else {
504 return;
505 };
506 let mut cache = self.cache.borrow_mut();
507 let data = cache.get_points_3d(tessellation_index);
508 for point in data {
509 geometry.push(point.x as f64 * multiplier);
510 geometry.push(point.y as f64 * multiplier);
511 geometry.push(point.z as f64 * multiplier);
512 }
513 }
514
515 fn load_geometry_flat(&mut self) -> (Vec<f64>, Vec<u32>) {
517 let multiplier: f64 = 1.0 / f64::from(self.extent);
519 let geometry: Vec<f64> = match self.load_geometry() {
521 VectorGeometry::VectorPolys(polys) => {
522 let mut geo = polys
523 .iter()
524 .flat_map(|p| {
525 p.iter().flat_map(|p| {
526 p.geometry.clone().into_iter().flat_map(|p| {
527 vec![p.x as f64 * multiplier, p.y as f64 * multiplier]
528 })
529 })
530 })
531 .collect();
532 self.add_tessellation(&mut geo, multiplier);
533 geo
534 }
535 VectorGeometry::VectorPolys3D(polys) => {
536 let mut geo = polys
537 .iter()
538 .flat_map(|p| {
539 p.iter().flat_map(|p| {
540 p.geometry.clone().into_iter().flat_map(|p| {
541 vec![p.x as f64 * multiplier, p.y as f64 * multiplier]
542 })
543 })
544 })
545 .collect();
546 self.add_tessellation_3d(&mut geo, multiplier);
547 geo
548 }
549 _ => {
550 panic!("unexpected geometry type")
551 }
552 };
553 let indices = self.read_indices();
555
556 (geometry, indices)
557 }
558
559 fn load_geometry(&mut self) -> VectorGeometry {
561 if let Some(geometry) = &self.geometry {
562 return geometry.clone();
563 }
564
565 self.geometry = Some(match self.r#type {
566 FeatureType::Points => VectorGeometry::VectorPoints(self._load_geometry_points()),
567 FeatureType::Points3D => {
568 VectorGeometry::VectorPoints3D(self._load_geometry_points_3d())
569 }
570 FeatureType::Lines => VectorGeometry::VectorLines(self._load_geometry_lines()),
571 FeatureType::Lines3D => VectorGeometry::VectorLines3D(self._load_geometry_lines_3d()),
572 FeatureType::Polygons => VectorGeometry::VectorPolys(self._load_geometry_polys()),
573 FeatureType::Polygons3D => {
574 VectorGeometry::VectorPolys3D(self._load_geometry_polys_3d())
575 }
576 });
577
578 self.load_geometry()
579 }
580}
581
582pub fn read_feature(
584 data: Vec<u8>,
585 extent: Extent,
586 cache: Rc<RefCell<ColumnCacheReader>>,
587 shape: &Shape,
588 m_shape: Shape,
589) -> OpenVectorFeature {
590 let mut pbf = Protobuf::from_input(data);
591 let r#type: FeatureType = pbf.read_varint();
593 let flags: u8 = pbf.read_varint();
595 let id: Option<u64> = if flags & 1 > 0 { Some(pbf.read_varint()) } else { None };
597 let has_bbox = flags & (1 << 1) > 0;
598 let has_offsets = (flags & (1 << 2)) > 0;
599 let has_indices = flags & (1 << 3) > 0;
600 let has_tessellation = flags & (1 << 4) > 0;
601 let has_m_values = flags & (1 << 5) > 0;
602 let single = flags & (1 << 6) > 0;
603 let value_index: usize = pbf.read_varint();
605 let properties = decode_value(value_index, shape, &mut cache.borrow_mut());
606 let mut geometry_indices: Vec<u32> = vec![];
608 let mut indices_index: Option<usize> = None;
609 let mut tessellation_index: Option<usize> = None;
610 if r#type == FeatureType::Points || r#type == FeatureType::Points3D {
611 if single {
612 geometry_indices.push(pbf.read_varint())
613 } else {
614 geometry_indices = cache.borrow_mut().get_indices(pbf.read_varint());
615 }
616 } else {
617 geometry_indices = cache.borrow_mut().get_indices(pbf.read_varint());
618 }
619 if r#type == FeatureType::Polygons || r#type == FeatureType::Polygons3D {
621 if has_indices {
622 indices_index = Some(pbf.read_varint());
623 }
624 if has_tessellation {
625 tessellation_index = Some(pbf.read_varint());
626 }
627 }
628 let bbox_index = if has_bbox { Some(pbf.read_varint()) } else { None };
629
630 OpenVectorFeature {
631 id,
632 properties,
633 r#type,
634 cache,
635 m_shape,
636 extent,
637 geometry_indices,
638 geometry: None,
639 single,
640 bbox_index,
641 has_offsets,
642 has_m_values,
643 indices_index,
644 tessellation_index,
645 }
646}
647
648pub fn write_feature(
650 feature: &BaseVectorFeature,
651 shape: &Shape,
652 m_shape: Option<&Shape>,
653 cache: &mut ColumnCacheWriter,
654) -> Vec<u8> {
655 let mut pbf = Protobuf::new();
657 pbf.write_varint(feature.get_type());
659 let id = feature.id();
661 let has_id: bool = id.is_some();
662 let indices = feature.indices();
663 let has_indices = indices.is_some() && !indices.unwrap().is_empty();
664 let tessellation = feature.tessellation();
665 let has_tessellation = tessellation.is_some() && !tessellation.as_ref().unwrap().is_empty();
666 let has_offsets = feature.has_offsets();
667 let bbox = feature.bbox();
668 let has_bbox = bbox.is_some();
669 let has_m_values = feature.has_m_values();
670 let single = feature.single();
671 let mut flags: u8 = 0;
672 if has_id {
673 flags += 1;
674 }
675 if has_bbox {
676 flags += 1 << 1;
677 }
678 if has_offsets {
679 flags += 1 << 2;
680 }
681 if has_indices {
682 flags += 1 << 3;
683 }
684 if has_tessellation {
685 flags += 1 << 4;
686 }
687 if has_m_values {
688 flags += 1 << 5;
689 }
690 if single {
691 flags += 1 << 6;
692 }
693 pbf.write_varint(flags);
694 if has_id {
696 pbf.write_varint(id.unwrap());
697 }
698 let value_index = encode_value(feature.properties(), shape, cache);
700 pbf.write_varint(value_index);
701 let stored_geo = feature.encode_to_cache(cache, m_shape);
703 pbf.write_varint(stored_geo);
704 if has_indices {
706 pbf.write_varint(cache.add_indices(feature.indices().unwrap()));
707 }
708 if has_tessellation {
710 match tessellation.unwrap() {
711 TessellationWrapper::Tessellation(t) => pbf.write_varint(cache.add_points(t)),
712 TessellationWrapper::Tessellation3D(t) => pbf.write_varint(cache.add_points_3d(t)),
713 }
714 }
715 if has_bbox {
717 pbf.write_varint(cache.add_bbox(bbox.unwrap()));
718 }
719
720 pbf.take()
721}