Thanks @SychPL.
This commit is contained in:
1 parent
77b33efd8f
commit
3501fa2c54
2 files changed
+41
-6
No files matched your search
@@ -161,6 +161,8 @@ fn emboss(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let at = solidcraft_doc::apply_point(&s.active_component_frame(), local);
|
||||
let state = s.world_state();
|
||||
let mut candidates = Vec::new();
|
||||
// The nearest face off the point: (distance, body), for the error when none holds it.
|
||||
let mut nearest: Option<(f64, &str)> = None;
|
||||
for body in &state.bodies {
|
||||
let definition = body.definition_name();
|
||||
if !targets.is_empty() && !targets.iter().any(|n| n == definition || n == &body.name) {
|
||||
@@ -179,14 +181,30 @@ fn emboss(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
inside.then_some(((at - a).dot(n).abs(), *face as usize))
|
||||
})
|
||||
.min_by(|a, b| a.0.total_cmp(&b.0));
|
||||
if let Some((distance, index)) = closest
|
||||
&& distance < (body.body.size() * 1e-3).max(1e-3)
|
||||
{
|
||||
candidates.push((body, index));
|
||||
match closest {
|
||||
Some((distance, index)) if distance < (body.body.size() * 1e-3).max(1e-3) => candidates.push((body, index)),
|
||||
Some((distance, _)) if nearest.is_none_or(|(d, _)| distance < d) => nearest = Some((distance, body.name.as_str())),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if candidates.len() != 1 {
|
||||
return Err(bad(cmd, "`face` must identify exactly one target body surface"));
|
||||
// #392: say what is wrong with the point, not only that it picks no single face.
|
||||
let point = format!("[{}, {}, {}]", local.x, local.y, local.z);
|
||||
match (candidates.as_slice(), nearest) {
|
||||
([], Some((d, body))) => {
|
||||
return Err(bad(
|
||||
cmd,
|
||||
format!("`face` {point} lies on no face: the nearest, on `{body}`, is {d:.3} mm away; give a point on the face"),
|
||||
));
|
||||
}
|
||||
([], None) => return Err(bad(cmd, format!("`face` {point} lies on no face of the target bodies"))),
|
||||
([_], _) => {}
|
||||
(more, _) => {
|
||||
let names: Vec<&str> = more.iter().map(|(b, _)| b.name.as_str()).collect();
|
||||
return Err(bad(
|
||||
cmd,
|
||||
format!("`face` {point} lies on faces of {} bodies ({}): name one in `targets`", names.len(), names.join(", ")),
|
||||
));
|
||||
}
|
||||
}
|
||||
let (selected, index) = candidates.first().copied().ok_or_else(|| bad(cmd, "no target face"))?;
|
||||
let name = selected.definition_name();
|
||||
|
||||
@@ -92,6 +92,23 @@ fn emboss_and_deboss_on_a_face() {
|
||||
assert!(s.execute("solid.emboss", &json!({"sketch": "Logo", "depth": 1, "mode": "sideways"})).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emboss_face_off_the_part_says_how_far() {
|
||||
// #392: a point beside the face was refused with "`face` must identify exactly one target
|
||||
// body surface", which didn't say the point was off the face.
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "solid.box", json!({"length": 40, "width": 30, "height": 10, "body_name": "A"}));
|
||||
run(&mut s, "sketch.create", json!({"plane": {"face": [20, 15, 10]}, "name": "Logo"}));
|
||||
run(&mut s, "sketch.rectangle.two_point", json!({"p0": [5, 5], "p1": [15, 15]}));
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
let e = s.execute("solid.emboss", &json!({"sketch": "Logo", "depth": 1, "face": [20, 15, 11.25]})).unwrap_err().to_string();
|
||||
assert!(e.contains("[20, 15, 11.25] lies on no face: the nearest, on `A`, is 1.250 mm away"), "{e}");
|
||||
run(&mut s, "solid.box", json!({"length": 10, "width": 30, "height": 10, "corner": [40, 0, 0], "operation": "new_body", "body_name": "B"}));
|
||||
let e = s.execute("solid.emboss", &json!({"sketch": "Logo", "depth": 1, "face": [40, 15, 5]})).unwrap_err().to_string();
|
||||
assert!(e.contains("lies on faces of 2 bodies (A, B): name one in `targets`"), "{e}");
|
||||
run(&mut s, "solid.emboss", json!({"sketch": "Logo", "depth": 1, "face": [20, 15, 10]}));
|
||||
}
|
||||
|
||||
fn cylinder_badge() -> Session {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "parameters.add", json!({"name":"badge_depth","expression":"1 mm"}));
|
||||
|
||||
Reference in new issue
Block a user