1use 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::decoder::GeometryType::{LineString, Point, Polygon};
12use crate::decoder::{
13 ColumnType, GeometryType, GeometryValues, LengthType, Levels, LogicalEncoding, OffsetType,
14 StreamType, VertexLogical, decode_topology,
15};
16use crate::encoder::model::StreamCtx;
17use crate::encoder::{Codecs, Encoder};
18use crate::{Decoder, MltError, MltResult};
19
20impl GeometryValues {
21 #[hotpath::measure]
23 pub fn write_to(self, enc: &mut Encoder, codecs: &mut Codecs) -> MltResult<()> {
24 let Self {
25 vector_types,
26 geometry_offsets,
27 part_offsets,
28 ring_offsets,
29 index_buffer,
30 triangle_offsets,
31 vertices,
32 #[cfg(feature = "unstable-v2")]
34 z_step: _,
35 } = self;
36
37 let geom_offsets = geometry_offsets.unwrap_or_default();
40 let part_offsets = part_offsets.unwrap_or_default();
41 let ring_offsets = ring_offsets.unwrap_or_default();
42 let index_buffer = index_buffer.unwrap_or_default();
43 let triangle_offsets = triangle_offsets.unwrap_or_default();
44 let vertices = vertices.unwrap_or_default();
45
46 let (triangle_offsets, index_buffer) = if index_buffer.is_empty() {
50 (Vec::new(), Vec::new())
51 } else {
52 (triangle_offsets, index_buffer)
53 };
54
55 seed_curve_caches(enc, &vertices);
56
57 let meta: Vec<u32> = vector_types.iter().map(|t| *t as u32).collect();
58
59 let part_offsets = if geom_offsets.is_empty()
60 && !ring_offsets.is_empty()
61 && !part_offsets.is_empty()
62 && part_offsets.len() != vector_types.len() + 1
63 {
64 normalize_part_offsets_for_rings(&vector_types, &part_offsets, &ring_offsets)
66 } else {
67 part_offsets
68 };
69
70 enc.write_column_type(ColumnType::Geometry)?;
73 let stream_count_pos = enc.data().len();
74 enc.data_mut().push(0); let mut n: u8 = 0;
76
77 let ctx = StreamCtx::geom(StreamType::Length(LengthType::VarBinary), "meta");
79 codecs.write_int_stream(&meta, &ctx, enc)?;
80 n += 1;
81
82 let mut seen = Levels::default();
84 if !geom_offsets.is_empty() {
85 let geom_offsets = if geom_offsets.len() == vector_types.len() + 1 {
86 geom_offsets
87 } else {
88 normalize_geometry_offsets(&vector_types, &geom_offsets)
89 };
90 let data = encode_root_length_stream(&vector_types, &geom_offsets, Polygon);
91 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
92 n += write_length(data, ctx, enc, codecs, &mut seen.geometries)?;
93
94 if !part_offsets.is_empty() {
100 if ring_offsets.is_empty() {
101 let data = encode_level1_without_ring_buffer_length_stream(
103 &vector_types,
104 &geom_offsets,
105 &part_offsets,
106 );
107 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "no_rings");
108 n += write_length(data, ctx, enc, codecs, &mut seen.parts)?;
109 } else {
110 let data = encode_level1_length_stream(
113 &vector_types,
114 &geom_offsets,
115 &part_offsets,
116 false,
117 );
118 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "rings");
119 n += write_length(data, ctx, enc, codecs, &mut seen.parts)?;
120
121 let data = encode_level2_length_stream(
122 &vector_types,
123 &geom_offsets,
124 &part_offsets,
125 &ring_offsets,
126 );
127 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Rings), "rings2");
128 n += write_length(data, ctx, enc, codecs, &mut seen.rings)?;
129 }
130 }
131 } else if !part_offsets.is_empty() {
132 if ring_offsets.is_empty() {
133 let data = encode_root_length_stream(&vector_types, &part_offsets, Point);
134 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "no_rings");
135 n += write_length(data, ctx, enc, codecs, &mut seen.parts)?;
136 } else {
137 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
141 n += write_length(Vec::new(), ctx, enc, codecs, &mut seen.geometries)?;
142
143 let data = encode_root_length_stream(&vector_types, &part_offsets, LineString);
144 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Parts), "parts");
145 n += write_length(data, ctx, enc, codecs, &mut seen.parts)?;
146
147 let has_line_string = vector_types
151 .iter()
152 .copied()
153 .any(GeometryType::is_linestring);
154 let data = encode_ring_lengths_for_mixed(
155 &vector_types,
156 &part_offsets,
157 &ring_offsets,
158 has_line_string,
159 );
160 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Rings), "parts_ring");
161 n += write_length(data, ctx, enc, codecs, &mut seen.rings)?;
162 }
163 }
164
165 let (triangles, index_buffer) =
166 feature_relative_triangles(vector_types, seen, triangle_offsets, index_buffer)?;
167 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Triangles), "triangles");
168 n += write_geo_u32_stream(&triangles, ctx, enc, codecs)?;
169 let ctx = StreamCtx::geom(StreamType::Offset(OffsetType::Index), "triangles_indexes");
170 n += write_geo_u32_stream(&index_buffer, ctx, enc, codecs)?;
171
172 if let Some(forced) = enc.override_vertex_buffer_type() {
173 n += match forced {
174 VertexBufferType::Vec2 => encode_vec2_vertex_stream(&vertices, enc, codecs)?,
175 VertexBufferType::Morton => encode_morton_vertex_streams(&vertices, enc, codecs)?,
176 VertexBufferType::Hilbert => encode_hilbert_vertex_streams(&vertices, enc, codecs)?,
177 VertexBufferType::Rans => {
178 return Err(MltError::UnsupportedLogicalEncoding(
179 LogicalEncoding::Vertex(VertexLogical::Rans),
180 "v1, which has no rANS vertex coding",
181 ));
182 }
183 };
184 } else if dict_may_be_beneficial(&vertices, enc) {
185 let mut winner_size: usize = usize::MAX;
187 let mut winner_stream_cnt: u8 = 0;
188 let mut alt = enc.try_alternatives();
189 alt.with(|e| {
190 let ds = e.data().len();
191 let ms = e.meta().len();
192 winner_stream_cnt = encode_vec2_vertex_stream(&vertices, e, codecs)?;
193 winner_size = (e.data().len() - ds) + (e.meta().len() - ms);
194 Ok(())
195 })?;
196 alt.with(|e| {
197 let ds = e.data().len();
198 let ms = e.meta().len();
199 let cnt = encode_hilbert_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 winner_size = size;
204 }
205 Ok(())
206 })?;
207 alt.with(|e| {
208 let ds = e.data().len();
209 let ms = e.meta().len();
210 let cnt = encode_morton_vertex_streams(&vertices, e, codecs)?;
211 let size = (e.data().len() - ds) + (e.meta().len() - ms);
212 if size < winner_size {
213 winner_stream_cnt = cnt;
214 }
215 Ok(())
216 })?;
217 drop(alt);
218 n += winner_stream_cnt;
219 } else {
220 n += encode_vec2_vertex_stream(&vertices, enc, codecs)?;
221 }
222
223 debug_assert!(n <= 127, "geometry stream count must fit in one byte");
225 enc.data_mut()[stream_count_pos] = n;
226 Ok(())
227 }
228}
229
230fn write_length(
232 data: Vec<u32>,
233 ctx: StreamCtx,
234 enc: &mut Encoder,
235 codecs: &mut Codecs,
236 seen: &mut Option<Vec<u32>>,
237) -> MltResult<u8> {
238 let n = write_geo_u32_stream(&data, ctx, enc, codecs)?;
239 if n != 0 {
240 *seen = Some(data);
241 }
242 Ok(n)
243}
244
245fn feature_relative_triangles(
247 vector_types: Vec<GeometryType>,
248 seen: Levels,
249 triangle_offsets: Vec<u32>,
250 index_buffer: Vec<u32>,
251) -> MltResult<(Vec<u32>, Vec<u32>)> {
252 if index_buffer.is_empty() {
253 return Ok((Vec::new(), Vec::new()));
254 }
255 let triangles = triangle_offsets.windows(2).map(|w| w[1] - w[0]).collect();
256 let mut dec = Decoder::default();
257 let offsets = decode_topology(&vector_types, seen, &mut dec)?;
258 let mut dense = GeometryValues {
259 vector_types,
260 geometry_offsets: offsets.geometries,
261 part_offsets: offsets.parts,
262 ring_offsets: offsets.rings,
263 index_buffer: Some(index_buffer),
264 triangle_offsets: Some(triangle_offsets),
265 vertices: None,
266 #[cfg(feature = "unstable-v2")]
267 z_step: None,
268 };
269 dense.rebase_indices_to_feature()?;
270 Ok((triangles, dense.index_buffer.unwrap_or_default()))
271}