1#[macro_export] macro_rules! inner_define_linear_map_2d {
3 {} => {
4 pub struct LinearMap2d<Number = f64>
6 where
7 Number: ArithmeticOps,
8 {
9 pub c: [[Number; 2]; 2],
10 }
11
12 impl<Number: ArithmeticOps> LinearMap2d<Number> {
13 pub const fn new(coefficients: [[Number; 2]; 2]) -> Self {
15 Self { c: coefficients }
16 }
17
18 pub fn rotation<AngleUnit>(angle: Measure<AngleUnit, Number>) -> Self
24 where
25 AngleUnit: AngleMeasurementUnit,
26 {
27 Self::rotation_by_radians(angle.convert::<Radian>().value)
28 }
29
30 pub fn right_rotation() -> Self {
32 Self {
33 c: [[Number::ZERO, Number::ONE], [-Number::ONE, Number::ZERO]],
34 }
35 }
36
37 pub fn left_rotation() -> Self {
39 Self {
40 c: [[Number::ZERO, -Number::ONE], [Number::ONE, Number::ZERO]],
41 }
42 }
43
44 pub fn projection_by_angle<AngleUnit: AngleMeasurementUnit>(
48 angle: impl Into<MeasurePoint<AngleUnit, Number>>,
49 ) -> Self {
50 Self::projection_by_radians(angle.into().convert::<Radian>().value)
51 }
52
53 pub fn projection_by_unit_vector<Unit>(v: Measure2d<Unit, Number>) -> Self
56 where
57 Unit: MeasurementUnit<Property: VectorProperty>,
58 {
59 Self::projection_by_cos_sin(v.values[0], v.values[1])
60 }
61
62 pub fn reflection_by_angle<AngleUnit>(angle: impl Into<MeasurePoint<AngleUnit, Number>>) -> Self
66 where
67 AngleUnit: AngleMeasurementUnit,
68 {
69 Self::reflection_by_radians(angle.into().convert::<Radian>().value)
70 }
71
72 pub fn reflection_by_unit_vector<Unit>(v: Measure2d<Unit, Number>) -> Self
75 where
76 Unit: MeasurementUnit<Property: VectorProperty>,
77 {
78 Self::reflection_by_cos_sin(v.values[0], v.values[1])
79 }
80
81 pub fn scaling(factors: [Number; 2]) -> Self {
84 Self {
85 c: [[factors[0], Number::ZERO], [Number::ZERO, factors[1]]],
86 }
87 }
88
89 pub fn inverted(&self) -> Self {
92 let inv_determinant =
93 Number::ONE / (self.c[0][0] * self.c[1][1] - self.c[0][1] * self.c[1][0]);
94 Self {
95 c: [
96 [
97 self.c[1][1] * inv_determinant,
98 self.c[0][1] * -inv_determinant,
99 ],
100 [
101 self.c[1][0] * -inv_determinant,
102 self.c[0][0] * inv_determinant,
103 ],
104 ],
105 }
106 }
107
108 pub fn combined_with(&self, other: &LinearMap2d<Number>) -> Self {
112 Self {
113 c: [
114 [
115 other.c[0][0] * self.c[0][0] + other.c[0][1] * self.c[1][0],
116 other.c[0][0] * self.c[0][1] + other.c[0][1] * self.c[1][1],
117 ],
118 [
119 other.c[1][0] * self.c[0][0] + other.c[1][1] * self.c[1][0],
120 other.c[1][0] * self.c[0][1] + other.c[1][1] * self.c[1][1],
121 ],
122 ],
123 }
124 }
125
126 pub fn apply_to<Unit>(&self, m: Measure2d<Unit, Number>) -> Measure2d<Unit, Number>
127 where
128 Unit: MeasurementUnit<Property: VectorProperty>,
129 {
130 Measure2d::<Unit, Number>::new([
131 self.c[0][0] * m.values[0] + self.c[0][1] * m.values[1],
132 self.c[1][0] * m.values[0] + self.c[1][1] * m.values[1],
133 ])
134 }
135
136 fn rotation_by_radians(a: Number) -> Self {
137 let (sin_a, cos_a) = a.sin_cos();
138 Self {
139 c: [[cos_a, -sin_a], [sin_a, cos_a]],
140 }
141 }
142
143 fn projection_by_cos_sin(cos_a: Number, sin_a: Number) -> Self {
144 Self {
145 c: [
146 [cos_a * cos_a, cos_a * sin_a],
147 [sin_a * cos_a, sin_a * sin_a],
148 ],
149 }
150 }
151
152 fn projection_by_radians(a: Number) -> Self {
153 let (sin_a, cos_a) = a.sin_cos();
154 Self::projection_by_cos_sin(cos_a, sin_a)
155 }
156
157 fn reflection_by_cos_sin(cos_a: Number, sin_a: Number) -> Self {
158 let one = Number::ONE;
159 let two = Number::ONE + Number::ONE;
160 Self {
161 c: [
162 [two * cos_a * cos_a - one, two * cos_a * sin_a],
163 [two * cos_a * sin_a, two * sin_a * sin_a - one],
164 ],
165 }
166 }
167
168 fn reflection_by_radians(radians: Number) -> Self {
169 let (sin_a, cos_a) = radians.sin_cos();
170 Self::reflection_by_cos_sin(cos_a, sin_a)
171 }
172 }
173
174 impl<Number> Default for LinearMap2d<Number>
175 where
176 Number: ArithmeticOps,
177 {
178 fn default() -> Self {
181 Self::new([[Number::ONE, Number::ZERO], [Number::ZERO, Number::ONE]])
182 }
183 }
184
185 impl<Number> PartialEq<LinearMap2d<Number>> for LinearMap2d<Number>
187 where
188 Number: ArithmeticOps,
189 {
190 fn eq(&self, other: &LinearMap2d<Number>) -> bool {
191 self.c == other.c
192 }
193 }
194
195 impl<Number> Clone for LinearMap2d<Number>
197 where
198 Number: ArithmeticOps,
199 {
200 fn clone(&self) -> Self {
201 Self { c: self.c.clone() }
202 }
203 }
204
205 impl From<LinearMap2d<f32>> for LinearMap2d<f64> {
206 fn from(m: LinearMap2d<f32>) -> Self {
207 Self::new([
208 [m.c[0][0] as f64, m.c[0][1] as f64],
209 [m.c[1][0] as f64, m.c[1][1] as f64],
210 ])
211 }
212 }
213
214 impl<Number: ArithmeticOps> fmt::Display for LinearMap2d<Number> {
217 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
218 write!(
219 formatter,
220 "{}",
221 measures::matrix_utils::format_matrix::<2, 2, Number>(&self.c, "", 1)
222 )
223 }
224 }
225
226 impl<Number: ArithmeticOps> fmt::Debug for LinearMap2d<Number> {
228 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
229 write!(
230 formatter,
231 "{}",
232 measures::matrix_utils::format_matrix::<2, 2, Number>(&self.c, "", 1)
233 )
234 }
235 }
236 };
237}