1use crate::error::{IgtlError, Result};
7use crate::protocol::message::Message;
8use bytes::{Buf, BufMut};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum AttributeType {
13 Point = 0,
14 Cell = 1,
15}
16
17impl AttributeType {
18 pub fn from_u8(value: u8) -> Result<Self> {
20 match value {
21 0 => Ok(AttributeType::Point),
22 1 => Ok(AttributeType::Cell),
23 _ => Err(IgtlError::InvalidSize {
24 expected: 0,
25 actual: value as usize,
26 }),
27 }
28 }
29}
30
31#[derive(Debug, Clone, PartialEq)]
33pub struct Attribute {
34 pub attr_type: AttributeType,
36 pub num_components: u8,
38 pub name: String,
40 pub data: Vec<f32>,
42}
43
44impl Attribute {
45 pub fn new(
47 attr_type: AttributeType,
48 num_components: u8,
49 name: impl Into<String>,
50 data: Vec<f32>,
51 ) -> Self {
52 Attribute {
53 attr_type,
54 num_components,
55 name: name.into(),
56 data,
57 }
58 }
59}
60
61#[derive(Debug, Clone, PartialEq)]
68pub struct PolyDataMessage {
69 pub points: Vec<[f32; 3]>,
71 pub vertices: Vec<u32>,
73 pub lines: Vec<u32>,
75 pub polygons: Vec<u32>,
77 pub triangle_strips: Vec<u32>,
79 pub attributes: Vec<Attribute>,
81}
82
83impl PolyDataMessage {
84 pub fn new(points: Vec<[f32; 3]>) -> Self {
86 PolyDataMessage {
87 points,
88 vertices: Vec::new(),
89 lines: Vec::new(),
90 polygons: Vec::new(),
91 triangle_strips: Vec::new(),
92 attributes: Vec::new(),
93 }
94 }
95
96 pub fn with_vertices(mut self, vertices: Vec<u32>) -> Self {
98 self.vertices = vertices;
99 self
100 }
101
102 pub fn with_lines(mut self, lines: Vec<u32>) -> Self {
104 self.lines = lines;
105 self
106 }
107
108 pub fn with_polygons(mut self, polygons: Vec<u32>) -> Self {
110 self.polygons = polygons;
111 self
112 }
113
114 pub fn with_triangle_strips(mut self, strips: Vec<u32>) -> Self {
116 self.triangle_strips = strips;
117 self
118 }
119
120 pub fn add_attribute(&mut self, attr: Attribute) {
122 self.attributes.push(attr);
123 }
124
125 pub fn num_points(&self) -> usize {
127 self.points.len()
128 }
129}
130
131impl Message for PolyDataMessage {
132 fn message_type() -> &'static str {
133 "POLYDATA"
134 }
135
136 fn encode_content(&self) -> Result<Vec<u8>> {
137 let mut buf = Vec::new();
138
139 buf.put_u32(self.points.len() as u32);
141
142 for point in &self.points {
144 for &coord in point {
145 buf.put_f32(coord);
146 }
147 }
148
149 buf.put_u32(self.vertices.len() as u32);
151 for &v in &self.vertices {
152 buf.put_u32(v);
153 }
154
155 buf.put_u32(self.lines.len() as u32);
157 for &l in &self.lines {
158 buf.put_u32(l);
159 }
160
161 buf.put_u32(self.polygons.len() as u32);
163 for &p in &self.polygons {
164 buf.put_u32(p);
165 }
166
167 buf.put_u32(self.triangle_strips.len() as u32);
169 for &t in &self.triangle_strips {
170 buf.put_u32(t);
171 }
172
173 buf.put_u32(self.attributes.len() as u32);
175
176 for attr in &self.attributes {
178 buf.put_u8(attr.attr_type as u8);
180
181 buf.put_u8(attr.num_components);
183
184 let mut name_bytes = [0u8; 64];
186 let name_str = attr.name.as_bytes();
187 let copy_len = name_str.len().min(63);
188 name_bytes[..copy_len].copy_from_slice(&name_str[..copy_len]);
189 buf.extend_from_slice(&name_bytes);
190
191 buf.put_u32(attr.data.len() as u32);
193
194 for &val in &attr.data {
196 buf.put_f32(val);
197 }
198 }
199
200 Ok(buf)
201 }
202
203 fn decode_content(mut data: &[u8]) -> Result<Self> {
204 if data.len() < 4 {
205 return Err(IgtlError::InvalidSize {
206 expected: 4,
207 actual: data.len(),
208 });
209 }
210
211 let num_points = data.get_u32() as usize;
213
214 let mut points = Vec::with_capacity(num_points);
216 for _ in 0..num_points {
217 if data.remaining() < 12 {
218 return Err(IgtlError::InvalidSize {
219 expected: 12,
220 actual: data.remaining(),
221 });
222 }
223 points.push([data.get_f32(), data.get_f32(), data.get_f32()]);
224 }
225
226 let num_vertices = data.get_u32() as usize;
228 let mut vertices = Vec::with_capacity(num_vertices);
229 for _ in 0..num_vertices {
230 vertices.push(data.get_u32());
231 }
232
233 let num_lines = data.get_u32() as usize;
235 let mut lines = Vec::with_capacity(num_lines);
236 for _ in 0..num_lines {
237 lines.push(data.get_u32());
238 }
239
240 let num_polygons = data.get_u32() as usize;
242 let mut polygons = Vec::with_capacity(num_polygons);
243 for _ in 0..num_polygons {
244 polygons.push(data.get_u32());
245 }
246
247 let num_strips = data.get_u32() as usize;
249 let mut triangle_strips = Vec::with_capacity(num_strips);
250 for _ in 0..num_strips {
251 triangle_strips.push(data.get_u32());
252 }
253
254 let num_attributes = data.get_u32() as usize;
256 let mut attributes = Vec::with_capacity(num_attributes);
257
258 for _ in 0..num_attributes {
259 let attr_type = AttributeType::from_u8(data.get_u8())?;
261
262 let num_components = data.get_u8();
264
265 let name_bytes = &data[..64];
267 data.advance(64);
268 let name_len = name_bytes.iter().position(|&b| b == 0).unwrap_or(64);
269 let name = String::from_utf8(name_bytes[..name_len].to_vec())?;
270
271 let data_size = data.get_u32() as usize;
273
274 let mut attr_data = Vec::with_capacity(data_size);
276 for _ in 0..data_size {
277 attr_data.push(data.get_f32());
278 }
279
280 attributes.push(Attribute {
281 attr_type,
282 num_components,
283 name,
284 data: attr_data,
285 });
286 }
287
288 if !data.is_empty() {
289 return Err(IgtlError::InvalidSize {
290 expected: 0,
291 actual: data.remaining(),
292 });
293 }
294
295 Ok(PolyDataMessage {
296 points,
297 vertices,
298 lines,
299 polygons,
300 triangle_strips,
301 attributes,
302 })
303 }
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn test_message_type() {
312 assert_eq!(PolyDataMessage::message_type(), "POLYDATA");
313 }
314
315 #[test]
316 fn test_new() {
317 let points = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
318 let poly = PolyDataMessage::new(points.clone());
319 assert_eq!(poly.num_points(), 3);
320 assert_eq!(poly.points, points);
321 }
322
323 #[test]
324 fn test_with_polygons() {
325 let points = vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]];
326 let poly = PolyDataMessage::new(points).with_polygons(vec![3, 0, 1, 2]); assert_eq!(poly.polygons, vec![3, 0, 1, 2]);
329 }
330
331 #[test]
332 fn test_add_attribute() {
333 let points = vec![[0.0, 0.0, 0.0]];
334 let mut poly = PolyDataMessage::new(points);
335
336 let attr = Attribute::new(AttributeType::Point, 3, "Normals", vec![0.0, 0.0, 1.0]);
337 poly.add_attribute(attr);
338
339 assert_eq!(poly.attributes.len(), 1);
340 }
341
342 #[test]
343 fn test_encode_simple() {
344 let points = vec![[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]];
345 let poly = PolyDataMessage::new(points);
346 let encoded = poly.encode_content().unwrap();
347
348 assert!(encoded.len() >= 48);
350 }
351
352 #[test]
353 fn test_roundtrip_points_only() {
354 let original = PolyDataMessage::new(vec![
355 [0.0, 0.0, 0.0],
356 [1.0, 0.0, 0.0],
357 [0.0, 1.0, 0.0],
358 [0.0, 0.0, 1.0],
359 ]);
360
361 let encoded = original.encode_content().unwrap();
362 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
363
364 assert_eq!(decoded.num_points(), 4);
365 assert_eq!(decoded.points, original.points);
366 }
367
368 #[test]
369 fn test_roundtrip_with_polygons() {
370 let original =
371 PolyDataMessage::new(vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
372 .with_polygons(vec![3, 0, 1, 2]);
373
374 let encoded = original.encode_content().unwrap();
375 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
376
377 assert_eq!(decoded.polygons, vec![3, 0, 1, 2]);
378 }
379
380 #[test]
381 fn test_roundtrip_with_attribute() {
382 let mut original = PolyDataMessage::new(vec![[0.0, 0.0, 0.0]]);
383
384 original.add_attribute(Attribute::new(
385 AttributeType::Point,
386 3,
387 "Normals",
388 vec![0.0, 0.0, 1.0],
389 ));
390
391 let encoded = original.encode_content().unwrap();
392 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
393
394 assert_eq!(decoded.attributes.len(), 1);
395 assert_eq!(decoded.attributes[0].name, "Normals");
396 assert_eq!(decoded.attributes[0].num_components, 3);
397 assert_eq!(decoded.attributes[0].data, vec![0.0, 0.0, 1.0]);
398 }
399
400 #[test]
401 fn test_roundtrip_complex() {
402 let mut original = PolyDataMessage::new(vec![
403 [0.0, 0.0, 0.0],
404 [1.0, 0.0, 0.0],
405 [1.0, 1.0, 0.0],
406 [0.0, 1.0, 0.0],
407 ])
408 .with_polygons(vec![4, 0, 1, 2, 3])
409 .with_lines(vec![2, 0, 1]);
410
411 original.add_attribute(Attribute::new(
412 AttributeType::Cell,
413 1,
414 "Quality",
415 vec![0.95],
416 ));
417
418 let encoded = original.encode_content().unwrap();
419 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
420
421 assert_eq!(decoded.num_points(), 4);
422 assert_eq!(decoded.polygons, vec![4, 0, 1, 2, 3]);
423 assert_eq!(decoded.lines, vec![2, 0, 1]);
424 assert_eq!(decoded.attributes.len(), 1);
425 }
426
427 #[test]
428 fn test_decode_invalid() {
429 let data = vec![0u8; 2]; let result = PolyDataMessage::decode_content(&data);
431 assert!(result.is_err());
432 }
433}