1#[macro_export] macro_rules! inner_define_affine_map_2d {
3 {} => {
4 pub struct AffineMap2d<Unit, Number = f64>
6 where
7 Unit: MeasurementUnit<Property: VectorProperty>,
8 Number: ArithmeticOps,
9 {
10 pub c: [[Number; 3]; 2],
11 phantom: core::marker::PhantomData<Unit>,
12 }
13
14 impl<Unit, Number> AffineMap2d<Unit, Number>
15 where
16 Unit: MeasurementUnit<Property: VectorProperty>,
17 Number: ArithmeticOps,
18 {
19 pub const fn new(coefficients: [[Number; 3]; 2]) -> Self {
21 Self {
22 c: coefficients,
23 phantom: PhantomData,
24 }
25 }
26
27 pub fn convert<DestUnit>(&self) -> AffineMap2d<DestUnit, Number>
29 where
30 DestUnit: MeasurementUnit<Property = Unit::Property>,
31 {
32 let factor = Number::from_f64(Unit::RATIO / DestUnit::RATIO);
33 AffineMap2d::<DestUnit, Number>::new([
34 [self.c[0][0], self.c[0][1], self.c[0][2] * factor],
35 [self.c[1][0], self.c[1][1], self.c[1][2] * factor],
36 ])
37 }
38
39 pub const fn translation(v: Measure2d<Unit, Number>) -> Self {
41 Self::new([
42 [Number::ONE, Number::ZERO, v.values[0]],
43 [Number::ZERO, Number::ONE, v.values[1]],
44 ])
45 }
46
47 pub fn rotation<AngleUnit>(
49 fixed_point: MeasurePoint2d<Unit, Number>,
50 angle: Measure<AngleUnit, Number>,
51 ) -> Self
52 where
53 AngleUnit: AngleMeasurementUnit,
54 {
55 Self::rotation_by_radians(fixed_point.values, angle.convert::<Radian>().value)
56 }
57
58 pub fn right_rotation(fixed_point: MeasurePoint2d<Unit, Number>) -> Self {
60 Self::right_rotation_by_sin(fixed_point.values, -Number::ONE)
61 }
62
63 pub fn left_rotation(fixed_point: MeasurePoint2d<Unit, Number>) -> Self {
65 Self::right_rotation_by_sin(fixed_point.values, Number::ONE)
66 }
67
68 pub fn projection_by_angle<AngleUnit>(
73 fixed_point: MeasurePoint2d<Unit, Number>,
74 angle: impl Into<MeasurePoint<AngleUnit, Number>>,
75 ) -> Self
76 where
77 AngleUnit: AngleMeasurementUnit,
78 {
79 let (sin_a, cos_a) = angle.into().convert::<Radian>().value.sin_cos();
80 Self::projection_by_cos_sin(fixed_point.values, cos_a, sin_a)
81 }
82
83 pub fn projection_by_unit_vector(
87 fixed_point: MeasurePoint2d<Unit, Number>,
88 uv: Measure2d<Unit, Number>,
89 ) -> Self {
90 Self::projection_by_cos_sin(fixed_point.values, uv.values[0], uv.values[1])
91 }
92
93 pub fn reflection_by_angle<AngleUnit>(
98 fixed_point: MeasurePoint2d<Unit, Number>,
99 angle: impl Into<MeasurePoint<AngleUnit, Number>>,
100 ) -> Self
101 where
102 AngleUnit: AngleMeasurementUnit,
103 {
104 let (sin_a, cos_a) = angle.into().convert::<Radian>().value.sin_cos();
105 Self::reflection_by_cos_sin(fixed_point.values, cos_a, sin_a)
106 }
107
108 pub fn reflection_by_unit_vector(
112 fixed_point: MeasurePoint2d<Unit, Number>,
113 uv: Measure2d<Unit, Number>,
114 ) -> Self {
115 Self::reflection_by_cos_sin(fixed_point.values, uv.values[0], uv.values[1])
116 }
117
118 pub fn scaling(fixed_point: MeasurePoint2d<Unit, Number>, factors: [Number; 2]) -> Self {
120 Self::new([
121 [
122 factors[0],
123 Number::ZERO,
124 fixed_point.values[0] * (Number::ONE - factors[0]),
125 ],
126 [
127 Number::ZERO,
128 factors[1],
129 fixed_point.values[1] * (Number::ONE - factors[1]),
130 ],
131 ])
132 }
133
134 pub fn inverted(&self) -> Self {
135 let inv_determinant =
136 Number::ONE / (self.c[0][0] * self.c[1][1] - self.c[0][1] * self.c[1][0]);
137 Self::new([
138 [
139 self.c[1][1] * inv_determinant,
140 self.c[0][1] * -inv_determinant,
141 (self.c[0][1] * self.c[1][2] - self.c[0][2] * self.c[1][1]) * inv_determinant,
142 ],
143 [
144 self.c[1][0] * -inv_determinant,
145 self.c[0][0] * inv_determinant,
146 (self.c[0][2] * self.c[1][0] - self.c[0][0] * self.c[1][2]) * inv_determinant,
147 ],
148 ])
149 }
150
151 pub fn combined_with(&self, other: &AffineMap2d<Unit, Number>) -> Self {
155 Self::new([
156 [
157 other.c[0][0] * self.c[0][0] + other.c[0][1] * self.c[1][0],
158 other.c[0][0] * self.c[0][1] + other.c[0][1] * self.c[1][1],
159 other.c[0][0] * self.c[0][2] + other.c[0][1] * self.c[1][2] + other.c[0][2],
160 ],
161 [
162 other.c[1][0] * self.c[0][0] + other.c[1][1] * self.c[1][0],
163 other.c[1][0] * self.c[0][1] + other.c[1][1] * self.c[1][1],
164 other.c[1][0] * self.c[0][2] + other.c[1][1] * self.c[1][2] + other.c[1][2],
165 ],
166 ])
167 }
168
169 pub fn apply_to(&self, m: MeasurePoint2d<Unit, Number>) -> MeasurePoint2d<Unit, Number> {
170 MeasurePoint2d::<Unit, Number>::new([
171 self.c[0][0] * m.values[0] + self.c[0][1] * m.values[1] + self.c[0][2],
172 self.c[1][0] * m.values[0] + self.c[1][1] * m.values[1] + self.c[1][2],
173 ])
174 }
175
176 fn rotation_by_radians(fp: [Number; 2], radians: Number) -> Self {
177 let (sin_a, cos_a) = radians.sin_cos();
178 Self::new([
179 [cos_a, -sin_a, fp[0] - cos_a * fp[0] + sin_a * fp[1]],
180 [sin_a, cos_a, fp[1] - sin_a * fp[0] - cos_a * fp[1]],
181 ])
182 }
183
184 fn right_rotation_by_sin(fp: [Number; 2], sine: Number) -> Self {
185 Self::new([
186 [Number::ZERO, -sine, fp[0] + sine * fp[1]],
187 [sine, Number::ZERO, fp[1] - sine * fp[0]],
188 ])
189 }
190
191 fn projection_by_cos_sin(fp: [Number; 2], cos_a: Number, sin_a: Number) -> Self {
192 let cc = cos_a * cos_a;
193 let cs = cos_a * sin_a;
194 let ss = sin_a * sin_a;
195 let sxmcy = sin_a * fp[0] - cos_a * fp[1];
196 Self::new([[cc, cs, sin_a * sxmcy], [cs, ss, -cos_a * sxmcy]])
197 }
198
199 fn reflection_by_cos_sin(fp: [Number; 2], cos_a: Number, sin_a: Number) -> Self {
200 let c2ms2 = cos_a * cos_a - sin_a * sin_a;
201 let two = Number::ONE + Number::ONE;
202 let cs_bis = two * cos_a * sin_a;
203 let sxmcy_bis = two * (sin_a * fp[0] - cos_a * fp[1]);
204 Self::new([
205 [c2ms2, cs_bis, sin_a * sxmcy_bis],
206 [cs_bis, -c2ms2, -cos_a * sxmcy_bis],
207 ])
208 }
209 }
210
211 impl<Unit, Number> Default for AffineMap2d<Unit, Number>
212 where
213 Unit: MeasurementUnit<Property: VectorProperty>,
214 Number: ArithmeticOps,
215 {
216 fn default() -> Self {
219 Self::new([
220 [Number::ONE, Number::ZERO, Number::ZERO],
221 [Number::ZERO, Number::ONE, Number::ZERO],
222 ])
223 }
224 }
225
226 impl<Unit, Number> PartialEq<AffineMap2d<Unit, Number>> for AffineMap2d<Unit, Number>
228 where
229 Unit: MeasurementUnit<Property: VectorProperty>,
230 Number: ArithmeticOps,
231 {
232 fn eq(&self, other: &AffineMap2d<Unit, Number>) -> bool {
233 self.c == other.c
234 }
235 }
236
237 impl<Unit, Number> Clone for AffineMap2d<Unit, Number>
239 where
240 Unit: MeasurementUnit<Property: VectorProperty>,
241 Number: ArithmeticOps,
242 {
243 fn clone(&self) -> Self {
244 Self::new(self.c.clone())
245 }
246 }
247
248 impl<Unit> From<AffineMap2d<Unit, f32>> for AffineMap2d<Unit, f64>
249 where
250 Unit: MeasurementUnit<Property: VectorProperty>,
251 {
252 fn from(m: AffineMap2d<Unit, f32>) -> Self {
253 Self::new([
254 [m.c[0][0] as f64, m.c[0][1] as f64, m.c[0][2] as f64],
255 [m.c[1][0] as f64, m.c[1][1] as f64, m.c[1][2] as f64],
256 ])
257 }
258 }
259
260 impl<Unit, Number> fmt::Display for AffineMap2d<Unit, Number>
263 where
264 Unit: MeasurementUnit<Property: VectorProperty>,
265 Number: ArithmeticOps,
266 {
267 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
268 write!(
269 formatter,
270 "{}",
271 measures::matrix_utils::format_matrix::<2, 3, Number>(&self.c, Unit::SUFFIX, 1)
272 )
273 }
274 }
275
276 impl<Unit, Number> fmt::Debug for AffineMap2d<Unit, Number>
278 where
279 Unit: MeasurementUnit<Property: VectorProperty>,
280 Number: ArithmeticOps,
281 {
282 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
283 write!(
284 formatter,
285 "{}",
286 measures::matrix_utils::format_matrix::<2, 3, Number>(&self.c, Unit::SUFFIX, 1)
287 )
288 }
289 }
290 };
291}