feat: preserve adaptive sketch profiles and curved modeling workflows
This commit is contained in:
1 parent
4c4a0449a4
commit
4e595deff2
62 files changed
+7114
-362
No files matched your search
@@ -465,3 +465,57 @@ fn transferred_frozen_face_paint_ignores_consumed_legacy_offset() {
|
||||
let paint = s.doc.appearances.faces.iter().find(|face| face.body == "Foreign (copy)").unwrap();
|
||||
assert!(paint.point.dist(expected) < 1e-6, "{:?} versus {expected:?}", paint.point);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn boundary_material_proof_requires_resolvable_stock_and_void() {
|
||||
use solvecraft_geom::Vec3;
|
||||
let a = solvecraft_kernel::box_solid(Vec3::ZERO, Vec3::new(10., 10., 10.)).unwrap().tessellate(1e-3).unwrap();
|
||||
let b = solvecraft_kernel::box_solid(Vec3::new(1e-5, 0., 0.), Vec3::new(10.00001, 10., 10.)).unwrap().tessellate(1e-3).unwrap();
|
||||
let p = Vec3::new(5e-6, 5., 5.);
|
||||
assert_ne!(a.contains(p), b.contains(p));
|
||||
assert!((super::mesh_distance(&a, p) - 5e-6).abs() < 1e-12);
|
||||
assert!((super::mesh_distance(&b, p) - 5e-6).abs() < 1e-12);
|
||||
assert!(super::material_probe_matches(&a, &b, p, 1e-3, 1e-3));
|
||||
let shifted = solvecraft_kernel::box_solid(Vec3::new(1., 0., 0.), Vec3::new(11., 10., 10.)).unwrap().tessellate(1e-3).unwrap();
|
||||
assert!(!super::material_probe_matches(&a, &shifted, p, 1e-3, 1e-3));
|
||||
let thin = solvecraft_kernel::box_solid(Vec3::ZERO, Vec3::new(10., 10., 1e-4)).unwrap().tessellate(1e-6).unwrap();
|
||||
let thin_shifted = solvecraft_kernel::box_solid(Vec3::new(0., 0., 1e-4), Vec3::new(10., 10., 2e-4)).unwrap().tessellate(1e-6).unwrap();
|
||||
// Every resolvable replacement is void: thin ambiguous material is refused.
|
||||
assert!(!super::material_probe_matches(&thin, &thin_shifted, Vec3::new(5., 5., 5e-5), 1e-3, 1e-3));
|
||||
assert!(!super::material_probe_matches(&a, &b, p, f64::INFINITY, 1e-3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn frozen_bore_boundary_copy_preserves_stock_void_and_reopen() {
|
||||
use solvecraft_geom::Vec3;
|
||||
let bore = |center: f64| {
|
||||
let mut s = Session::default();
|
||||
run(&mut s, "solid.box", json!({"length":30,"width":20,"height":10,"body_name":"Drilled"}));
|
||||
run(&mut s, "solid.cylinder", json!({"base":[center,10,0],"radius":4,"height":10,"operation":"cut"}));
|
||||
s
|
||||
};
|
||||
let mut s = bore(10.);
|
||||
let source = s.model.state().body("Drilled").unwrap().body.tessellate(1e-3).unwrap();
|
||||
// The exact R4 wall passes through x6; a chord may end either side of that
|
||||
// cardinal angle, so its distance is bounded by the requested sag tolerance.
|
||||
assert!(super::mesh_distance(&source, Vec3::new(6., 10., 5.)) <= 1e-3);
|
||||
let shifted = bore(11.).model.state().body("Drilled").unwrap().body.tessellate(1e-3).unwrap();
|
||||
let lost = solvecraft_kernel::box_solid(Vec3::ZERO, Vec3::new(30., 20., 10.)).unwrap().tessellate(1e-3).unwrap();
|
||||
assert!(!super::material_probe_matches(&source, &shifted, Vec3::new(6.5, 10., 5.), 1e-3, 1e-3));
|
||||
assert!(!super::material_probe_matches(&source, &lost, Vec3::new(10., 10., 5.), 1e-3, 1e-3));
|
||||
let created = run(&mut s, "component.from_bodies", json!({"bodies":["Drilled"]}));
|
||||
let part = created["components"][0]["component"].as_u64().unwrap();
|
||||
let copied = copy(&mut s, part)["component"].as_u64().unwrap();
|
||||
let check = |session: &Session| {
|
||||
let state = session.model.state();
|
||||
let body = state.bodies.iter().find(|body| session.doc.model_body_component(body) == copied).unwrap();
|
||||
let mesh = body.body.tessellate(1e-3).unwrap();
|
||||
for (point, stock) in
|
||||
[(Vec3::new(5.5, 10., 5.), true), (Vec3::new(6.5, 10., 5.), false), (Vec3::new(10., 10., 5.), false), (Vec3::new(18., 10., 5.), true)]
|
||||
{
|
||||
assert_eq!(mesh.contains(point), stock, "{point:?}");
|
||||
}
|
||||
};
|
||||
check(&s);
|
||||
check(&Session::new(solvecraft_doc::Document::from_json(&s.doc.to_json()).unwrap()));
|
||||
}
|
||||
Reference in new issue
Block a user