Shell: an open face next to a concave edge no longer cuts the wall past it (#1495)
The pushed-out cavity is trimmed so that past an open face's plane it only reaches through the open face itself.
This commit is contained in:
1 parent
723c7b61c4
commit
2141a3802a
2 files changed
+143
No files matched your search
@@ -0,0 +1,58 @@
|
||||
//! A shell whose open face meets a concave edge must not cut into the wall past that edge.
|
||||
//!
|
||||
//! Lower box `[0, 25] × [0, 17.5] × [0, 35]`, top box `[7.5, 22.5] × [0, w] × [35, 42.5]` with
|
||||
//! `w ≤ 17.5`, and the shell opens the top box's left face (x = 7.5). That face's bottom edge is
|
||||
//! concave: the lower box's top runs on from it. With walls `t` thick, the cavity is
|
||||
//!
|
||||
//! - in the lower box: `[t, 25 − t] × [t, 17.5 − t] × [t, 35 − t]`
|
||||
//! - in the top box, out to the open face: `[7.5, 22.5 − t] × [t, w − t] × [35 − t, 42.5 − t]`
|
||||
//!
|
||||
//! The shell's volume is the solid's volume less those two boxes. The open face used to be
|
||||
//! pushed out past the lower box's top, cutting a strip through that wall.
|
||||
use serde_json::json;
|
||||
use solidcraft_engine::Session;
|
||||
|
||||
fn run(s: &mut Session, id: &str, p: serde_json::Value) {
|
||||
if let Err(e) = s.execute(id, &p) {
|
||||
panic!("{id} {p}: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
fn shell_volume(w: f64, t: f64) -> f64 {
|
||||
let solid = 25.0 * 17.5 * 35.0 + 15.0 * w * 7.5;
|
||||
let lower = (25.0 - 2.0 * t) * (17.5 - 2.0 * t) * (35.0 - 2.0 * t);
|
||||
let upper = (15.0 - t) * (w - 2.0 * t) * 7.5;
|
||||
solid - lower - upper
|
||||
}
|
||||
|
||||
fn shelled(w: f64, t: f64) -> Session {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "solid.box", json!({"height": 35.0, "length": 25.0, "width": 17.5}));
|
||||
run(&mut s, "solid.box", json!({"corner": [7.5, 0.0, 35.0], "height": 7.5, "length": 15.0, "operation": "join", "width": w}));
|
||||
run(&mut s, "solid.shell", json!({"faces": [[7.5, w / 2.0, 38.75]], "thickness": t}));
|
||||
s
|
||||
}
|
||||
|
||||
fn check(s: &Session, want: f64) {
|
||||
let errors: Vec<_> = s.model.results.iter().filter_map(|r| r.error.clone()).collect();
|
||||
assert!(errors.is_empty(), "{errors:?}");
|
||||
let st = s.model.state();
|
||||
assert_eq!(st.bodies.len(), 1, "one body");
|
||||
let b = &st.bodies[0].body;
|
||||
assert!(b.validity().is_empty(), "{:?}", b.validity());
|
||||
assert_eq!(b.shell_count(), 1, "one shell");
|
||||
let got = solidcraft_kernel::measure(b).map(|m| m.volume).unwrap_or(f64::NAN);
|
||||
assert!((got - want).abs() < 1e-6 * want, "shell volume {got}, want {want}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_face_flush_with_the_back_keeps_the_wall_past_its_concave_edge() {
|
||||
for t in [1.0, 1.5] {
|
||||
check(&shelled(17.5, t), shell_volume(17.5, t));
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn open_face_inside_the_footprint_keeps_the_wall_past_its_concave_edge() {
|
||||
check(&shelled(15.0, 1.5), shell_volume(15.0, 1.5));
|
||||
}
|
||||
Reference in new issue
Block a user