mlt_core/encoder/geometry/
encode01.rs1use super::model::VertexBufferType;
4use super::streams::{
5 dict_may_be_beneficial, encode_hilbert_vertex_streams, encode_level1_length_stream,
6 encode_level1_without_ring_buffer_length_stream, encode_level2_length_stream,
7 encode_morton_vertex_streams, encode_ring_lengths_for_mixed, encode_root_length_stream,
8 encode_vec2_vertex_stream, normalize_geometry_offsets, normalize_part_offsets_for_rings,
9 write_geo_u32_stream,
10};
11use crate::MltResult;
12use crate::decoder::GeometryType::{LineString, Point, Polygon};
13use crate::decoder::{
14 ColumnType, GeometryType, GeometryValues, LengthType, Morton, OffsetType, StreamType,
15};
16use crate::encoder::model::{CurveParams, StreamCtx};
17use crate::encoder::{Codecs, Encoder};
18
19impl GeometryValues {
20 #[hotpath::measure]
22 pub fn write_to(self, enc: &mut Encoder, codecs: &mut Codecs) -> MltResult<()> {
23 let Self {
24 vector_types,
25 geometry_offsets,
26 part_offsets,
27 ring_offsets,
28 index_buffer,
29 triangles,
30 vertices,
31 } = self;
32
33 let geom_offsets = geometry_offsets.unwrap_or_default();
38 let part_offsets = part_offsets.unwrap_or_default();
39 let ring_offsets = ring_offsets.unwrap_or_default();
40 let index_buffer = index_buffer.unwrap_or_default();
41 let triangles = triangles.unwrap_or_default();
42 let vertices = vertices.unwrap_or_default();
43
44 if enc.hilbert_cache.is_none() {
48 enc.hilbert_cache = Some(CurveParams::from_vertices(&vertices));
49 }
50 if enc.morton_cache.is_none() {
51 let p = enc.hilbert_cache.expect("populated above");
52 enc.morton_cache = Morton::new(p.bits, p.shift).ok();
53 }
54
55 let meta: Vec<u32> = vector_types.iter().map(|t| *t as u32).collect();
56
57 let part_offsets = if geom_offsets.is_empty()
58 && !ring_offsets.is_empty()
59 && !part_offsets.is_empty()
60 && part_offsets.len() != vector_types.len() + 1
61 {
62 normalize_part_offsets_for_rings(&vector_types, &part_offsets, &ring_offsets)
64 } else {
65 part_offsets
66 };
67
68 enc.write_column_type(ColumnType::Geometry)?;
71 let stream_count_pos = enc.data().len();
72 enc.data_mut().push(0); let mut n: u8 = 0;
74
75 let ctx = StreamCtx::geom(StreamType::Length(LengthType::VarBinary), "meta");
77 codecs.write_int_stream(&meta, &ctx, enc)?;
78 n += 1;
79
80 if !geom_offsets.is_empty() {
82 let geom_offsets = if geom_offsets.len() == vector_types.len() + 1 {
83 geom_offsets
84 } else {
85 normalize_geometry_offsets(&vector_types, &geom_offsets)
86 };
87 let data = encode_root_length_stream(&vector_types, &geom_offsets, Polygon);
88 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
89 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
90
91 if !part_offsets.is_empty() {
97 if ring_offsets.is_empty() {
98 let data = encode_level1_without_ring_buffer_length_stream(
100 &vector_types,
101 &geom_offsets,
102 &part_offsets,
103 );
104 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "no_rings");
105 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
106 } else {
107 let data = encode_level1_length_stream(
110 &vector_types,
111 &geom_offsets,
112 &part_offsets,
113 false,
114 );
115 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "rings");
116 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
117
118 let data = encode_level2_length_stream(
119 &vector_types,
120 &geom_offsets,
121 &part_offsets,
122 &ring_offsets,
123 );
124 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Rings), "rings2");
125 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
126 }
127 }
128 } else if !part_offsets.is_empty() {
129 if ring_offsets.is_empty() {
130 let data = encode_root_length_stream(&vector_types, &part_offsets, Point);
131 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "no_rings");
132 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
133 } else {
134 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
138 n += write_geo_u32_stream(&[], ctx, enc, codecs)?;
139
140 let data = encode_root_length_stream(&vector_types, &part_offsets, LineString);
141 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "parts");
142 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
143
144 let has_line_string = vector_types
148 .iter()
149 .copied()
150 .any(GeometryType::is_linestring);
151 let data = encode_ring_lengths_for_mixed(
152 &vector_types,
153 &part_offsets,
154 &ring_offsets,
155 has_line_string,
156 );
157 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Rings), "parts_ring");
158 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
159 }
160 }
161
162 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Triangles), "triangles");
163 n += write_geo_u32_stream(&triangles, ctx, enc, codecs)?;
164 let ctx = StreamCtx::geom(StreamType::Offset(OffsetType::Index), "triangles_indexes");
165 n += write_geo_u32_stream(&index_buffer, ctx, enc, codecs)?;
166
167 if let Some(forced) = enc.override_vertex_buffer_type() {
168 n += match forced {
169 VertexBufferType::Vec2 => encode_vec2_vertex_stream(&vertices, enc, codecs)?,
170 VertexBufferType::Morton => encode_morton_vertex_streams(&vertices, enc, codecs)?,
171 VertexBufferType::Hilbert => encode_hilbert_vertex_streams(&vertices, enc, codecs)?,
172 };
173 } else if dict_may_be_beneficial(&vertices, enc) {
174 let mut winner_size: usize = usize::MAX;
176 let mut winner_stream_cnt: u8 = 0;
177 let mut alt = enc.try_alternatives();
178 alt.with(|e| {
179 let ds = e.data().len();
180 let ms = e.meta().len();
181 winner_stream_cnt = encode_vec2_vertex_stream(&vertices, e, codecs)?;
182 winner_size = (e.data().len() - ds) + (e.meta().len() - ms);
183 Ok(())
184 })?;
185 alt.with(|e| {
186 let ds = e.data().len();
187 let ms = e.meta().len();
188 let cnt = encode_hilbert_vertex_streams(&vertices, e, codecs)?;
189 let size = (e.data().len() - ds) + (e.meta().len() - ms);
190 if size < winner_size {
191 winner_stream_cnt = cnt;
192 winner_size = size;
193 }
194 Ok(())
195 })?;
196 alt.with(|e| {
197 let ds = e.data().len();
198 let ms = e.meta().len();
199 let cnt = encode_morton_vertex_streams(&vertices, e, codecs)?;
200 let size = (e.data().len() - ds) + (e.meta().len() - ms);
201 if size < winner_size {
202 winner_stream_cnt = cnt;
203 }
204 Ok(())
205 })?;
206 drop(alt);
207 n += winner_stream_cnt;
208 } else {
209 n += encode_vec2_vertex_stream(&vertices, enc, codecs)?;
210 }
211
212 debug_assert!(n <= 127, "geometry stream count must fit in one byte");
214 enc.data_mut()[stream_count_pos] = n;
215 Ok(())
216 }
217}