1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
use na::*;
use num_traits::Float;
use alga::general::{SupersetOf,SubsetOf};
use std::mem;

/// Represents a rectangle with operations over it
#[derive(Clone,Copy,Debug,PartialEq,Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Deserialize))]
pub struct Rect<T: BaseNum = f32>{
    pub pos: Pnt2<T>,
    pub width: T,
    pub height: T
}

/// Trait to calculate if something is inside a rectangle
pub trait InsideRect<T: BaseNum>{
    fn inside(&self, rect: &Rect<T>) -> bool;
}

impl<T:Float + BaseNum> InsideRect<T> for Pnt2<T>{
    fn inside(&self, rect: &Rect<T>) -> bool{
        self.x > rect.pos.x && self.y > rect.pos.y && self.x < rect.pos.x + rect.width && self.y < rect.pos.y + rect.height
    }
}

impl<T:Float + BaseNum> InsideRect<T> for Rect<T>{
    fn inside(&self, rect: &Rect<T>) -> bool{
        self.pos.x > rect.pos.x && self.pos.y > rect.pos.y &&
        self.pos.x + self.width < rect.pos.x + rect.width &&
        self.pos.y + self.height < rect.pos.y + rect.height
    }
}

impl<N1:BaseNum, N2:BaseNum + SupersetOf<N1>> SubsetOf<Rect<N2>> for Rect<N1>
    where Pnt2<N2>: SupersetOf<Pnt2<N1>>{
    fn is_in_subset(t: &Rect<N2>) -> bool{
        t.pos.is_in_subset() && t.width.is_in_subset() && t.height.is_in_subset()
    }

    unsafe fn from_superset_unchecked(t: &Rect<N2>) -> Rect<N1>{
        Rect{
            pos: t.pos.to_subset_unchecked(),
            width: t.width.to_subset_unchecked(),
            height: t.height.to_subset_unchecked(),
        }
    }

    fn to_superset(&self) -> Rect<N2>{
        Rect{
            pos: self.pos.to_superset(),
            width: convert(self.width),
            height: convert(self.height),
        }
    }
}

impl<T: Float + BaseNum> Rect<T>{
    pub fn aspect_ratio(&self) -> T{
        self.width / self.height
    }

    pub fn min_x(&self) -> T {
        self.pos.x.min(self.pos.x + self.width)
    }

    pub fn max_x(&self) -> T {
        self.pos.x.max(self.pos.x + self.width)
    }

    pub fn min_y(&self) -> T {
        self.pos.y.min(self.pos.y + self.height)
    }

    pub fn max_y(&self) -> T {
        self.pos.y.max(self.pos.y + self.height)
    }

    pub fn max_pos(&self) -> Pnt2<T>{
        pnt2(self.max_x(), self.max_y())
    }

    pub fn min_pos(&self) -> Pnt2<T>{
        pnt2(self.min_x(), self.min_y())
    }

    pub fn overlaps(&self, other: &Rect<T>) -> bool{
        let self_min = self.min_pos();
        let self_max = self.max_pos();
        let other_min = other.min_pos();
        let other_max = other.max_pos();
        self_min.x < other_max.x && self_max.x > other_min.x &&
        self_min.y < other_max.y && self_max.y > other_min.y
    }

    pub fn intersection(&self, other: &Rect<T>) -> Rect<T>{
        let x0 = self.min_x().max(other.min_x());
        let x1 = self.max_x().min(other.max_x());
        let width = x1 - x0;

        let y0 = self.min_y().max(other.min_y());
        let y1 = self.max_y().min(other.max_y());
        let height = y1 - y0;

        Rect{pos: pnt2(x0, y0), width, height}
    }
}


impl<T: BaseNum> Rect<T>{
    pub fn top_left(&self) -> Pnt2<T>{
        self.pos
    }

    pub fn top_right(&self) -> Pnt2<T>{
        pnt2(self.pos.x + self.width, self.pos.y)
    }

    pub fn bottom_left(&self) -> Pnt2<T>{
        pnt2(self.pos.x, self.pos.y + self.height)
    }

    pub fn bottom_right(&self) -> Pnt2<T>{
        pnt2(self.pos.x + self.width, self.pos.y + self.height)
    }

    pub fn center(&self) -> Pnt2<T> where i32: SubsetOf<T>{
        let two: T = convert(2);
        pnt2(self.pos.x + self.width, self.pos.y + self.height) / two
    }
}


impl<T: BaseNum> AsRef<[T;4]> for Rect<T>{
    fn as_ref(&self) -> &[T;4]{
        unsafe{ mem::transmute(self) }
    }
}

#[cfg(any(feature="gl", feture="gles", feature="webgl"))]
impl From<glin::Rect> for Rect<u32>{
    fn from(rect: glin::Rect) -> Rect<u32>{
        Rect{pos: pnt2(rect.left, rect.bottom), width: rect.width, height: rect.height}
    }
}

#[cfg(any(feature="gl", feture="gles", feature="webgl"))]
impl From<glin::Viewport> for Rect<i32>{
    fn from(rect: glin::Viewport) -> Rect<i32>{
        Rect{pos: pnt2(rect.x, rect.y), width: rect.width, height: rect.height}
    }
}