mazth 0.6.0

Matrix utilities.
Documentation
use std::cmp;
use std::f64;

use i_bound::BoundType;
use i_bound::IBound;
use i_shape::ShapeType;

#[derive(Debug, Clone)]
pub struct AxisAlignedBBox {
    pub _bound_lower: [f64; 3],
    pub _bound_upper: [f64; 3],
}

#[derive(Debug, Clone)]
pub enum Axis {
    X,
    Y,
    Z,
}

impl AxisAlignedBBox {
    pub fn init(shape_type: ShapeType, vals: &[f64]) -> AxisAlignedBBox {
        match shape_type {
            ShapeType::Ray => {
                assert!(vals.len() == 6);
                let mut bounds = [(0f64, 0f64); 3];
                for i in 0..3 {
                    let b = if vals[3 + i] > 0f64 {
                        (vals[i], f64::INFINITY)
                    } else if vals[3 + i] < 0f64 {
                        (f64::NEG_INFINITY, vals[i])
                    } else {
                        (vals[i], vals[i])
                    };
                    bounds[i] = b;
                }
                AxisAlignedBBox {
                    _bound_lower: [bounds[0].0, bounds[1].0, bounds[2].0],
                    _bound_upper: [bounds[0].1, bounds[1].1, bounds[2].1],
                }
            }
            ShapeType::Point => {
                assert!(vals.len() == 3);
                AxisAlignedBBox {
                    _bound_lower: [vals[0], vals[1], vals[2]],
                    _bound_upper: [vals[0], vals[1], vals[2]],
                }
            }
            ShapeType::Sphere => {
                assert!(vals.len() == 4);
                AxisAlignedBBox {
                    _bound_lower: [vals[0] - vals[3], vals[1] - vals[3], vals[2] - vals[3]],
                    _bound_upper: [vals[0] + vals[3], vals[1] + vals[3], vals[2] + vals[3]],
                }
            }
            ShapeType::Plane => {
                assert!(vals.len() == 6);
                AxisAlignedBBox {
                    _bound_lower: [f64::NEG_INFINITY; 3],
                    _bound_upper: [f64::INFINITY; 3],
                }
            }
            ShapeType::Box => {
                assert!(vals.len() == 4);
                AxisAlignedBBox {
                    _bound_lower: [vals[0] - vals[3], vals[1] - vals[3], vals[2] - vals[3]],
                    _bound_upper: [vals[0] + vals[3], vals[1] + vals[3], vals[2] + vals[3]],
                }
            }
            ShapeType::Rect => {
                assert!(vals.len() == 6);
                AxisAlignedBBox {
                    _bound_lower: [vals[0], vals[1], vals[2]],
                    _bound_upper: [vals[3], vals[4], vals[5]],
                }
            }
            ShapeType::Frustum => {
                unimplemented!();
            }
            _ => {
                unimplemented!();
            }
        }
    }
    pub fn get_longest_axis(&self) -> (Axis, f64) {
        let dx = (Axis::X, self._bound_upper[0] - self._bound_lower[0]);
        let dy = (Axis::Y, self._bound_upper[1] - self._bound_lower[1]);
        let dz = (Axis::Z, self._bound_upper[2] - self._bound_lower[2]);
        let longest = [dx, dy, dz]
            .iter()
            .cloned()
            .max_by(|x, y| {
                if x.1 < y.1 {
                    cmp::Ordering::Less
                } else if x.1 < y.1 {
                    cmp::Ordering::Greater
                } else {
                    cmp::Ordering::Equal
                }
            })
            .unwrap();
        longest
    }
}

impl IBound for AxisAlignedBBox {
    fn get_type(&self) -> BoundType {
        BoundType::AxisAlignBox
    }
    fn intersect(&self, other: &dyn IBound) -> bool {
        match other.get_type() {
            BoundType::AxisAlignBox => {
                let a_bounds = self.get_bound_data();
                let b_bounds = other.get_bound_data();

                let a_lower = &a_bounds[0..3];
                let a_upper = &a_bounds[3..6];
                let b_lower = &b_bounds[0..3];
                let b_upper = &b_bounds[3..6];

                for i in 0..3 {
                    if a_lower[i] > b_upper[i] || a_upper[i] < b_lower[i] {
                        return false;
                    }
                }
                return true;
            }
            _ => {
                unimplemented!();
            }
        }
    }
    fn get_shortest_separation(&self, _other: &dyn IBound) -> f64 {
        unimplemented!();
    }
    fn get_bound_data(&self) -> [f64; 32] {
        let mut arr = [0f64; 32];
        for i in 0..3 {
            arr[i] = self._bound_lower[i];
        }
        for i in 0..3 {
            arr[i + 3] = self._bound_upper[i];
        }
        arr
    }
    fn get_union(&mut self, bounds: &[&dyn IBound]) {
        self._bound_lower = [f64::INFINITY; 3];
        self._bound_upper = [f64::NEG_INFINITY; 3];
        for i in bounds {
            match i.get_type() {
                BoundType::AxisAlignBox => (),
                _ => {
                    unimplemented!();
                }
            }
            let b = i.get_bound_data();
            let b_lower = &b[0..3];
            let b_upper = &b[3..6];
            for j in 0..3 {
                self._bound_lower[j] = self._bound_lower[j].min(b_lower[j]);
                self._bound_upper[j] = self._bound_upper[j].max(b_upper[j]);
            }
        }
    }
    fn get_centroid(&self) -> [f64; 3] {
        match self.get_type() {
            BoundType::AxisAlignBox => {
                let b = self.get_bound_data();
                let b_lower = &b[0..3];
                let b_upper = &b[3..6];
                return [
                    (b_lower[0] + b_upper[0]) / 2f64,
                    (b_lower[1] + b_upper[1]) / 2f64,
                    (b_lower[2] + b_upper[2]) / 2f64,
                ];
            }
            _ => {
                unimplemented!();
            }
        }
    }
}

impl Default for AxisAlignedBBox {
    fn default() -> AxisAlignedBBox {
        AxisAlignedBBox {
            _bound_lower: [f64::NEG_INFINITY; 3],
            _bound_upper: [f64::INFINITY; 3],
        }
    }
}