1use geop_core_math::{
5 geop_error::{GeopError, GeopResult},
6 primitives::TriangleFace,
7};
8use geop_core_rasterize::{
9 rasterize,
10 stl::{StlFormat, StlTriangle, outward, write_stl},
11};
12
13use super::NamedModel;
14
15pub type SolidMeshes = Vec<(String, Vec<TriangleFace>)>;
17
18impl NamedModel {
19 pub fn solid_meshes(&self, quality: usize) -> GeopResult<SolidMeshes> {
23 let model = self.topology();
24 let raster = rasterize(model, quality)?;
25 let mut out = Vec::new();
26 for &solid in model.solids.keys() {
27 let mut faces = model.solid_faces(solid)?;
28 faces.sort_by_key(|f| f.0);
29 let triangles = faces
30 .iter()
31 .filter_map(|f| raster.faces.get(f))
32 .flatten()
33 .cloned()
34 .collect();
35 let name = self.name_of(solid).unwrap_or_default();
36 out.push((name.to_string(), triangles));
37 }
38 out.sort_by(|a, b| a.0.cmp(&b.0));
39 Ok(out)
40 }
41}
42
43pub const STL_QUALITY: usize = geop_core_editor::view::RESOLUTION;
46
47pub fn stl_bytes<'t>(
50 triangles: impl IntoIterator<Item = &'t TriangleFace>,
51 name: &str,
52 format: StlFormat,
53) -> GeopResult<Vec<u8>> {
54 let triangles: Vec<StlTriangle> = triangles.into_iter().map(outward).collect();
55 let mut bytes = Vec::new();
56 write_stl(&triangles, name, format, &mut bytes)
57 .map_err(|e| GeopError::new(format!("writing {name}.stl: {e}")))?;
58 Ok(bytes)
59}