Another project
1use bone_types::{Angle, Length, SketchEntityId, dimensioned_serde};
2use serde::{Deserialize, Serialize};
3
4#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
5pub enum DimensionKind {
6 Driving,
7 Driven,
8}
9
10#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
11pub enum DimensionValue {
12 #[serde(with = "dimensioned_serde::length_si")]
13 Length(Length),
14 #[serde(with = "dimensioned_serde::angle_si")]
15 Angle(Angle),
16}
17
18#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
19#[serde(deny_unknown_fields)]
20pub enum SketchDimension {
21 Linear {
22 a: SketchEntityId,
23 b: SketchEntityId,
24 #[serde(with = "dimensioned_serde::length_si")]
25 value: Length,
26 kind: DimensionKind,
27 },
28 Radius {
29 target: SketchEntityId,
30 #[serde(with = "dimensioned_serde::length_si")]
31 value: Length,
32 kind: DimensionKind,
33 },
34 Diameter {
35 target: SketchEntityId,
36 #[serde(with = "dimensioned_serde::length_si")]
37 value: Length,
38 kind: DimensionKind,
39 },
40 Angular {
41 a: SketchEntityId,
42 b: SketchEntityId,
43 #[serde(with = "dimensioned_serde::angle_si")]
44 value: Angle,
45 kind: DimensionKind,
46 },
47}
48
49impl SketchDimension {
50 #[must_use]
51 pub const fn kind(&self) -> DimensionKind {
52 match *self {
53 Self::Linear { kind, .. }
54 | Self::Radius { kind, .. }
55 | Self::Diameter { kind, .. }
56 | Self::Angular { kind, .. } => kind,
57 }
58 }
59
60 #[must_use]
61 pub const fn value(&self) -> DimensionValue {
62 match *self {
63 Self::Linear { value, .. }
64 | Self::Radius { value, .. }
65 | Self::Diameter { value, .. } => DimensionValue::Length(value),
66 Self::Angular { value, .. } => DimensionValue::Angle(value),
67 }
68 }
69
70 #[must_use]
71 pub const fn references(&self) -> DimensionRefs {
72 match *self {
73 Self::Linear { a, b, .. } | Self::Angular { a, b, .. } => {
74 DimensionRefs([Some(a), Some(b)])
75 }
76 Self::Radius { target, .. } | Self::Diameter { target, .. } => {
77 DimensionRefs([Some(target), None])
78 }
79 }
80 }
81
82 #[must_use]
83 pub const fn with_kind(self, kind: DimensionKind) -> Self {
84 match self {
85 Self::Linear { a, b, value, .. } => Self::Linear { a, b, value, kind },
86 Self::Radius { target, value, .. } => Self::Radius {
87 target,
88 value,
89 kind,
90 },
91 Self::Diameter { target, value, .. } => Self::Diameter {
92 target,
93 value,
94 kind,
95 },
96 Self::Angular { a, b, value, .. } => Self::Angular { a, b, value, kind },
97 }
98 }
99
100 pub fn with_value(self, value: DimensionValue) -> Result<Self, DimensionValueMismatch> {
101 match (self, value) {
102 (Self::Linear { a, b, kind, .. }, DimensionValue::Length(value)) => {
103 Ok(Self::Linear { a, b, value, kind })
104 }
105 (Self::Radius { target, kind, .. }, DimensionValue::Length(value)) => {
106 Ok(Self::Radius {
107 target,
108 value,
109 kind,
110 })
111 }
112 (Self::Diameter { target, kind, .. }, DimensionValue::Length(value)) => {
113 Ok(Self::Diameter {
114 target,
115 value,
116 kind,
117 })
118 }
119 (Self::Angular { a, b, kind, .. }, DimensionValue::Angle(value)) => {
120 Ok(Self::Angular { a, b, value, kind })
121 }
122 _ => Err(DimensionValueMismatch),
123 }
124 }
125}
126
127#[derive(Copy, Clone, Debug, PartialEq)]
128pub struct DimensionRefs([Option<SketchEntityId>; 2]);
129
130impl IntoIterator for DimensionRefs {
131 type Item = SketchEntityId;
132 type IntoIter = core::iter::Flatten<core::array::IntoIter<Option<SketchEntityId>, 2>>;
133
134 fn into_iter(self) -> Self::IntoIter {
135 self.0.into_iter().flatten()
136 }
137}
138
139#[derive(Copy, Clone, Debug, PartialEq, Eq, thiserror::Error)]
140#[error("dimension value kind does not match variant")]
141pub struct DimensionValueMismatch;