projective/traits/
dim2.rs

1use num_traits::real::Real;
2
3/// 2D projective transformations
4///
5/// ![](https://s2.ax1x.com/2019/05/29/VuEtUA.png)
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}