forked from 1b-agent/fieldcraft-upstream
Geometry: a face's area centroid and a point a fraction along an edge
Shape::face_centre and Edge::point_at place datum points on a design's named faces and edges. 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
0bf150633c
commit
fbaba5fecd
2 files changed
+71
No files matched your search
@@ -33,6 +33,24 @@ impl Edge {
|
||||
pub fn length(&self) -> f64 {
|
||||
self.points.windows(2).map(|w| distance(w[0], w[1])).sum()
|
||||
}
|
||||
|
||||
/// The point `fraction` of its length along it from its start (0: the start, 1: the end);
|
||||
/// `None` for a fraction outside 0..=1 or an edge without points.
|
||||
pub fn point_at(&self, fraction: f64) -> Option<[f64; 3]> {
|
||||
if !(0.0..=1.0).contains(&fraction) {
|
||||
return None;
|
||||
}
|
||||
let mut left = fraction * self.length();
|
||||
for w in self.points.windows(2) {
|
||||
let l = distance(w[0], w[1]);
|
||||
if left <= l && l > 0.0 {
|
||||
let t = left / l;
|
||||
return Some([0, 1, 2].map(|k| w[0][k] + t * (w[1][k] - w[0][k])));
|
||||
}
|
||||
left -= l;
|
||||
}
|
||||
self.points.last().copied()
|
||||
}
|
||||
}
|
||||
|
||||
fn distance(a: [f64; 3], b: [f64; 3]) -> f64 {
|
||||
@@ -186,6 +204,19 @@ mod tests {
|
||||
assert_eq!(n, names(&ea));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn points_along_an_edge() {
|
||||
let e = super::Edge { name: "e".into(), faces: vec![], points: vec![[0.0, 0.0, 0.0], [2.0, 0.0, 0.0], [2.0, 2.0, 0.0]] };
|
||||
assert_eq!(e.point_at(0.0), Some([0.0, 0.0, 0.0]));
|
||||
assert_eq!(e.point_at(0.5), Some([2.0, 0.0, 0.0]));
|
||||
assert_eq!(e.point_at(0.75), Some([2.0, 1.0, 0.0]));
|
||||
assert_eq!(e.point_at(1.0), Some([2.0, 2.0, 0.0]));
|
||||
for bad in [-0.1, 1.5, f64::NAN] {
|
||||
assert_eq!(e.point_at(bad), None);
|
||||
}
|
||||
assert_eq!(super::Edge { points: vec![], ..e }.point_at(0.5), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn partition_cut_edges_are_named_after_the_cut_faces() {
|
||||
let d = open_design(&sample::plate_design(&Plate::default()).unwrap()).unwrap();
|
||||
|
||||
Reference in new issue
Block a user