slvs/constraint/
arc_arc_difference.rs

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    /// The lengths of `arc_a` and `arc_b` differ by `difference`
16    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(&center_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(&center_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}