lib3mf_core/parser/
displacement_parser.rs1use crate::error::{Lib3mfError, Result};
2use crate::model::{
3 Channel, Displacement2D, DisplacementMesh, DisplacementTriangle, FilterMode, GradientVector,
4 NormalVector, ResourceId, TileStyle, Vertex,
5};
6use crate::parser::xml_parser::{XmlParser, get_attribute_f32, get_attribute_u32};
7use quick_xml::events::Event;
8use std::io::BufRead;
9
10pub fn parse_displacement_mesh<R: BufRead>(parser: &mut XmlParser<R>) -> Result<DisplacementMesh> {
11 let mut vertices = Vec::new();
12 let mut triangles = Vec::new();
13 let mut normals = Vec::new();
14 let mut gradients = Vec::new();
15
16 loop {
17 match parser.read_next_event()? {
18 Event::Start(e) => {
19 let local_name = e.local_name();
20 match local_name.as_ref() {
21 b"vertices" => {
22 vertices = parse_displacement_vertices(parser)?;
23 }
24 b"triangles" => {
25 triangles = parse_displacement_triangles(parser)?;
26 }
27 b"normvectors" => {
28 normals = parse_normal_vectors(parser)?;
29 }
30 b"disp2dgroups" => {
31 gradients = parse_disp2d_groups(parser)?;
33 }
34 _ => {}
35 }
36 }
37 Event::End(e) if e.local_name().as_ref() == b"displacementmesh" => break,
38 Event::Eof => {
39 return Err(Lib3mfError::Validation(
40 "Unexpected EOF in displacementmesh".to_string(),
41 ));
42 }
43 _ => {}
44 }
45 }
46
47 Ok(DisplacementMesh {
48 vertices,
49 triangles,
50 normals,
51 gradients: if gradients.is_empty() {
52 None
53 } else {
54 Some(gradients)
55 },
56 })
57}
58
59fn parse_displacement_vertices<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<Vertex>> {
60 let mut vertices = Vec::new();
61 loop {
62 match parser.read_next_event()? {
63 Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"vertex" => {
64 let x = get_attribute_f32(&e, b"x")?;
65 let y = get_attribute_f32(&e, b"y")?;
66 let z = get_attribute_f32(&e, b"z")?;
67 vertices.push(Vertex { x, y, z });
68 }
69 Event::End(e) if e.local_name().as_ref() == b"vertices" => break,
70 Event::Eof => {
71 return Err(Lib3mfError::Validation(
72 "Unexpected EOF in vertices".to_string(),
73 ));
74 }
75 _ => {}
76 }
77 }
78 Ok(vertices)
79}
80
81fn parse_displacement_triangles<R: BufRead>(
82 parser: &mut XmlParser<R>,
83) -> Result<Vec<DisplacementTriangle>> {
84 let mut triangles = Vec::new();
85 loop {
86 match parser.read_next_event()? {
87 Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"triangle" => {
88 let v1 = get_attribute_u32(&e, b"v1")?;
89 let v2 = get_attribute_u32(&e, b"v2")?;
90 let v3 = get_attribute_u32(&e, b"v3")?;
91 let d1 = get_attribute_u32(&e, b"d1").ok();
92 let d2 = get_attribute_u32(&e, b"d2").ok();
93 let d3 = get_attribute_u32(&e, b"d3").ok();
94 let p1 = get_attribute_u32(&e, b"p1").ok();
95 let p2 = get_attribute_u32(&e, b"p2").ok();
96 let p3 = get_attribute_u32(&e, b"p3").ok();
97 let pid = get_attribute_u32(&e, b"pid").ok();
98
99 triangles.push(DisplacementTriangle {
100 v1,
101 v2,
102 v3,
103 d1,
104 d2,
105 d3,
106 p1,
107 p2,
108 p3,
109 pid,
110 });
111 }
112 Event::End(e) if e.local_name().as_ref() == b"triangles" => break,
113 Event::Eof => {
114 return Err(Lib3mfError::Validation(
115 "Unexpected EOF in triangles".to_string(),
116 ));
117 }
118 _ => {}
119 }
120 }
121 Ok(triangles)
122}
123
124fn parse_normal_vectors<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<NormalVector>> {
125 let mut normals = Vec::new();
126 loop {
127 match parser.read_next_event()? {
128 Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"normvector" => {
129 let nx = get_attribute_f32(&e, b"nx")?;
130 let ny = get_attribute_f32(&e, b"ny")?;
131 let nz = get_attribute_f32(&e, b"nz")?;
132 normals.push(NormalVector { nx, ny, nz });
133 }
134 Event::End(e) if e.local_name().as_ref() == b"normvectors" => break,
135 Event::Eof => {
136 return Err(Lib3mfError::Validation(
137 "Unexpected EOF in normvectors".to_string(),
138 ));
139 }
140 _ => {}
141 }
142 }
143 Ok(normals)
144}
145
146fn parse_disp2d_groups<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<GradientVector>> {
147 let mut gradients = Vec::new();
148 loop {
149 match parser.read_next_event()? {
150 Event::Start(e) => {
151 if e.local_name().as_ref() == b"disp2dgroup" {
152 loop {
154 match parser.read_next_event()? {
155 Event::Start(grad_e) | Event::Empty(grad_e)
156 if grad_e.local_name().as_ref() == b"gradient" =>
157 {
158 let gu = get_attribute_f32(&grad_e, b"gu")?;
159 let gv = get_attribute_f32(&grad_e, b"gv")?;
160 gradients.push(GradientVector { gu, gv });
161 }
162 Event::End(end_e) if end_e.local_name().as_ref() == b"disp2dgroup" => {
163 break;
164 }
165 Event::Eof => {
166 return Err(Lib3mfError::Validation(
167 "Unexpected EOF in disp2dgroup".to_string(),
168 ));
169 }
170 _ => {}
171 }
172 }
173 }
174 }
175 Event::End(e) if e.local_name().as_ref() == b"disp2dgroups" => break,
176 Event::Eof => {
177 return Err(Lib3mfError::Validation(
178 "Unexpected EOF in disp2dgroups".to_string(),
179 ));
180 }
181 _ => {}
182 }
183 }
184 Ok(gradients)
185}
186
187#[allow(clippy::too_many_arguments)]
188pub fn parse_displacement_2d<R: BufRead>(
189 parser: &mut XmlParser<R>,
190 id: ResourceId,
191 path: String,
192 channel: Channel,
193 tile_style: TileStyle,
194 filter: FilterMode,
195 height: f32,
196 offset: f32,
197) -> Result<Displacement2D> {
198 loop {
200 match parser.read_next_event()? {
201 Event::End(e) if e.local_name().as_ref() == b"displacement2d" => break,
202 Event::Eof => {
203 return Err(Lib3mfError::Validation(
204 "Unexpected EOF in displacement2d".to_string(),
205 ));
206 }
207 _ => {}
208 }
209 }
210
211 Ok(Displacement2D {
212 id,
213 path,
214 channel,
215 tile_style,
216 filter,
217 height,
218 offset,
219 })
220}