runmat-meshing-core 0.6.0

Deterministic meshing preparation contracts for RunMat
Documentation
use crate::quality::predicate::Point3;

use super::types::Aabb3;

pub(super) fn grid_dimensions(bounds: Aabb3, entry_count: usize) -> [usize; 3] {
    let target_axis_count = ((entry_count as f64).cbrt().ceil() as usize).clamp(1, 64);
    let spans = [
        bounds.max_m[0] - bounds.min_m[0],
        bounds.max_m[1] - bounds.min_m[1],
        bounds.max_m[2] - bounds.min_m[2],
    ];
    let max_span = spans.into_iter().fold(0.0_f64, f64::max);
    if max_span <= f64::EPSILON {
        return [1, 1, 1];
    }
    spans.map(|span| {
        ((span / max_span) * target_axis_count as f64)
            .ceil()
            .max(1.0) as usize
    })
}

pub(super) fn cell_for_point(bounds: Aabb3, dimensions: [usize; 3], point: Point3) -> [usize; 3] {
    let mut cell = [0_usize; 3];
    for axis in 0..3 {
        let span = bounds.max_m[axis] - bounds.min_m[axis];
        if span <= f64::EPSILON || dimensions[axis] <= 1 {
            cell[axis] = 0;
            continue;
        }
        let t = ((point[axis] - bounds.min_m[axis]) / span).clamp(0.0, 1.0);
        cell[axis] = ((t * dimensions[axis] as f64).floor() as usize).min(dimensions[axis] - 1);
    }
    cell
}

pub(super) fn ray_bounds_intersection(
    origin: Point3,
    direction: Point3,
    bounds: Aabb3,
) -> Option<(f64, f64)> {
    let mut ray_min = f64::NEG_INFINITY;
    let mut ray_max = f64::INFINITY;
    for axis in 0..3 {
        if direction[axis].abs() <= f64::EPSILON {
            if origin[axis] < bounds.min_m[axis] || origin[axis] > bounds.max_m[axis] {
                return None;
            }
            continue;
        }
        let t0 = (bounds.min_m[axis] - origin[axis]) / direction[axis];
        let t1 = (bounds.max_m[axis] - origin[axis]) / direction[axis];
        ray_min = ray_min.max(t0.min(t1));
        ray_max = ray_max.min(t0.max(t1));
        if ray_min > ray_max {
            return None;
        }
    }
    Some((ray_min, ray_max))
}

pub(super) fn add_point(left: Point3, right: Point3) -> Point3 {
    [left[0] + right[0], left[1] + right[1], left[2] + right[2]]
}

pub(super) fn scale_point(point: Point3, scale: f64) -> Point3 {
    [point[0] * scale, point[1] * scale, point[2] * scale]
}