Skip to main content

geop_ops_model/
notes.rs

1//! What a step says of a solid it built beyond its shape, kept as the
2//! part's target [`solid_notes`]: a solid only drawn, which is no body (a
3//! harness' swept bundle), the thickness of a sheet-metal body, the wires
4//! ordered in a bundle's place. Whoever weighs, checks or orders a part
5//! reads them here, knowing no step that writes them.
6
7use std::collections::BTreeMap;
8
9use geop_core_math::scalars::Scalar;
10use geop_core_program::{
11    element::{ElementReference, HasElements, Kind, whole},
12    reader::Reader,
13    target::{Target, TargetReference},
14};
15
16/// What a step says of a solid it built beyond its shape (see
17/// [`solid_notes`]).
18#[derive(Clone, Debug, Default, PartialEq)]
19pub struct SolidNote {
20    /// Whether it only shows something that is no body — a harness'
21    /// swept bundle — so that it is neither weighed, checked for
22    /// interference nor ordered as one .
23    pub drawn_only: bool,
24    /// The thickness of the sheet it is bent from (mm), for a sheet-metal
25    /// body or a flat pattern of one.
26    pub thickness: Option<f64>,
27    /// The wires ordered in its place, each cut to length: a harness'.
28    pub wires: Vec<CutWire>,
29}
30
31/// A wire cut to length, as a bill of materials orders it.
32#[derive(Clone, Debug, PartialEq)]
33pub struct CutWire {
34    pub name: String,
35    /// Its colour, `#rrggbb`.
36    pub colour: String,
37    /// Its outer diameter, insulation included.
38    pub diameter: f64,
39    /// Its American wire gauge, if it was given by one.
40    pub gauge: Option<i32>,
41    /// The length to cut it to. An enclosure, as every measured length is.
42    pub cut_length: Scalar,
43}
44
45/// What the steps of a part said of its solids, by the solids' names: the
46/// value of its target [`solid_notes`], which every step that says
47/// something of a solid it built revises.
48#[derive(Clone, Debug, Default, PartialEq)]
49pub struct SolidNotes(BTreeMap<String, SolidNote>);
50
51/// What the steps of the part said of its solids.
52pub fn solid_notes() -> TargetReference<SolidNotes> {
53    TargetReference::new("solid_notes")
54}
55
56impl SolidNotes {
57    /// The note on the solid `solid`, made empty if there is none yet.
58    pub fn note_mut(&mut self, solid: impl Into<String>) -> &mut SolidNote {
59        self.0.entry(solid.into()).or_default()
60    }
61
62    /// Forgets the note on the solid `solid`: one a step consumed.
63    pub fn remove(&mut self, solid: &str) {
64        self.0.remove(solid);
65    }
66
67    /// The note on the solid `solid`, if there is one.
68    pub fn get(&self, solid: &str) -> Option<&SolidNote> {
69        self.0.get(solid)
70    }
71
72    /// Every note, by its solid's name, in the order of the names.
73    pub fn iter(&self) -> impl Iterator<Item = (&str, &SolidNote)> {
74        self.0.iter().map(|(name, note)| (name.as_str(), note))
75    }
76}
77
78/// Every step that says something of a solid adds to them.
79impl Target for SolidNotes {
80    const CHAIN: bool = true;
81}
82
83/// Read whole.
84impl Kind for SolidNotes {
85    const NAME: &'static str = "solid_notes";
86}
87
88impl HasElements<SolidNotes> for SolidNotes {
89    type Element<'a> = &'a SolidNotes;
90    const SINGLETON: Option<&'static str> = Some("solid_notes");
91
92    fn element(&self, name: &str) -> geop_core_math::geop_error::GeopResult<&SolidNotes> {
93        whole(self, name)
94    }
95}
96
97/// What the steps of the part `reader` reads said of its solids: nothing,
98/// if none said anything.
99pub fn notes_of<'a>(reader: &Reader<'a>) -> Option<&'a SolidNotes> {
100    reader.defines(&solid_notes()).then_some(())?;
101    reader
102        .retrieve_element(&ElementReference::<SolidNotes, SolidNotes>::whole(
103            solid_notes(),
104        ))
105        .ok()
106}