1use serde::{Deserialize, Serialize};
2
3use super::AsConstraintData;
4use crate::{
5 bindings::{Slvs_hEntity, Slvs_hGroup, SLVS_C_ARC_ARC_DIFFERENCE},
6 define_element,
7 element::{AsGroup, AsHandle, AsSlvsType, FromSystem},
8 entity::{ArcOfCircle, EntityHandle},
9 group::Group,
10 System,
11};
12
13define_element!(
14 SLVS_C_ARC_ARC_DIFFERENCE,
15 struct ArcArcDifference {
17 arc_a: EntityHandle<ArcOfCircle>,
18 arc_b: EntityHandle<ArcOfCircle>,
19 difference: f64,
20 }
21);
22
23impl AsConstraintData for ArcArcDifference {
24 fn workplane(&self) -> Option<Slvs_hEntity> {
25 None
26 }
27
28 fn entities(&self) -> Option<[Slvs_hEntity; 4]> {
29 Some([self.arc_a.handle(), self.arc_b.handle(), 0, 0])
30 }
31
32 fn val(&self) -> Option<f64> {
33 Some(self.difference)
34 }
35}
36
37impl FromSystem for ArcArcDifference {
38 fn from_system(sys: &System, element: &impl AsHandle) -> Result<Self, &'static str>
39 where
40 Self: Sized,
41 {
42 let slvs_constraint = sys.slvs_constraint(element.handle())?;
43
44 if SLVS_C_ARC_ARC_DIFFERENCE == slvs_constraint.type_ as _ {
45 Ok(Self {
46 group: Group(slvs_constraint.group),
47 arc_a: EntityHandle::new(slvs_constraint.entityA),
48 arc_b: EntityHandle::new(slvs_constraint.entityB),
49 difference: slvs_constraint.valA,
50 })
51 } else {
52 Err("Expected constraint to have type SLVS_C_ARC_ARC_DIFFERENCE.")
53 }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use crate::{
60 constraint::ArcArcDifference,
61 entity::{ArcOfCircle, Normal, Point, Workplane},
62 len_within_tolerance,
63 utils::{arc_len, make_quaternion},
64 System,
65 };
66
67 #[test]
68 fn arc_arc_difference() {
69 let mut sys = System::new();
70
71 let workplane_g = sys.add_group();
72 let origin = sys
73 .sketch(Point::new_in_3d(workplane_g, [0.0, 0.0, 0.0]))
74 .expect("origin created");
75 let normal = sys
76 .sketch(Normal::new_in_3d(
77 workplane_g,
78 make_quaternion([1.0, 0.0, 0.0], [0.0, 1.0, 0.0]),
79 ))
80 .expect("normal created");
81 let workplane = sys
82 .sketch(Workplane::new(workplane_g, origin, normal))
83 .expect("workplane created");
84
85 let g = sys.add_group();
86 let center_a = sys
87 .sketch(Point::new_on_workplane(g, workplane, [-5.0, 56.0]))
88 .expect("point created");
89 let arc_start_a = sys
90 .sketch(Point::new_on_workplane(g, workplane, [-62.0, -57.0]))
91 .expect("point created");
92 let arc_end_a = sys
93 .sketch(Point::new_on_workplane(g, workplane, [-9.0, 42.0]))
94 .expect("point created");
95 let arc_a = sys
96 .sketch(ArcOfCircle::new(
97 g,
98 workplane,
99 center_a,
100 arc_start_a,
101 arc_end_a,
102 ))
103 .expect("arc created");
104 let center_b = sys
105 .sketch(Point::new_on_workplane(g, workplane, [-50.0, -10.0]))
106 .expect("point created");
107 let arc_start_b = sys
108 .sketch(Point::new_on_workplane(g, workplane, [-41.0, -27.0]))
109 .expect("point created");
110 let arc_end_b = sys
111 .sketch(Point::new_on_workplane(g, workplane, [-12.0, 26.0]))
112 .expect("point created");
113 let arc_b = sys
114 .sketch(ArcOfCircle::new(
115 g,
116 workplane,
117 center_b,
118 arc_start_b,
119 arc_end_b,
120 ))
121 .expect("arc created");
122
123 let difference = 100.0;
124 sys.constrain(ArcArcDifference::new(g, arc_a, arc_b, difference))
125 .expect("constraint added");
126 dbg!(sys.solve(&g));
127 dbg!(sys.solve(&g));
128
129 let arc_a_len = if let (
130 Point::OnWorkplane { coords: center, .. },
131 Point::OnWorkplane {
132 coords: arc_start, ..
133 },
134 Point::OnWorkplane {
135 coords: arc_end, ..
136 },
137 ) = (
138 sys.entity_data(¢er_a).expect("data found"),
139 sys.entity_data(&arc_start_a).expect("data found"),
140 sys.entity_data(&arc_end_a).expect("data found"),
141 ) {
142 arc_len(center, arc_start, arc_end)
143 } else {
144 unreachable!()
145 };
146 let arc_b_len = if let (
147 Point::OnWorkplane { coords: center, .. },
148 Point::OnWorkplane {
149 coords: arc_start, ..
150 },
151 Point::OnWorkplane {
152 coords: arc_end, ..
153 },
154 ) = (
155 sys.entity_data(¢er_b).expect("data found"),
156 sys.entity_data(&arc_start_b).expect("data found"),
157 sys.entity_data(&arc_end_b).expect("data found"),
158 ) {
159 arc_len(center, arc_start, arc_end)
160 } else {
161 unreachable!()
162 };
163
164 len_within_tolerance!(arc_a_len - arc_b_len, difference);
165 }
166}