fix: restore shell and cut wall topology in 0.2.1
This commit is contained in:
1 parent
1aedbf6631
commit
ef8f6ca6f9
31 files changed
+2976
-678
No files matched your search
+39
-14
@@ -23,28 +23,53 @@ fn rel(a: f64, b: f64) -> f64 {
|
||||
#[test]
|
||||
fn join_extrude_from_a_chamfered_top_face() {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "parameters.add", json!({"name":"height","expression":"20 mm"}));
|
||||
run(&mut s, "parameters.add", json!({"name":"bevel","expression":"2 mm"}));
|
||||
run(&mut s, "sketch.create", json!({"plane": "XY"}));
|
||||
run(&mut s, "sketch.circle.center", json!({"center": [0, 0], "radius": 10}));
|
||||
run(&mut s, "solid.extrude", json!({"distance": 20}));
|
||||
run(&mut s, "solid.chamfer", json!({"edges": [[10, 0, 20]], "distance": 2}));
|
||||
let source = run(&mut s, "solid.extrude", json!({"distance": "height","name":"Stem"}))["feature"].as_u64().unwrap();
|
||||
run(&mut s, "solid.chamfer", json!({"edges": [[10, 0, 20]], "distance": "bevel"}));
|
||||
let base = volume(&mut s);
|
||||
let before = s.doc.to_json();
|
||||
let active = s.active_sketch;
|
||||
assert!(s.execute("sketch.create", &json!({"plane":{"face":[0,0,20]}})).is_err(), "modified faces require an explicit fixed plane");
|
||||
assert_eq!(s.doc.to_json(), before);
|
||||
assert_eq!(s.active_sketch, active);
|
||||
assert!(rel(volume(&mut s), base) < 1e-12);
|
||||
let id = run(&mut s, "sketch.create", json!({"plane": {"face": [0, 0, 20],"fixed":true}}))["sketch"].as_u64().unwrap();
|
||||
let solvecraft_doc::FeatureKind::Sketch { plane: solvecraft_doc::PlaneRef::Custom { plane }, sketch } = &s.doc.feature(id).unwrap().kind else {
|
||||
panic!("explicit fixed face must become a custom plane");
|
||||
let id = run(&mut s, "sketch.create", json!({"plane": {"face": [0, 0, 20]}}))["sketch"].as_u64().unwrap();
|
||||
let solvecraft_doc::FeatureKind::Sketch { plane: solvecraft_doc::PlaneRef::Face { anchor: Some(anchor), .. }, sketch } =
|
||||
&s.doc.feature(id).unwrap().kind
|
||||
else {
|
||||
panic!("the chamfered cap retains its exact original construction support");
|
||||
};
|
||||
assert!((plane.origin.z - 20.).abs() < 1e-9);
|
||||
assert!(sketch.links.is_empty(), "fresh fixed plane does not create live auto-projections");
|
||||
run(&mut s, "sketch.circle.center", json!({"center":[0,0],"radius":8}));
|
||||
assert_eq!(anchor.target.origin_feature, source);
|
||||
assert!(matches!(anchor.target.certificate, Some(solvecraft_doc::config::FaceCertificate::ExtrudeCap { high: true, .. })));
|
||||
assert!(!sketch.links.is_empty());
|
||||
assert!(sketch.links.iter().all(|link| link.auto_face && !link.lost));
|
||||
// The default linked cap outline is radius8; no explicit fixed plane or
|
||||
// duplicate manually drawn circle is required to join a pad to that face.
|
||||
run(&mut s, "sketch.finish", json!({}));
|
||||
run(&mut s, "solid.extrude", json!({"distance": 5, "operation": "join"}));
|
||||
assert_eq!(s.model.state().bodies.len(), 1);
|
||||
assert!(rel(volume(&mut s), base + PI * 64.0 * 5.0) < 5e-4);
|
||||
for (height, bevel) in [(20., 2.), (25., 3.)] {
|
||||
run(&mut s, "parameters.change", json!({"name":"height","expression":format!("{height} mm")}));
|
||||
run(&mut s, "parameters.change", json!({"name":"bevel","expression":format!("{bevel} mm")}));
|
||||
let expected = PI * (100. * height - (10. * bevel * bevel - bevel * bevel * bevel / 3.) + (10. - bevel) * (10. - bevel) * 5.);
|
||||
let loaded = solvecraft_doc::Document::from_json(&s.doc.to_json()).unwrap();
|
||||
let mut cold = Session::new(loaded);
|
||||
let warm_volume = volume(&mut s);
|
||||
let cold_volume = volume(&mut cold);
|
||||
assert!(rel(warm_volume, expected) < 5e-4, "{warm_volume} vs {expected}");
|
||||
assert!((warm_volume - cold_volume).abs() < 1e-8);
|
||||
for current in [&s, &cold] {
|
||||
assert!(current.model.results.iter().all(|result| result.error.is_none() && result.warning.is_none()), "{:?}", current.model.results);
|
||||
let state = current.model.state();
|
||||
assert_eq!(state.bodies.len(), 1);
|
||||
let solved = state.sketch(id).unwrap();
|
||||
assert!((solved.plane.origin.z - height).abs() < 1e-8);
|
||||
assert!(solved.sketch.links.iter().all(|link| link.auto_face && !link.lost));
|
||||
let body = &state.bodies[0];
|
||||
assert!(body.body.contains(solvecraft_geom::Vec3::new(0., 0., height + 4.)));
|
||||
assert!(!body.body.contains(solvecraft_geom::Vec3::new(0., 0., height + 6.)));
|
||||
assert!(body.body.contains(solvecraft_geom::Vec3::new(10. - bevel - 0.5, 0., height + 4.)));
|
||||
assert!(!body.body.contains(solvecraft_geom::Vec3::new(10. - bevel + 0.5, 0., height + 4.)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A join that bridges two bodies makes them one body, not an overlap of the first and the second.
|
||||
|
||||
Reference in new issue
Block a user