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, OffsetType, StreamType,
14};
15use crate::decoder::{Levels, decode_topology};
16use crate::encoder::model::StreamCtx;
17use crate::encoder::{Codecs, Encoder};
18use crate::{Decoder, 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 } = self;
33
34 let geom_offsets = geometry_offsets.unwrap_or_default();
37 let part_offsets = part_offsets.unwrap_or_default();
38 let ring_offsets = ring_offsets.unwrap_or_default();
39 let index_buffer = index_buffer.unwrap_or_default();
40 let triangle_offsets = triangle_offsets.unwrap_or_default();
41 let vertices = vertices.unwrap_or_default();
42
43 let (triangle_offsets, index_buffer) = if index_buffer.is_empty() {
47 (Vec::new(), Vec::new())
48 } else {
49 (triangle_offsets, index_buffer)
50 };
51
52 seed_curve_caches(enc, &vertices);
53
54 let meta: Vec<u32> = vector_types.iter().map(|t| *t as u32).collect();
55
56 let part_offsets = if geom_offsets.is_empty()
57 && !ring_offsets.is_empty()
58 && !part_offsets.is_empty()
59 && part_offsets.len() != vector_types.len() + 1
60 {
61 normalize_part_offsets_for_rings(&vector_types, &part_offsets, &ring_offsets)
63 } else {
64 part_offsets
65 };
66
67 enc.write_column_type(ColumnType::Geometry)?;
70 let stream_count_pos = enc.data().len();
71 enc.data_mut().push(0); let mut n: u8 = 0;
73
74 let ctx = StreamCtx::geom(StreamType::Length(LengthType::VarBinary), "meta");
76 codecs.write_int_stream(&meta, &ctx, enc)?;
77 n += 1;
78
79 let mut seen = Levels::default();
81 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_length(data, ctx, enc, codecs, &mut seen.geometries)?;
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_length(data, ctx, enc, codecs, &mut seen.parts)?;
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_length(data, ctx, enc, codecs, &mut seen.parts)?;
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_length(data, ctx, enc, codecs, &mut seen.rings)?;
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_length(data, ctx, enc, codecs, &mut seen.parts)?;
133 } else {
134 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Geometries), "geometries");
138 n += write_length(Vec::new(), ctx, enc, codecs, &mut seen.geometries)?;
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_length(data, ctx, enc, codecs, &mut seen.parts)?;
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_length(data, ctx, enc, codecs, &mut seen.rings)?;
159 }
160 }
161
162 let (triangles, index_buffer) =
163 feature_relative_triangles(vector_types, seen, triangle_offsets, index_buffer)?;
164 let ctx = StreamCtx::geom(StreamType::Length(LengthType::Triangles), "triangles");
165 n += write_geo_u32_stream(&triangles, ctx, enc, codecs)?;
166 let ctx = StreamCtx::geom(StreamType::Offset(OffsetType::Index), "triangles_indexes");
167 n += write_geo_u32_stream(&index_buffer, ctx, enc, codecs)?;
168
169 if let Some(forced) = enc.override_vertex_buffer_type() {
170 n += match forced {
171 VertexBufferType::Vec2 => encode_vec2_vertex_stream(&vertices, enc, codecs)?,
172 VertexBufferType::Morton => encode_morton_vertex_streams(&vertices, enc, codecs)?,
173 VertexBufferType::Hilbert => encode_hilbert_vertex_streams(&vertices, enc, codecs)?,
174 };
175 } else if dict_may_be_beneficial(&vertices, enc) {
176 let mut winner_size: usize = usize::MAX;
178 let mut winner_stream_cnt: u8 = 0;
179 let mut alt = enc.try_alternatives();
180 alt.with(|e| {
181 let ds = e.data().len();
182 let ms = e.meta().len();
183 winner_stream_cnt = encode_vec2_vertex_stream(&vertices, e, codecs)?;
184 winner_size = (e.data().len() - ds) + (e.meta().len() - ms);
185 Ok(())
186 })?;
187 alt.with(|e| {
188 let ds = e.data().len();
189 let ms = e.meta().len();
190 let cnt = encode_hilbert_vertex_streams(&vertices, e, codecs)?;
191 let size = (e.data().len() - ds) + (e.meta().len() - ms);
192 if size < winner_size {
193 winner_stream_cnt = cnt;
194 winner_size = size;
195 }
196 Ok(())
197 })?;
198 alt.with(|e| {
199 let ds = e.data().len();
200 let ms = e.meta().len();
201 let cnt = encode_morton_vertex_streams(&vertices, e, codecs)?;
202 let size = (e.data().len() - ds) + (e.meta().len() - ms);
203 if size < winner_size {
204 winner_stream_cnt = cnt;
205 }
206 Ok(())
207 })?;
208 drop(alt);
209 n += winner_stream_cnt;
210 } else {
211 n += encode_vec2_vertex_stream(&vertices, enc, codecs)?;
212 }
213
214 debug_assert!(n <= 127, "geometry stream count must fit in one byte");
216 enc.data_mut()[stream_count_pos] = n;
217 Ok(())
218 }
219}
220
221fn write_length(
223 data: Vec<u32>,
224 ctx: StreamCtx,
225 enc: &mut Encoder,
226 codecs: &mut Codecs,
227 seen: &mut Option<Vec<u32>>,
228) -> MltResult<u8> {
229 let n = write_geo_u32_stream(&data, ctx, enc, codecs)?;
230 if n != 0 {
231 *seen = Some(data);
232 }
233 Ok(n)
234}
235
236fn feature_relative_triangles(
238 vector_types: Vec<GeometryType>,
239 seen: Levels,
240 triangle_offsets: Vec<u32>,
241 index_buffer: Vec<u32>,
242) -> MltResult<(Vec<u32>, Vec<u32>)> {
243 if index_buffer.is_empty() {
244 return Ok((Vec::new(), Vec::new()));
245 }
246 let triangles = triangle_offsets.windows(2).map(|w| w[1] - w[0]).collect();
247 let mut dec = Decoder::default();
248 let offsets = decode_topology(&vector_types, seen, &mut dec)?;
249 let mut dense = GeometryValues {
250 vector_types,
251 geometry_offsets: offsets.geometries,
252 part_offsets: offsets.parts,
253 ring_offsets: offsets.rings,
254 index_buffer: Some(index_buffer),
255 triangle_offsets: Some(triangle_offsets),
256 vertices: None,
257 };
258 dense.rebase_indices_to_feature()?;
259 Ok((triangles, dense.index_buffer.unwrap_or_default()))
260}