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
use std::convert::From;
use graphics::math::{ self, Scalar };

use { Point, Size };

/// A rectangle.
#[derive(Clone, Copy, Debug)]
pub struct Rect {
    /// The position of the top left corner of the rectangle.
    pub pos: Point,
    /// The width and height of the rectangle.
    pub size: Size,
}

impl<P: Into<Point>, S: Into<Size>> From<(P, S)> for Rect {
    /// Creates a rectangle from the position of its top left corner and its size.
    fn from((pos, size): (P, S)) -> Rect {
        let (pos, size): (Point, Size) = (pos.into(), size.into());
        Rect { pos: pos, size: size }
    }
}

impl From<Rect> for [Scalar; 4] {
    fn from(rect: Rect) -> [Scalar; 4] {
        [rect.pos.x, rect.pos.y, rect.size.w, rect.size.h]
    }
}

impl From<[Scalar; 4]> for Rect {
    /// Creates a rectangle from an array.
    fn from(v: [Scalar; 4]) -> Rect {
        Rect {
            pos: Point { x: v[0], y: v[1] },
            size: Size { w: v[2], h: v[3] },
        }
    }
}

impl From<(Scalar, Scalar, Scalar, Scalar)> for Rect {
    fn from((x, y, w, h): (Scalar, Scalar, Scalar, Scalar)) -> Rect {
        Rect {
            pos: Point { x: x, y: y },
            size: Size { w: w, h: h },
        }
    }
}

impl Rect {
    /// Returns the position of the bottom side of the rectangle.
    pub fn bottom(&self) -> Scalar {
        self.pos.y + self.size.h
    }

    /// Computes a rectangle with quadruple the surface area of self and with center
    /// (self.x, self.y).
    pub fn centered(self) -> Rect {
        Rect {
            pos: Point {
                 x: self.pos.x - self.size.w,
                 y: self.pos.y - self.size.h,
            },
            size: self.size * 2.0,
        }
    }

    /// Compute whether or not the point is inside the rectangle.
    #[inline(always)]
    pub fn contains<T: Into<Point>>(&self, point: T) -> bool {
        let point: Point = point.into();
        self.left() < point.x && point.x < self.right() &&
        self.top() < point.y && point.y < self.bottom()
    }

    /// Create a rectangle that circumscribes the given circle.
    pub fn new_circle<T: Into<Point>>(center: T, radius: Scalar) -> Rect {
        let center: Point = center.into();
        Rect {
            pos: Point {
                x: center.x - radius,
                y: center.y - radius,
            },
            size: Size {
                w: 2.0 * radius,
                h: 2.0 * radius,
            },
        }
    }

    /// Create a square rectangle with sides of length len and top left corner at pos.
    pub fn new_square<T: Into<Point>>(pos: T, len: Scalar) -> Rect {
        let pos: Point = pos.into();
        Rect {
            pos: pos,
            size: Size { w: len, h: len },
        }
    }

    /// Returns the position of the left side of the rectangle.
    pub fn left(&self) -> Scalar {
        self.pos.x
    }

    /// Computes a rectangle whose perimeter forms the inside edge of margin with size m for self.
    #[inline(always)]
    pub fn margin(self, m: Scalar) -> Rect {
        math::margin_rectangle(self.into(), m).into()
    }

    /// Computes a rectangle translated (slid) in the direction of the vector a distance relative
    /// to the size of the rectangle. For example, self.relative([1.0, 1.0]) returns a rectangle
    /// one rectangle to the right and down from the original.
    #[inline(always)]
    pub fn relative<T: Into<Point>>(self, v: T) -> Rect {
        let v: Point = v.into();
        Rect {
            pos: Point {
                x: self.pos.x + self.size.w * v.x,
                y: self.pos.y + self.size.h * v.y,
            },
            size: self.size,
        }
    }

    /// Returns the position of the right side of the rectangle.
    pub fn right(&self) -> Scalar {
        self.pos.x + self.size.w
    }

    /// Computes a scaled rectangle with the same position as self.
    pub fn scaled<T: Into<Size>>(self, v: T) -> Rect {
        let v: Size = v.into();
        Rect {
            pos: self.pos,
            size: self.size * v,
        }
    }

    /// Returns the position of the top side of the rectangle.
    pub fn top(&self) -> Scalar {
        self.pos.y
    }
}