1use std::collections::BTreeSet;
2
3use crate::codecs::morton::{encode_morton, morton_deltas, z_order_params};
4use crate::codecs::zigzag::encode_componentwise_delta_vec2s;
5use crate::errors::AsMltError as _;
6use crate::utils::AsUsize as _;
7use crate::v01::{
8 DictionaryType, EncodedGeometry, EncodedStream, GeometryType, GeometryValues, IntEncoder,
9 IntEncoding, LengthType, LogicalEncoding, MortonMeta, OffsetType, PhysicalEncoder, StreamMeta,
10 StreamType, VertexBufferType,
11};
12use crate::{MltError, MltResult};
13
14fn encode_vertex_buffer(vertices: &[i32], physical: PhysicalEncoder) -> MltResult<EncodedStream> {
16 let physical_u32 = encode_componentwise_delta_vec2s(vertices);
18 let num_values = u32::try_from(physical_u32.len())?;
19 let (data, physical_encoding) = physical.encode_u32s(physical_u32)?;
20 Ok(EncodedStream {
21 meta: StreamMeta::new(
22 StreamType::Data(DictionaryType::Vertex),
23 IntEncoding::new(LogicalEncoding::ComponentwiseDelta, physical_encoding),
24 num_values,
25 ),
26 data,
27 })
28}
29
30fn encode_morton_vertex_buffer(
35 codes: &[u32],
36 meta: MortonMeta,
37 physical: PhysicalEncoder,
38) -> MltResult<EncodedStream> {
39 let deltas = morton_deltas(codes);
40 let num_values = u32::try_from(deltas.len())?;
41 let (data, physical_encoding) = physical.encode_u32s(deltas)?;
42 Ok(EncodedStream {
43 meta: StreamMeta::new(
44 StreamType::Data(DictionaryType::Morton),
45 IntEncoding::new(LogicalEncoding::MortonDelta(meta), physical_encoding),
46 num_values,
47 ),
48 data,
49 })
50}
51
52fn build_morton_dict(vertices: &[i32], meta: MortonMeta) -> Result<(Vec<u32>, Vec<u32>), MltError> {
60 let codes: Vec<u32> = vertices
61 .chunks_exact(2)
62 .map(|c| encode_morton(c[0], c[1], meta))
63 .collect::<Result<_, _>>()?;
64
65 let dict: Vec<u32> = codes
66 .iter()
67 .copied()
68 .collect::<BTreeSet<_>>()
69 .into_iter()
70 .collect();
71
72 let offsets: Vec<u32> = codes
73 .iter()
74 .map(|&code| u32::try_from(dict.partition_point(|&c| c < code)).or_overflow())
75 .collect::<Result<_, _>>()?;
76
77 Ok((dict, offsets))
78}
79
80fn encode_root_length_stream(
90 geometry_types: &[GeometryType],
91 geometry_offsets: &[u32],
92 buffer_id: GeometryType,
93) -> Vec<u32> {
94 let mut lengths = Vec::new();
95
96 if geometry_offsets.len() == geometry_types.len() + 1 {
97 for (i, &geom_type) in geometry_types.iter().enumerate() {
99 if geom_type > buffer_id {
100 let start = geometry_offsets[i];
101 let end = geometry_offsets[i + 1];
102 lengths.push(end - start);
103 }
104 }
105 } else {
106 let mut offset_idx = 0;
108 for &geom_type in geometry_types {
109 if geom_type > buffer_id {
110 let start = geometry_offsets[offset_idx];
111 let end = geometry_offsets[offset_idx + 1];
112 lengths.push(end - start);
113 offset_idx += 1;
114 }
115 }
116 }
117
118 lengths
119}
120
121fn encode_level1_length_stream(
127 geometry_types: &[GeometryType],
128 geometry_offsets: &[u32],
129 part_offsets: &[u32],
130 is_line_string_present: bool,
131) -> Vec<u32> {
132 let mut lengths = Vec::new();
133 let mut part_idx = 0;
134
135 for (i, &geom_type) in geometry_types.iter().enumerate() {
136 let num_geoms = geometry_offsets[i + 1] - geometry_offsets[i];
137
138 let needs_length =
139 geom_type.is_polygon() || (is_line_string_present && geom_type.is_linestring());
140
141 if needs_length {
142 for _ in 0..num_geoms {
143 let start = part_offsets[part_idx];
144 let end = part_offsets[part_idx + 1];
145 lengths.push(end - start);
146 part_idx += 1;
147 }
148 }
149 }
152
153 lengths
154}
155
156fn encode_ring_lengths_for_mixed(
164 geometry_types: &[GeometryType],
165 part_offsets: &[u32],
166 ring_offsets: &[u32],
167 is_line_string_present: bool,
168) -> Vec<u32> {
169 let mut lengths = Vec::new();
170 for (i, &geom_type) in geometry_types.iter().enumerate() {
171 let needs_length =
172 geom_type.is_polygon() || (is_line_string_present && geom_type.is_linestring());
173 if needs_length {
174 let slot_start = part_offsets[i].as_usize();
175 let slot_end = part_offsets[i + 1].as_usize();
176 for slot in slot_start..slot_end {
177 lengths.push(ring_offsets[slot + 1] - ring_offsets[slot]);
178 }
179 }
180 }
181 lengths
182}
183
184fn encode_level2_length_stream(
190 geometry_types: &[GeometryType],
191 geometry_offsets: &[u32],
192 part_offsets: &[u32],
193 ring_offsets: &[u32],
194) -> Vec<u32> {
195 let mut lengths = Vec::new();
196 let mut part_idx = 0;
197 let mut ring_idx = 0;
198
199 for (i, &geom_type) in geometry_types.iter().enumerate() {
200 let num_geoms = geometry_offsets[i + 1] - geometry_offsets[i];
201
202 if geom_type.is_polygon() {
206 for _ in 0..num_geoms {
208 let num_parts = part_offsets[part_idx + 1] - part_offsets[part_idx];
209 part_idx += 1;
210 for _ in 0..num_parts {
211 let start = ring_offsets[ring_idx];
212 let end = ring_offsets[ring_idx + 1];
213 lengths.push(end - start);
214 ring_idx += 1;
215 }
216 }
217 } else if geom_type.is_linestring() {
218 for _ in 0..num_geoms {
221 let start = ring_offsets[ring_idx];
222 let end = ring_offsets[ring_idx + 1];
223 lengths.push(end - start);
224 ring_idx += 1;
225 }
226 }
227 }
229
230 lengths
231}
232
233fn encode_level1_without_ring_buffer_length_stream(
238 geometry_types: &[GeometryType],
239 geometry_offsets: &[u32],
240 part_offsets: &[u32],
241) -> Vec<u32> {
242 let mut lengths = Vec::new();
243 let mut part_idx = 0;
244
245 for (i, &geom_type) in geometry_types.iter().enumerate() {
246 let num_geoms = (geometry_offsets[i + 1] - geometry_offsets[i]).as_usize();
247
248 if geom_type.is_linestring() || geom_type.is_polygon() {
249 for _ in 0..num_geoms {
250 let start = part_offsets[part_idx];
251 let end = part_offsets[part_idx + 1];
252 lengths.push(end - start);
253 part_idx += 1;
254 }
255 }
256 }
258
259 lengths
260}
261
262fn normalize_geometry_offsets(vector_types: &[GeometryType], geometry_offsets: &[u32]) -> Vec<u32> {
272 if geometry_offsets.len() == vector_types.len() + 1 {
274 return geometry_offsets.to_vec();
275 }
276
277 let mut normalized = Vec::with_capacity(vector_types.len() + 1);
278 let mut current_offset = 0_u32;
279 let mut sparse_idx = 0_usize; for &geom_type in vector_types {
282 normalized.push(current_offset);
283
284 if geom_type.is_multi() {
285 if sparse_idx + 1 < geometry_offsets.len() {
287 let start = geometry_offsets[sparse_idx];
288 let end = geometry_offsets[sparse_idx + 1];
289 current_offset += end - start;
290 sparse_idx += 1;
291 }
292 } else {
293 current_offset += 1;
295 }
296 }
297
298 normalized.push(current_offset);
299 normalized
300}
301
302fn normalize_part_offsets_for_rings(
311 vector_types: &[GeometryType],
312 part_offsets: &[u32],
313 ring_offsets: &[u32],
314) -> Vec<u32> {
315 let num_rings = if ring_offsets.is_empty() {
316 0
317 } else {
318 u32::try_from(ring_offsets.len() - 1).expect("ring count overflow")
319 };
320
321 if part_offsets.len() == vector_types.len() + 1 {
323 return part_offsets.to_vec();
324 }
325
326 let mut normalized = Vec::with_capacity(vector_types.len() + 1);
328 let mut ring_idx = 0_u32;
329 let mut part_idx = 0_usize;
330
331 for &geom_type in vector_types {
332 normalized.push(ring_idx);
333
334 if geom_type == GeometryType::Point {
335 } else if geom_type.is_linestring() {
337 ring_idx += 1;
339 } else if geom_type.is_polygon() {
340 if part_idx + 1 < part_offsets.len() {
342 let ring_count = part_offsets[part_idx + 1] - part_offsets[part_idx];
343 ring_idx += ring_count;
344 part_idx += 1;
345 }
346 }
347 }
349
350 normalized.push(ring_idx.min(num_rings));
351 normalized
352}
353
354#[expect(clippy::type_complexity)]
361pub fn encode_geometry(
362 decoded: &GeometryValues,
363 encoder: &GeometryEncoder,
364 mut on_stream: Option<&mut dyn FnMut(StreamType, &[u32])>,
365) -> MltResult<EncodedGeometry> {
366 let GeometryValues {
367 vector_types,
368 geometry_offsets,
369 part_offsets,
370 ring_offsets,
371 index_buffer,
372 triangles,
373 vertices,
374 } = decoded;
375
376 let normalized_parts = if geometry_offsets.is_none() && ring_offsets.is_some() {
380 if let Some(part_offs) = part_offsets {
381 if let Some(ring_offs) = ring_offsets {
382 Some(normalize_part_offsets_for_rings(
384 vector_types,
385 part_offs,
386 ring_offs,
387 ))
388 } else {
389 part_offsets.clone()
390 }
391 } else {
392 None
393 }
394 } else {
395 part_offsets.clone()
396 };
397 let part_offsets = &normalized_parts;
398
399 let normalized_geom_offs = geometry_offsets
401 .as_ref()
402 .map(|g| normalize_geometry_offsets(vector_types, g));
403 let geometry_offsets = &normalized_geom_offs;
404
405 let meta = {
407 let vector_types_u32: Vec<u32> = vector_types.iter().map(|t| *t as u32).collect();
408 if let Some(cb) = &mut on_stream {
409 cb(StreamType::Length(LengthType::VarBinary), &vector_types_u32);
410 }
411 EncodedStream::encode_u32s_of_type(
412 &vector_types_u32,
413 encoder.meta,
414 StreamType::Length(LengthType::VarBinary),
415 )?
416 };
417
418 let mut items = Vec::new();
419 let has_linestrings = vector_types
420 .iter()
421 .copied()
422 .any(GeometryType::is_linestring);
423 let has_tessellation = triangles.is_some();
424
425 if let Some(geom_offs) = geometry_offsets {
427 let lengths = encode_root_length_stream(vector_types, geom_offs, GeometryType::Polygon);
429 if !lengths.is_empty() || has_tessellation {
430 if let Some(cb) = &mut on_stream {
433 cb(StreamType::Length(LengthType::Geometries), &lengths);
434 }
435 items.push(EncodedStream::encode_u32s_of_type(
436 &lengths,
437 encoder.geometries,
438 StreamType::Length(LengthType::Geometries),
439 )?);
440 }
441
442 if let Some(part_offs) = part_offsets {
443 if let Some(ring_offs) = ring_offsets {
444 let part_lengths = encode_level1_length_stream(
448 vector_types,
449 geom_offs,
450 part_offs,
451 false, );
453 if !part_lengths.is_empty() {
454 if let Some(cb) = &mut on_stream {
455 cb(StreamType::Length(LengthType::Parts), &part_lengths);
456 }
457 items.push(EncodedStream::encode_u32s_of_type(
458 &part_lengths,
459 encoder.rings,
460 StreamType::Length(LengthType::Parts),
461 )?);
462 }
463
464 let ring_lengths =
465 encode_level2_length_stream(vector_types, geom_offs, part_offs, ring_offs);
466 if !ring_lengths.is_empty() {
467 if let Some(cb) = &mut on_stream {
468 cb(StreamType::Length(LengthType::Rings), &ring_lengths);
469 }
470 items.push(EncodedStream::encode_u32s_of_type(
471 &ring_lengths,
472 encoder.rings2,
473 StreamType::Length(LengthType::Rings),
474 )?);
475 }
476 } else {
477 let part_lengths = encode_level1_without_ring_buffer_length_stream(
479 vector_types,
480 geom_offs,
481 part_offs,
482 );
483 if !part_lengths.is_empty() {
484 if let Some(cb) = &mut on_stream {
485 cb(StreamType::Length(LengthType::Parts), &part_lengths);
486 }
487 items.push(EncodedStream::encode_u32s_of_type(
488 &part_lengths,
489 encoder.no_rings,
490 StreamType::Length(LengthType::Parts),
491 )?);
492 }
493 }
494 }
495 } else if let Some(part_offs) = part_offsets {
496 if let Some(ring_offs) = ring_offsets {
498 if has_tessellation {
502 if let Some(cb) = &mut on_stream {
503 cb(StreamType::Length(LengthType::Geometries), &[]);
504 }
505 items.push(EncodedStream::encode_u32s_of_type(
506 &[],
507 encoder.geometries,
508 StreamType::Length(LengthType::Geometries),
509 )?);
510 }
511
512 let part_lengths =
513 encode_root_length_stream(vector_types, part_offs, GeometryType::LineString);
514 if !part_lengths.is_empty() {
515 if let Some(cb) = &mut on_stream {
516 cb(StreamType::Length(LengthType::Parts), &part_lengths);
517 }
518 items.push(EncodedStream::encode_u32s_of_type(
519 &part_lengths,
520 encoder.parts,
521 StreamType::Length(LengthType::Parts),
522 )?);
523 }
524
525 let ring_lengths =
530 encode_ring_lengths_for_mixed(vector_types, part_offs, ring_offs, has_linestrings);
531 if !ring_lengths.is_empty() {
532 if let Some(cb) = &mut on_stream {
533 cb(StreamType::Length(LengthType::Rings), &ring_lengths);
534 }
535 items.push(EncodedStream::encode_u32s_of_type(
536 &ring_lengths,
537 encoder.parts_ring,
538 StreamType::Length(LengthType::Rings),
539 )?);
540 }
541 } else {
542 let lengths = encode_root_length_stream(vector_types, part_offs, GeometryType::Point);
544 if !lengths.is_empty() {
545 if let Some(cb) = &mut on_stream {
546 cb(StreamType::Length(LengthType::Parts), &lengths);
547 }
548 items.push(EncodedStream::encode_u32s_of_type(
549 &lengths,
550 encoder.only_parts,
551 StreamType::Length(LengthType::Parts),
552 )?);
553 }
554 }
555 }
556
557 if let Some(tris) = triangles {
559 if let Some(cb) = &mut on_stream {
560 cb(StreamType::Length(LengthType::Triangles), tris);
561 }
562 items.push(EncodedStream::encode_u32s_of_type(
563 tris,
564 encoder.triangles,
565 StreamType::Length(LengthType::Triangles),
566 )?);
567 }
568
569 if let Some(idx_buf) = index_buffer {
571 if let Some(cb) = &mut on_stream {
572 cb(StreamType::Offset(OffsetType::Index), idx_buf);
573 }
574 items.push(EncodedStream::encode_u32s_of_type(
575 idx_buf,
576 encoder.triangles_indexes,
577 StreamType::Offset(OffsetType::Index),
578 )?);
579 }
580
581 if let Some(verts) = vertices {
583 match encoder.vertex_buffer_type {
584 VertexBufferType::Vec2 => {
585 if let Some(cb) = &mut on_stream {
586 let delta = encode_componentwise_delta_vec2s(verts);
587 cb(StreamType::Data(DictionaryType::Vertex), &delta);
588 }
589 items.push(encode_vertex_buffer(verts, encoder.vertex.physical)?);
590 }
591 VertexBufferType::Morton => {
592 let morton_meta = z_order_params(verts)?;
593 let (dict, offsets) = build_morton_dict(verts, morton_meta)?;
594 if let Some(cb) = &mut on_stream {
595 cb(StreamType::Offset(OffsetType::Vertex), &offsets);
596 cb(
597 StreamType::Data(DictionaryType::Morton),
598 &morton_deltas(&dict),
599 );
600 }
601 items.push(EncodedStream::encode_u32s_of_type(
602 &offsets,
603 encoder.vertex_offsets,
604 StreamType::Offset(OffsetType::Vertex),
605 )?);
606 items.push(encode_morton_vertex_buffer(
607 &dict,
608 morton_meta,
609 encoder.vertex.physical,
610 )?);
611 }
612 }
613 }
614
615 Ok(EncodedGeometry { meta, items })
616}
617
618#[derive(Debug, Clone, Copy)]
620#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
621#[cfg_attr(all(not(test), feature = "arbitrary"), derive(arbitrary::Arbitrary))]
622pub struct GeometryEncoder {
623 pub meta: IntEncoder,
625
626 pub geometries: IntEncoder,
628
629 pub rings: IntEncoder,
631 pub rings2: IntEncoder,
633 pub no_rings: IntEncoder,
635
636 pub parts: IntEncoder,
638 pub parts_ring: IntEncoder,
640
641 pub only_parts: IntEncoder,
643
644 pub triangles: IntEncoder,
646 pub triangles_indexes: IntEncoder,
648
649 pub vertex: IntEncoder,
651 pub vertex_offsets: IntEncoder,
653
654 #[cfg_attr(test, proptest(value = "VertexBufferType::Vec2"))]
658 #[cfg_attr(all(not(test), feature = "arbitrary"), arbitrary(value = VertexBufferType::Vec2))]
659 pub vertex_buffer_type: VertexBufferType,
660}
661
662impl GeometryEncoder {
663 #[must_use]
665 pub fn all(encoder: IntEncoder) -> Self {
666 Self {
667 meta: encoder,
668 geometries: encoder,
669 rings: encoder,
670 rings2: encoder,
671 no_rings: encoder,
672 parts: encoder,
673 parts_ring: encoder,
674 only_parts: encoder,
675 triangles: encoder,
676 triangles_indexes: encoder,
677 vertex: encoder,
678 vertex_offsets: encoder,
679 vertex_buffer_type: VertexBufferType::Vec2,
680 }
681 }
682
683 pub fn meta(&mut self, e: IntEncoder) -> &mut Self {
685 self.meta = e;
686 self
687 }
688
689 pub fn geometries(&mut self, e: IntEncoder) -> &mut Self {
691 self.geometries = e;
692 self
693 }
694
695 pub fn rings(&mut self, e: IntEncoder) -> &mut Self {
697 self.rings = e;
698 self
699 }
700
701 pub fn rings2(&mut self, e: IntEncoder) -> &mut Self {
703 self.rings2 = e;
704 self
705 }
706
707 pub fn no_rings(&mut self, e: IntEncoder) -> &mut Self {
709 self.no_rings = e;
710 self
711 }
712
713 pub fn parts(&mut self, e: IntEncoder) -> &mut Self {
715 self.parts = e;
716 self
717 }
718
719 pub fn parts_ring(&mut self, e: IntEncoder) -> &mut Self {
721 self.parts_ring = e;
722 self
723 }
724
725 pub fn only_parts(&mut self, e: IntEncoder) -> &mut Self {
727 self.only_parts = e;
728 self
729 }
730
731 pub fn triangles(&mut self, e: IntEncoder) -> &mut Self {
733 self.triangles = e;
734 self
735 }
736
737 pub fn triangles_indexes(&mut self, e: IntEncoder) -> &mut Self {
739 self.triangles_indexes = e;
740 self
741 }
742
743 pub fn vertex(&mut self, e: IntEncoder) -> &mut Self {
745 self.vertex = e;
746 self
747 }
748
749 pub fn vertex_offsets(&mut self, e: IntEncoder) -> &mut Self {
751 self.vertex_offsets = e;
752 self
753 }
754
755 pub fn vertex_buffer_type(&mut self, t: VertexBufferType) -> &mut Self {
757 self.vertex_buffer_type = t;
758 self
759 }
760}
761
762#[cfg(test)]
763mod tests {
764 use super::*;
765
766 #[test]
767 fn test_encode_root_length_stream() {
768 let types = vec![GeometryType::Polygon];
770 let offsets = vec![0, 1]; let lengths = encode_root_length_stream(&types, &offsets, GeometryType::Polygon);
773 assert!(lengths.is_empty());
775
776 let types = vec![GeometryType::MultiPolygon];
778 let offsets = vec![0, 2]; let lengths = encode_root_length_stream(&types, &offsets, GeometryType::Polygon);
781 assert_eq!(lengths, vec![2]);
782 }
783}