geo-nd 0.8.0

Traits and types particularly for 2D and 3D geometry with implementations for [float] and optionally SIMD
Documentation
use crate::{
    FArray, FArray2, Float, QArray, Quaternion, SqMatrix, SqMatrix3, SqMatrix4, Transform, Vector3,
    Vector4,
};

impl<F> Transform<F> for FArray2<F, 4, 16>
where
    F: Float,
    QArray<F>: Quaternion<F>,
    FArray2<F, 4, 16>: SqMatrix4<F> + std::ops::Mul<FArray<F, 4>, Output = FArray<F, 4>>,
    FArray<F, 3>: Vector3<F>,
    FArray<F, 4>: Vector4<F>,
{
    const UNIFORM_SCALING: bool = false;
    type Vec3 = FArray<F, 3>;
    type Vec4 = FArray<F, 4>;
    type Quat = QArray<F>;
    fn of_trs<A: AsRef<[F; 3]>>(t: A, r: Self::Quat, s: A) -> Option<Self> {
        let t = t.as_ref();
        let mut m = Self::default();
        r.set_rotation4(&mut m);
        m.scale_by(s);
        m[3] = t[0];
        m[7] = t[1];
        m[11] = t[2];
        Some(m)
    }

    fn of_trsu<A: AsRef<[F; 3]>>(t: A, r: Self::Quat, s: F) -> Self {
        let t = t.as_ref();
        let mut m = Self::default();
        r.set_rotation4(&mut m);
        m.scale_uniform_by(s);
        m[3] = t[0];
        m[7] = t[1];
        m[11] = t[2];
        m
    }

    fn is_uniform_scale(&self) -> bool {
        false
    }

    fn scale(&self) -> Option<Self::Vec3> {
        None
    }

    fn uniform_scale(&self) -> Option<F> {
        None
    }

    fn translation(&self) -> Self::Vec3 {
        [self[3], self[7], self[11]].into()
    }

    fn rotation(&self) -> Option<Self::Quat> {
        None
    }

    fn set_identity(&mut self) {
        *self = Self::identity();
    }

    fn set_scale<A: AsRef<[F; 3]>>(&mut self, _scale: A) -> bool {
        false
    }

    fn set_uniform_scale(&mut self, scale: F) {
        let s = self.determinant();
        if s.abs() > F::epsilon() {
            self.scale_uniform_by(scale / s);
        }
    }

    fn set_translation<A: AsRef<[F; 3]>>(&mut self, translation: A) {
        let t = translation.as_ref();
        self[3] = t[0];
        self[7] = t[1];
        self[11] = t[2];
    }

    fn set_rotation(&mut self, rotation: Self::Quat) {
        let s = self.determinant();
        if s.abs() > F::epsilon() {
            let mut m: FArray2<F, 4, 16> = [F::ZERO; 16].into();
            rotation.set_rotation4(&mut m);
            m.scale_uniform_by(s);
            m[3] = self[3];
            m[7] = self[7];
            m[11] = self[11];
        }
    }

    fn scale_uniform_by(&mut self, scale: F) {
        for c in self.iter_mut().take(12) {
            *c = *c * scale;
        }
    }

    fn scale_by<A: AsRef<[F; 3]>>(&mut self, scale: A) -> bool {
        for (i, c) in self.iter_mut().take(12).enumerate() {
            *c = *c * scale.as_ref()[i / 4];
        }
        true
    }

    fn translate_by<A: AsRef<[F; 3]>>(&mut self, translation: A, scale: F) {
        let translation = translation.as_ref();
        for i in 0..3 {
            self[i * 4 + 3] = self[i * 4 + 3] + translation[i] * scale;
        }
    }

    fn rotate_by(&mut self, quaternion: &Self::Quat) {
        let mut m: Self = [F::ZERO; 16].into();
        quaternion.set_rotation4(&mut m);
        *self = *self * m;
    }

    fn transform_by<T: Transform<F, Quat = Self::Quat>>(&mut self, transformer: &T) -> bool {
        let m = transformer.as_mat4::<Self>();
        *self = *self * m;
        true
    }

    fn inverse(&self) -> Option<Self> {
        Some(<Self as SqMatrix<_, _, _>>::inverse(self))
    }

    fn invert(&mut self) -> bool {
        *self = <Self as SqMatrix<_, _, _>>::inverse(self);
        true
    }

    fn apply3_arr(&self, other: &[F; 3]) -> [F; 3] {
        let v = [other[0], other[1], other[2], F::ONE];
        let v = self.transform_arr(&v);
        [v[0], v[1], v[2]]
    }

    fn apply4_arr(&self, other: &[F; 4]) -> [F; 4] {
        self.transform_arr(other)
    }

    fn as_mat3<M: SqMatrix3<F>>(&self) -> M {
        let mut m = M::default();
        for (i, c) in m.iter_mut().enumerate() {
            *c = self[i + i / 3];
        }
        m
    }

    fn as_mat4<M: SqMatrix4<F>>(&self) -> M {
        self.as_ref().into()
    }
}