rebound-rs 4.6.0-alpha.1

Rust wrapper for the REBOUND N-body simulation library.
Documentation
use std::ops::Mul;

use rebound_bind as rb;

use crate::types::Vec3d;

#[derive(Debug, Clone, Copy, Default, PartialEq)]
pub struct Rotation {
    pub ix: f64,
    pub iy: f64,
    pub iz: f64,
    pub r: f64,
}

impl Rotation {
    pub fn inverse(self) -> Self {
        let scale = 1.0 / self.length_squared();
        let conjugate = self.conjugate();
        Self {
            ix: conjugate.ix * scale,
            iy: conjugate.iy * scale,
            iz: conjugate.iz * scale,
            r: conjugate.r * scale,
        }
    }

    pub fn identity() -> Self {
        Self {
            ix: 0.0,
            iy: 0.0,
            iz: 0.0,
            r: 1.0,
        }
    }

    pub fn normalize(self) -> Self {
        let scale = 1.0 / self.length_squared().sqrt();
        Self {
            ix: self.ix * scale,
            iy: self.iy * scale,
            iz: self.iz * scale,
            r: self.r * scale,
        }
    }

    pub fn conjugate(self) -> Self {
        Self {
            ix: -self.ix,
            iy: -self.iy,
            iz: -self.iz,
            r: self.r,
        }
    }

    pub fn init_from_to(from: Vec3d, to: Vec3d) -> Self {
        unsafe { rb::reb_rotation_init_from_to(from.into(), to.into()) }.into()
    }

    pub fn init_angle_axis(angle: f64, axis: Vec3d) -> Self {
        unsafe { rb::reb_rotation_init_angle_axis(angle, axis.into()) }.into()
    }

    pub fn init_orbit(
        ascending_node_longitude: f64,
        inclination: f64,
        argument_of_periapsis: f64,
    ) -> Self {
        unsafe {
            rb::reb_rotation_init_orbit(
                ascending_node_longitude,
                inclination,
                argument_of_periapsis,
            )
        }
        .into()
    }

    pub fn init_to_new_axes(newz: Vec3d, newx: Vec3d) -> Self {
        unsafe { rb::reb_rotation_init_to_new_axes(newz.into(), newx.into()) }.into()
    }

    pub fn slerp(self, other: Self, t: f64) -> Self {
        unsafe { rb::reb_rotation_slerp(self.into(), other.into(), t) }.into()
    }

    pub fn imag(self) -> Vec3d {
        Vec3d(self.ix, self.iy, self.iz)
    }

    fn dot(self, other: Self) -> f64 {
        self.r * other.r + self.ix * other.ix + self.iy * other.iy + self.iz * other.iz
    }

    fn length_squared(self) -> f64 {
        self.dot(self)
    }
}

impl Mul<Rotation> for Rotation {
    type Output = Self;

    fn mul(self, rhs: Rotation) -> Self::Output {
        Rotation {
            r: self.r * rhs.r - self.ix * rhs.ix - self.iy * rhs.iy - self.iz * rhs.iz,
            ix: self.r * rhs.ix + self.ix * rhs.r + self.iy * rhs.iz - self.iz * rhs.iy,
            iy: self.r * rhs.iy - self.ix * rhs.iz + self.iy * rhs.r + self.iz * rhs.ix,
            iz: self.r * rhs.iz + self.ix * rhs.iy - self.iy * rhs.ix + self.iz * rhs.r,
        }
    }
}

impl From<rb::reb_rotation> for Rotation {
    fn from(value: rb::reb_rotation) -> Self {
        Self {
            ix: value.ix,
            iy: value.iy,
            iz: value.iz,
            r: value.r,
        }
    }
}

impl From<Rotation> for rb::reb_rotation {
    fn from(value: Rotation) -> Self {
        Self {
            ix: value.ix,
            iy: value.iy,
            iz: value.iz,
            r: value.r,
        }
    }
}