sfml_types/rect.rs
1/*
2* Rust-SFML - Copyright (c) 2013 Letang Jeremy.
3*
4* The original software, SFML library, is provided by Laurent Gomila.
5*
6* This software is provided 'as-is', without any express or implied warranty.
7* In no event will the authors be held liable for any damages arising from
8* the use of this software.
9*
10* Permission is granted to anyone to use this software for any purpose,
11* including commercial applications, and to alter it and redistribute it
12* freely, subject to the following restrictions:
13*
14* 1. The origin of this software must not be misrepresented; you must not claim
15* that you wrote the original software. If you use this software in a product,
16* an acknowledgment in the product documentation would be appreciated but is
17* not required.
18*
19* 2. Altered source versions must be plainly marked as such, and must not be
20* misrepresented as being the original software.
21*
22* 3. This notice may not be removed or altered from any source distribution.
23*/
24
25use Vector2;
26use std::ops::{Add, Sub};
27
28/// Utility type for manipulating 2D axis-aligned rectangles.
29#[repr(C)]
30#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Copy, Default)]
31pub struct Rect<T> {
32 /// Left coordinate of the rectangle.
33 pub left: T,
34 /// Top coordinate of the rectangle.
35 pub top: T,
36 /// Width of the rectangle.
37 pub width: T,
38 /// Height of the rectangle.
39 pub height: T
40}
41
42/// A `Rect` of `i32`.
43pub type IntRect = Rect<i32>;
44/// A `Rect` of `f32`.
45pub type FloatRect = Rect<f32>;
46
47impl<T> Rect<T> {
48 /// Construct a rectangle from its coordinates.
49 pub fn new(left: T, top: T, width: T, height: T) -> Rect<T> {
50 Rect {
51 left: left,
52 top: top,
53 width: width,
54 height: height
55 }
56 }
57
58 /// Construct a rectangle from its position and size.
59 pub fn from_vecs(pos: Vector2<T>, size: Vector2<T>) -> Rect<T> {
60 Rect {
61 left: pos.x,
62 top: pos.y,
63 width: size.x,
64 height: size.y
65 }
66 }
67}
68
69impl<T: PartialOrd + Add<Output=T> + Sub<Output=T> + Copy> Rect<T> {
70 /// Check if a point is inside the rectangle's area.
71 #[inline]
72 pub fn contains(self, point: Vector2<T>) -> bool {
73 self.contains2(point.x, point.y)
74 }
75
76 /// Check if a point is inside the rectangle's area.
77 pub fn contains2(self, x: T, y: T) -> bool {
78 // Based on SFML's implementation.
79 // Rectangles with negative dimensions are allowed.
80 let (min_x, max_x) = min_max(self.left, self.left + self.width);
81 let (min_y, max_y) = min_max(self.top, self.top + self.height);
82 x >= min_x && x < max_x && y >= min_y && y < max_y
83 }
84
85 /// Check the intersection between two rectangles.
86 ///
87 /// If the rectangles intersect, returns Some filled with the intersection
88 /// of the two rectangles. Otherwise, returns None.
89 pub fn intersects(self, other: &Rect<T>) -> Option<Rect<T>> {
90 // Based on SFML's implementation.
91 // Compute the min and max coordinates on various axes.
92 let (r1_min_x, r1_max_x) = min_max(self.left, self.left + self.width);
93 let (r1_min_y, r1_max_y) = min_max(self.top, self.top + self.height);
94 let (r2_min_x, r2_max_x) = min_max(other.left, other.left + other.width);
95 let (r2_min_y, r2_max_y) = min_max(other.top, other.top + other.height);
96 // Compute the intersection.
97 let left = max(r1_min_x, r2_min_x);
98 let top = max(r1_min_y, r2_min_y);
99 let right = min(r1_max_x, r2_max_x);
100 let bottom = min(r1_max_y, r2_max_y);
101 // Return the result.
102 if left < right && top < bottom {
103 Some(Rect::new(left, top, right - left, bottom - top))
104 } else {
105 None
106 }
107 }
108}
109
110#[inline]
111fn min<T: PartialOrd>(a: T, b: T) -> T {
112 if a < b { a } else { b }
113}
114
115#[inline]
116fn max<T: PartialOrd>(a: T, b: T) -> T {
117 if a > b { a } else { b }
118}
119
120#[inline]
121fn min_max<T: PartialOrd + Copy>(a: T, b: T) -> (T, T) {
122 (min(a, b), max(a, b))
123}