summaryrefslogtreecommitdiff
path: root/src/geom/transform.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-11-23 22:04:08 +0100
committerLaurenz <laurmaedje@gmail.com>2021-11-23 22:04:08 +0100
commit8a88f71cb11565c1a78bd57f02a8df17cb2bf7a0 (patch)
tree8802c1ff48e2be118e3872d25bd2f2c1f7a21b4a /src/geom/transform.rs
parentc77c5a0f0ae6560a03a85e847006c29de9c7ae62 (diff)
Transformations
Diffstat (limited to 'src/geom/transform.rs')
-rw-r--r--src/geom/transform.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/geom/transform.rs b/src/geom/transform.rs
new file mode 100644
index 00000000..ca44667b
--- /dev/null
+++ b/src/geom/transform.rs
@@ -0,0 +1,73 @@
+use super::*;
+
+/// A scale-skew-translate transformation.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
+pub struct Transform {
+ pub sx: Relative,
+ pub ky: Relative,
+ pub kx: Relative,
+ pub sy: Relative,
+ pub tx: Length,
+ pub ty: Length,
+}
+
+impl Transform {
+ /// The identity transformation.
+ pub const fn identity() -> Self {
+ Self {
+ sx: Relative::one(),
+ ky: Relative::zero(),
+ kx: Relative::zero(),
+ sy: Relative::one(),
+ tx: Length::zero(),
+ ty: Length::zero(),
+ }
+ }
+
+ /// A translation transform.
+ pub const fn translation(tx: Length, ty: Length) -> Self {
+ Self { tx, ty, ..Self::identity() }
+ }
+
+ /// A scaling transform.
+ pub const fn scaling(sx: Relative, sy: Relative) -> Self {
+ Self { sx, sy, ..Self::identity() }
+ }
+
+ /// A rotation transform.
+ pub fn rotation(angle: Angle) -> Self {
+ let v = angle.to_rad();
+ let cos = Relative::new(v.cos());
+ let sin = Relative::new(v.sin());
+ Self {
+ sx: cos,
+ ky: sin,
+ kx: -sin,
+ sy: cos,
+ ..Self::default()
+ }
+ }
+
+ /// Whether this is the identity transformation.
+ pub fn is_identity(&self) -> bool {
+ *self == Self::identity()
+ }
+
+ /// Pre-concatenate another transformation.
+ pub fn pre_concat(&self, prev: Self) -> Self {
+ Transform {
+ sx: self.sx * prev.sx + self.kx * prev.ky,
+ ky: self.ky * prev.sx + self.sy * prev.ky,
+ kx: self.sx * prev.kx + self.kx * prev.sy,
+ sy: self.ky * prev.kx + self.sy * prev.sy,
+ tx: self.sx.resolve(prev.tx) + self.kx.resolve(prev.ty) + self.tx,
+ ty: self.ky.resolve(prev.tx) + self.sy.resolve(prev.ty) + self.ty,
+ }
+ }
+}
+
+impl Default for Transform {
+ fn default() -> Self {
+ Self::identity()
+ }
+}