numerical_analysis 0.1.2

A collection of algorithms for numerical analysis.
Documentation
use nalgebra as na;

type Vec2 = nalgebra::Vector2<f32>;
type Vec3 = nalgebra::Vector3<f32>;
type Vec4 = nalgebra::Vector4<f32>;

type IVec2 = nalgebra::Vector2<i32>;
type IVec4 = nalgebra::Vector4<i32>;

use crate::multilinear::sample_multilinear;

#[repr(C, align(16))]
#[derive(Default, Copy, Clone, Debug)]
pub struct GridSampler
{
    pub extents: Vec4,
    pub corner: Vec4,
    pub resolution: IVec4,
    pub cell_size: f32,
}

impl GridSampler
{
    pub fn new(corner: &Vec3, extents: &Vec3, cell_size: f32) -> GridSampler
    {
        let resolution = (extents / cell_size).map(|v| v.ceil());

        GridSampler {
            extents: Vec4::new(extents.x, extents.y, extents.z, 0.0),
            corner: Vec4::new(corner.x, corner.y, corner.z, 0.0),
            cell_size,
            resolution: IVec4::new(
                resolution.x as i32,
                resolution.y as i32,
                resolution.z as i32,
                0,
            ),
        }
    }

    pub fn resolution(&self) -> IVec4 { self.resolution }

    pub fn position_to_grid_coord(&self, pos: &Vec2) -> IVec2
    {
        let coord: IVec2 =
            na::try_convert((pos - self.corner.xy()) / self.cell_size).unwrap();

        coord
    }

    pub fn quantize_position(&self, pos: &Vec2) -> Vec2
    {
        let coord = IVec2::new(
            ((pos.x - self.corner.x) / self.cell_size).floor() as i32,
            ((pos.y - self.corner.y) / self.cell_size).floor() as i32,
        );

        let res: Vec2 = na::convert(coord);
        res * self.cell_size + self.corner.xy()
    }

    pub fn coord_to_pos(&self, index: &IVec2) -> Vec2
    {
        let pos: Vec2 = na::convert(*index);
        pos * self.cell_size + self.corner.xy()
    }

    pub fn index_to_coord(&self, index: usize) -> IVec2
    {
        let resolution = self.resolution();
        let x = index as i32 / resolution.y;
        let y = index as i32 % resolution.y;
        IVec2::new(x, y)
    }

    pub fn coord_to_index(&self, coord: &IVec2) -> usize
    {
        let resolution = self.resolution();
        let index = (coord.x * resolution.y + coord.y) as usize;

        index
    }

    pub fn bounds(&self) -> (Vec2, Vec2)
    {
        (self.corner.xy(), self.corner.xy() + self.extents.xy())
    }

    pub fn linear_sample(&self, pos: &Vec2, data: &[f32]) -> f32
    {
        sample_multilinear(
            &[pos[0], pos[1]],
            &[self.corner.x, self.corner.y],
            &[self.extents.x, self.extents.y],
            self.cell_size,
            &data,
        )
    }
}