use super::Vec3;
use crate::Real;
pub trait SpatialVec: Sized {
type DualType: SpatialVec;
fn from_pair(top: Vec3, bottom: Vec3) -> Self;
fn top(&self) -> Vec3;
fn bottom(&self) -> Vec3;
#[inline]
fn dot(&self, rhs: &Self::DualType) -> Real {
self.top().dot(&rhs.top()) + self.bottom().dot(&rhs.bottom())
}
#[inline]
fn cross_dual(&self, rhs: &Self::DualType) -> Self::DualType {
Self::DualType::from_pair(
self.top().cross(&rhs.top()) + self.bottom().cross(&rhs.bottom()),
self.top().cross(&rhs.bottom()),
)
}
#[inline]
fn transpose(&self) -> Self::DualType {
Self::DualType::from_pair(self.top(), self.bottom())
}
}
#[cfg(test)]
mod tests {
use approx::assert_relative_eq;
use super::*;
use crate::{SpatialForceVector, SpatialMotionVector};
#[test]
fn test_cross_dual() {
let spatial_v = SpatialMotionVector::from_array([1., 2., 3., 4., 5., 6.]);
let spatial_f = SpatialForceVector::from_array([7., 8., 9., 10., 11., 12.]);
let result = spatial_v.cross_dual(&spatial_f);
let w = spatial_v.top;
let v = spatial_v.bottom;
let n = spatial_f.top;
let f = spatial_f.bottom;
assert_relative_eq!(result.top, w.cross(&n) + v.cross(&f));
assert_relative_eq!(result.bottom, w.cross(&f));
}
#[test]
fn test_dot() {
let spatial_v = SpatialMotionVector::from_array([1., 2., 3., 4., 5., 6.]);
let spatial_f = SpatialForceVector::from_array([7., 8., 9., 10., 11., 12.]);
let result = spatial_v.dot(&spatial_f);
let w = spatial_v.top;
let v = spatial_v.bottom;
let n = spatial_f.top;
let f = spatial_f.bottom;
assert_relative_eq!(result, w.dot(&n) + v.dot(&f));
}
}