forked from 1b-agent/fieldcraft-upstream
Geometry: the nearest face of a body to points
Shape::nearest_faces finds, for each point, the face whose tessellation lies nearest: how a mirrored mesh finds the faces of the body it is the image of. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
This commit is contained in:
1 parent
b73a3bb976
commit
9fc8e27933
1 file changed
+24
@@ -209,6 +209,15 @@ impl Faces {
|
||||
}
|
||||
}
|
||||
|
||||
impl Shape {
|
||||
/// For each point, the face (by index, the [`SurfaceMesh::tri_face`] tag) nearest to it,
|
||||
/// measured to a tessellation within `tolerance`; `None` for a body without faces.
|
||||
pub fn nearest_faces(&self, points: &[[f64; 3]], tolerance: f64) -> Result<Vec<Option<u32>>> {
|
||||
let faces = Faces { surfaces: Vec::new(), names: Vec::new(), mesh: self.tessellate(tolerance)? };
|
||||
Ok(points.iter().map(|p| faces.nearest(*p, |_| true).and_then(|f| u32::try_from(f).ok())).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether two analytic surfaces are the same surface (within `tol`); free-form faces match any
|
||||
/// free-form face.
|
||||
fn same_surface(a: Option<FaceSurface>, b: Option<FaceSurface>, tol: f64) -> bool {
|
||||
@@ -460,6 +469,21 @@ mod tests {
|
||||
assert!(p.cuts.iter().all(|c| c.split.is_empty() && c.faces == 0), "{:?}", p.cuts);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_nearest_face_of_a_point() {
|
||||
let d = plate();
|
||||
let b = &d.bodies[0];
|
||||
// Above the top (z = 10) and beside the side at y = 0.
|
||||
let f = b.nearest_faces(&[[30.0, 20.0, 10.5], [30.0, -0.5, 5.0]], 0.05).unwrap();
|
||||
let surfaces = b.face_surfaces().unwrap();
|
||||
let normal = |f: Option<u32>| match surfaces[f.unwrap() as usize] {
|
||||
Some(FaceSurface::Plane { normal, .. }) => normal,
|
||||
s => panic!("{s:?}"),
|
||||
};
|
||||
assert!((normal(f[0])[2] - 1.0).abs() < 1e-12);
|
||||
assert!((normal(f[1])[1] + 1.0).abs() < 1e-12);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hostile_planes_are_an_error() {
|
||||
let d = plate();
|
||||
|
||||
Reference in new issue
Block a user