#![allow(non_camel_case_types)]
use std::ops;
use crate::{E, symbol, sin, cos};
#[derive(Clone)]
pub struct vect3sym {
pub x: E,
pub y: E,
pub z: E,
}
impl vect3sym {
pub fn new(base: &str) -> Self {
vect3sym {
x: symbol(&format!("{}.x", base)),
y: symbol(&format!("{}.y", base)),
z: symbol(&format!("{}.z", base)),
}
}
pub fn sincos(&self) -> (vect3sym, vect3sym) {
(
vect3sym {
x: sin(self.x.clone()),
y: sin(self.y.clone()),
z: sin(self.z.clone()),
},
vect3sym {
x: cos(self.x.clone()),
y: cos(self.y.clone()),
z: cos(self.z.clone()),
},
)
}
pub fn rotation_matrix(&self) -> matrix3sym {
let (s, c) = self.sincos();
matrix3sym {
rows: [
vect3sym {
x: c.y.clone() * c.z.clone(),
y: -c.x.clone() * s.z.clone() + c.z.clone() * s.x.clone() * s.y.clone(),
z: c.x.clone() * c.z.clone() * s.y.clone() + s.x.clone() * s.z.clone(),
},
vect3sym {
x: c.y.clone() * s.z.clone(),
y: c.x.clone() * c.z.clone() + s.x.clone() * s.y.clone() * s.z.clone(),
z: c.x.clone() * s.y.clone() * s.z.clone() - c.z.clone() * s.x.clone(),
},
vect3sym {
x: -s.y.clone(),
y: c.y.clone() * s.x.clone(),
z: c.x.clone() * c.y.clone(),
},
],
}
}
}
impl ops::Add<vect3sym> for vect3sym {
type Output = vect3sym;
fn add(self, rhs: vect3sym) -> vect3sym {
vect3sym { x: self.x + rhs.x, y: self.y + rhs.y, z: self.z + rhs.z }
}
}
impl ops::Sub<vect3sym> for vect3sym {
type Output = vect3sym;
fn sub(self, rhs: vect3sym) -> vect3sym {
vect3sym { x: self.x - rhs.x, y: self.y - rhs.y, z: self.z - rhs.z }
}
}
impl ops::Neg for vect3sym {
type Output = vect3sym;
fn neg(self) -> vect3sym {
vect3sym { x: -self.x, y: -self.y, z: -self.z }
}
}
impl ops::Mul<E> for vect3sym {
type Output = vect3sym;
fn mul(self, rhs: E) -> vect3sym {
vect3sym { x: self.x * rhs.clone(), y: self.y * rhs.clone(), z: self.z * rhs }
}
}
impl ops::Mul<vect3sym> for E {
type Output = vect3sym;
fn mul(self, rhs: vect3sym) -> vect3sym {
vect3sym { x: self.clone() * rhs.x, y: self.clone() * rhs.y, z: self * rhs.z }
}
}
impl ops::Mul<vect3sym> for vect3sym {
type Output = E;
fn mul(self, rhs: vect3sym) -> E {
self.x * rhs.x + self.y * rhs.y + self.z * rhs.z
}
}
#[derive(Clone)]
pub struct vect2sym {
pub x: E,
pub y: E,
}
impl vect2sym {
pub fn new(base: &str) -> Self {
vect2sym {
x: symbol(&format!("{}.x", base)),
y: symbol(&format!("{}.y", base)),
}
}
}
impl ops::Sub<vect2sym> for vect2sym {
type Output = vect2sym;
fn sub(self, rhs: vect2sym) -> vect2sym {
vect2sym { x: self.x - rhs.x, y: self.y - rhs.y }
}
}
impl ops::Add<vect2sym> for vect2sym {
type Output = vect2sym;
fn add(self, rhs: vect2sym) -> vect2sym {
vect2sym { x: self.x + rhs.x, y: self.y + rhs.y }
}
}
impl ops::Neg for vect2sym {
type Output = vect2sym;
fn neg(self) -> vect2sym {
vect2sym { x: -self.x, y: -self.y }
}
}
impl ops::Mul<E> for vect2sym {
type Output = vect2sym;
fn mul(self, rhs: E) -> vect2sym {
vect2sym { x: self.x * rhs.clone(), y: self.y * rhs }
}
}
impl ops::Mul<vect2sym> for E {
type Output = vect2sym;
fn mul(self, rhs: vect2sym) -> vect2sym {
vect2sym { x: self.clone() * rhs.x, y: self * rhs.y }
}
}
impl ops::Mul<vect2sym> for vect2sym {
type Output = E;
fn mul(self, rhs: vect2sym) -> E {
self.x * rhs.x + self.y * rhs.y
}
}
impl ops::Div<E> for vect2sym {
type Output = vect2sym;
fn div(self, rhs: E) -> vect2sym {
vect2sym { x: self.x / rhs.clone(), y: self.y / rhs }
}
}
impl vect2sym {
pub fn square(&self) -> E {
self.x.clone() * self.x.clone() + self.y.clone() * self.y.clone()
}
pub fn norm(&self) -> E {
crate::sqrt(self.square())
}
pub fn unit(self) -> vect2sym {
let n = self.norm();
self / n
}
pub fn across(self) -> vect2sym {
vect2sym { x: -self.y, y: self.x }
}
pub fn cross(&self, rhs: &vect2sym) -> E {
self.x.clone() * rhs.y.clone() - self.y.clone() * rhs.x.clone()
}
}
#[derive(Clone)]
pub struct matrix3sym {
pub rows: [vect3sym; 3],
}
impl matrix3sym {
pub fn new(base: &str) -> Self {
matrix3sym {
rows: [
vect3sym::new(&format!("{}[0]", base)),
vect3sym::new(&format!("{}[1]", base)),
vect3sym::new(&format!("{}[2]", base)),
],
}
}
pub fn get_euler_angles(&self) -> vect3sym {
vect3sym {
x: crate::atan2(self.rows[2].y.clone(), self.rows[2].z.clone()),
y: -crate::asin(self.rows[2].x.clone()),
z: crate::atan2(self.rows[1].x.clone(), self.rows[0].x.clone()),
}
}
pub fn transpose(&self) -> matrix3sym {
matrix3sym {
rows: [
vect3sym { x: self.rows[0].x.clone(), y: self.rows[1].x.clone(), z: self.rows[2].x.clone() },
vect3sym { x: self.rows[0].y.clone(), y: self.rows[1].y.clone(), z: self.rows[2].y.clone() },
vect3sym { x: self.rows[0].z.clone(), y: self.rows[1].z.clone(), z: self.rows[2].z.clone() },
],
}
}
}
impl ops::Mul<matrix3sym> for matrix3sym {
type Output = matrix3sym;
fn mul(self, rhs: matrix3sym) -> matrix3sym {
let rhs_t = rhs.transpose();
matrix3sym {
rows: [
vect3sym {
x: self.rows[0].clone() * rhs_t.rows[0].clone(),
y: self.rows[0].clone() * rhs_t.rows[1].clone(),
z: self.rows[0].clone() * rhs_t.rows[2].clone(),
},
vect3sym {
x: self.rows[1].clone() * rhs_t.rows[0].clone(),
y: self.rows[1].clone() * rhs_t.rows[1].clone(),
z: self.rows[1].clone() * rhs_t.rows[2].clone(),
},
vect3sym {
x: self.rows[2].clone() * rhs_t.rows[0].clone(),
y: self.rows[2].clone() * rhs_t.rows[1].clone(),
z: self.rows[2].clone() * rhs_t.rows[2].clone(),
},
],
}
}
}
impl ops::Mul<vect3sym> for matrix3sym {
type Output = vect3sym;
fn mul(self, rhs: vect3sym) -> vect3sym {
vect3sym {
x: self.rows[0].x.clone() * rhs.x.clone() + self.rows[0].y.clone() * rhs.y.clone() + self.rows[0].z.clone() * rhs.z.clone(),
y: self.rows[1].x.clone() * rhs.x.clone() + self.rows[1].y.clone() * rhs.y.clone() + self.rows[1].z.clone() * rhs.z.clone(),
z: self.rows[2].x.clone() * rhs.x.clone() + self.rows[2].y.clone() * rhs.y.clone() + self.rows[2].z.clone() * rhs.z.clone(),
}
}
}
impl ops::Index<usize> for matrix3sym {
type Output = vect3sym;
fn index(&self, index: usize) -> &vect3sym {
&self.rows[index]
}
}
#[derive(Clone)]
pub struct matrix2sym {
pub rows: [vect2sym; 2],
}
impl matrix2sym {
pub fn new(base: &str) -> Self {
matrix2sym {
rows: [
vect2sym::new(&format!("{}[0]", base)),
vect2sym::new(&format!("{}[1]", base)),
],
}
}
}
impl ops::Index<usize> for matrix2sym {
type Output = vect2sym;
fn index(&self, index: usize) -> &vect2sym {
&self.rows[index]
}
}
#[derive(Clone)]
pub struct quaternsym {
pub t: E,
pub v: vect3sym,
}
impl quaternsym {
pub fn new(base: &str) -> Self {
quaternsym {
t: symbol(&format!("{}.t", base)),
v: vect3sym::new(&format!("{}.v", base)),
}
}
}