1use crate::protocol::message::Message;
7use crate::error::{IgtlError, Result};
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)
327 .with_polygons(vec![3, 0, 1, 2]); assert_eq!(poly.polygons, vec![3, 0, 1, 2]);
330 }
331
332 #[test]
333 fn test_add_attribute() {
334 let points = vec![[0.0, 0.0, 0.0]];
335 let mut poly = PolyDataMessage::new(points);
336
337 let attr = Attribute::new(
338 AttributeType::Point,
339 3,
340 "Normals",
341 vec![0.0, 0.0, 1.0],
342 );
343 poly.add_attribute(attr);
344
345 assert_eq!(poly.attributes.len(), 1);
346 }
347
348 #[test]
349 fn test_encode_simple() {
350 let points = vec![[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]];
351 let poly = PolyDataMessage::new(points);
352 let encoded = poly.encode_content().unwrap();
353
354 assert!(encoded.len() >= 48);
356 }
357
358 #[test]
359 fn test_roundtrip_points_only() {
360 let original = PolyDataMessage::new(vec![
361 [0.0, 0.0, 0.0],
362 [1.0, 0.0, 0.0],
363 [0.0, 1.0, 0.0],
364 [0.0, 0.0, 1.0],
365 ]);
366
367 let encoded = original.encode_content().unwrap();
368 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
369
370 assert_eq!(decoded.num_points(), 4);
371 assert_eq!(decoded.points, original.points);
372 }
373
374 #[test]
375 fn test_roundtrip_with_polygons() {
376 let original = PolyDataMessage::new(vec![
377 [0.0, 0.0, 0.0],
378 [1.0, 0.0, 0.0],
379 [0.0, 1.0, 0.0],
380 ])
381 .with_polygons(vec![3, 0, 1, 2]);
382
383 let encoded = original.encode_content().unwrap();
384 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
385
386 assert_eq!(decoded.polygons, vec![3, 0, 1, 2]);
387 }
388
389 #[test]
390 fn test_roundtrip_with_attribute() {
391 let mut original = PolyDataMessage::new(vec![[0.0, 0.0, 0.0]]);
392
393 original.add_attribute(Attribute::new(
394 AttributeType::Point,
395 3,
396 "Normals",
397 vec![0.0, 0.0, 1.0],
398 ));
399
400 let encoded = original.encode_content().unwrap();
401 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
402
403 assert_eq!(decoded.attributes.len(), 1);
404 assert_eq!(decoded.attributes[0].name, "Normals");
405 assert_eq!(decoded.attributes[0].num_components, 3);
406 assert_eq!(decoded.attributes[0].data, vec![0.0, 0.0, 1.0]);
407 }
408
409 #[test]
410 fn test_roundtrip_complex() {
411 let mut original = PolyDataMessage::new(vec![
412 [0.0, 0.0, 0.0],
413 [1.0, 0.0, 0.0],
414 [1.0, 1.0, 0.0],
415 [0.0, 1.0, 0.0],
416 ])
417 .with_polygons(vec![4, 0, 1, 2, 3])
418 .with_lines(vec![2, 0, 1]);
419
420 original.add_attribute(Attribute::new(
421 AttributeType::Cell,
422 1,
423 "Quality",
424 vec![0.95],
425 ));
426
427 let encoded = original.encode_content().unwrap();
428 let decoded = PolyDataMessage::decode_content(&encoded).unwrap();
429
430 assert_eq!(decoded.num_points(), 4);
431 assert_eq!(decoded.polygons, vec![4, 0, 1, 2, 3]);
432 assert_eq!(decoded.lines, vec![2, 0, 1]);
433 assert_eq!(decoded.attributes.len(), 1);
434 }
435
436 #[test]
437 fn test_decode_invalid() {
438 let data = vec![0u8; 2]; let result = PolyDataMessage::decode_content(&data);
440 assert!(result.is_err());
441 }
442}