use geometry_model::Box as ModelBox;
use geometry_strategy::{EnvelopeStrategy, EnvelopeStrategyForKind};
use geometry_trait::{Box as BoxTrait, Geometry, IndexedAccess, PointMut, corner, fold_dims};
#[inline]
pub fn expand<B, G, P>(bounds: &mut B, geometry: &G)
where
B: BoxTrait<Point = P>,
G: Geometry<Point = P>,
P: PointMut + Default,
G::Kind: EnvelopeStrategyForKind,
<G::Kind as EnvelopeStrategyForKind>::S: EnvelopeStrategy<G, Output = ModelBox<P>> + Default,
{
expand_with(
bounds,
geometry,
<<G::Kind as EnvelopeStrategyForKind>::S as Default>::default(),
);
}
#[inline]
#[allow(
clippy::needless_pass_by_value,
reason = "envelope strategies are zero-sized or small Copy values, matching the crate's other _with entry points"
)]
pub fn expand_with<B, G, P, S>(bounds: &mut B, geometry: &G, strategy: S)
where
B: BoxTrait<Point = P>,
G: Geometry<Point = P>,
P: PointMut + Default,
S: EnvelopeStrategy<G, Output = ModelBox<P>>,
{
let incoming = strategy.envelope(geometry);
fold_dims((), incoming.min(), |(), _, dimension| match dimension {
0 => expand_dimension::<B, P, 0>(bounds, &incoming),
1 => expand_dimension::<B, P, 1>(bounds, &incoming),
2 => expand_dimension::<B, P, 2>(bounds, &incoming),
3 => expand_dimension::<B, P, 3>(bounds, &incoming),
_ => unreachable!("fold_dims limits point dimensions to MAX_DIM"),
});
}
#[inline]
fn expand_dimension<B, P, const D: usize>(bounds: &mut B, incoming: &ModelBox<P>)
where
B: BoxTrait<Point = P>,
P: PointMut,
{
let incoming_min = incoming.get_indexed::<{ corner::MIN }, D>();
let incoming_max = incoming.get_indexed::<{ corner::MAX }, D>();
let current_min = bounds.get_indexed::<{ corner::MIN }, D>();
let current_max = bounds.get_indexed::<{ corner::MAX }, D>();
if incoming_min < current_min {
bounds.set_indexed::<{ corner::MIN }, D>(incoming_min);
}
if incoming_max > current_max {
bounds.set_indexed::<{ corner::MAX }, D>(incoming_max);
}
}