1use {
2 super::num::{One, Zero},
3 std::ops::{Add, Div, Mul, Sub},
4};
5
6#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
7pub struct Point<T> {
8 pub x: T,
9 pub y: T,
10}
11
12impl<T> Point<T> {
13 pub const fn new(x: T, y: T) -> Self {
14 Self { x, y }
15 }
16
17 pub fn apply_transform(self, t: Transform<T>) -> Self
18 where
19 T: Add<Output = T> + Copy + Mul<Output = T>,
20 {
21 Self::new(
22 self.x * t.xx + self.y * t.yx + t.tx,
23 self.x * t.xy + self.y * t.yy + t.ty,
24 )
25 }
26}
27
28impl<T> Add<Size<T>> for Point<T>
29where
30 T: Add<Output = T>,
31{
32 type Output = Self;
33
34 fn add(self, size: Size<T>) -> Self::Output {
35 Self::new(self.x + size.width, self.y + size.height)
36 }
37}
38
39impl<T> Div<T> for Point<T>
40where
41 T: Div<Output = T> + Copy,
42{
43 type Output = Self;
44
45 fn div(self, scalar: T) -> Self::Output {
46 Self::new(self.x / scalar, self.y / scalar)
47 }
48}
49
50impl<T> Mul<T> for Point<T>
51where
52 T: Mul<Output = T> + Copy,
53{
54 type Output = Self;
55
56 fn mul(self, scalar: T) -> Self::Output {
57 Self::new(self.x * scalar, self.y * scalar)
58 }
59}
60
61impl<T> Sub for Point<T>
62where
63 T: Sub<Output = T>,
64{
65 type Output = Size<T>;
66
67 fn sub(self, other: Self) -> Self::Output {
68 Size::new(self.x - other.x, self.y - other.y)
69 }
70}
71
72impl<T> Sub<Size<T>> for Point<T>
73where
74 T: Sub<Output = T>,
75{
76 type Output = Self;
77
78 fn sub(self, size: Size<T>) -> Self::Output {
79 Self::new(self.x - size.width, self.y - size.height)
80 }
81}
82
83impl<T> From<Size<T>> for Point<T> {
84 fn from(size: Size<T>) -> Self {
85 Self::new(size.width, size.height)
86 }
87}
88
89impl<T> Zero for Point<T>
90where
91 T: Zero,
92{
93 const ZERO: Self = Self::new(T::ZERO, T::ZERO);
94}
95
96#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
97pub struct Size<T> {
98 pub width: T,
99 pub height: T,
100}
101
102impl<T> Size<T> {
103 pub const fn new(width: T, height: T) -> Self {
104 Self { width, height }
105 }
106
107 pub fn apply_transform(self, t: Transform<T>) -> Self
108 where
109 T: Add<Output = T> + Copy + Mul<Output = T>,
110 {
111 Self::new(
112 self.width * t.xx + self.height * t.yx,
113 self.width * t.xy + self.height * t.yy,
114 )
115 }
116}
117
118impl<T> Add for Size<T>
119where
120 T: Add<Output = T>,
121{
122 type Output = Self;
123
124 fn add(self, other: Self) -> Self::Output {
125 Self::new(self.width + other.width, self.height + other.height)
126 }
127}
128
129impl<T> From<T> for Size<T>
130where
131 T: Copy,
132{
133 fn from(scalar: T) -> Self {
134 Self::new(scalar, scalar)
135 }
136}
137
138impl<T> From<Point<T>> for Size<T> {
139 fn from(point: Point<T>) -> Self {
140 Self::new(point.x, point.y)
141 }
142}
143
144impl<T> Div<T> for Size<T>
145where
146 T: Div<Output = T> + Copy,
147{
148 type Output = Self;
149
150 fn div(self, scalar: T) -> Self::Output {
151 Self::new(self.width / scalar, self.height / scalar)
152 }
153}
154
155impl<T> Mul<T> for Size<T>
156where
157 T: Mul<Output = T> + Copy,
158{
159 type Output = Self;
160
161 fn mul(self, scalar: T) -> Self::Output {
162 Self::new(self.width * scalar, self.height * scalar)
163 }
164}
165
166impl<T> Sub for Size<T>
167where
168 T: Sub<Output = T>,
169{
170 type Output = Self;
171
172 fn sub(self, other: Self) -> Self::Output {
173 Self::new(self.width - other.width, self.height - other.height)
174 }
175}
176
177impl<T> Zero for Size<T>
178where
179 T: Zero,
180{
181 const ZERO: Self = Self::new(T::ZERO, T::ZERO);
182}
183
184#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
185pub struct Rect<T> {
186 pub origin: Point<T>,
187 pub size: Size<T>,
188}
189
190impl<T> Rect<T> {
191 pub const fn new(origin: Point<T>, size: Size<T>) -> Self {
192 Self { origin, size }
193 }
194
195 pub fn is_empty(self) -> bool
196 where
197 T: Eq + PartialEq + Zero,
198 {
199 self.size == Size::ZERO
200 }
201
202 pub fn contains_point(self, point: Point<T>) -> bool
203 where
204 T: Add<Output = T> + Copy + Ord,
205 {
206 if !(self.min().x..self.max().x).contains(&point.x) {
207 return false;
208 }
209 if !(self.min().y..self.max().y).contains(&point.y) {
210 return false;
211 }
212 true
213 }
214
215 pub fn contains_point_inclusive(self, point: Point<T>) -> bool
216 where
217 T: Add<Output = T> + Copy + Ord,
218 {
219 if !(self.min().x..=self.max().x).contains(&point.x) {
220 return false;
221 }
222 if !(self.min().y..=self.max().y).contains(&point.y) {
223 return false;
224 }
225 true
226 }
227
228 pub fn contains_rect(self, other: Self) -> bool
229 where
230 T: Add<Output = T> + Copy + Ord,
231 {
232 if !self.contains_point(other.min()) {
233 return false;
234 }
235 if !self.contains_point_inclusive(other.max()) {
236 return false;
237 }
238 true
239 }
240
241 pub fn min(self) -> Point<T>
242 where
243 T: Copy,
244 {
245 self.origin
246 }
247
248 pub fn max(self) -> Point<T>
249 where
250 T: Add<Output = T> + Copy,
251 {
252 self.origin + self.size
253 }
254
255 pub fn pad(self, padding: impl Into<Size<T>>) -> Self
256 where
257 T: Add<Output = T> + Copy + Sub<Output = T>,
258 {
259 self._pad(padding.into())
260 }
261
262 fn _pad(self, padding: Size<T>) -> Self
263 where
264 T: Add<Output = T> + Copy + Sub<Output = T>,
265 {
266 Self::new(self.origin - padding, self.size + padding + padding)
267 }
268
269 pub fn unpad(self, padding: impl Into<Size<T>>) -> Self
270 where
271 T: Add<Output = T> + Copy + Sub<Output = T>,
272 {
273 self._unpad(padding.into())
274 }
275
276 fn _unpad(self, padding: Size<T>) -> Self
277 where
278 T: Add<Output = T> + Copy + Sub<Output = T>,
279 {
280 Self::new(self.origin + padding, self.size - padding - padding)
281 }
282
283 pub fn apply_transform(self, t: Transform<T>) -> Self
284 where
285 T: Add<Output = T> + Copy + Mul<Output = T>,
286 {
287 Self::new(self.origin.apply_transform(t), self.size.apply_transform(t))
288 }
289
290 pub fn union(self, other: impl Into<Self>) -> Self
291 where
292 T: Add<Output = T> + Copy + Ord + Sub<Output = T>,
293 {
294 self._union(other.into())
295 }
296
297 fn _union(self, other: Self) -> Self
298 where
299 T: Add<Output = T> + Copy + Ord + Sub<Output = T>,
300 {
301 let min = Point::new(
302 self.min().x.min(other.min().x),
303 self.min().y.min(other.min().y),
304 );
305 let max = Point::new(
306 self.max().x.max(other.max().x),
307 self.max().y.max(other.max().y),
308 );
309 Self::new(min, max - min)
310 }
311}
312
313impl<T> From<Size<T>> for Rect<T>
314where
315 T: Default + Zero,
316{
317 fn from(size: Size<T>) -> Self {
318 Self::new(Point::ZERO, size)
319 }
320}
321
322impl<T> Zero for Rect<T>
323where
324 T: Zero,
325{
326 const ZERO: Self = Self::new(Point::ZERO, Size::ZERO);
327}
328
329#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
330pub struct Transform<T> {
331 pub xx: T,
332 pub xy: T,
333 pub yx: T,
334 pub yy: T,
335 pub tx: T,
336 pub ty: T,
337}
338
339impl<T> Transform<T> {
340 pub fn identity() -> Self
341 where
342 T: One + Zero,
343 {
344 Self {
345 xx: T::ONE,
346 xy: T::ZERO,
347 yx: T::ZERO,
348 yy: T::ONE,
349 tx: T::ZERO,
350 ty: T::ZERO,
351 }
352 }
353
354 pub fn from_scale(sx: T, sy: T) -> Self
355 where
356 T: Zero,
357 {
358 Self {
359 xx: sx,
360 xy: T::ZERO,
361 yx: T::ZERO,
362 yy: sy,
363 tx: T::ZERO,
364 ty: T::ZERO,
365 }
366 }
367
368 pub fn from_scale_uniform(s: T) -> Self
369 where
370 T: Copy + Zero,
371 {
372 Self::from_scale(s, s)
373 }
374
375 pub fn from_translate(tx: T, ty: T) -> Self
376 where
377 T: One + Zero,
378 {
379 Self {
380 xx: T::ONE,
381 xy: T::ZERO,
382 yx: T::ZERO,
383 yy: T::ONE,
384 tx,
385 ty,
386 }
387 }
388
389 pub fn translate(self, tx: T, ty: T) -> Self
390 where
391 T: Add<Output = T> + Copy,
392 {
393 Self {
394 tx: self.tx + tx,
395 ty: self.ty + ty,
396 ..self
397 }
398 }
399
400 pub fn scale(self, sx: T, sy: T) -> Self
401 where
402 T: Add<Output = T> + Copy + Mul<Output = T> + Zero,
403 {
404 Self {
405 xx: self.xx * sx,
406 xy: self.xy * sy,
407 yx: self.yx * sx,
408 yy: self.yy * sy,
409 tx: self.tx * sx,
410 ty: self.ty * sy,
411 }
412 }
413
414 pub fn scale_uniform(self, s: T) -> Self
415 where
416 T: Add<Output = T> + Copy + Mul<Output = T> + Zero,
417 {
418 self.scale(s, s)
419 }
420
421 pub fn concat(self, other: Self) -> Self
422 where
423 T: Add<Output = T> + Copy + Mul<Output = T>,
424 {
425 Self {
426 xx: self.xx * other.xx + self.xy * other.yx,
427 xy: self.xx * other.xy + self.xy * other.yy,
428 yx: self.yx * other.xx + self.yy * other.yx,
429 yy: self.yx * other.xy + self.yy * other.yy,
430 tx: self.tx * other.xx + self.ty * other.yx + other.tx,
431 ty: self.tx * other.xy + self.ty * other.yy + other.ty,
432 }
433 }
434}
435
436impl<T> Default for Transform<T>
437where
438 T: One + Zero,
439{
440 fn default() -> Self {
441 Self::identity()
442 }
443}