mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-07 20:41:50 +00:00
kernel: the record test takes the one wall a circle of arcs extrudes to
Since tangency-labs/smlib#67 an extruded profile's arcs on one circle sweep one full-turn wall face, made from all of them (Profile 4, 5 and 6 here), where it was a face per arc. The geometric check of the record finds a face over several segments by its triangles' centres and vertices on them; the revolved arcs keep a face each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,7 +49,9 @@ fn mesh_points(b: &Body) -> (Vec<Vec<Vec3>>, Vec<Vec<Vec3>>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The segments a face lies over: its vertices on them within `tol`, its triangles' centres
|
/// The segments a face lies over: its vertices on them within `tol`, its triangles' centres
|
||||||
/// near them (`to_2d` takes a point into the profile's plane).
|
/// near them (`to_2d` takes a point into the profile's plane). A face over one segment has all
|
||||||
|
/// of them on it; a face over several (the one wall a circle drawn in arcs sweeps) has each
|
||||||
|
/// centre near one of them and each vertex on one of them.
|
||||||
fn swept_from(b: &Body, loops: &[&Loop2], to_2d: impl Fn(Vec3) -> Vec2, tol: f64) -> Vec<Vec<usize>> {
|
fn swept_from(b: &Body, loops: &[&Loop2], to_2d: impl Fn(Vec3) -> Vec2, tol: f64) -> Vec<Vec<usize>> {
|
||||||
let (corners, centres) = mesh_points(b);
|
let (corners, centres) = mesh_points(b);
|
||||||
let flat = |pts: &Vec<Vec3>| pts.iter().map(|p| to_2d(*p)).collect::<Vec<_>>();
|
let flat = |pts: &Vec<Vec3>| pts.iter().map(|p| to_2d(*p)).collect::<Vec<_>>();
|
||||||
@@ -57,8 +59,19 @@ fn swept_from(b: &Body, loops: &[&Loop2], to_2d: impl Fn(Vec3) -> Vec2, tol: f64
|
|||||||
.iter()
|
.iter()
|
||||||
.zip(¢res)
|
.zip(¢res)
|
||||||
.map(|(v, c)| {
|
.map(|(v, c)| {
|
||||||
let near = under(loops, &flat(c), b.size() * 3e-3);
|
let (v, c) = (flat(v), flat(c));
|
||||||
under(loops, &flat(v), tol).into_iter().filter(|k| near.contains(k)).collect()
|
let near = under(loops, &c, b.size() * 3e-3);
|
||||||
|
let one: Vec<usize> = under(loops, &v, tol).into_iter().filter(|k| near.contains(k)).collect();
|
||||||
|
if !one.is_empty() {
|
||||||
|
return one;
|
||||||
|
}
|
||||||
|
let each = |pts: &[Vec2], tol: f64| pts.iter().map(|q| under(loops, std::slice::from_ref(q), tol)).collect::<Vec<_>>();
|
||||||
|
let centre_segs = each(&c, b.size() * 3e-3);
|
||||||
|
let mut over: Vec<usize> = centre_segs.iter().flatten().copied().collect();
|
||||||
|
over.sort_unstable();
|
||||||
|
over.dedup();
|
||||||
|
let covered = |segs: &[Vec<usize>]| segs.iter().all(|s| s.iter().any(|k| over.contains(k)));
|
||||||
|
if over.len() > 1 && covered(¢re_segs) && covered(&each(&v, tol)) { over } else { Vec::new() }
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
@@ -234,7 +247,8 @@ fn revolve_partial_and_full() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Loops given clockwise, a hole that is a full circle of three arcs: extrude and revolve
|
/// Loops given clockwise, a hole that is a full circle of three arcs: extrude and revolve
|
||||||
/// number every face by the segment as given, one face each.
|
/// number every face by the segments as given. Extruded, the circle's arcs sweep one wall,
|
||||||
|
/// made from all three; the rectangle's sides one face each.
|
||||||
#[test]
|
#[test]
|
||||||
fn clockwise_loops_and_a_circle_of_arcs_keep_their_numbers() {
|
fn clockwise_loops_and_a_circle_of_arcs_keep_their_numbers() {
|
||||||
let (c, rad) = (Vec2::new(20.0, 10.0), 4.0);
|
let (c, rad) = (Vec2::new(20.0, 10.0), 4.0);
|
||||||
@@ -245,9 +259,11 @@ fn clockwise_loops_and_a_circle_of_arcs_keep_their_numbers() {
|
|||||||
let b = crate::extrude(&Plane::XY, std::slice::from_ref(&r), 0.0, 10.0).unwrap().pop().unwrap();
|
let b = crate::extrude(&Plane::XY, std::slice::from_ref(&r), 0.0, 10.0).unwrap().pop().unwrap();
|
||||||
let got = origins(&b);
|
let got = origins(&b);
|
||||||
assert_eq!(got, expected_extrusion(&b, &Plane::XY, &r, 10.0));
|
assert_eq!(got, expected_extrusion(&b, &Plane::XY, &r, 10.0));
|
||||||
for k in 0..7 {
|
for k in 0..4 {
|
||||||
assert_eq!(got.iter().filter(|o| **o == [P(k)]).count(), 1, "segment {k}");
|
assert_eq!(got.iter().filter(|o| **o == [P(k)]).count(), 1, "segment {k}");
|
||||||
}
|
}
|
||||||
|
assert_eq!(got.iter().filter(|o| **o == [P(4), P(5), P(6)]).count(), 1, "the circle's one wall");
|
||||||
|
assert_eq!(got.len(), 7, "four sides, the wall, two caps");
|
||||||
// Revolved, each arc turns into a face of its own, as the rectangle's sides do.
|
// Revolved, each arc turns into a face of its own, as the rectangle's sides do.
|
||||||
for angle in [FRAC_PI_2, TAU] {
|
for angle in [FRAC_PI_2, TAU] {
|
||||||
let b = crate::revolve(&SIDE, std::slice::from_ref(&r), Vec2::ZERO, Vec2::Y, angle).unwrap().pop().unwrap();
|
let b = crate::revolve(&SIDE, std::slice::from_ref(&r), Vec2::ZERO, Vec2::Y, angle).unwrap().pop().unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user