Rolling-ball blends now handle knife edges, where the two faces have opposite normals; an edge that runs out along an end face tangent to one side; and rounds that end in an earlier round on curved faces, picked together or one after another. The three edges at a vertex of smooth faces, rounded to one radius, end in a piece of sphere. When the given order of up to four edges is refused, or leaves a face boundary off its surface, other orders are tried. Closes #851. Co-authored-by: lasselian <22126420+lasselian@users.noreply.github.com>
This commit is contained in:
1 parent
45f92277cb
commit
a2c7396160
10 files changed
+1364
-54
No files matched your search
@@ -4,6 +4,7 @@
|
||||
use mt::{BoundedCurve, ParametricCurve, ParametricSurface, ParametricSurface3D, SearchNearestParameter};
|
||||
|
||||
use super::*;
|
||||
use crate::blend::plane_normal;
|
||||
use crate::{Body, BoolOp, boolean, cylinder, fillet};
|
||||
|
||||
fn tee(scale: f64, origin: Vec3) -> Body {
|
||||
@@ -352,6 +353,28 @@ fn a_refused_edge_is_not_rolled_again_after_blends_far_from_it() {
|
||||
assert!(fillet(&body, &ends, 3.0).is_ok());
|
||||
}
|
||||
|
||||
/// At a knife edge (the plane and the wall's normals opposite) the ball's centre is the same
|
||||
/// whichever face is side 1: `r` inside the plane and `r` outside the wall's cylinder.
|
||||
#[test]
|
||||
fn knife_edge_ball_centre_does_not_depend_on_the_side_order() {
|
||||
const R: f64 = 21.0;
|
||||
let tip = Vec3::new(62.0 + 1.0 / 6.0, 0.0, 5.0);
|
||||
let slab = crate::box_solid(Vec3::new(0.0, -R, 0.0), Vec3::new(tip.x, 0.0, 10.0)).unwrap();
|
||||
let disc = cylinder(Vec3::new(tip.x, -R, 0.0), Vec3::Z, R, 10.0).unwrap();
|
||||
let body = boolean(&slab, &disc, BoolOp::Cut).unwrap().unwrap();
|
||||
let faces: Vec<&mt::Face> = body.solid.face_iter().collect();
|
||||
let plane = faces.iter().copied().find(|f| plane_normal(f).is_some_and(|n| n.y > 0.99)).unwrap();
|
||||
let wall = faces.iter().copied().find(|f| plane_normal(f).is_none()).unwrap();
|
||||
for r in [0.5, 2.0, 5.0] {
|
||||
let centre = Vec3::new(tip.x - (4.0 * R * r).sqrt(), -r, tip.z);
|
||||
// `cusp` is +1 when n1 × t points into the cusp: the wall's normal is −y, the plane's +y.
|
||||
for (f1, f2, cusp) in [(wall, plane, 1.0), (plane, wall, -1.0)] {
|
||||
let s = solve(&[f1], &[f2], tip, Vec3::Z, r, -1.0, cusp, None, 1e-6).unwrap();
|
||||
assert!(s.c.dist(centre) < 1e-6, "r={r} cusp={cusp}: centre {:?}, expected {centre:?}", s.c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// #896: the seams where rounds run into the faces beside them are picked to be rounded again.
|
||||
/// The faces meet tangentially there, so there is nothing to round: the refusal says so, rather
|
||||
/// than that blending such an edge isn't supported yet.
|
||||
|
||||
Reference in new issue
Block a user