mutils/geom/
transform.rs

1use std::convert::From;
2use std::ops::Add;
3
4use num_traits::sign::Signed;
5
6use crate::geom::Line;
7use crate::geom::Point;
8use crate::geom::Size;
9use crate::num::Num;
10use crate::num::NumIdentity;
11
12#[derive(Copy, Clone, Debug, PartialEq)]
13pub struct Transform<N: Num = f32> {
14    scale: Size<N>,
15    position: Point<N>,
16    rotation: f32,
17}
18
19impl<N: Num> Transform<N> {
20    #[must_use]
21    pub fn new() -> Self {
22        Self {
23            position: Point::new_zero_value(),
24            scale: Size::new_one_value(),
25            rotation: 0.0,
26        }
27    }
28
29    #[must_use]
30    pub fn set_position(mut self, position: Point<N>) -> Self {
31        self.position = position;
32        self
33    }
34
35    pub fn position(&self) -> Point<N> {
36        self.position
37    }
38
39    #[must_use]
40    pub fn set_rotation(mut self, rotation: f32) -> Self {
41        self.rotation = rotation;
42        self
43    }
44
45    pub fn rotation(&self) -> f32 {
46        self.rotation
47    }
48
49    #[must_use]
50    fn set_scale_width(mut self, scale_width: N) -> Self {
51        self.scale.set_width(scale_width);
52        self
53    }
54
55    #[must_use]
56    fn set_scale_height(mut self, scale_height: N) -> Self {
57        self.scale.set_height(scale_height);
58        self
59    }
60
61    #[must_use]
62    pub fn set_scale(mut self, scale: Size<N>) -> Self {
63        self.scale = scale;
64        self
65    }
66
67    pub fn scale(self) -> Size<N> {
68        self.scale
69    }
70}
71
72impl<N> Transform<N>
73where
74    N: Num + Signed,
75{
76    pub fn set_flip_x_from_dir_num(self, dir: f32) -> Self {
77        self.set_flip_x_from_bool(dir < 0.0)
78    }
79
80    pub fn set_flip_y_from_dir_num(self, dir: f32) -> Self {
81        self.set_flip_y_from_bool(dir < 0.0)
82    }
83
84    pub fn set_flip_x_from_bool(self, is_flipped: bool) -> Self {
85        if is_flipped {
86            self.set_scale_width(-<N as NumIdentity>::one())
87        } else {
88            self.set_scale_width(<N as NumIdentity>::one())
89        }
90    }
91
92    pub fn set_flip_y_from_bool(self, is_flipped: bool) -> Self {
93        if is_flipped {
94            self.set_scale_height(-<N as NumIdentity>::one())
95        } else {
96            self.set_scale_height(<N as NumIdentity>::one())
97        }
98    }
99}
100
101impl<N> Add<Line<N>> for Transform<N>
102where
103    N: Num,
104{
105    type Output = Line<N>;
106
107    fn add(self, line: Self::Output) -> Self::Output {
108        line.rotate_around_zero(self.rotation()) * self.scale() + self.position()
109    }
110}
111
112impl<N> Add<Point<N>> for Transform<N>
113where
114    N: Num,
115{
116    type Output = Point<N>;
117
118    fn add(self, point: Self::Output) -> Self::Output {
119        point.rotate_around_zero(self.rotation()) * self.scale() + self.position()
120    }
121}
122
123impl<N> From<Point<N>> for Transform<N>
124where
125    N: Num,
126{
127    fn from(p: Point<N>) -> Self {
128        Self::new().set_position(p)
129    }
130}
131
132impl<N> From<Size<N>> for Transform<N>
133where
134    N: Num,
135{
136    fn from(s: Size<N>) -> Self {
137        Self::new().set_scale(s)
138    }
139}