1#[macro_export]
2macro_rules! inner_define_linear_map_3d {
3 {} => {
4 pub struct LinearMap3d<Number: ArithmeticOps> {
5 c: [[Number; 3]; 3],
6 }
7
8 impl<Number: ArithmeticOps> LinearMap3d<Number> {
9 pub const fn new(coefficients: [[Number; 3]; 3]) -> Self {
10 Self { c: coefficients }
11 }
12
13 pub fn rotation<AngleUnit: AngleMeasurementUnit<Property = Angle>, AxisUnit: MeasurementUnit>(
20 angle: Measure<AngleUnit, Number>,
21 unit_vector: Measure3d<AxisUnit, Number>,
22 ) -> Self
23 where
24 AxisUnit::Property: VectorProperty,
25 {
26 Self::rotation_by_radians_around_unit_vector(
27 angle.convert::<Radian>().value,
28 unit_vector.x,
29 unit_vector.y,
30 unit_vector.z,
31 )
32 }
33
34 pub fn projection_onto_line<Unit: MeasurementUnit>(
39 unit_vector: Measure3d<Unit, Number>,
40 ) -> Self {
41 Self {
42 c: [
43 [
44 unit_vector.x * unit_vector.x,
45 unit_vector.y * unit_vector.x,
46 unit_vector.z * unit_vector.x,
47 ],
48 [
49 unit_vector.x * unit_vector.y,
50 unit_vector.y * unit_vector.y,
51 unit_vector.z * unit_vector.y,
52 ],
53 [
54 unit_vector.x * unit_vector.z,
55 unit_vector.y * unit_vector.z,
56 unit_vector.z * unit_vector.z,
57 ],
58 ],
59 }
60 }
61
62 pub fn projection_onto_plane<Unit: MeasurementUnit>(
65 unit_vector: Measure3d<Unit, Number>,
66 ) -> Self {
67 Self {
68 c: [
69 [
70 Number::ONE - unit_vector.x * unit_vector.x,
71 -unit_vector.y * unit_vector.x,
72 -unit_vector.z * unit_vector.x,
73 ],
74 [
75 -unit_vector.x * unit_vector.y,
76 Number::ONE - unit_vector.y * unit_vector.y,
77 -unit_vector.z * unit_vector.y,
78 ],
79 [
80 -unit_vector.x * unit_vector.z,
81 -unit_vector.y * unit_vector.z,
82 Number::ONE - unit_vector.z * unit_vector.z,
83 ],
84 ],
85 }
86 }
87
88 pub fn reflection_over_line<Unit: MeasurementUnit>(
93 unit_vector: Measure3d<Unit, Number>,
94 ) -> Self {
95 let two = Number::ONE + Number::ONE;
96 Self {
97 c: [
98 [
99 two * unit_vector.x * unit_vector.x - Number::ONE,
100 two * unit_vector.y * unit_vector.x,
101 two * unit_vector.z * unit_vector.x,
102 ],
103 [
104 two * unit_vector.x * unit_vector.y,
105 two * unit_vector.y * unit_vector.y - Number::ONE,
106 two * unit_vector.z * unit_vector.y,
107 ],
108 [
109 two * unit_vector.x * unit_vector.z,
110 two * unit_vector.y * unit_vector.z,
111 two * unit_vector.z * unit_vector.z - Number::ONE,
112 ],
113 ],
114 }
115 }
116
117 pub fn reflection_over_plane<Unit: MeasurementUnit>(
120 unit_vector: Measure3d<Unit, Number>,
121 ) -> Self {
122 let minus_two = -(Number::ONE + Number::ONE);
123 Self {
124 c: [
125 [
126 minus_two * unit_vector.x * unit_vector.x + Number::ONE,
127 minus_two * unit_vector.y * unit_vector.x,
128 minus_two * unit_vector.z * unit_vector.x,
129 ],
130 [
131 minus_two * unit_vector.x * unit_vector.y,
132 minus_two * unit_vector.y * unit_vector.y + Number::ONE,
133 minus_two * unit_vector.z * unit_vector.y,
134 ],
135 [
136 minus_two * unit_vector.x * unit_vector.z,
137 minus_two * unit_vector.y * unit_vector.z,
138 minus_two * unit_vector.z * unit_vector.z + Number::ONE,
139 ],
140 ],
141 }
142 }
143
144 pub fn scaling(kx: Number, ky: Number, kz: Number) -> Self {
147 Self {
148 c: [
149 [kx, Number::ZERO, Number::ZERO],
150 [Number::ZERO, ky, Number::ZERO],
151 [Number::ZERO, Number::ZERO, kz],
152 ],
153 }
154 }
155
156 pub fn inverted(&self) -> Self {
159 let inv_determinant = Number::ONE
160 / (self.c[0][0] * (self.c[1][1] * self.c[2][2] - self.c[1][2] * self.c[2][1])
161 - self.c[0][1] * (self.c[1][0] * self.c[2][2] - self.c[1][2] * self.c[2][0])
162 + self.c[0][2] * (self.c[1][0] * self.c[2][1] - self.c[1][1] * self.c[2][0]));
163 Self {
164 c: [
165 [
166 (self.c[1][1] * self.c[2][2] - self.c[1][2] * self.c[2][1]) * inv_determinant,
167 -(self.c[0][1] * self.c[2][2] - self.c[0][2] * self.c[2][1]) * inv_determinant,
168 (self.c[0][1] * self.c[1][2] - self.c[0][2] * self.c[1][1]) * inv_determinant,
169 ],
170 [
171 -(self.c[1][0] * self.c[2][2] - self.c[1][2] * self.c[2][0]) * inv_determinant,
172 (self.c[0][0] * self.c[2][2] - self.c[0][2] * self.c[2][0]) * inv_determinant,
173 -(self.c[0][0] * self.c[1][2] - self.c[0][2] * self.c[1][0]) * inv_determinant,
174 ],
175 [
176 (self.c[1][0] * self.c[2][1] - self.c[1][1] * self.c[2][0]) * inv_determinant,
177 -(self.c[0][0] * self.c[2][1] - self.c[0][1] * self.c[2][0]) * inv_determinant,
178 (self.c[0][0] * self.c[1][1] - self.c[0][1] * self.c[1][0]) * inv_determinant,
179 ],
180 ],
181 }
182 }
183
184 pub fn combined_with(&self, other: &LinearMap3d<Number>) -> Self {
188 Self {
189 c: [
190 [
191 other.c[0][0] * self.c[0][0]
192 + other.c[0][1] * self.c[1][0]
193 + other.c[0][2] * self.c[2][0],
194 other.c[0][0] * self.c[0][1]
195 + other.c[0][1] * self.c[1][1]
196 + other.c[0][2] * self.c[2][1],
197 other.c[0][0] * self.c[0][2]
198 + other.c[0][1] * self.c[1][2]
199 + other.c[0][2] * self.c[2][2],
200 ],
201 [
202 other.c[1][0] * self.c[0][0]
203 + other.c[1][1] * self.c[1][0]
204 + other.c[1][2] * self.c[2][0],
205 other.c[1][0] * self.c[0][1]
206 + other.c[1][1] * self.c[1][1]
207 + other.c[1][2] * self.c[2][1],
208 other.c[1][0] * self.c[0][2]
209 + other.c[1][1] * self.c[1][2]
210 + other.c[1][2] * self.c[2][2],
211 ],
212 [
213 other.c[2][0] * self.c[0][0]
214 + other.c[2][1] * self.c[1][0]
215 + other.c[2][2] * self.c[2][0],
216 other.c[2][0] * self.c[0][1]
217 + other.c[2][1] * self.c[1][1]
218 + other.c[2][2] * self.c[2][1],
219 other.c[2][0] * self.c[0][2]
220 + other.c[2][1] * self.c[1][2]
221 + other.c[2][2] * self.c[2][2],
222 ],
223 ],
224 }
225 }
226
227 pub fn apply_to<Unit: MeasurementUnit>(
228 &self,
229 m: Measure3d<Unit, Number>,
230 ) -> Measure3d<Unit, Number>
231 where
232 Unit::Property: VectorProperty,
233 {
234 Measure3d::<Unit, Number>::new(
235 self.c[0][0] * m.x + self.c[0][1] * m.y + self.c[0][2] * m.z,
236 self.c[1][0] * m.x + self.c[1][1] * m.y + self.c[1][2] * m.z,
237 self.c[2][0] * m.x + self.c[2][1] * m.y + self.c[2][2] * m.z,
238 )
239 }
240
241 fn rotation_by_radians_around_unit_vector(
242 a: Number,
243 ux: Number,
244 uy: Number,
245 uz: Number,
246 ) -> Self {
247 let (sin_a, cos_a) = a.sin_cos();
248 let one_minus_cos_a = Number::ONE - cos_a;
249 Self {
250 c: [
251 [
252 cos_a + ux * ux * one_minus_cos_a,
253 ux * uy * one_minus_cos_a - uz * sin_a,
254 ux * uz * one_minus_cos_a + uy * sin_a,
255 ],
256 [
257 uy * ux * one_minus_cos_a + uz * sin_a,
258 cos_a + uy * uy * one_minus_cos_a,
259 uy * uz * one_minus_cos_a - ux * sin_a,
260 ],
261 [
262 uz * ux * one_minus_cos_a - uy * sin_a,
263 uz * uy * one_minus_cos_a + ux * sin_a,
264 cos_a + uz * uz * one_minus_cos_a,
265 ],
266 ],
267 }
268 }
269 }
270
271 impl<Number> Default for LinearMap3d<Number>
272 where
273 Number: ArithmeticOps,
274 {
275 fn default() -> Self {
277 Self::new([
278 [Number::ONE, Number::ZERO, Number::ZERO],
279 [Number::ZERO, Number::ONE, Number::ZERO],
280 [Number::ZERO, Number::ZERO, Number::ONE],
281 ])
282 }
283 }
284
285 impl<Number: ArithmeticOps> fmt::Display for LinearMap3d<Number> {
287 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
288 write!(
289 formatter,
290 "{}",
291 rs_measures::matrix_utils::format_matrix::<3, 3, Number>(&self.c, "")
292 )
293 }
294 }
295
296 impl<Number: ArithmeticOps> fmt::Debug for LinearMap3d<Number> {
298 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
299 write!(
300 formatter,
301 "{}",
302 rs_measures::matrix_utils::format_matrix::<3, 3, Number>(&self.c, "")
303 )
304 }
305 }
306 };
307}