Skip to main content

geop_core_part/
datum.rs

1//! A [`Part`]'s datums: reference geometry — points, axes and planes the
2//! part is built *with*, not *of*. A sketch is placed on a datum plane, a
3//! datum axis is picked as a direction, a datum is built from another one.
4//! Named like any other entity.
5
6use geop_core_math::{
7    geop_error::{GeopError, GeopResult},
8    primitives::CoordinateSystem,
9    scalars::Scalar,
10};
11use serde::{Deserialize, Serialize};
12
13use crate::ids::DatumId;
14use crate::part::Part;
15
16/// What a datum stands for.
17#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
18#[serde(rename_all = "snake_case")]
19pub enum DatumKind {
20    /// The frame's origin — with the frame itself, a coordinate system.
21    Point,
22    /// The line through the frame's origin along its `w`.
23    Axis,
24    /// The plane through the frame's origin normal to its `w`; `u`/`v` are
25    /// a sketch's `x`/`y` on it.
26    Plane,
27}
28
29/// One datum: a right-handed orthonormal frame, and which part of it the
30/// datum stands for. Every datum has a whole frame, whatever its kind, so
31/// anything built on it — a sketch on a plane, a datum offset from a point
32/// — has axes to be built along.
33#[derive(Clone, Debug)]
34pub struct Datum<S: Scalar> {
35    pub kind: DatumKind,
36    pub frame: CoordinateSystem<S>,
37}
38
39impl<S: Scalar> Part<S> {
40    /// Adds `datum` to the part under `name`. Fails, leaving the part
41    /// unchanged, if `name` is already taken.
42    pub fn add_datum(&mut self, datum: Datum<S>, name: impl Into<String>) -> GeopResult<DatumId> {
43        let id = DatumId(self.fresh_id());
44        self.names.insert(id, name)?;
45        self.datums.insert(id, datum);
46        Ok(id)
47    }
48
49    pub fn datum(&self, id: DatumId) -> GeopResult<&Datum<S>> {
50        self.datums
51            .get(&id)
52            .ok_or_else(|| GeopError::new(format!("Part has no datum {id}")))
53    }
54
55    /// Every datum, in the order they were added.
56    pub fn datums(&self) -> impl Iterator<Item = (DatumId, &Datum<S>)> {
57        self.datums.iter().map(|(&id, d)| (id, d))
58    }
59}