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