use serde::{Deserialize, Serialize};
use super::AsConstraintData;
use crate::{
bindings::{Slvs_hEntity, Slvs_hGroup, SLVS_C_WHERE_DRAGGED},
define_element,
element::{AsGroup, AsHandle, AsSlvsType, FromSystem},
entity::{EntityHandle, Point, Workplane},
group::Group,
System,
};
define_element!(
SLVS_C_WHERE_DRAGGED,
struct WhereDragged {
point: EntityHandle<Point>,
workplane: Option<EntityHandle<Workplane>>,
}
);
impl AsConstraintData for WhereDragged {
fn workplane(&self) -> Option<Slvs_hEntity> {
self.workplane.map(|workplane| workplane.handle())
}
fn points(&self) -> Option<[Slvs_hEntity; 2]> {
Some([self.point.handle(), 0])
}
}
impl FromSystem for WhereDragged {
fn from_system(sys: &System, element: &impl AsHandle) -> Result<Self, &'static str>
where
Self: Sized,
{
let slvs_constraint = sys.slvs_constraint(element.handle())?;
if SLVS_C_WHERE_DRAGGED == slvs_constraint.type_ as _ {
Ok(Self {
group: Group(slvs_constraint.group),
point: EntityHandle::new(slvs_constraint.ptA),
workplane: match slvs_constraint.wrkpl {
0 => None,
h => Some(EntityHandle::new(h)),
},
})
} else {
Err("Expected constraint to have type SLVS_C_WHERE_DRAGGED.")
}
}
}
#[cfg(test)]
mod tests {
use crate::{
constraint::{PtPtDistance, WhereDragged},
entity::Point,
len_within_tolerance,
utils::distance,
System,
};
#[test]
fn where_dragged() {
let mut sys = System::new();
let g = sys.add_group();
let initial_coords = [-87.0, 57.0, -32.0];
let point_a = sys
.sketch(Point::new_in_3d(g, initial_coords))
.expect("point created");
let point_b = sys
.sketch(Point::new_in_3d(g, [-14.0, 46.0, -54.0]))
.expect("point created");
sys.constrain(WhereDragged::new(g, point_a, None))
.expect("constraint added");
sys.constrain(PtPtDistance::new(g, point_a, point_b, 10.0, None))
.expect("constraint added");
dbg!(sys.solve(&g));
if let Point::In3d { coords, .. } = sys.entity_data(&point_a).expect("data found") {
len_within_tolerance!(distance(initial_coords, coords), 0.0);
} else {
unreachable!()
}
}
}