1use super::Movement;
2
3use scalars::{Exp, Inv, One, Zero};
4use vector_space::{AffineSpace, VectorSpace, interpolate};
5
6use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
7
8#[derive(Copy, Clone, Debug, PartialEq, Eq)]
9pub struct Transform<V, R> {
10 pub position: V,
11 pub orientation: R,
12}
13
14impl<V, R> Transform<V, R>
15where
16 V: Clone + AffineSpace + Add<V::Diff, Output = V>,
17 V::Diff: VectorSpace,
18 R: Clone + AffineSpace + Add<R::Diff, Output = R>,
19 R::Diff: VectorSpace<Scalar = <V::Diff as VectorSpace>::Scalar>,
20{
21 pub fn lerp(&self, other: &Self, ratio: <V::Diff as VectorSpace>::Scalar) -> Self {
22 Self {
23 position: interpolate(self.position.clone(), other.position.clone(), ratio),
24 orientation: interpolate(self.orientation.clone(), other.orientation.clone(), ratio),
25 }
26 }
27}
28
29impl<V: Copy + Add<Output = V>, R: vector_space::Transform<V>> Transform<V, R> {
30 pub fn apply(&self, point: V) -> V {
31 self.position + self.orientation.apply_point(point)
32 }
33}
34
35impl<V: Zero, R: One> One for Transform<V, R> {
36 fn one() -> Self {
37 Self {
38 position: V::zero(),
39 orientation: R::one(),
40 }
41 }
42
43 fn is_one(&self) -> bool {
44 self.position.is_zero() && self.orientation.is_one()
45 }
46}
47
48impl<V, R> Mul for Transform<V, R>
49where
50 V: Add<Output = V>,
51 R: Copy + Mul<Output = R> + vector_space::Transform<V>,
52{
53 type Output = Self;
54
55 fn mul(self, other: Self) -> Self {
56 Self {
57 position: self.position + self.orientation.apply_point(other.position),
58 orientation: self.orientation * other.orientation,
59 }
60 }
61}
62
63impl<V, R> Div for Transform<V, R>
64where
65 V: Add<Output = V> + Neg<Output = V>,
66 R: Copy + Mul<Output = R> + Inv<Output = R> + vector_space::Transform<V>,
67{
68 type Output = Self;
69
70 fn div(self, other: Self) -> Self {
71 self * other.inv()
72 }
73}
74
75impl<V, R> Inv for Transform<V, R>
76where
77 V: Neg<Output = V>,
78 R: Copy + Inv<Output = R> + vector_space::Transform<V>,
79{
80 type Output = Self;
81
82 fn inv(self) -> Self {
83 let orientation = self.orientation.inv();
84 Self {
85 position: -orientation.apply_point(self.position),
86 orientation,
87 }
88 }
89}
90
91impl<V, R> MulAssign for Transform<V, R>
92where
93 V: AddAssign,
94 R: Copy + MulAssign + vector_space::Transform<V>,
95{
96 fn mul_assign(&mut self, other: Self) {
97 self.position += self.orientation.apply_point(other.position);
98 self.orientation *= other.orientation;
99 }
100}
101
102impl<V, R> DivAssign for Transform<V, R>
103where
104 V: SubAssign,
105 R: Copy + DivAssign + vector_space::Transform<V>,
106{
107 fn div_assign(&mut self, other: Self) {
108 self.orientation /= other.orientation;
109 self.position -= self.orientation.apply_point(other.position);
110 }
111}
112
113impl<V, R, B> Add<Movement<V, B>> for Transform<V, R>
114where
115 V: Add<Output = V>,
116 B: Exp<Output = R>,
117 R: Mul<Output = R>,
118{
119 type Output = Self;
120
121 fn add(self, movement: Movement<V, B>) -> Self {
122 Self {
123 position: self.position + movement.velocity,
124 orientation: self.orientation * movement.spin.exp(),
125 }
126 }
127}
128
129impl<V, R, B> Sub<Movement<V, B>> for Transform<V, R>
130where
131 V: Sub<Output = V>,
132 B: Exp<Output = R>,
133 R: Div<Output = R>,
134{
135 type Output = Self;
136
137 fn sub(self, movement: Movement<V, B>) -> Self {
138 Self {
139 position: self.position - movement.velocity,
140 orientation: self.orientation / movement.spin.exp(),
141 }
142 }
143}
144
145impl<V, R, B> AddAssign<Movement<V, B>> for Transform<V, R>
146where
147 V: AddAssign,
148 B: Exp<Output = R>,
149 R: MulAssign,
150{
151 fn add_assign(&mut self, movement: Movement<V, B>) {
152 self.position += movement.velocity;
153 self.orientation *= movement.spin.exp();
154 }
155}
156
157impl<V, R, B> SubAssign<Movement<V, B>> for Transform<V, R>
158where
159 V: SubAssign,
160 B: Exp<Output = R>,
161 R: DivAssign,
162{
163 fn sub_assign(&mut self, movement: Movement<V, B>) {
164 self.position -= movement.velocity;
165 self.orientation /= movement.spin.exp();
166 }
167}
168
169impl<V, R> vector_space::Transform<V> for Transform<V, R>
170where
171 V: Copy + Add<Output = V>,
172 R: vector_space::Transform<V>,
173{
174 fn apply_point(&self, point: V) -> V {
175 self.apply(point)
176 }
177}