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