1#[macro_export]
2macro_rules! inner_define_linear_map_2d {
3 {} => {
4 pub struct LinearMap2d<Number: ArithmeticOps> {
5 c: [[Number; 2]; 2],
6 }
7
8 impl<Number: ArithmeticOps> LinearMap2d<Number> {
9 pub const fn new(coefficients: [[Number; 2]; 2]) -> Self {
10 Self { c: coefficients }
11 }
12
13 pub fn rotation<AngleUnit: AngleMeasurementUnit<Property = Angle>>(
19 angle: Measure<AngleUnit, Number>,
20 ) -> Self {
21 Self::rotation_by_radians(angle.convert::<Radian>().value)
22 }
23
24 pub fn rotation_at_right() -> Self {
25 Self {
26 c: [[Number::ZERO, Number::ONE], [-Number::ONE, Number::ZERO]],
27 }
28 }
29
30 pub fn rotation_at_left() -> Self {
31 Self {
32 c: [[Number::ZERO, -Number::ONE], [Number::ONE, Number::ZERO]],
33 }
34 }
35
36 pub fn projection_by_point_angle<Unit: AngleMeasurementUnit<Property = Angle>>(
40 angle: MeasurePoint<Unit, Number>,
41 ) -> Self {
42 Self::projection_by_radians(angle.convert::<Radian>().value)
43 }
44
45 pub fn projection_by_signed_direction<Unit: AngleMeasurementUnit<Property = Angle>>(
47 direction: SignedDirection<Unit, Number>,
48 ) -> Self {
49 Self::projection_by_radians(direction.convert::<Radian>().value)
50 }
51
52 pub fn projection_by_unsigned_direction<Unit: AngleMeasurementUnit<Property = Angle>>(
54 angle: UnsignedDirection<Unit, Number>,
55 ) -> Self {
56 Self::projection_by_radians(angle.convert::<Radian>().value)
57 }
58
59 pub fn projection_by_unit_vector<Unit: MeasurementUnit>(v: Measure2d<Unit, Number>) -> Self {
62 Self::projection_by_cos_sin(v.x, v.y)
63 }
64
65 pub fn reflection_by_point_angle<AngleUnit: AngleMeasurementUnit<Property = Angle>>(
69 angle: MeasurePoint<AngleUnit, Number>,
70 ) -> Self {
71 Self::reflection_by_radians(angle.convert::<Radian>().value)
72 }
73
74 pub fn reflection_by_signed_direction<AngleUnit: AngleMeasurementUnit<Property = Angle>>(
76 direction: SignedDirection<AngleUnit, Number>,
77 ) -> Self {
78 Self::reflection_by_radians(direction.convert::<Radian>().value)
79 }
80
81 pub fn reflection_by_unsigned_direction<AngleUnit: AngleMeasurementUnit<Property = Angle>>(
83 direction: UnsignedDirection<AngleUnit, Number>,
84 ) -> Self {
85 Self::reflection_by_radians(direction.convert::<Radian>().value)
86 }
87
88 pub fn reflection_by_unit_vector<Unit: MeasurementUnit>(v: Measure2d<Unit, Number>) -> Self {
91 Self::reflection_by_cos_sin(v.x, v.y)
92 }
93
94 pub fn scaling(kx: Number, ky: Number) -> Self {
97 Self {
98 c: [[kx, Number::ZERO], [Number::ZERO, ky]],
99 }
100 }
101
102 pub fn inverted(&self) -> Self {
105 let inv_determinant =
106 Number::ONE / (self.c[0][0] * self.c[1][1] - self.c[0][1] * self.c[1][0]);
107 Self {
108 c: [
109 [
110 self.c[1][1] * inv_determinant,
111 self.c[0][1] * -inv_determinant,
112 ],
113 [
114 self.c[1][0] * -inv_determinant,
115 self.c[0][0] * inv_determinant,
116 ],
117 ],
118 }
119 }
120
121 pub fn combined_with(&self, other: &LinearMap2d<Number>) -> Self {
125 Self {
126 c: [
127 [
128 other.c[0][0] * self.c[0][0] + other.c[0][1] * self.c[1][0],
129 other.c[0][0] * self.c[0][1] + other.c[0][1] * self.c[1][1],
130 ],
131 [
132 other.c[1][0] * self.c[0][0] + other.c[1][1] * self.c[1][0],
133 other.c[1][0] * self.c[0][1] + other.c[1][1] * self.c[1][1],
134 ],
135 ],
136 }
137 }
138
139 pub fn apply_to<Unit: MeasurementUnit>(
140 &self,
141 m: Measure2d<Unit, Number>,
142 ) -> Measure2d<Unit, Number>
143 where
144 Unit::Property: VectorProperty,
145 {
146 Measure2d::<Unit, Number>::new(
147 self.c[0][0] * m.x + self.c[0][1] * m.y,
148 self.c[1][0] * m.x + self.c[1][1] * m.y,
149 )
150 }
151
152 fn rotation_by_radians(a: Number) -> Self {
153 let (sin_a, cos_a) = a.sin_cos();
154 Self {
155 c: [[cos_a, -sin_a], [sin_a, cos_a]],
156 }
157 }
158
159 fn projection_by_cos_sin(cos_a: Number, sin_a: Number) -> Self {
160 Self {
161 c: [
162 [cos_a * cos_a, cos_a * sin_a],
163 [sin_a * cos_a, sin_a * sin_a],
164 ],
165 }
166 }
167
168 fn projection_by_radians(a: Number) -> Self {
169 let (sin_a, cos_a) = a.sin_cos();
170 Self::projection_by_cos_sin(cos_a, sin_a)
171 }
172
173 fn reflection_by_cos_sin(cos_a: Number, sin_a: Number) -> Self {
174 let one = Number::ONE;
175 let two = Number::ONE + Number::ONE;
176 Self {
177 c: [
178 [two * cos_a * cos_a - one, two * cos_a * sin_a],
179 [two * cos_a * sin_a, two * sin_a * sin_a - one],
180 ],
181 }
182 }
183
184 fn reflection_by_radians(radians: Number) -> Self {
185 let (sin_a, cos_a) = radians.sin_cos();
186 Self::reflection_by_cos_sin(cos_a, sin_a)
187 }
188 }
189
190 impl<Number> Default for LinearMap2d<Number>
191 where
192 Number: ArithmeticOps,
193 {
194 fn default() -> Self {
196 Self::new([[Number::ONE, Number::ZERO], [Number::ZERO, Number::ONE]])
197 }
198 }
199
200 impl<Number: ArithmeticOps> fmt::Display for LinearMap2d<Number> {
202 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
203 write!(
204 formatter,
205 "{}",
206 rs_measures::matrix_utils::format_matrix::<2, 2, Number>(&self.c, "")
207 )
208 }
209 }
210
211 impl<Number: ArithmeticOps> fmt::Debug for LinearMap2d<Number> {
213 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
214 write!(
215 formatter,
216 "{}",
217 rs_measures::matrix_utils::format_matrix::<2, 2, Number>(&self.c, "")
218 )
219 }
220 }
221 };
222}