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