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 seed_curve_caches, write_geo_u32_stream,
10};
11use crate::MltResult;
12use crate::decoder::GeometryType::{LineString, Point, Polygon};
13use crate::decoder::{
14 ColumnType, GeometryType, GeometryValues, LengthType, OffsetType, StreamType,
15};
16use crate::encoder::model::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();
36 let part_offsets = part_offsets.unwrap_or_default();
37 let ring_offsets = ring_offsets.unwrap_or_default();
38 let index_buffer = index_buffer.unwrap_or_default();
39 let triangles = triangles.unwrap_or_default();
40 let vertices = vertices.unwrap_or_default();
41
42 let (triangles, index_buffer) = if index_buffer.is_empty() {
46 (Vec::new(), Vec::new())
47 } else {
48 (triangles, index_buffer)
49 };
50
51 seed_curve_caches(enc, &vertices);
52
53 let meta: Vec<u32> = vector_types.iter().map(|t| *t as u32).collect();
54
55 let part_offsets = if geom_offsets.is_empty()
56 && !ring_offsets.is_empty()
57 && !part_offsets.is_empty()
58 && part_offsets.len() != vector_types.len() + 1
59 {
60 normalize_part_offsets_for_rings(&vector_types, &part_offsets, &ring_offsets)
62 } else {
63 part_offsets
64 };
65
66 enc.write_column_type(ColumnType::Geometry)?;
69 let stream_count_pos = enc.data().len();
70 enc.data_mut().push(0); let mut n: u8 = 0;
72
73 let ctx = StreamCtx::geom(StreamType::Length(LengthType::VarBinary), "meta");
75 codecs.write_int_stream(&meta, &ctx, enc)?;
76 n += 1;
77
78 if !geom_offsets.is_empty() {
80 let geom_offsets = if geom_offsets.len() == vector_types.len() + 1 {
81 geom_offsets
82 } else {
83 normalize_geometry_offsets(&vector_types, &geom_offsets)
84 };
85 let data = encode_root_length_stream(&vector_types, &geom_offsets, Polygon);
86 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
87 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
88
89 if !part_offsets.is_empty() {
95 if ring_offsets.is_empty() {
96 let data = encode_level1_without_ring_buffer_length_stream(
98 &vector_types,
99 &geom_offsets,
100 &part_offsets,
101 );
102 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "no_rings");
103 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
104 } else {
105 let data = encode_level1_length_stream(
108 &vector_types,
109 &geom_offsets,
110 &part_offsets,
111 false,
112 );
113 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "rings");
114 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
115
116 let data = encode_level2_length_stream(
117 &vector_types,
118 &geom_offsets,
119 &part_offsets,
120 &ring_offsets,
121 );
122 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Rings), "rings2");
123 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
124 }
125 }
126 } else if !part_offsets.is_empty() {
127 if ring_offsets.is_empty() {
128 let data = encode_root_length_stream(&vector_types, &part_offsets, Point);
129 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "no_rings");
130 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
131 } else {
132 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
136 n += write_geo_u32_stream(&[], ctx, enc, codecs)?;
137
138 let data = encode_root_length_stream(&vector_types, &part_offsets, LineString);
139 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "parts");
140 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
141
142 let has_line_string = vector_types
146 .iter()
147 .copied()
148 .any(GeometryType::is_linestring);
149 let data = encode_ring_lengths_for_mixed(
150 &vector_types,
151 &part_offsets,
152 &ring_offsets,
153 has_line_string,
154 );
155 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Rings), "parts_ring");
156 n += write_geo_u32_stream(&data, ctx, enc, codecs)?;
157 }
158 }
159
160 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Triangles), "triangles");
161 n += write_geo_u32_stream(&triangles, ctx, enc, codecs)?;
162 let ctx = StreamCtx::geom(StreamType::Offset(OffsetType::Index), "triangles_indexes");
163 n += write_geo_u32_stream(&index_buffer, ctx, enc, codecs)?;
164
165 if let Some(forced) = enc.override_vertex_buffer_type() {
166 n += match forced {
167 VertexBufferType::Vec2 => encode_vec2_vertex_stream(&vertices, enc, codecs)?,
168 VertexBufferType::Morton => encode_morton_vertex_streams(&vertices, enc, codecs)?,
169 VertexBufferType::Hilbert => encode_hilbert_vertex_streams(&vertices, enc, codecs)?,
170 };
171 } else if dict_may_be_beneficial(&vertices, enc) {
172 let mut winner_size: usize = usize::MAX;
174 let mut winner_stream_cnt: u8 = 0;
175 let mut alt = enc.try_alternatives();
176 alt.with(|e| {
177 let ds = e.data().len();
178 let ms = e.meta().len();
179 winner_stream_cnt = encode_vec2_vertex_stream(&vertices, e, codecs)?;
180 winner_size = (e.data().len() - ds) + (e.meta().len() - ms);
181 Ok(())
182 })?;
183 alt.with(|e| {
184 let ds = e.data().len();
185 let ms = e.meta().len();
186 let cnt = encode_hilbert_vertex_streams(&vertices, e, codecs)?;
187 let size = (e.data().len() - ds) + (e.meta().len() - ms);
188 if size < winner_size {
189 winner_stream_cnt = cnt;
190 winner_size = size;
191 }
192 Ok(())
193 })?;
194 alt.with(|e| {
195 let ds = e.data().len();
196 let ms = e.meta().len();
197 let cnt = encode_morton_vertex_streams(&vertices, e, codecs)?;
198 let size = (e.data().len() - ds) + (e.meta().len() - ms);
199 if size < winner_size {
200 winner_stream_cnt = cnt;
201 }
202 Ok(())
203 })?;
204 drop(alt);
205 n += winner_stream_cnt;
206 } else {
207 n += encode_vec2_vertex_stream(&vertices, enc, codecs)?;
208 }
209
210 debug_assert!(n <= 127, "geometry stream count must fit in one byte");
212 enc.data_mut()[stream_count_pos] = n;
213 Ok(())
214 }
215}