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