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}