projective/traits/dim2.rs
1use num_traits::real::Real;
2
3/// 2D projective transformations
4///
5/// 
6///
7/// ## Supported 2D operations
8///
9/// | Operation | Description |
10/// |------------------------------------|-------------|
11/// | [transform](Projective::transform) | ----------- |
12/// | [translate](Projective::translate) | ----------- |
13/// | [rotate](Projective::rotate) | ----------- |
14/// | [scale](Projective::scale) | ----------- |
15#[doc = "## Examples"]
16#[doc = "```"]
17#[doc = include_str ! ("../../tests/point.rs")]
18#[doc = "```"]
19pub trait Projective<T>
20where
21 Self: Sized,
22 T: Real,
23{
24 /// Transform by a 3×3 matrix.
25 ///
26 /// # Matrix
27 ///
28 /// ```math
29 /// \begin{bmatrix}
30 /// m_0 & m_1 & m_2 \\
31 /// m_3 & m_4 & m_5 \\
32 /// m_6 & m_7 & m_8 \\
33 /// \end{bmatrix}
34 /// ```
35 fn transform(&mut self, matrix: &[&T; 9]);
36 /// Transform by length $\delta x, \delta y$.
37 ///
38 /// # Matrix
39 ///
40 /// ```math
41 /// \begin{bmatrix}
42 /// 1 & 0 & x \\
43 /// 0 & 1 & y \\
44 /// 0 & 0 & 1 \\
45 /// \end{bmatrix}
46 /// ```
47 #[inline(always)]
48 #[rustfmt::skip]
49 fn translate(&mut self, x: &T, y: &T) {
50 self.transform(&[
51 &T::one(), &T::zero(), x,
52 &T::zero(), &T::one(), y,
53 &T::zero(), &T::zero(), &T::one()
54 ])
55 }
56 /// Transform by length $\delta x$.
57 ///
58 /// # Matrix
59 ///
60 /// ```math
61 /// \begin{bmatrix}
62 /// 1 & 0 & x \\
63 /// 0 & 1 & 0 \\
64 /// 0 & 0 & 1 \\
65 /// \end{bmatrix}
66 /// ```
67 #[inline(always)]
68 fn translate_x(&mut self, x: &T) {
69 self.translate(x, &T::zero())
70 }
71 /// Transform by length $\delta y$.
72 ///
73 /// # Matrix
74 ///
75 /// ```math
76 /// \begin{bmatrix}
77 /// 1 & 0 & 0 \\
78 /// 0 & 1 & y \\
79 /// 0 & 0 & 1 \\
80 /// \end{bmatrix}
81 /// ```
82 #[inline(always)]
83 fn translate_y(&mut self, y: &T) {
84 self.translate(&T::zero(), y)
85 }
86 /// Transform by rotate degree $\alpha$.
87 ///
88 /// # Matrix
89 ///
90 /// ```math
91 /// \begin{bmatrix}
92 /// \cos\alpha & \sin\alpha & 0 \\
93 /// -\sin\alpha & \cos\alpha & 0 \\
94 /// 0 & 0 & 1 \\
95 /// \end{bmatrix}
96 /// ```
97 #[inline(always)]
98 #[rustfmt::skip]
99 fn rotate(&mut self, angle: &T) {
100 let cos = angle.cos();
101 let sin = angle.sin();
102 self.transform(&[
103 &cos, &sin, &T::zero(),
104 &sin.neg(), &cos, &T::zero(),
105 &T::zero(), &T::zero(), &T::one(),
106 ])
107 }
108 /// Transform by rotate with a point $\alpha$.
109 ///
110 /// # Matrix
111 ///
112 /// ```math
113 /// \begin{aligned}
114 /// x =& (x_0 - p_x)\cos α - (y_0 - p_y)\sin α + p_x \\
115 /// y =& (x_0 - p_x)\sin α + (y_0 - p_y)\cos α + p_y \\
116 /// \end{aligned}
117 /// ```
118 #[inline(always)]
119 fn rotate_point(&mut self, point: &[&T; 2], angle: &T) {
120 self.translate(&point[0].neg(), &point[1].neg());
121 self.rotate(angle);
122 self.translate(point[0], point[1])
123 }
124 /// Transform by scale $x, y$.
125 ///
126 /// # Matrix
127 ///
128 /// ```math
129 /// \begin{bmatrix}
130 /// x & 0 & 0 \\
131 /// 0 & y & 0 \\
132 /// 0 & 0 & 1 \\
133 /// \end{bmatrix}
134 /// ```
135 #[inline(always)]
136 #[rustfmt::skip]
137 fn scale(&mut self, x: &T, y: &T) {
138 self.transform(&[
139 x, &T::zero(), &T::zero(),
140 &T::zero(), y, &T::zero(),
141 &T::zero(), &T::zero(), &T::one(),
142 ])
143 }
144 /// Transform by scale $x$.
145 ///
146 /// # Matrix
147 ///
148 /// ```math
149 /// \begin{bmatrix}
150 /// x & 0 & 0 \\
151 /// 0 & 1 & 0 \\
152 /// 0 & 0 & 1 \\
153 /// \end{bmatrix}
154 /// ```
155 #[inline(always)]
156 fn scale_x(&mut self, x: &T) {
157 self.scale(x, &T::one())
158 }
159 /// Transform by scale $y$.
160 ///
161 /// # Matrix
162 ///
163 /// ```math
164 /// \begin{bmatrix}
165 /// 1 & 0 & 0 \\
166 /// 0 & y & 0 \\
167 /// 0 & 0 & 1 \\
168 /// \end{bmatrix}
169 /// ```
170 #[inline(always)]
171 fn scale_y(&mut self, y: &T) {
172 self.scale(&T::one(), y)
173 }
174 /// Transform by skew $x, y$.
175 #[inline(always)]
176 #[rustfmt::skip]
177 fn reflect(&mut self, x: &T, y: &T) {
178 self.transform(&[
179 &T::one(), &T::zero(), &T::zero(),
180 &T::zero(), &T::one(), &T::zero(),
181 x, y, &T::one(),
182 ])
183 }
184 /// Transform by skew $x$.
185 #[inline(always)]
186 fn reflect_x(&mut self) {
187 self.reflect(&T::zero(), &T::one())
188 }
189 /// Transform by skew $y$.
190
191 #[inline(always)]
192 fn reflect_y(&mut self) {
193 self.reflect(&T::one(), &T::zero())
194 }
195 /// Transform by angle $\alpha, \beta$.
196 ///
197 /// # Matrix
198 ///
199 /// ```math
200 /// \begin{bmatrix}
201 /// 1 & \tan\alpha & 0 \\
202 /// \tan\beta & 1 & 0 \\
203 /// 0 & 0 & 1 \\
204 /// \end{bmatrix}
205 /// ```
206 #[inline(always)]
207 #[rustfmt::skip]
208 fn skew(&mut self, a: &T, b: &T) {
209 self.transform(&[
210 &T::one(), &a.tan(), &T::zero(),
211 &b.tan(), &T::one(), &T::zero(),
212 &T::zero(), &T::zero(), &T::one(),
213 ])
214 }
215 /// Transform by angle $\alpha$.
216 ///
217 /// # Matrix
218 ///
219 /// ```math
220 /// \begin{bmatrix}
221 /// 1 & \tan\alpha & 0 \\
222 /// \tan\beta & 1 & 0 \\
223 /// 0 & 0 & 1 \\
224 /// \end{bmatrix}
225 /// ```
226 #[inline(always)]
227 fn skew_x(&mut self, a: &T) {
228 self.skew(a, &T::zero())
229 }
230 /// Transform by angle $\beta$.
231 ///
232 /// # Matrix
233 ///
234 /// ```math
235 /// \begin{vmatrix}
236 /// 1 & \tan\alpha & 0 \\
237 /// \tan\beta & 1 & 0 \\
238 /// 0 & 0 & 1 \\
239 /// \end{vmatrix}
240 /// ```
241 #[inline(always)]
242 fn skew_y(&mut self, b: &T) {
243 self.skew(&T::zero(), b)
244 }
245}