lib3mf_core/parser/
beamlattice_parser.rs1use crate::error::{Lib3mfError, Result};
2use crate::model::{Beam, BeamLattice, BeamSet, CapMode, ClippingMode};
3use crate::parser::xml_parser::{XmlParser, get_attribute, get_attribute_f32, get_attribute_u32};
4use quick_xml::events::Event;
5use std::io::BufRead;
6pub fn parse_beam_lattice_content<R: BufRead>(
14 parser: &mut XmlParser<R>,
15 radius: Option<f32>,
16 min_length: f32,
17 precision: f32,
18 clipping_mode: ClippingMode,
19) -> Result<BeamLattice> {
20 let mut beams = Vec::new();
21 let mut beam_sets = Vec::new();
22 let default_radius = radius.unwrap_or(0.0);
23
24 loop {
25 match parser.read_next_event()? {
26 Event::Start(e) => match e.local_name().as_ref() {
27 b"beams" => {
28 beams = parse_beams(parser, default_radius)?;
29 }
30 b"beamsets" => {
31 beam_sets = parse_beam_sets(parser)?;
32 }
33 _ => {}
34 },
35 Event::End(e) if e.local_name().as_ref() == b"beamlattice" => break,
36 Event::Eof => {
37 return Err(Lib3mfError::Validation(
38 "Unexpected EOF in beamlattice".to_string(),
39 ));
40 }
41 _ => {}
42 }
43 }
44
45 Ok(BeamLattice {
46 radius,
47 min_length,
48 precision,
49 clipping_mode,
50 beams,
51 beam_sets,
52 })
53}
54
55fn parse_beams<R: BufRead>(parser: &mut XmlParser<R>, default_radius: f32) -> Result<Vec<Beam>> {
56 let mut beams = Vec::new();
57 loop {
58 match parser.read_next_event()? {
59 Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"beam" => {
60 let v1 = get_attribute_u32(&e, b"v1")?;
61 let v2 = get_attribute_u32(&e, b"v2")?;
62 let r1 = get_attribute_f32(&e, b"r1").unwrap_or(default_radius);
63 let r2 = get_attribute_f32(&e, b"r2").unwrap_or(r1);
64 let p1 = get_attribute_u32(&e, b"p1").ok();
65 let p2 = get_attribute_u32(&e, b"p2").ok();
66
67 let cap_mode = if let Some(s) = get_attribute(&e, b"cap") {
68 match s.as_ref() {
69 "sphere" => CapMode::Sphere,
70 "hemisphere" => CapMode::Hemisphere,
71 "butt" => CapMode::Butt,
72 _ => CapMode::Sphere,
73 }
74 } else {
75 CapMode::Sphere
76 };
77
78 beams.push(Beam {
79 v1,
80 v2,
81 r1,
82 r2,
83 p1,
84 p2,
85 cap_mode,
86 });
87 }
88 Event::End(e) if e.local_name().as_ref() == b"beams" => break,
89 Event::Eof => {
90 return Err(Lib3mfError::Validation(
91 "Unexpected EOF in beams".to_string(),
92 ));
93 }
94 _ => {}
95 }
96 }
97 Ok(beams)
98}
99
100fn parse_beam_sets<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<BeamSet>> {
101 let mut sets = Vec::new();
102 loop {
103 let event = parser.read_next_event()?;
104 match event {
105 Event::Start(e) if e.local_name().as_ref() == b"beamset" => {
106 let name = get_attribute(&e, b"name").map(|s| s.into_owned());
107 let identifier = get_attribute(&e, b"identifier").map(|s| s.into_owned());
108 let refs = parse_refs(parser)?;
109 sets.push(BeamSet {
110 name,
111 identifier,
112 refs,
113 });
114 }
115 Event::Empty(e) if e.local_name().as_ref() == b"beamset" => {
116 let name = get_attribute(&e, b"name").map(|s| s.into_owned());
117 let identifier = get_attribute(&e, b"identifier").map(|s| s.into_owned());
118 sets.push(BeamSet {
119 name,
120 identifier,
121 refs: Vec::new(),
122 });
123 }
124 Event::End(e) if e.local_name().as_ref() == b"beamsets" => break,
125 Event::Eof => {
126 return Err(Lib3mfError::Validation(
127 "Unexpected EOF in beamsets".to_string(),
128 ));
129 }
130 _ => {}
131 }
132 }
133 Ok(sets)
134}
135
136fn parse_refs<R: BufRead>(parser: &mut XmlParser<R>) -> Result<Vec<u32>> {
137 let mut refs = Vec::new();
138 loop {
139 match parser.read_next_event()? {
140 Event::Start(e) | Event::Empty(e) if e.local_name().as_ref() == b"ref" => {
141 let idx = get_attribute_u32(&e, b"index")?;
142 refs.push(idx);
143 }
144 Event::End(e) if e.local_name().as_ref() == b"beamset" => break,
145 Event::Eof => {
146 return Err(Lib3mfError::Validation(
147 "Unexpected EOF in beamset".to_string(),
148 ));
149 }
150 _ => {}
151 }
152 }
153 Ok(refs)
154}