Shell Outside and Both (walls grown out of the faces, or half out and half in: an offset body less a cavity) and tangent-chain face selection (open faces joined smoothly to the picked ones, by the surface normals either side of each edge)
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
a46d00f361
commit
8e36d5d2fe
4 files changed
+163
-4
No files matched your search
@@ -75,7 +75,7 @@ pub static COMMANDS: &[CommandSpec] = &[
|
||||
CommandSpec::new("solid.shell", "Shell", shell)
|
||||
.at("SOLID", "MODIFY")
|
||||
.icon("shell")
|
||||
.params("faces: [[x,y,z] points on the faces to remove]; thickness: expr (inside); body?"),
|
||||
.params("faces: [[x,y,z] points on the faces to remove]; thickness: expr; direction?: inside|outside|both; tangent_chain?: bool (also open faces joined smoothly to the picked ones); body?"),
|
||||
CommandSpec::new("solid.draft", "Draft", draft)
|
||||
.at("SOLID", "MODIFY")
|
||||
.icon("draft")
|
||||
@@ -992,7 +992,21 @@ fn shell(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
let faces = face_points(p, cmd)?;
|
||||
let thickness = req_expr(cmd, p, "thickness")?;
|
||||
check_expr(s, &thickness, Kind::Length, cmd, "thickness")?;
|
||||
add_feature(s, p, FeatureKind::Shell { faces, thickness, body: str_(p, "body").map(str::to_string) })
|
||||
let direction = str_(p, "direction").map(str::to_ascii_lowercase).unwrap_or_default();
|
||||
if !matches!(direction.as_str(), "" | "inside" | "outside" | "both") {
|
||||
return Err(bad(cmd, "`direction` must be inside, outside or both"));
|
||||
}
|
||||
add_feature(
|
||||
s,
|
||||
p,
|
||||
FeatureKind::Shell {
|
||||
faces,
|
||||
thickness,
|
||||
body: str_(p, "body").map(str::to_string),
|
||||
direction: if direction == "inside" { String::new() } else { direction },
|
||||
tangent_chain: bool_(p, "tangent_chain").unwrap_or(false),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn draft(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
|
||||
@@ -1715,3 +1715,30 @@ fn revolve_two_sides_symmetric_and_to_object() {
|
||||
let (v, _) = ring(json!({"to": corner}));
|
||||
assert!(rel(v, v90) < 1e-3, "{v} {v90}");
|
||||
}
|
||||
|
||||
/// Shell Inside, Outside and Both, and a tangent chain of open faces.
|
||||
#[test]
|
||||
fn shell_directions_and_tangent_chain() {
|
||||
let shell = |extra: Value| {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "solid.box", json!({"length": 40, "width": 30, "height": 20}));
|
||||
let mut p = json!({"faces": [[20, 15, 20]], "thickness": 2});
|
||||
for (k, v) in extra.as_object().into_iter().flatten() {
|
||||
p[k] = v.clone();
|
||||
}
|
||||
run(&mut s, "solid.shell", p);
|
||||
let m = run(&mut s, "inspect.measure", json!({}));
|
||||
(m["total"]["volume_mm3"].as_f64().unwrap_or(0.0), m["bodies"][0]["bbox"].clone())
|
||||
};
|
||||
let (v, _) = shell(json!({}));
|
||||
assert!(rel(v, 40.0 * 30.0 * 20.0 - 36.0 * 26.0 * 18.0) < 1e-6, "{v}");
|
||||
// Outside: the walls grow out; the original box is the cavity.
|
||||
let (v, b) = shell(json!({"direction": "outside"}));
|
||||
assert!(rel(v, 44.0 * 34.0 * 22.0 - 40.0 * 30.0 * 20.0) < 1e-6, "{v} {b}");
|
||||
// Both: 1 mm out, 1 mm in.
|
||||
let (v, _) = shell(json!({"direction": "both"}));
|
||||
assert!(rel(v, 42.0 * 32.0 * 21.0 - 38.0 * 28.0 * 19.0) < 1e-6, "{v}");
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "solid.box", json!({"length": 40, "width": 30, "height": 20}));
|
||||
assert!(s.execute("solid.shell", &json!({"faces": [[20, 15, 20]], "thickness": 2, "direction": "sideways"})).is_err());
|
||||
}
|
||||
Reference in new issue
Block a user