rect: fix bug in rect; add doc; rename method.

This commit is contained in:
Andelf
2014-04-19 15:59:54 +08:00
parent 22eb756d41
commit 552f5571e9
+69 -26
View File
@@ -1,34 +1,38 @@
/*!
Rectangle Functions
*/
use std::cast;
use libc::c_int;
use std::ptr;
#[deriving(Eq)]
#[deriving(Clone)]
pub struct Point{
/// A structure that defines a two dimensional point.
#[deriving(Eq, Clone, Show)]
pub struct Point {
pub x: i32,
pub y: i32
}
#[deriving(Eq)]
#[deriving(Clone)]
/// A structure that defines a rectangle, with the origin at the upper left.
#[deriving(Eq, Clone, Show)]
pub struct Rect {
pub x: i32,
pub y: i32,
pub w: i32,
pub h: i32
pub h: i32
}
#[doc(hidden)]
#[allow(non_camel_case_types)]
pub mod ll {
use libc::{c_int};
use rect::Rect;
use rect::Point;
use libc::c_int;
use super::Rect;
use super::Point;
pub type SDL_Rect = Rect;
pub type SDL_Point = Point;
pub type SDL_bool = c_int;
extern "C" {
pub fn SDL_HasIntersection(A: *SDL_Rect, B: *SDL_Rect) -> SDL_bool;
pub fn SDL_IntersectRect(A: *SDL_Rect, B: *SDL_Rect, result: *SDL_Rect) -> SDL_bool;
@@ -38,10 +42,6 @@ pub mod ll {
}
}
pub fn Point(x: i32, y: i32) -> Point {
Point { x: x, y: y }
}
impl Point {
pub fn new(x: i32, y: i32) -> Point {
Point {
@@ -51,10 +51,6 @@ impl Point {
}
}
pub fn Rect(x: i32, y: i32, w: i32, h: i32) -> Rect {
Rect { x: x, y: y, w: w, h: h }
}
impl Rect {
pub fn new(x: i32, y: i32, w: i32, h: i32) -> Rect {
Rect {
@@ -65,16 +61,17 @@ impl Rect {
}
}
pub fn enclose_points(points: &[Point], clip: Option<Rect>) -> Option<Rect> {
/// Calculate a minimal rectangle enclosing a set of points.
pub fn from_enclose_points(points: &[Point], clip: Option<Rect>) -> Option<Rect> {
let out: Rect = Rect::new(0, 0, 0, 0);
let result = unsafe {
ll::SDL_EnclosePoints(
cast::transmute(points.as_ptr()),
points.len() as c_int,
match clip { Some(ref rect) => cast::transmute(rect), None => ptr::null() },
cast::transmute(clip.as_ref()),
&out
) == 0
) != 0
};
if result {
@@ -84,21 +81,24 @@ impl Rect {
}
}
pub fn empty(&self) -> bool {
/// Check whether a rectangle has no area.
pub fn is_empty(&self) -> bool {
(self.w <= 0) || (self.h <= 0)
}
/// Determine whether two rectangles intersect.
pub fn has_intersection(&self, other: &Rect) -> bool {
unsafe {
ll::SDL_HasIntersection(self, other) == 0
ll::SDL_HasIntersection(self, other) != 0
}
}
/// Calculate the intersection of two rectangles.
pub fn intersection(&self, other: &Rect) -> Option<Rect> {
let out: Rect = Rect::new(0, 0, 0, 0);
let result = unsafe {
ll::SDL_IntersectRect(self, other, &out) == 0
ll::SDL_IntersectRect(self, other, &out) != 0
};
if result {
@@ -108,6 +108,7 @@ impl Rect {
}
}
/// Calculate the union of two rectangles.
pub fn union(&self, other: &Rect) -> Rect {
let out: Rect = Rect::new(0, 0, 0, 0);
@@ -118,12 +119,13 @@ impl Rect {
out
}
/// Calculate the intersection of a rectangle and line segment. return points of intersection.
pub fn intersect_line(&self, start: &Point, end: &Point) -> Option<(Point, Point)> {
let out_start: Point = start.clone();
let out_end: Point = end.clone();
let result = unsafe {
ll::SDL_IntersectRectAndLine(self, &out_start.x, &out_start.y, &out_end.x, &out_end.y) == 0
ll::SDL_IntersectRectAndLine(self, &out_start.x, &out_start.y, &out_end.x, &out_end.y) != 0
};
if result {
@@ -133,3 +135,44 @@ impl Rect {
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_from_enclose_points() {
assert_eq!(Rect::from_enclose_points(&[Point::new(2, 4), Point::new(5,9)], None),
Some(Rect::new(2, 4, 4, 6)));
assert!(Rect::from_enclose_points(&[Point::new(0, 0), Point::new(10,10)],
Some(Rect::new(3, 3, 1, 1))).is_none());
}
#[test]
fn test_has_intersection() {
assert!(Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(9, 9, 10, 10)));
// edge
assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(10, 10, 10, 10)));
// out
assert!(! Rect::new(0, 0, 10, 10).has_intersection(&Rect::new(11, 11, 10, 10)));
}
#[test]
fn test_intersection() {
assert_eq!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(9, 9, 10, 10)),
Some(Rect::new(9, 9, 1, 1)));
assert!(Rect::new(0, 0, 10, 10).intersection(&Rect::new(11, 11, 10, 10)).is_none());
}
#[test]
fn test_union() {
assert_eq!(Rect::new(0, 0, 1, 1).union(&Rect::new(9, 9, 1, 1)),
Rect::new(0, 0, 10, 10));
}
#[test]
fn test_intersect_line() {
assert_eq!(Rect::new(1, 1, 5, 5).intersect_line(&Point::new(0, 0), &Point::new(10, 10)),
Some((Point::new(1, 1), Point::new(5, 5))));
}
}