forked from servo/euclid
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrect.rs
129 lines (105 loc) · 3.83 KB
/
rect.rs
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
// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use point::Point2D;
use size::Size2D;
use core::cmp::{Eq, Ord};
#[deriving(Eq)]
pub struct Rect<T> {
origin: Point2D<T>,
size: Size2D<T>,
}
pub fn Rect<T:Copy + Ord + Add<T,T> + Sub<T,T>>(origin: Point2D<T>,
size: Size2D<T>)
-> Rect<T> {
return Rect {
origin: copy origin,
size: copy size
}
}
pub impl<T: Copy + Ord + Add<T,T> + Sub<T,T>> Rect<T> {
fn intersects(&self, other: &Rect<T>) -> bool {
self.origin.x < other.origin.x + other.size.width &&
other.origin.x < self.origin.x + self.size.width &&
self.origin.y < other.origin.y + other.size.height &&
other.origin.y < self.origin.y + self.size.height
}
fn intersection(&self, other: &Rect<T>) -> Option<Rect<T>> {
if !self.intersects(other) {
return None;
}
Some(Rect(Point2D(max(self.origin.x, other.origin.x),
max(self.origin.y, other.origin.y)),
Size2D(min(self.origin.x + self.size.width,
other.origin.x + other.size.width),
min(self.origin.y + self.size.height,
other.origin.y + other.size.height))))
}
fn union(&self, other: &Rect<T>) -> Rect<T> {
let upper_left = Point2D(min(self.origin.x, other.origin.x),
min(self.origin.y, other.origin.y));
let lower_right = Point2D(max(self.origin.x + self.size.width,
other.origin.x + other.size.width),
max(self.origin.y + self.size.height,
other.origin.y + other.size.height));
Rect {
origin: upper_left,
size: Size2D(lower_right.x - upper_left.x, lower_right.y - upper_left.y)
}
}
fn translate(&self, other: &Point2D<T>) -> Rect<T> {
Rect {
origin: Point2D(self.origin.x + other.x, self.origin.y + other.y),
size: copy self.size
}
}
}
pub fn min<T:Copy + Ord>(x: T, y: T) -> T {
if x <= y { x } else { y }
}
pub fn max<T:Copy + Ord>(x: T, y: T) -> T {
if x >= y { x } else { y }
}
#[test]
fn test_min_max() {
assert!(min(0, 1) == 0);
assert!(min(-1.0, 0.0) == -1.0);
assert!(max(0, 1) == 1);
assert!(max(-1.0, 0.0) == 0.0);
}
#[test]
fn test_translate() {
let p = Rect(Point2D(0, 0), Size2D(50, 40));
let pp = p.translate(&Point2D(10,15));
assert!(pp.size.width == 50);
assert!(pp.size.height == 40);
assert!(pp.origin.x == 10);
assert!(pp.origin.y == 15);
let r = Rect(Point2D(-10, -5), Size2D(50, 40));
let rr = r.translate(&Point2D(0,-10));
assert!(rr.size.width == 50);
assert!(rr.size.height == 40);
assert!(rr.origin.x == -10);
assert!(rr.origin.y == -15);
}
#[test]
fn test_union() {
let p = Rect(Point2D(0,0), Size2D(50, 40));
let q = Rect(Point2D(20,20), Size2D(5, 5));
let r = Rect(Point2D(-15, -30), Size2D(200, 15));
let s = Rect(Point2D(20, -15), Size2D(250, 200));
let pq = p.union(&q);
assert!(pq.origin == Point2D(0, 0));
assert!(pq.size == Size2D(50, 40));
let pr = p.union(&r);
assert!(pr.origin == Point2D(-15, -30));
assert!(pr.size == Size2D(200, 70));
let ps = p.union(&s);
assert!(ps.origin == Point2D(0, -15));
assert!(ps.size == Size2D(270, 200));
}