Here's a cute little problem. I have a `Vec<glam::Vec3>`

and I want the maximum and minimum values of the x, y, and z values, to get the bounding box of a mesh. Obviously I can do this with a "for" loop. Or I could have six iterator passes of "min" and "max" calls, which is inefficient. Is there some idiomatic and efficient way to do this in Rust?

2 Likes

Iterator::fold, where the accumulator is a (min, max) pair: ((x,y,z), (x,y,z))?

Since you want an axis-aligned bounding box (AABB), I would define an AAB (axis-aligned box) type and write appropriate functions for it, after which the desired operation is straightforwardly expressed as:

```
points.into_iter().map(Aab::from_point).reduce(Aab::union)
```

Full code:

```
use glam::Vec3;
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Aab {
pub min: Vec3,
pub max: Vec3,
}
impl Aab {
pub fn from_point(point: Vec3) -> Self {
Self {
min: point,
max: point,
}
}
/// Returns [`None`] if there are no points.
pub fn bounding_box_of(points: impl IntoIterator<Item = Vec3>) -> Option<Self> {
points.into_iter().map(Self::from_point).reduce(Self::union)
}
pub fn union(self, other: Self) -> Self {
Self {
min: self.min.min(other.min),
max: self.max.max(other.max),
}
}
}
#[test]
fn points_test() {
assert_eq!(
Aab::bounding_box_of([Vec3::new(0., 10., 0.), Vec3::new(10., 0., 5.)]),
Some(Aab {
min: Vec3::new(0., 0., 0.),
max: Vec3::new(10., 10., 5.),
})
)
}
```

This could be done with `reduce()`

without the struct, but with considerably more bother inside closures. Note that I use `reduce()`

rather than `fold()`

because the min/max of zero items is undefined.

Conveniently, `glam`

already has element-wise min and max functions to help us with this implementation.

9 Likes

That approach works and I'm now using it. Thanks.

1 Like