1use crate::geom::{quad, scalar, Align, Edge, Point2, Quad, Range, Scalar, Tri};
2use crate::glam::{DVec2, Vec2};
3use crate::math::{self, num_traits::Float};
4use core::ops::Neg;
5
6#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
8pub struct Rect<S = scalar::Default> {
9 pub x: Range<S>,
11 pub y: Range<S>,
13}
14
15#[derive(Copy, Clone, Debug, PartialEq)]
17pub struct Padding<S = scalar::Default> {
18 pub x: Range<S>,
20 pub y: Range<S>,
22}
23
24#[derive(Copy, Clone, Debug, PartialEq, Eq)]
26pub enum Corner {
27 TopLeft,
29 TopRight,
31 BottomLeft,
33 BottomRight,
35}
36
37#[derive(Clone)]
42pub struct Subdivisions<S = scalar::Default> {
43 ranges: SubdivisionRanges<S>,
44 subdivision_index: u8,
45}
46
47#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
49pub struct SubdivisionRanges<S = scalar::Default> {
50 pub x_a: Range<S>,
52 pub x_b: Range<S>,
54 pub y_a: Range<S>,
56 pub y_b: Range<S>,
58}
59
60#[derive(Clone, Debug)]
62pub struct Corners<S = scalar::Default> {
63 rect: Rect<S>,
64 index: u8,
65}
66
67pub type Triangles<S> = quad::Triangles<[S; 2]>;
69
70pub const NUM_SUBDIVISIONS: u8 = 4;
72
73pub const NUM_CORNERS: u8 = 4;
75
76pub const NUM_TRIANGLES: u8 = 2;
78
79impl<S> Padding<S>
80where
81 S: Scalar,
82{
83 pub fn none() -> Self {
85 Padding {
86 x: Range::new(S::zero(), S::zero()),
87 y: Range::new(S::zero(), S::zero()),
88 }
89 }
90}
91
92macro_rules! subdivision_from_index {
94 ($ranges:expr,0) => {
95 Rect {
96 x: $ranges.x_a,
97 y: $ranges.y_a,
98 }
99 };
100 ($ranges:expr,1) => {
101 Rect {
102 x: $ranges.x_b,
103 y: $ranges.y_a,
104 }
105 };
106 ($ranges:expr,2) => {
107 Rect {
108 x: $ranges.x_a,
109 y: $ranges.y_b,
110 }
111 };
112 ($ranges:expr,3) => {
113 Rect {
114 x: $ranges.x_b,
115 y: $ranges.y_b,
116 }
117 };
118}
119
120macro_rules! corner_from_index {
122 ($rect:expr,0) => {
123 [$rect.x.start, $rect.y.end]
124 };
125 ($rect:expr,1) => {
126 [$rect.x.end, $rect.y.end]
127 };
128 ($rect:expr,2) => {
129 [$rect.x.end, $rect.y.start]
130 };
131 ($rect:expr,3) => {
132 [$rect.x.start, $rect.y.start]
133 };
134}
135
136impl<S> Rect<S>
137where
138 S: Scalar + Float,
139{
140 pub fn from_x_y_w_h(x: S, y: S, w: S, h: S) -> Self {
142 Rect {
143 x: Range::from_pos_and_len(x, w),
144 y: Range::from_pos_and_len(y, h),
145 }
146 }
147
148 pub fn from_w_h(w: S, h: S) -> Self {
150 Self::from_x_y_w_h(S::zero(), S::zero(), w, h)
151 }
152
153 pub fn x(&self) -> S {
155 self.x.middle()
156 }
157
158 pub fn y(&self) -> S {
160 self.y.middle()
161 }
162
163 pub fn x_y(&self) -> (S, S) {
165 (self.x(), self.y())
166 }
167
168 pub fn x_y_w_h(&self) -> (S, S, S, S) {
170 let (x, y) = self.x_y();
171 let (w, h) = self.w_h();
172 (x, y, w, h)
173 }
174
175 pub fn align_x_of(self, align: Align, other: Self) -> Self {
177 Rect {
178 x: self.x.align_to(align, other.x),
179 y: self.y,
180 }
181 }
182
183 pub fn align_y_of(self, align: Align, other: Self) -> Self {
185 Rect {
186 x: self.x,
187 y: self.y.align_to(align, other.y),
188 }
189 }
190
191 pub fn align_middle_x_of(self, other: Self) -> Self {
193 Rect {
194 x: self.x.align_middle_of(other.x),
195 y: self.y,
196 }
197 }
198
199 pub fn align_middle_y_of(self, other: Self) -> Self {
201 Rect {
202 x: self.x,
203 y: self.y.align_middle_of(other.y),
204 }
205 }
206
207 pub fn mid_top_of(self, other: Self) -> Self {
209 self.align_middle_x_of(other).align_top_of(other)
210 }
211
212 pub fn mid_bottom_of(self, other: Self) -> Self {
214 self.align_middle_x_of(other).align_bottom_of(other)
215 }
216
217 pub fn mid_left_of(self, other: Self) -> Self {
219 self.align_left_of(other).align_middle_y_of(other)
220 }
221
222 pub fn mid_right_of(self, other: Self) -> Self {
224 self.align_right_of(other).align_middle_y_of(other)
225 }
226
227 pub fn middle_of(self, other: Self) -> Self {
229 self.align_middle_x_of(other).align_middle_y_of(other)
230 }
231
232 pub fn subdivision_ranges(&self) -> SubdivisionRanges<S> {
234 let (x, y) = self.x_y();
235 let x_a = Range::new(self.x.start, x);
236 let x_b = Range::new(x, self.x.end);
237 let y_a = Range::new(self.y.start, y);
238 let y_b = Range::new(y, self.y.end);
239 SubdivisionRanges { x_a, x_b, y_a, y_b }
240 }
241
242 pub fn subdivisions(&self) -> [Self; NUM_SUBDIVISIONS as usize] {
251 self.subdivision_ranges().rects()
252 }
253
254 pub fn subdivisions_iter(&self) -> Subdivisions<S> {
256 self.subdivision_ranges().rects_iter()
257 }
258}
259
260impl<S> Rect<S>
261where
262 S: Scalar,
263{
264 pub fn from_corner_points([ax, ay]: [S; 2], [bx, by]: [S; 2]) -> Self {
266 let (left, right) = if ax < bx { (ax, bx) } else { (bx, ax) };
267 let (bottom, top) = if ay < by { (ay, by) } else { (by, ay) };
268 Rect {
269 x: Range {
270 start: left,
271 end: right,
272 },
273 y: Range {
274 start: bottom,
275 end: top,
276 },
277 }
278 }
279
280 pub fn absolute(self) -> Self {
283 let x = self.x.absolute();
284 let y = self.y.absolute();
285 Rect { x, y }
286 }
287
288 pub fn overlap(self, other: Self) -> Option<Self> {
290 self.x
291 .overlap(other.x)
292 .and_then(|x| self.y.overlap(other.y).map(|y| Rect { x: x, y: y }))
293 }
294
295 pub fn max(self, other: Self) -> Self
297 where
298 S: Float,
299 {
300 Rect {
301 x: self.x.max(other.x),
302 y: self.y.max(other.y),
303 }
304 }
305
306 pub fn bottom(&self) -> S {
308 self.y.absolute().start
309 }
310
311 pub fn top(&self) -> S {
313 self.y.absolute().end
314 }
315
316 pub fn left(&self) -> S {
318 self.x.absolute().start
319 }
320
321 pub fn right(&self) -> S {
323 self.x.absolute().end
324 }
325
326 pub fn l_r_b_t(&self) -> (S, S, S, S) {
328 (self.left(), self.right(), self.bottom(), self.top())
329 }
330
331 pub fn shift_x(self, x: S) -> Self {
333 Rect {
334 x: self.x.shift(x),
335 ..self
336 }
337 }
338
339 pub fn shift_y(self, y: S) -> Self {
341 Rect {
342 y: self.y.shift(y),
343 ..self
344 }
345 }
346
347 pub fn left_of(self, other: Self) -> Self {
349 Rect {
350 x: self.x.align_before(other.x),
351 y: self.y,
352 }
353 }
354
355 pub fn right_of(self, other: Self) -> Self {
357 Rect {
358 x: self.x.align_after(other.x),
359 y: self.y,
360 }
361 }
362
363 pub fn below(self, other: Self) -> Self {
365 Rect {
366 x: self.x,
367 y: self.y.align_before(other.y),
368 }
369 }
370
371 pub fn above(self, other: Self) -> Self {
373 Rect {
374 x: self.x,
375 y: self.y.align_after(other.y),
376 }
377 }
378
379 pub fn align_left_of(self, other: Self) -> Self {
381 Rect {
382 x: self.x.align_start_of(other.x),
383 y: self.y,
384 }
385 }
386
387 pub fn align_right_of(self, other: Self) -> Self {
389 Rect {
390 x: self.x.align_end_of(other.x),
391 y: self.y,
392 }
393 }
394
395 pub fn align_bottom_of(self, other: Self) -> Self {
397 Rect {
398 x: self.x,
399 y: self.y.align_start_of(other.y),
400 }
401 }
402
403 pub fn align_top_of(self, other: Self) -> Self {
405 Rect {
406 x: self.x,
407 y: self.y.align_end_of(other.y),
408 }
409 }
410
411 pub fn top_left_of(self, other: Self) -> Self {
413 self.align_left_of(other).align_top_of(other)
414 }
415
416 pub fn top_right_of(self, other: Self) -> Self {
418 self.align_right_of(other).align_top_of(other)
419 }
420
421 pub fn bottom_left_of(self, other: Self) -> Self {
423 self.align_left_of(other).align_bottom_of(other)
424 }
425
426 pub fn bottom_right_of(self, other: Self) -> Self {
428 self.align_right_of(other).align_bottom_of(other)
429 }
430
431 pub fn contains_point(self, [x, y]: [S; 2]) -> bool {
433 self.x.contains(x) && self.y.contains(y)
434 }
435
436 pub fn stretch_to_point(self, [px, py]: [S; 2]) -> Self {
438 let Rect { x, y } = self;
439 Rect {
440 x: x.stretch_to_value(px),
441 y: y.stretch_to_value(py),
442 }
443 }
444
445 pub fn closest_corner(&self, [x, y]: [S; 2]) -> Corner {
447 let x_edge = self.x.closest_edge(x);
448 let y_edge = self.y.closest_edge(y);
449 match (x_edge, y_edge) {
450 (Edge::Start, Edge::Start) => Corner::BottomLeft,
451 (Edge::Start, Edge::End) => Corner::TopLeft,
452 (Edge::End, Edge::Start) => Corner::BottomRight,
453 (Edge::End, Edge::End) => Corner::TopRight,
454 }
455 }
456
457 pub fn corners(&self) -> Quad<[S; 2]> {
459 Quad::from([
460 corner_from_index!(self, 0),
461 corner_from_index!(self, 1),
462 corner_from_index!(self, 2),
463 corner_from_index!(self, 3),
464 ])
465 }
466
467 pub fn corners_iter(&self) -> Corners<S> {
469 let rect = *self;
470 let index = 0;
471 Corners { rect, index }
472 }
473
474 pub fn triangles(&self) -> (Tri<[S; 2]>, Tri<[S; 2]>) {
476 self.corners().triangles()
477 }
478
479 pub fn triangles_iter(self) -> Triangles<S> {
481 self.corners().triangles_iter()
482 }
483
484 pub fn corner_at_index(&self, index: u8) -> Option<[S; 2]> {
486 match index {
487 0 => Some(corner_from_index!(self, 0)),
488 1 => Some(corner_from_index!(self, 1)),
489 2 => Some(corner_from_index!(self, 2)),
490 3 => Some(corner_from_index!(self, 3)),
491 _ => None,
492 }
493 }
494}
495
496impl Rect<f32> {
497 pub fn from_xy_wh(p: Point2, s: Vec2) -> Self {
499 Self::from_x_y_w_h(p.x, p.y, s.x, s.y)
500 }
501
502 pub fn from_wh(s: Vec2) -> Self {
504 Self::from_w_h(s.x, s.y)
505 }
506
507 pub fn from_corners(a: Point2, b: Point2) -> Self {
509 Self::from_corner_points(a.into(), b.into())
510 }
511
512 pub fn xy(&self) -> Point2 {
514 [self.x(), self.y()].into()
515 }
516
517 pub fn wh(&self) -> Vec2 {
519 [self.w(), self.h()].into()
520 }
521
522 pub fn xy_wh(&self) -> (Point2, Vec2) {
524 (self.xy(), self.wh())
525 }
526
527 pub fn top_left(&self) -> Point2 {
529 [self.left(), self.top()].into()
530 }
531
532 pub fn bottom_left(&self) -> Point2 {
534 [self.left(), self.bottom()].into()
535 }
536
537 pub fn top_right(&self) -> Point2 {
539 [self.right(), self.top()].into()
540 }
541
542 pub fn bottom_right(&self) -> Point2 {
544 [self.right(), self.bottom()].into()
545 }
546
547 pub fn mid_left(&self) -> Point2 {
549 [self.left(), self.y()].into()
550 }
551
552 pub fn mid_top(&self) -> Point2 {
554 [self.x(), self.top()].into()
555 }
556
557 pub fn mid_right(&self) -> Point2 {
559 [self.right(), self.y()].into()
560 }
561
562 pub fn mid_bottom(&self) -> Point2 {
564 [self.x(), self.bottom()].into()
565 }
566
567 pub fn shift(self, v: Vec2) -> Self {
569 self.shift_x(v.x).shift_y(v.y)
570 }
571
572 pub fn contains(&self, p: Point2) -> bool {
574 self.contains_point(p.into())
575 }
576
577 pub fn stretch_to(self, p: Point2) -> Self {
579 self.stretch_to_point(p.into())
580 }
581}
582
583impl Rect<f64> {
584 pub fn from_xy_wh_f64(p: DVec2, s: DVec2) -> Self {
586 Self::from_x_y_w_h(p.x, p.y, s.x, s.y)
587 }
588
589 pub fn from_wh_f64(s: DVec2) -> Self {
591 Self::from_w_h(s.x, s.y)
592 }
593
594 pub fn from_corners_f64(a: DVec2, b: DVec2) -> Self {
596 Self::from_corner_points(a.into(), b.into())
597 }
598
599 pub fn xy(&self) -> DVec2 {
601 [self.x(), self.y()].into()
602 }
603
604 pub fn wh(&self) -> DVec2 {
606 [self.w(), self.h()].into()
607 }
608
609 pub fn xy_wh(&self) -> (DVec2, DVec2) {
611 (self.xy(), self.wh())
612 }
613
614 pub fn top_left(&self) -> DVec2 {
616 [self.left(), self.top()].into()
617 }
618
619 pub fn bottom_left(&self) -> DVec2 {
621 [self.left(), self.bottom()].into()
622 }
623
624 pub fn top_right(&self) -> DVec2 {
626 [self.right(), self.top()].into()
627 }
628
629 pub fn bottom_right(&self) -> DVec2 {
631 [self.right(), self.bottom()].into()
632 }
633
634 pub fn mid_left(&self) -> DVec2 {
636 [self.left(), self.y()].into()
637 }
638
639 pub fn mid_top(&self) -> DVec2 {
641 [self.x(), self.top()].into()
642 }
643
644 pub fn mid_right(&self) -> DVec2 {
646 [self.right(), self.y()].into()
647 }
648
649 pub fn mid_bottom(&self) -> DVec2 {
651 [self.x(), self.bottom()].into()
652 }
653
654 pub fn shift(self, v: DVec2) -> Self {
656 self.shift_x(v.x).shift_y(v.y)
657 }
658
659 pub fn contains(&self, p: DVec2) -> bool {
661 self.contains_point(p.into())
662 }
663
664 pub fn stretch_to(self, p: DVec2) -> Self {
666 self.stretch_to_point(p.into())
667 }
668}
669
670impl<S> SubdivisionRanges<S>
671where
672 S: Copy,
673{
674 pub fn rects(&self) -> [Rect<S>; NUM_SUBDIVISIONS as usize] {
683 let r1 = subdivision_from_index!(self, 0);
684 let r2 = subdivision_from_index!(self, 1);
685 let r3 = subdivision_from_index!(self, 2);
686 let r4 = subdivision_from_index!(self, 3);
687 [r1, r2, r3, r4]
688 }
689
690 pub fn rects_iter(self) -> Subdivisions<S> {
692 Subdivisions {
693 ranges: self,
694 subdivision_index: 0,
695 }
696 }
697
698 fn subdivision_at_index(&self, index: u8) -> Option<Rect<S>> {
700 let rect = match index {
701 0 => subdivision_from_index!(self, 0),
702 1 => subdivision_from_index!(self, 1),
703 2 => subdivision_from_index!(self, 2),
704 3 => subdivision_from_index!(self, 3),
705 _ => return None,
706 };
707 Some(rect)
708 }
709}
710
711impl<S> Rect<S>
712where
713 S: Scalar + Neg<Output = S>,
714{
715 pub fn w(&self) -> S {
717 self.x.len()
718 }
719
720 pub fn h(&self) -> S {
722 self.y.len()
723 }
724
725 pub fn w_h(&self) -> (S, S) {
727 (self.w(), self.h())
728 }
729
730 pub fn len(&self) -> S {
732 math::partial_max(self.w(), self.h())
733 }
734
735 pub fn l_t_w_h(&self) -> (S, S, S, S) {
737 let (w, h) = self.w_h();
738 (self.left(), self.top(), w, h)
739 }
740
741 pub fn l_b_w_h(&self) -> (S, S, S, S) {
743 let (w, h) = self.w_h();
744 (self.left(), self.bottom(), w, h)
745 }
746
747 pub fn pad_left(self, pad: S) -> Self {
749 Rect {
750 x: self.x.pad_start(pad),
751 ..self
752 }
753 }
754
755 pub fn pad_right(self, pad: S) -> Self {
757 Rect {
758 x: self.x.pad_end(pad),
759 ..self
760 }
761 }
762
763 pub fn pad_bottom(self, pad: S) -> Self {
765 Rect {
766 y: self.y.pad_start(pad),
767 ..self
768 }
769 }
770
771 pub fn pad_top(self, pad: S) -> Self {
773 Rect {
774 y: self.y.pad_end(pad),
775 ..self
776 }
777 }
778
779 pub fn pad(self, pad: S) -> Self {
781 let Rect { x, y } = self;
782 Rect {
783 x: x.pad(pad),
784 y: y.pad(pad),
785 }
786 }
787
788 pub fn padding(self, padding: Padding<S>) -> Self {
790 Rect {
791 x: self.x.pad_ends(padding.x.start, padding.x.end),
792 y: self.y.pad_ends(padding.y.start, padding.y.end),
793 }
794 }
795
796 pub fn relative_to_x(self, x: S) -> Self {
798 Rect {
799 x: self.x.shift(-x),
800 ..self
801 }
802 }
803
804 pub fn relative_to_y(self, y: S) -> Self {
806 Rect {
807 y: self.y.shift(-y),
808 ..self
809 }
810 }
811
812 pub fn relative_to(self, [x, y]: [S; 2]) -> Self {
814 self.relative_to_x(x).relative_to_y(y)
815 }
816
817 pub fn invert_x(self) -> Self {
819 Rect {
820 x: self.x.invert(),
821 ..self
822 }
823 }
824
825 pub fn invert_y(self) -> Self {
827 Rect {
828 y: self.y.invert(),
829 ..self
830 }
831 }
832}
833
834impl<S> Iterator for Subdivisions<S>
835where
836 S: Copy,
837{
838 type Item = Rect<S>;
839
840 fn next(&mut self) -> Option<Self::Item> {
841 if let Some(sd) = self.ranges.subdivision_at_index(self.subdivision_index) {
842 self.subdivision_index += 1;
843 return Some(sd);
844 }
845 None
846 }
847
848 fn size_hint(&self) -> (usize, Option<usize>) {
849 let len = self.len();
850 (len, Some(len))
851 }
852}
853
854impl<S> DoubleEndedIterator for Subdivisions<S>
855where
856 S: Copy,
857{
858 fn next_back(&mut self) -> Option<Self::Item> {
859 let next_index = self.subdivision_index + 1;
860 if let Some(sd) = self
861 .ranges
862 .subdivision_at_index(NUM_SUBDIVISIONS - next_index)
863 {
864 self.subdivision_index = next_index;
865 return Some(sd);
866 }
867 None
868 }
869}
870
871impl<S> ExactSizeIterator for Subdivisions<S>
872where
873 S: Copy,
874{
875 fn len(&self) -> usize {
876 NUM_SUBDIVISIONS as usize - self.subdivision_index as usize
877 }
878}
879
880impl<S> Iterator for Corners<S>
881where
882 S: Scalar,
883{
884 type Item = [S; 2];
885 fn next(&mut self) -> Option<Self::Item> {
886 if let Some(corner) = self.rect.corner_at_index(self.index) {
887 self.index += 1;
888 return Some(corner);
889 }
890 None
891 }
892
893 fn size_hint(&self) -> (usize, Option<usize>) {
894 let len = self.len();
895 (len, Some(len))
896 }
897}
898
899impl<S> DoubleEndedIterator for Corners<S>
900where
901 S: Scalar,
902{
903 fn next_back(&mut self) -> Option<Self::Item> {
904 let next_index = self.index + 1;
905 if let Some(corner) = self.rect.corner_at_index(NUM_CORNERS - next_index) {
906 self.index = next_index;
907 return Some(corner);
908 }
909 None
910 }
911}
912
913impl<S> ExactSizeIterator for Corners<S>
914where
915 S: Scalar,
916{
917 fn len(&self) -> usize {
918 (NUM_CORNERS - self.index) as usize
919 }
920}