lib3mf_core/parser/
mesh_parser.rs

1use crate::error::{Lib3mfError, Result};
2use crate::model::{ClippingMode, Mesh, Triangle, Vertex};
3use crate::parser::beamlattice_parser::parse_beam_lattice_content;
4use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_f32, get_attribute_u32};
5use quick_xml::events::Event;
6use std::io::BufRead;
7
8pub fn parse_mesh<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Mesh> {
9    let mut mesh = Mesh::default();
10
11    loop {
12        match parser.read_next_event()? {
13            Event::Start(e) => match e.name().as_ref() {
14                b"vertices" => parse_vertices(parser, &mut mesh)?,
15                b"triangles" => parse_triangles(parser, &mut mesh)?,
16                b"beamlattice" => {
17                    let min_length = get_attribute_f32(&e, b"minlength").unwrap_or(0.0);
18                    let precision = get_attribute_f32(&e, b"precision").unwrap_or(0.0);
19                    let clipping_mode = if let Some(s) = get_attribute(&e, b"clippingmode") {
20                        match s.as_ref() {
21                            "inside" => ClippingMode::Inside,
22                            "outside" => ClippingMode::Outside,
23                            _ => ClippingMode::None,
24                        }
25                    } else {
26                        ClippingMode::None
27                    };
28
29                    let lattice =
30                        parse_beam_lattice_content(parser, min_length, precision, clipping_mode)?;
31                    mesh.beam_lattice = Some(lattice);
32                }
33                _ => {} // Ignore headers/metadata inside mesh for now
34            },
35            Event::End(e) if e.name().as_ref() == b"mesh" => break,
36            Event::Eof => {
37                return Err(Lib3mfError::Validation(
38                    "Unexpected EOF in mesh".to_string(),
39                ));
40            }
41            _ => {}
42        }
43    }
44
45    Ok(mesh)
46}
47
48fn parse_vertices<R: BufRead>(parser: &mut XmlParser<R>, mesh: &mut Mesh) -> Result<()> {
49    loop {
50        match parser.read_next_event()? {
51            Event::Start(e) | Event::Empty(e) if e.name().as_ref() == b"vertex" => {
52                let x = get_attribute_f32(&e, b"x")?;
53                let y = get_attribute_f32(&e, b"y")?;
54                let z = get_attribute_f32(&e, b"z")?;
55                mesh.vertices.push(Vertex { x, y, z });
56            }
57            Event::End(e) if e.name().as_ref() == b"vertices" => break,
58            Event::Eof => {
59                return Err(Lib3mfError::Validation(
60                    "Unexpected EOF in vertices".to_string(),
61                ));
62            }
63            _ => {}
64        }
65    }
66    Ok(())
67}
68
69fn parse_triangles<R: BufRead>(parser: &mut XmlParser<R>, mesh: &mut Mesh) -> Result<()> {
70    loop {
71        match parser.read_next_event()? {
72            Event::Start(e) | Event::Empty(e) if e.name().as_ref() == b"triangle" => {
73                let v1 = get_attribute_u32(&e, b"v1")?;
74                let v2 = get_attribute_u32(&e, b"v2")?;
75                let v3 = get_attribute_u32(&e, b"v3")?;
76                let p1 = get_attribute_u32(&e, b"p1").ok();
77                let p2 = get_attribute_u32(&e, b"p2").ok();
78                let p3 = get_attribute_u32(&e, b"p3").ok();
79                let pid = get_attribute_u32(&e, b"pid").ok();
80
81                mesh.triangles.push(Triangle {
82                    v1,
83                    v2,
84                    v3,
85                    p1,
86                    p2,
87                    p3,
88                    pid,
89                });
90            }
91            Event::End(e) if e.name().as_ref() == b"triangles" => break,
92            Event::Eof => {
93                return Err(Lib3mfError::Validation(
94                    "Unexpected EOF in triangles".to_string(),
95                ));
96            }
97            _ => {}
98        }
99    }
100    Ok(())
101}