Skip to main content

mlt_core/frames/v01/geometry/
decode.rs

1use crate::enc_dec::Decode;
2use crate::utils::{AsUsize as _, SetOptionOnce as _};
3use crate::v01::{
4    DictionaryType, GeometryType, GeometryValues, LengthType, OffsetType, RawGeometry, RawStream,
5    StreamType,
6};
7use crate::{Decoder, MltError, MltResult};
8
9pub fn decode_geometry_types(
10    meta: RawStream<'_>,
11    dec: &mut Decoder,
12) -> Result<Vec<GeometryType>, MltError> {
13    // TODO: simplify this, e.g. use u8 or even GeometryType directly rather than going via Vec<u32>
14    let vector_types: Vec<u32> = meta.decode_u32s(dec)?;
15    let vector_types: Vec<GeometryType> = vector_types
16        .into_iter()
17        .map::<MltResult<GeometryType>, _>(|v| Ok(u8::try_from(v)?.try_into()?))
18        .collect::<Result<_, _>>()?;
19    Ok(vector_types)
20}
21
22/// Handle the parsing of the different topology length buffers separate not generic to reduce the
23/// branching and improve the performance
24pub fn decode_root_length_stream(
25    geometry_types: &[GeometryType],
26    root_length_stream: &[u32],
27    buffer_id: GeometryType,
28    dec: &mut Decoder,
29) -> Result<Vec<u32>, MltError> {
30    let alloc_size = geometry_types.len() + 1;
31    let mut root_buffer_offsets = dec.alloc(alloc_size)?;
32
33    root_buffer_offsets.push(0);
34    let mut previous_offset = 0_u32;
35    let mut root_length_counter = 0_usize;
36    for &geom_type in geometry_types {
37        let offset = previous_offset
38            + if geom_type > buffer_id {
39                let val = root_length_stream[root_length_counter];
40                root_length_counter += 1;
41                val
42            } else {
43                1
44            };
45        root_buffer_offsets.push(offset);
46        previous_offset = offset;
47    }
48
49    dec.adjust_alloc(&root_buffer_offsets, alloc_size);
50    Ok(root_buffer_offsets)
51}
52
53/// Case where no ring buffer exists so no `MultiPolygon` or `Polygon` geometry is part of the buffer
54pub fn decode_level1_without_ring_buffer_length_stream(
55    geometry_types: &[GeometryType],
56    root_offset_buffer: &[u32],
57    level1_length_buffer: &[u32],
58    dec: &mut Decoder,
59) -> Result<Vec<u32>, MltError> {
60    let alloc_size = root_offset_buffer[root_offset_buffer.len() - 1].as_usize() + 1;
61    let mut level1_buffer_offsets = dec.alloc(alloc_size)?;
62    level1_buffer_offsets.push(0);
63    let mut previous_offset = 0_u32;
64    let mut level1_length_counter = 0_usize;
65
66    for (i, &geometry_type) in geometry_types.iter().enumerate() {
67        let num_geometries = (root_offset_buffer[i + 1] - root_offset_buffer[i]).as_usize();
68
69        if geometry_type.is_linestring() {
70            // For MultiLineString and LineString a value in the level1LengthBuffer exists
71            for _j in 0..num_geometries {
72                previous_offset += level1_length_buffer[level1_length_counter];
73                level1_length_counter += 1;
74                level1_buffer_offsets.push(previous_offset);
75            }
76        } else {
77            // For MultiPoint and Point no value in level1LengthBuffer exists
78            for _j in 0..num_geometries {
79                previous_offset += 1;
80                level1_buffer_offsets.push(previous_offset);
81            }
82        }
83    }
84
85    dec.adjust_alloc(&level1_buffer_offsets, alloc_size);
86    Ok(level1_buffer_offsets)
87}
88
89pub fn decode_level1_length_stream(
90    geometry_types: &[GeometryType],
91    root_offset_buffer: &[u32],
92    level1_length_buffer: &[u32],
93    is_line_string_present: bool,
94    dec: &mut Decoder,
95) -> Result<Vec<u32>, MltError> {
96    let alloc_size = root_offset_buffer[root_offset_buffer.len() - 1].as_usize() + 1;
97    let mut level1_buffer_offsets = dec.alloc(alloc_size)?;
98    level1_buffer_offsets.push(0);
99    let mut previous_offset = 0_u32;
100    let mut level1_length_buffer_counter = 0_usize;
101
102    for (i, &geometry_type) in geometry_types.iter().enumerate() {
103        let num_geometries = (root_offset_buffer[i + 1] - root_offset_buffer[i]).as_usize();
104
105        if geometry_type.is_polygon() || (is_line_string_present && geometry_type.is_linestring()) {
106            // For MultiPolygon, Polygon and in some cases for MultiLineString and LineString
107            // a value in the level1LengthBuffer exists
108            for _j in 0..num_geometries {
109                previous_offset += level1_length_buffer[level1_length_buffer_counter];
110                level1_length_buffer_counter += 1;
111                level1_buffer_offsets.push(previous_offset);
112            }
113        } else {
114            // For MultiPoint and Point and in some cases for MultiLineString and LineString
115            // no value in the level1LengthBuffer exists
116            for _j in 0..num_geometries {
117                previous_offset += 1;
118                level1_buffer_offsets.push(previous_offset);
119            }
120        }
121    }
122
123    dec.adjust_alloc(&level1_buffer_offsets, alloc_size);
124    Ok(level1_buffer_offsets)
125}
126
127pub fn decode_level2_length_stream(
128    geometry_types: &[GeometryType],
129    root_offset_buffer: &[u32],
130    level1_offset_buffer: &[u32],
131    level2_length_buffer: &[u32],
132    dec: &mut Decoder,
133) -> Result<Vec<u32>, MltError> {
134    let alloc_size = level1_offset_buffer[level1_offset_buffer.len() - 1].as_usize() + 1;
135    let mut level2_buffer_offsets = dec.alloc(alloc_size)?;
136    level2_buffer_offsets.push(0);
137    let mut previous_offset = 0_u32;
138    let mut level1_offset_buffer_counter = 1_usize;
139    let mut level2_length_buffer_counter = 0_usize;
140
141    for (i, &geometry_type) in geometry_types.iter().enumerate() {
142        let num_geometries = (root_offset_buffer[i + 1] - root_offset_buffer[i]).as_usize();
143
144        if geometry_type != GeometryType::Point && geometry_type != GeometryType::MultiPoint {
145            // For MultiPolygon, MultiLineString, Polygon and LineString a value in level2LengthBuffer
146            // exists
147            for _j in 0..num_geometries {
148                let num_parts = (level1_offset_buffer[level1_offset_buffer_counter]
149                    - level1_offset_buffer[level1_offset_buffer_counter - 1])
150                    .as_usize();
151                level1_offset_buffer_counter += 1;
152                for _k in 0..num_parts {
153                    previous_offset += level2_length_buffer[level2_length_buffer_counter];
154                    level2_length_buffer_counter += 1;
155                    level2_buffer_offsets.push(previous_offset);
156                }
157            }
158        } else {
159            // For MultiPoint and Point no value in level2LengthBuffer exists
160            for _j in 0..num_geometries {
161                previous_offset += 1;
162                level2_buffer_offsets.push(previous_offset);
163                level1_offset_buffer_counter += 1;
164            }
165        }
166    }
167
168    dec.adjust_alloc(&level2_buffer_offsets, alloc_size);
169    Ok(level2_buffer_offsets)
170}
171
172impl Decode<GeometryValues> for RawGeometry<'_> {
173    fn decode(self, decoder: &mut Decoder) -> MltResult<GeometryValues> {
174        RawGeometry::decode(self, decoder)
175    }
176}
177
178impl RawGeometry<'_> {
179    /// Decode into [`GeometryValues`], charging `dec` before each `Vec<T>`
180    /// allocation.  All streams carry `num_values` in their metadata so every
181    /// charge is pre-hoc.
182    pub fn decode(self, dec: &mut Decoder) -> MltResult<GeometryValues> {
183        let RawGeometry { meta, items } = self;
184        let vector_types = decode_geometry_types(meta, dec)?;
185        let mut geometry_offsets: Option<Vec<u32>> = None;
186        let mut part_offsets: Option<Vec<u32>> = None;
187        let mut ring_offsets: Option<Vec<u32>> = None;
188        let mut vertex_offsets: Option<Vec<u32>> = None;
189        let mut index_buffer: Option<Vec<u32>> = None;
190        let mut triangles: Option<Vec<u32>> = None;
191        let mut vertices: Option<Vec<i32>> = None;
192
193        for stream in items {
194            match stream.meta.stream_type {
195                StreamType::Present => {}
196                StreamType::Data(v) => match v {
197                    DictionaryType::Vertex | DictionaryType::Morton => {
198                        vertices.set_once(stream.decode_i32s(dec)?)?;
199                    }
200                    _ => Err(MltError::UnexpectedStreamType(stream.meta.stream_type))?,
201                },
202                StreamType::Offset(v) => {
203                    let target = match v {
204                        OffsetType::Vertex => &mut vertex_offsets,
205                        OffsetType::Index => &mut index_buffer,
206                        _ => Err(MltError::UnexpectedStreamType(stream.meta.stream_type))?,
207                    };
208                    target.set_once(stream.decode_u32s(dec)?)?;
209                }
210                StreamType::Length(v) => {
211                    let target = match v {
212                        LengthType::Geometries => &mut geometry_offsets,
213                        LengthType::Parts => &mut part_offsets,
214                        LengthType::Rings => &mut ring_offsets,
215                        LengthType::Triangles => &mut triangles,
216                        _ => Err(MltError::UnexpectedStreamType(stream.meta.stream_type))?,
217                    };
218                    target.set_once(stream.decode_u32s(dec)?)?;
219                }
220            }
221        }
222
223        if index_buffer.is_some() && part_offsets.is_none() {
224            // Case when the indices of a Polygon outline are not encoded in the data so no
225            // topology data are present in the tile
226            //
227            // return FlatGpuVector::new(vector_types, triangles, index_buffer, vertices);
228            return Err(MltError::NotImplemented(
229                "index_buffer.is_some() && part_offsets.is_none() case",
230            ));
231        }
232
233        // Use decode_root_length_stream if geometry_offsets is present
234        if let Some(offsets) = geometry_offsets.take() {
235            geometry_offsets = Some(decode_root_length_stream(
236                &vector_types,
237                &offsets,
238                GeometryType::Polygon,
239                dec,
240            )?);
241            if let Some(part_offsets_copy) = part_offsets.take() {
242                if let Some(ring_offsets_copy) = ring_offsets.take() {
243                    part_offsets = Some(decode_level1_length_stream(
244                        &vector_types,
245                        geometry_offsets.as_ref().unwrap(),
246                        &part_offsets_copy,
247                        false, // isLineStringPresent
248                        dec,
249                    )?);
250                    ring_offsets = Some(decode_level2_length_stream(
251                        &vector_types,
252                        geometry_offsets.as_ref().unwrap(),
253                        part_offsets.as_ref().unwrap(),
254                        &ring_offsets_copy,
255                        dec,
256                    )?);
257                } else {
258                    part_offsets = Some(decode_level1_without_ring_buffer_length_stream(
259                        &vector_types,
260                        geometry_offsets.as_ref().unwrap(),
261                        &part_offsets_copy,
262                        dec,
263                    )?);
264                }
265            }
266        } else if let Some(offsets) = part_offsets.take() {
267            if let Some(ring_offsets_copy) = ring_offsets.take() {
268                let is_line_string_present = vector_types.iter().any(|t| t.is_linestring());
269                part_offsets = Some(decode_root_length_stream(
270                    &vector_types,
271                    &offsets,
272                    GeometryType::LineString,
273                    dec,
274                )?);
275                ring_offsets = Some(decode_level1_length_stream(
276                    &vector_types,
277                    part_offsets.as_ref().unwrap(),
278                    &ring_offsets_copy,
279                    is_line_string_present,
280                    dec,
281                )?);
282            } else {
283                part_offsets = Some(decode_root_length_stream(
284                    &vector_types,
285                    &offsets,
286                    GeometryType::Point,
287                    dec,
288                )?);
289            }
290        }
291
292        // Case when the indices of a Polygon outline are encoded in the tile
293        // This is handled by including index_buffer in the GeometryValues
294
295        // Expand vertex dictionary:
296        // If a vertex offset stream was present,
297        // - `vertices` holds only the unique dictionary entries and
298        // - `vertex_offsets` holds per-vertex indices into it.
299        //
300        // Expand them into a single flat (x, y) sequence so that `GeometryValues` always
301        // represents fully decoded data, regardless of the encoding that was used.
302        if let Some(offsets) = vertex_offsets.take()
303            && let Some(dict) = vertices.as_deref()
304        {
305            dec.consume_items::<[i32; 2]>(offsets.len())?;
306            vertices = Some(
307                offsets
308                    .iter()
309                    .flat_map(|&i| {
310                        let i = i.as_usize();
311                        [dict[i * 2], dict[i * 2 + 1]]
312                    })
313                    .collect(),
314            );
315        }
316
317        Ok(GeometryValues {
318            vector_types,
319            geometry_offsets,
320            part_offsets,
321            ring_offsets,
322            index_buffer,
323            triangles,
324            vertices,
325        })
326    }
327}