1use super::*;
2
3
4pub type Rectangle<T, const N : usize> = RectangleOf<Vector<T, N>>;
5
6#[repr(C)]
9pub struct RectangleOf<T>
10{
11 pub pos : T,
12 pub size : T,
13}
14impl_fixed_array!(RectangleOf, 2);
15
16impl<T> Default for RectangleOf<T> where T: Number
17{
18 fn default() -> Self { Self::SIZED_ONE }
19}
20
21impl<T> RectangleOf<T> where T: Number
22{
23 pub const SIZED_ONE : Self = Self::new_sized(T::ONE);
24}
25
26impl<T> From<(T,T)> for RectangleOf<T>
27{
28 fn from(value: (T,T)) -> Self {
29 Self::new(value.0, value.1)
30 }
31}
32
33impl<T> From<RectangleOf<T>> for (T,T)
34{
35 fn from(value: RectangleOf<T>) -> Self {
36 (value.pos, value.size)
37 }
38}
39
40impl<T> Rectangle<T,2> where T: Number
42{
43 pub fn down_left (&self) -> Vector<T,2> { self.pos }
44 pub fn down_right(&self) -> Vector<T,2> where T: One + Mul<T,Output = T> + Add<T, Output=T> { self.pos + self.size * Vector::<T,2>::X }
45
46 pub fn bottom_left (&self) -> Vector<T,2> { self.down_left() }
48 pub fn bottom_right(&self) -> Vector<T,2> where T: One + Mul<T,Output = T> + Add<T, Output=T> { self.down_right() }
50
51 pub fn up_right (&self) -> Vector<T,2> where T: Add<T, Output=T> { self.pos + self.size }
52 pub fn up_left (&self) -> Vector<T,2> where T: One, T : Mul<T,Output = T> + Add<T, Output=T> { self.pos + self.size * Vector::<T,2>::Y }
53
54 pub fn top_right (&self) -> Vector<T,2> where T: Add<T, Output=T> { self.up_right() }
56 pub fn top_left (&self) -> Vector<T,2> where T: One, T : Mul<T,Output = T> + Add<T, Output=T> { self.up_left() }
58}
59
60impl<T,const N : usize> Rectangle<T,N> where Vector<T,N> : Number, T : Number
61{
62 pub fn new_centered(pos_middle : Vector<T,N>, size : Vector<T,N>) -> Self { Self::new(pos_middle-size/ (Vector::<T,N>::two()), size) }
63 pub fn new_with_center(bottom_left : Vector<T,N>, size : Vector<T,N>, center_coef : Vector<T,N>) -> Self { Self::new(bottom_left - center_coef * size, size) }
64
65 pub fn get_coef(&self, coef : Vector<T,N>) -> Vector<T,N> where Vector<T,N> : Arithmetic { self.pos + self.size * coef }
66
67 pub fn middle (&self) -> Vector<T,N> { self.pos + self.size.take_half() }
69 pub fn center (&self) -> Vector<T,N> { self.pos + self.size.take_half() }
70
71 pub fn middle_right(&self) -> Vector<T,N> where Vector<T,N> : HaveX<T> { self.middle().with_x(self.right_value()) }
72 pub fn middle_left (&self) -> Vector<T,N> where Vector<T,N> : HaveX<T> { self.middle().with_x(self.left_value ()) }
73
74 pub fn middle_up (&self) -> Vector<T,N> where Vector<T,N> : HaveY<T> { self.middle().with_y(self.up_value ()) }
75 pub fn middle_down (&self) -> Vector<T,N> where Vector<T,N> : HaveY<T> { self.middle().with_y(self.down_value()) }
76
77 pub fn middle_forward (&self) -> Vector<T,N> where Vector<T,N> : HaveZ<T> { self.middle().with_z(self.forward_value ()) }
78 pub fn middle_backward (&self) -> Vector<T,N> where Vector<T,N> : HaveZ<T> { self.middle().with_z(self.backward_value()) }
79
80 pub fn middle_ana (&self) -> Vector<T,N> where Vector<T,N> : HaveW<T> { self.middle().with_w(self.ana_value ()) }
81 pub fn middle_kata (&self) -> Vector<T,N> where Vector<T,N> : HaveW<T> { self.middle().with_w(self.kata_value()) }
82
83 pub fn right_value (&self) -> T where Vector<T,N> : HaveX<T> { self.pos.x() + self.size.x() }
84 pub fn left_value (&self) -> T where Vector<T,N> : HaveX<T> { self.pos.x() }
85
86 pub fn up_value (&self) -> T where Vector<T,N> : HaveY<T> { self.pos.y() + self.size.y() }
87 pub fn down_value (&self) -> T where Vector<T,N> : HaveY<T> { self.pos.y() }
88
89 pub fn top_value (&self) -> T where Vector<T,N> : HaveY<T> { self.up_value() }
91 pub fn bottom_value (&self) -> T where Vector<T,N> : HaveY<T> { self.down_value() }
93
94 pub fn forward_value (&self) -> T where Vector<T,N> : HaveZ<T> { self.pos.z() + self.size.z() }
95 pub fn backward_value(&self) -> T where Vector<T,N> : HaveZ<T> { self.pos.z() }
96
97 pub fn ana_value (&self) -> T where Vector<T,N> : HaveW<T> { self.pos.w() + self.size.w() }
98 pub fn kata_value(&self) -> T where Vector<T,N> : HaveW<T> { self.pos.w() }
99
100
101
102
103}
104
105impl<T,const N : usize> SetRectangle<T,N> for Rectangle<T,N> where T: Number
106{
107 fn set_size(&mut self, size : Vector<T, N>) -> &mut Self { self.size = size; self }
108 fn set_size_x(&mut self, x : T) -> &mut Self where Vector<T, N> : HaveX<T> { self.size.set_x(x); self }
109 fn set_size_y(&mut self, y : T) -> &mut Self where Vector<T, N> : HaveY<T> { self.size.set_y(y); self }
110 fn set_size_z(&mut self, z : T) -> &mut Self where Vector<T, N> : HaveZ<T> { self.size.set_z(z); self }
111 fn set_size_w(&mut self, w : T) -> &mut Self where Vector<T, N> : HaveW<T> { self.size.set_w(w); self }
112
113 fn with_size(mut self, size : Vector<T, N>) -> Self { self.size = size; self }
114 fn with_size_x(mut self, x : T) -> Self where Vector<T, N> : HaveX<T> { self.size.set_x(x); self }
115 fn with_size_y(mut self, y : T) -> Self where Vector<T, N> : HaveY<T> { self.size.set_y(y); self }
116 fn with_size_z(mut self, z : T) -> Self where Vector<T, N> : HaveZ<T> { self.size.set_z(z); self }
117 fn with_size_w(mut self, w : T) -> Self where Vector<T, N> : HaveW<T> { self.size.set_w(w); self }
118}
119
120impl<T,const N : usize> Rectangle<T,N> where T: Primitive
130{
131 pub fn split_axis(&self, nb:T, axis: usize) -> impl Iterator<Item = Self>
132 {
133 let begin = self.pos[axis];
134 let end = begin + self.size[axis];
135 let step = self.size[axis] / nb;
136
137 let cuts = (begin..=end).step(step);
138
139 cuts
140 .clone()
141 .zip(cuts.skip(1))
142 .map(move |(x0, x1)| {
143 let mut r = self.clone();
144 r.pos[axis] = x0;
145 r.size[axis] = x1 - x0;
146 r
147 })
148 }
149
150 pub fn split_x(&self, nb:T) -> impl Iterator<Item = Self> where Vector<T,N>:HaveX<T>
151 { self.split_axis(nb, Vector::<T,N>::X_INDEX) }
152 pub fn split_y(&self, nb:T) -> impl Iterator<Item = Self> where Vector<T,N>:HaveY<T>
153 { self.split_axis(nb, Vector::<T,N>::Y_INDEX) }
154 pub fn split_z(&self, nb:T) -> impl Iterator<Item = Self> where Vector<T,N>:HaveZ<T>
155 { self.split_axis(nb, Vector::<T,N>::Z_INDEX) }
156 pub fn split_w(&self, nb:T) -> impl Iterator<Item = Self> where Vector<T,N>:HaveW<T>
157 { self.split_axis(nb, Vector::<T,N>::W_INDEX) }
158
159 pub fn split_min(&self, nb:T) -> impl Iterator<Item = Self> { self.split_axis(nb, self.size.min_element_idx()) }
160 pub fn split_max(&self, nb:T) -> impl Iterator<Item = Self> { self.split_axis(nb, self.size.max_element_idx()) }
161}
162
163impl<T,const N : usize> Rectangle<T,N> where T: Number
164{
165 pub fn is_inside(&self, point : Vector<T, N>) -> bool
191 {
192 self.bounds_min().all_with(&point, |axis, other_axis| other_axis >= axis) &&
193 self.bounds_max().all_with(&point, |axis, other_axis| other_axis < axis)
194 }
195
196 pub fn is_inside_inclusif(&self, point : Vector<T, N>) -> bool
199 {
200 self.bounds_min().all_with(&point, |axis, other_axis| other_axis >= axis) &&
201 self.bounds_max().all_with(&point, |axis, other_axis| other_axis <= axis)
202 }
203
204 pub fn is_rect_inside(&self, rect: Rectangle<T, N>) -> bool
205 {
206 self.is_inside(rect.bounds_min()) && self.is_inside_inclusif(rect.bounds_max())
207 }
208
209 pub fn is_empty(&self) -> bool { self.size.is_zero() }
210
211 pub fn clamp_vector(&self, vector : Vector<T, N>) -> Vector<T, N> where Vector<T, N>: Clamp { vector.clamp(self.bounds_min(), self.bounds_max())}
212
213 pub fn intersect_or_empty(self, other : Self) -> Self where Vector<T, N>: Max + Min
214 {
215 Self::from_pos_to_pos(self.bounds_min().max(other.pos), self.bounds_max().min(other.bounds_max()))
216 }
217 pub fn intersect(self, other : Self) -> Option<Self> where Vector<T, N>: Max + Min
219 {
220 let intersect = self.intersect_or_empty(other);
221 if intersect.size.is_zero()
222 {
223 Some(intersect)
224 }
225 else
226 {
227 None
228 }
229 }
230}
231
232impl<T> RectangleOf<T>
233{
234 pub const fn new(pos: T, size: T) -> Self { Self { pos, size } }
236 pub const fn new_sized(size : T) -> Self where T: Zero { Self::new(zero(), size) }
238}
239
240pub trait Crop<T, const N : usize> : GetRectangle<T, N> + Sized where T: Number
242{
243 fn crop(self, subrect : Rectangle<T, N>) -> Option<Self>;
247
248 unsafe fn crop_unchecked(self, subrect : Rectangle<T, N>) -> Self { self.crop(subrect).expect("invalid subrect") }
252
253 #[track_caller]
257 fn crop_or_panic(self, subrect : Rectangle<T, N>) -> Self { self.crop(subrect).expect("invalid subrect") }
258
259
260 fn crop_intersect(self, subrect : Rectangle<T, N>) -> Self
265 {
266 let rect = self.rect().intersect_or_empty(subrect);
267 unsafe { self.crop_unchecked(rect) }
268 }
269
270 fn crop_margin(self, margin_start : Vector<T,N>, margin_end : Vector<T,N>) -> Option<Self>
271 {
272 if margin_start.any(|a| a < &zero()) || margin_end.any(|a| a < &zero()) { return None; }
273
274 let mut subrect = self.rect();
275
276 let removed_size = margin_start + margin_end;
277 if removed_size.any_with(&subrect.size(), |a,b| a > b) { return None; }
278
279 subrect.pos += margin_start;
280 subrect.size -= removed_size;
281
282 Some(self.crop_or_panic(subrect))
283 }
284
285 unsafe fn crop_margin_unchecked(self, margin_start : Vector<T,N>, margin_end : Vector<T,N>) -> Self
286 {
287 let mut subrect = self.rect();
288 subrect.pos += margin_start;
289 subrect.size -= margin_start + margin_end;
290 unsafe { self.crop_unchecked(subrect) }
291 }
292
293 fn crop_margin_intersect(self, margin_start : Vector<T,N>, margin_end : Vector<T,N>) -> Self
297 {
298 let size = self.size() - margin_start - margin_end;
299 self.crop_intersect(Rectangle::new(margin_start, size))
300 }
301}
302
303impl<T,const N : usize> Crop<T,N> for Rectangle<T,N> where T: Number
304{
305 fn crop(self, mut subrect : Rectangle<T, N>) -> Option<Self>
309 {
310 subrect.move_by(self.pos);
311 if self.is_rect_inside(subrect) { Some(subrect) } else { None }
312 }
313 unsafe fn crop_unchecked(self, subrect : Rectangle<T, N>) -> Self { subrect.moved_by(self.pos) }
314
315 fn crop_intersect(self, subrect : Rectangle<T, N>) -> Self { self.intersect_or_empty(subrect.moved_by(self.pos)) }
316 unsafe fn crop_margin_unchecked(self, margin_start : Vector<T,N>, margin_end : Vector<T,N>) -> Self { Self::new(self.pos + margin_start, self.size - margin_start - margin_end) }
317}
318
319#[cfg(test)]
320mod rect_crop_test
321{
322 use crate::prelude::*;
323
324 #[test]
325 fn crop_margin_unchecked()
326 {
327 unsafe
328 {
329 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(2.splat2(), 2.splat2()), rect2i(7,7,6,6));
330 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(-1.splat2(), zero()), rect2i(4,4,11,11));
331 }
332 }
333
334 #[test]
335 fn crop_margin_intersect()
336 {
337 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(2.splat2(), 2.splat2()), rect2i(7,7,6,6));
338 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(-1.splat2(), zero()), rect2i(5,5,10,10));
339 }
340}
341
342
343impl<T,const N : usize> Rectangle<T,N> where T: Number
344{
345 pub fn from_pos_to_pos(start_pos : Vector<T,N>, end_pos : Vector<T,N>) -> Self { Self::new(start_pos, (end_pos - start_pos).map_with(zero(), |a,b| a.max_partial(b))) }
346}
347
348impl<T, const N : usize> GetPosition<T, N> for Rectangle<T, N> where T: Number
349{
350 #[inline(always)]
351 fn pos(&self) -> Vector<T,N> { self.pos }
352}
353impl<T, const N : usize> SetPosition<T, N> for Rectangle<T, N> where T: Number
354{
355 #[inline(always)]
356 fn set_pos(&mut self, pos : Vector<T,N>) -> &mut Self {
357 self.pos = pos;
358 self
359 }
360}
361impl<T, const N : usize> GetRectangle<T, N> for Rectangle<T, N> where T: Number
362{
363 #[inline(always)]
364 fn size(&self) -> Vector<T,N> { self.size }
365}
366
367
368pub trait GetRectangle<T, const N : usize> : GetPosition<T,N> where T: Number
369{
370 fn size(&self) -> Vector<T,N>;
371
372 #[inline(always)] fn size_x(&self) -> T where Vector<T,N> : HaveX<T> { self.size().x() }
373 #[inline(always)] fn size_y(&self) -> T where Vector<T,N> : HaveY<T> { self.size().y() }
374 #[inline(always)] fn size_z(&self) -> T where Vector<T,N> : HaveZ<T> { self.size().z() }
375 #[inline(always)] fn size_w(&self) -> T where Vector<T,N> : HaveW<T> { self.size().w() }
376
377 #[inline(always)]
379 fn width (&self) -> T where Vector<T,N> : HaveX<T> { self.size_x() }
380 #[inline(always)]
382 fn height(&self) -> T where Vector<T,N> : HaveY<T> { self.size_y() }
383 #[inline(always)]
385 fn depth (&self) -> T where Vector<T,N> : HaveZ<T> { self.size_z() }
386
387 #[inline(always)]
388 fn area(&self) -> T { self.size().area() }
389 #[inline(always)]
390 fn area_usize(&self) -> usize where T: Integer { self.size().area_usize() }
391
392 #[inline(always)]
393 fn is_inside(&self, pos : Vector<T,N>) -> bool { pos.is_inside(self.size()) }
394 #[inline(always)]
395 fn is_outside(&self, pos : Vector<T,N>) -> bool { !self.is_inside(pos) }
396
397 #[inline(always)]
398 fn begin(&self) -> Vector<T,N> { self.pos()}
399 #[inline(always)]
400 fn end(&self) -> Vector<T,N> { self.pos() + self.size() }
401
402 #[inline(always)]
404 fn bounds_min(&self) -> Vector<T,N> { self.begin() }
405 #[inline(always)]
407 fn bounds_max(&self) -> Vector<T,N> { self.end() }
408
409 #[inline(always)]
410 fn rect(&self) -> Rectangle<T, N> { Rectangle::new(self.begin(), self.size()) }
411
412 fn iter_x(&self) -> Range<T> where Vector<T,N> : HaveX<T>, Range<T> : IntoIterator { self.bounds_min().x()..self.bounds_max().x() }
413 fn iter_y(&self) -> Range<T> where Vector<T,N> : HaveY<T>, Range<T> : IntoIterator { self.bounds_min().y()..self.bounds_max().y() }
414 fn iter_z(&self) -> Range<T> where Vector<T,N> : HaveZ<T>, Range<T> : IntoIterator { self.bounds_min().z()..self.bounds_max().z() }
415 fn iter_w(&self) -> Range<T> where Vector<T,N> : HaveW<T>, Range<T> : IntoIterator { self.bounds_min().w()..self.bounds_max().w() }
416
417 #[inline(always)] fn is_inside_x(&self, x : T) -> bool where Vector<T,N> : HaveX<T> { x >= self.bounds_min().x() && x < self.bounds_max().x() }
418 #[inline(always)] fn is_inside_y(&self, y : T) -> bool where Vector<T,N> : HaveY<T> { y >= self.bounds_min().y() && y < self.bounds_max().y() }
419 #[inline(always)] fn is_inside_z(&self, z : T) -> bool where Vector<T,N> : HaveZ<T> { z >= self.bounds_min().z() && z < self.bounds_max().z() }
420 #[inline(always)] fn is_inside_w(&self, w : T) -> bool where Vector<T,N> : HaveW<T> { w >= self.bounds_min().w() && w < self.bounds_max().w() }
421
422 #[inline(always)] fn is_outside_x(&self, x : T) -> bool where Vector<T,N> : HaveX<T> { !self.is_inside_x(x) }
423 #[inline(always)] fn is_outside_y(&self, y : T) -> bool where Vector<T,N> : HaveY<T> { !self.is_inside_y(y) }
424 #[inline(always)] fn is_outside_z(&self, z : T) -> bool where Vector<T,N> : HaveZ<T> { !self.is_inside_z(z) }
425 #[inline(always)] fn is_outside_w(&self, w : T) -> bool where Vector<T,N> : HaveW<T> { !self.is_inside_w(w) }
426}
427
428pub trait SetRectangle<T, const N : usize> : GetRectangle<T,N> + SetPosition<T,N> where T: Number
429{
430 fn set_size(&mut self, size : Vector<T, N>) -> &mut Self;
431 #[inline(always)] fn resize(&mut self, size : Vector<T, N>) -> &mut Self { self.set_size(size) }
432
433 fn set_size_x(&mut self, x : T) -> &mut Self where Vector<T, N> : HaveX<T> { let mut p = self.pos(); p.set_x(x); self.set_pos(p); self }
434 #[inline(always)] fn set_size_y(&mut self, y : T) -> &mut Self where Vector<T, N> : HaveY<T> { let mut p = self.pos(); p.set_y(y); self.set_pos(p); self }
435 #[inline(always)] fn set_size_z(&mut self, z : T) -> &mut Self where Vector<T, N> : HaveZ<T> { let mut p = self.pos(); p.set_z(z); self.set_pos(p); self }
436 #[inline(always)] fn set_size_w(&mut self, w : T) -> &mut Self where Vector<T, N> : HaveW<T> { let mut p = self.pos(); p.set_w(w); self.set_pos(p); self }
437
438 #[inline(always)] fn with_size(mut self, size : Vector<T, N>) -> Self where Self : Sized { self.set_size(size); self }
439 #[inline(always)] fn with_size_x(mut self, x : T) -> Self where Vector<T, N> : HaveX<T>, Self : Sized { self.set_size_x(x); self }
440 #[inline(always)] fn with_size_y(mut self, y : T) -> Self where Vector<T, N> : HaveY<T>, Self : Sized { self.set_size_y(y); self }
441 #[inline(always)] fn with_size_z(mut self, z : T) -> Self where Vector<T, N> : HaveZ<T>, Self : Sized { self.set_size_z(z); self }
442 #[inline(always)] fn with_size_w(mut self, w : T) -> Self where Vector<T, N> : HaveW<T>, Self : Sized { self.set_size_w(w); self }
443}
444
445
446impl<Idx,const N : usize> IterIndex<Idx,N> for Rectangle<Idx,N> where Idx : Integer
507{
508 type IterIndex = RectangleIter<Idx,N>;
509 fn iter_index(&self) -> Self::IterIndex { RectangleIter::from_vec_iter(self.pos, self.size.iter_index()) }
510}
511
512
513
514
515#[cfg(test)]
516mod rect_test
517{
518 use super::*;
519
520
521 #[test]
522 fn crop_margin_unchecked()
523 {
524 unsafe
525 {
526 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(2.splat2(), 2.splat2()), rect2i(7,7,6,6));
527
528 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(2.splat2(), zero()), rect2i(7,7,8,8));
529 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(zero(), 2.splat2()), rect2i(5,5,8,8));
530
531 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(-1.splat2(), zero()), rect2i(4,4,11,11));
532 assert_eq!(rect2i(5,5,10,10).crop_margin_unchecked(zero(), -1.splat2()), rect2i(5,5,11,11));
533 }
534 }
535
536
537 #[test]
538 fn crop_margin()
539 {
540 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(2.splat2(), 2.splat2()), rect2i(7,7,6,6));
541
542 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(2.splat2(), zero()), rect2i(7,7,8,8));
543 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(zero(), 2.splat2()), rect2i(5,5,8,8));
544
545 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(-1.splat2(), zero()), rect2i(5,5,10,10));
546 assert_eq!(rect2i(5,5,10,10).crop_margin_intersect(zero(), -1.splat2()), rect2i(5,5,10,10));
547 }
548
549 #[test]
550 fn crop_normal()
551 {
552 let rect = rect2i(0, 0, 10, 10);
553 let cropped = rect.crop_margin_intersect(point2(1, 1), point2(2, 2));
554 assert_eq!(cropped, rect2i(1, 1, 7, 7));
555 }
556
557 #[test]
558 fn crop_to_much()
559 {
560 let rect = rect2i(0, 0, 10, 10);
561 let cropped = rect.crop_margin_intersect(point2(0, 0), point2(20, 20));
562 assert_eq!(cropped, zero());
563 }
564
565 #[test]
566 fn crop_to_much_2()
567 {
568 let rect = rect2i(0, 0, 10, 10);
569 let cropped = rect.crop_margin_intersect(point2(20, 20), point2(0, 0));
570 assert_eq!(cropped, rect2i(20, 20, 0, 0));
571 }
572
573 #[test]
574 fn crop_to_much_3()
575 {
576 let rect = rect2i(0, 0, 10, 10);
577 let cropped = rect.crop_margin_intersect(point2(20, 20), point2(20, 20));
578 assert_eq!(cropped, rect2i(20, 20, 0, 0));
579 }
580
581 #[test]
582 fn crop_2()
583 {
584 let r = rect2i(0, 0, 2, 3);
585 assert_eq!(r.crop(rect2i(0, 0, 0, 0)), Some(rect2i(0, 0, 0, 0)));
586 assert_eq!(r.crop(r), Some(r));
587 assert_eq!(r.crop(rect2i(0, 0, 2, 4)), None);
588
589 for idx in r.iter_index()
590 {
591 assert_eq!(r.is_inside(idx), true);
592 }
593 }
594}