kas_core/geom/
transform.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Affine transformation
7
8use super::DVec2;
9use core::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssign};
10
11/// Linear transformation: scaling and rotation
12///
13/// This represents scaling and rotation transformations (i.e. the linear
14/// mappings on [`DVec2`] in the mathematical sense, excluding skew).
15///
16/// A `Linear` transform `a` may be applied to a vector `v` via multiplication:
17/// `a * v`. Multiple transforms can be combined: `a * (b * v) == (a * b) * v`.
18///
19/// `Linear` transforms are a [ring algebra](https://en.wikipedia.org/wiki/Ring_(mathematics))
20/// with commutative operations. Both addition and multiplication operations are associative
21/// and commutative, e.g. `(a * b) * c == a * (b * c)` and `a * b == b * c`. The operators are also
22/// distributive: `a * (b + c) == a * b + a * c`.
23/// (Subject to the limitations of floating-point numbers.)
24#[derive(Clone, Copy, Debug, PartialEq)]
25pub struct Linear(DVec2);
26
27impl Linear {
28    /// The multiplicitive identity
29    pub const IDENTITY: Linear = Linear(DVec2(1.0, 0.0));
30
31    /// The additive identity
32    pub const ZERO: Linear = Linear(DVec2::ZERO);
33
34    /// Construct as a complex number
35    ///
36    /// The state is treated as a complex number of the form
37    /// `u + v*i = a * e^{i*t}` where `a` is the scale component and `t` is the
38    /// angle of rotation.
39    #[inline]
40    pub fn new(u: f64, v: f64) -> Self {
41        Linear(DVec2(u, v))
42    }
43
44    /// Construct a scaling transform
45    #[inline]
46    pub fn scale(scale: f64) -> Self {
47        Linear(DVec2(scale, 0.0))
48    }
49
50    /// Construct a rotating transform
51    ///
52    /// In case two vectors are available, it is preferable to use
53    /// `Linear::from_vectors(a, b).normalize()`.
54    ///
55    /// To also scale, use `Linear::rotate(radians) * scale`.
56    pub fn rotate(radians: f64) -> Self {
57        let (s, c) = radians.sin_cos();
58        Linear(DVec2(c, s))
59    }
60
61    /// Construct a scaling and rotation transform taking `a` to `b`
62    ///
63    /// This may be used to construct from two-finger touch motions. In this
64    /// case, `a = old.finger1 - old.finger2` and
65    /// `b = new.finger1 - new.finger2`.
66    #[inline]
67    pub fn from_vectors(a: DVec2, b: DVec2) -> Self {
68        Linear(b.complex_div(a))
69    }
70
71    /// Construct from two vectors with optional scaling and rotation
72    ///
73    /// This is a multiplexer over [`Self::from_vectors`] and other methods,
74    /// making scaling and rotation optional (though unless both are true,
75    /// the transform won't map `a` to `b`).
76    #[inline]
77    pub fn pan(a: DVec2, b: DVec2, (scale, rotate): (bool, bool)) -> Self {
78        match (scale, rotate) {
79            (false, false) => Self::IDENTITY,
80            (true, false) => Self::scale((b.sum_square() / a.sum_square()).sqrt()),
81            (false, true) => Linear::from_vectors(a, b).normalize(),
82            (true, true) => Linear::from_vectors(a, b),
83        }
84    }
85
86    /// Get the internal representation
87    ///
88    /// The state is treated as a complex number of the form
89    /// `u + v*i = a * e^{i*t}` where `a` is the scale component and `t` is the
90    /// angle of rotation. These components can be calculated as follows:
91    /// ```
92    /// # let alpha = kas_core::geom::Linear::IDENTITY;
93    /// let (u, v) = alpha.get_complex();
94    /// let a = (u*u + v*v).sqrt();
95    /// let t = v.atan2(a);
96    /// ```
97    ///
98    /// The matrix form of this transform is:
99    /// ```none
100    ///     u  -v
101    ///     v   u
102    /// ```
103    #[inline]
104    pub fn get_complex(self) -> (f64, f64) {
105        (self.0.0, self.0.1)
106    }
107
108    /// Get the internal representation as a [`DVec2`]
109    #[inline]
110    pub fn get_vec2(self) -> DVec2 {
111        self.0
112    }
113
114    /// Calculate the change in scale (non-trivial)
115    #[inline]
116    pub fn get_scale(self) -> f64 {
117        self.0.sum_square().sqrt()
118    }
119
120    /// Calculate the rotation angle (non-trivial)
121    #[inline]
122    pub fn get_angle(self) -> f64 {
123        self.0.1.atan2(self.0.0)
124    }
125
126    /// True if the transform scales its input
127    ///
128    /// This is a non-trivial operation.
129    #[inline]
130    pub fn has_scale(self) -> bool {
131        self.0.sum_square() != 1.0
132    }
133
134    /// True if the transform rotates its input
135    ///
136    /// This is a trivial operation.
137    #[inline]
138    pub fn has_rotation(self) -> bool {
139        self.0.1 != 0.0
140    }
141
142    /// True if all components are finite
143    #[inline]
144    pub fn is_finite(self) -> bool {
145        self.0.is_finite()
146    }
147
148    /// True if the transform has an inverse
149    ///
150    /// This test corresponds *approximately* but not exactly to `self.inverse().is_finite()`.
151    /// Further, `self.is_bijective()` *approximately* implies `self.inverse().is_bijective()`.
152    #[inline]
153    pub fn is_bijective(self) -> bool {
154        self.0.0.is_normal() && (self.0.1.is_normal() || self.0.1 == 0.0)
155    }
156
157    /// Remove the scaling component
158    #[inline]
159    pub fn normalize(self) -> Self {
160        Linear(self.0 / self.0.sum_square().sqrt())
161    }
162
163    /// Calculate the inverse
164    ///
165    /// This is the reciprical: `Self::IDENTITY / self`.
166    /// Due to the limitations of floating-point numbers, it is not guaranteed
167    /// that `self * self.inverse() == Self::IDENTITY` in general.
168    #[inline]
169    pub fn inverse(self) -> Self {
170        Linear(self.0.complex_inv())
171    }
172}
173
174impl Neg for Linear {
175    type Output = Self;
176
177    #[inline]
178    fn neg(self) -> Self {
179        Linear(-self.0)
180    }
181}
182
183impl Mul<f64> for Linear {
184    type Output = Linear;
185
186    #[inline]
187    fn mul(self, rhs: f64) -> Linear {
188        Linear(self.0 * rhs)
189    }
190}
191
192impl MulAssign<f64> for Linear {
193    #[inline]
194    fn mul_assign(&mut self, rhs: f64) {
195        self.0 *= rhs;
196    }
197}
198
199impl Div<f64> for Linear {
200    type Output = Linear;
201
202    #[inline]
203    fn div(self, rhs: f64) -> Linear {
204        Linear(self.0 / rhs)
205    }
206}
207
208impl DivAssign<f64> for Linear {
209    #[inline]
210    fn div_assign(&mut self, rhs: f64) {
211        self.0 /= rhs;
212    }
213}
214
215impl Add<Linear> for Linear {
216    type Output = Linear;
217
218    #[inline]
219    fn add(self, rhs: Linear) -> Linear {
220        Linear(self.0 + rhs.0)
221    }
222}
223
224impl AddAssign<Linear> for Linear {
225    #[inline]
226    fn add_assign(&mut self, rhs: Linear) {
227        self.0 += rhs.0;
228    }
229}
230
231impl Sub<Linear> for Linear {
232    type Output = Linear;
233
234    #[inline]
235    fn sub(self, rhs: Linear) -> Linear {
236        Linear(self.0 - rhs.0)
237    }
238}
239
240impl SubAssign<Linear> for Linear {
241    #[inline]
242    fn sub_assign(&mut self, rhs: Linear) {
243        self.0 -= rhs.0;
244    }
245}
246
247impl Mul<Linear> for Linear {
248    type Output = Linear;
249
250    #[inline]
251    fn mul(self, rhs: Linear) -> Linear {
252        Linear(self.0.complex_mul(rhs.0))
253    }
254}
255
256impl MulAssign<Linear> for Linear {
257    #[inline]
258    fn mul_assign(&mut self, rhs: Linear) {
259        *self = *self * rhs;
260    }
261}
262
263impl Div<Linear> for Linear {
264    type Output = Linear;
265
266    #[inline]
267    fn div(self, rhs: Linear) -> Linear {
268        Linear(self.0.complex_div(rhs.0))
269    }
270}
271
272impl DivAssign<Linear> for Linear {
273    #[inline]
274    fn div_assign(&mut self, rhs: Linear) {
275        self.0 = self.0.complex_div(rhs.0);
276    }
277}
278
279impl Mul<DVec2> for Linear {
280    type Output = DVec2;
281
282    #[inline]
283    fn mul(self, rhs: DVec2) -> DVec2 {
284        self.0.complex_mul(rhs)
285    }
286}
287
288/// Affine transformations: move/scale/rotate
289///
290/// Note that the current representation is limited to transformations which
291/// preserve the angle: it cannot represent reflection or shear transformations.
292///
293/// An `Affine` transform `a` may be applied to a [`DVec2`] coordinate `v` via
294/// multiplication: `a * v`. This is equivalent to `a.alpha() * v + a.delta()`.
295/// Two transforms `a`, `b` may be combined via multiplication: `a * b`. Note
296/// that this is associative but not commutative:
297/// `b * (a * v) == (b * a) * v` but `a * b != b * a` in general.
298#[derive(Clone, Copy, Debug, PartialEq)]
299pub struct Affine {
300    /// Rotation and scale component
301    alpha: Linear,
302    /// Translation component
303    delta: DVec2,
304}
305
306impl Affine {
307    /// The identity transform
308    pub const IDENTITY: Affine = Affine {
309        alpha: Linear::IDENTITY,
310        delta: DVec2::ZERO,
311    };
312
313    /// Construct from components
314    #[inline]
315    pub fn new(alpha: Linear, delta: DVec2) -> Self {
316        Affine { alpha, delta }
317    }
318
319    /// Construct a translation transform
320    #[inline]
321    pub fn translate(delta: DVec2) -> Self {
322        Affine {
323            alpha: Linear::IDENTITY,
324            delta,
325        }
326    }
327
328    /// Construct a scaling and rotation transform taking `x0` to `x1` and `y0` to `y1`
329    ///
330    /// This may be used to construct from two-finger touch motions. In this
331    /// case, `x0 = old.finger1`, `x1 = new.finger1`, `y0 = old.finger2` and
332    /// `y1 = new.finger2`.
333    pub fn from_vectors(x0: DVec2, x1: DVec2, y0: DVec2, y1: DVec2) -> Self {
334        let alpha = Linear::from_vectors(x1 - x0, y1 - y0);
335        // Average delta from both movements:
336        let delta = (x1 - alpha * x0 + y1 - alpha * y0) * 0.5;
337        Affine { alpha, delta }
338    }
339
340    /// Construct from two vectors with optional scaling and rotation
341    ///
342    /// This is a multiplexer over [`Self::from_vectors`] and other methods,
343    /// making scaling and rotation optional (though unless both are true,
344    /// the transform won't map `x0` to `x1` and `y0` to `y1`).
345    pub fn pan(x0: DVec2, x1: DVec2, y0: DVec2, y1: DVec2, (scale, rotate): (bool, bool)) -> Self {
346        let alpha = Linear::pan(y0 - x0, y1 - x1, (scale, rotate));
347        // Average delta from both movements:
348        let delta = (x1 - alpha * x0 + y1 - alpha * y0) * 0.5;
349        Affine { alpha, delta }
350    }
351
352    /// Get component `alpha`
353    ///
354    /// This represents scaling and rotation transformations.
355    #[inline]
356    pub fn alpha(self) -> Linear {
357        self.alpha
358    }
359
360    /// Get component `delta`
361    ///
362    /// This is the translation, applied after rotation and scaling.
363    #[inline]
364    pub fn delta(self) -> DVec2 {
365        self.delta
366    }
367
368    /// True if the transform translates its input
369    #[inline]
370    pub fn has_translation(self) -> bool {
371        self.delta != DVec2::ZERO
372    }
373
374    /// Get as `delta` if `self` represents a pure translation
375    #[inline]
376    pub fn as_translation(self) -> Option<DVec2> {
377        if self.alpha == Linear::IDENTITY {
378            Some(self.delta)
379        } else {
380            None
381        }
382    }
383
384    /// Get as `(scale, delta)` if `self` represents a scaling and translation
385    #[inline]
386    pub fn as_scale_and_translation(self) -> Option<(f64, DVec2)> {
387        if self.alpha.0.1 == 0.0 {
388            Some((self.alpha.0.0, self.delta))
389        } else {
390            None
391        }
392    }
393
394    /// True if all components are finite
395    #[inline]
396    pub fn is_finite(self) -> bool {
397        self.alpha.is_finite() && self.delta.is_finite()
398    }
399
400    /// Calculate the inverse transform
401    ///
402    /// If `self` has scale zero (i.e. maps everything to a point) then the
403    /// result will not be finite.
404    pub fn inverse(self) -> Self {
405        let alpha = self.alpha.inverse();
406        let delta = -alpha * self.delta;
407        Affine { alpha, delta }
408    }
409}
410
411impl From<Linear> for Affine {
412    #[inline]
413    fn from(alpha: Linear) -> Self {
414        Affine {
415            alpha,
416            delta: DVec2::ZERO,
417        }
418    }
419}
420
421impl Mul<DVec2> for Affine {
422    type Output = DVec2;
423
424    #[inline]
425    fn mul(self, rhs: DVec2) -> DVec2 {
426        self.alpha * rhs + self.delta
427    }
428}
429
430impl Mul<Linear> for Affine {
431    type Output = Affine;
432
433    #[inline]
434    fn mul(mut self, rhs: Linear) -> Affine {
435        self.alpha *= rhs;
436        self
437    }
438}
439
440impl MulAssign<Linear> for Affine {
441    #[inline]
442    fn mul_assign(&mut self, rhs: Linear) {
443        self.alpha *= rhs;
444    }
445}
446
447impl Mul<Affine> for Linear {
448    type Output = Affine;
449
450    fn mul(self, rhs: Affine) -> Affine {
451        let alpha = self * rhs.alpha;
452        let delta = self * rhs.delta;
453        Affine { alpha, delta }
454    }
455}
456
457impl Mul<Affine> for Affine {
458    type Output = Affine;
459
460    fn mul(self, rhs: Affine) -> Affine {
461        let alpha = self.alpha * rhs.alpha;
462        let delta = self.alpha * rhs.delta + self.delta;
463        Affine { alpha, delta }
464    }
465}
466
467impl Div<Linear> for Affine {
468    type Output = Affine;
469
470    #[inline]
471    fn div(mut self, rhs: Linear) -> Affine {
472        self.alpha /= rhs;
473        self
474    }
475}
476
477impl DivAssign<Linear> for Affine {
478    #[inline]
479    fn div_assign(&mut self, rhs: Linear) {
480        self.alpha /= rhs;
481    }
482}
483
484impl Div<Affine> for Linear {
485    type Output = Affine;
486
487    fn div(self, rhs: Affine) -> Affine {
488        let alpha = self / rhs.alpha;
489        let delta = -alpha * rhs.delta;
490        Affine { alpha, delta }
491    }
492}
493
494impl Div<Affine> for Affine {
495    type Output = Affine;
496
497    fn div(self, rhs: Affine) -> Affine {
498        let alpha = self.alpha / rhs.alpha;
499        let delta = self.delta - alpha * rhs.delta;
500        Affine { alpha, delta }
501    }
502}
503
504impl Add<DVec2> for Affine {
505    type Output = Affine;
506
507    #[inline]
508    fn add(mut self, rhs: DVec2) -> Affine {
509        self.delta += rhs;
510        self
511    }
512}
513
514impl AddAssign<DVec2> for Affine {
515    #[inline]
516    fn add_assign(&mut self, rhs: DVec2) {
517        self.delta += rhs;
518    }
519}
520
521impl Sub<DVec2> for Affine {
522    type Output = Affine;
523
524    #[inline]
525    fn sub(mut self, rhs: DVec2) -> Affine {
526        self.delta -= rhs;
527        self
528    }
529}
530
531impl SubAssign<DVec2> for Affine {
532    #[inline]
533    fn sub_assign(&mut self, rhs: DVec2) {
534        self.delta -= rhs;
535    }
536}