Skip to main content

geop_ops_model/
mesh.rs

1//! A model's solids as triangle meshes, for files that hold meshes (STL),
2//! and the STL file they are written as ([`stl_bytes`]).
3
4use 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
15/// Solids, each by name with its triangles.
16pub type SolidMeshes = Vec<(String, Vec<TriangleFace>)>;
17
18impl NamedModel {
19    /// Every solid, by name, as triangles, meshed `quality` fine (see
20    /// [`rasterize`]), in name order so a file written from them does not
21    /// depend on how the model stores them.
22    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
43/// How finely an STL file's curved faces are meshed unless asked otherwise:
44/// as finely as the editor draws them.
45pub const STL_QUALITY: usize = geop_core_editor::view::RESOLUTION;
46
47/// `triangles` as an STL file called `name`, each facing out (see
48/// [`outward`]).
49pub 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}