rectcut_rs/
lib.rs

1
2/// The Rect struct represents an area, such as an area of the screen,
3/// by its minimum x and y and maximum x and y.
4#[derive(Copy, Clone, Debug)]
5pub struct Rect {
6    pub minx: f32,
7    pub miny: f32,
8    pub maxx: f32,
9    pub maxy: f32,
10}
11
12impl Rect {
13    /// Create a new Rect.
14    pub fn new(minx: f32, miny: f32, maxx: f32, maxy: f32) -> Rect {
15        return Rect { minx, miny, maxx, maxy };
16    }
17
18    /// Cut out the left of the rect, returning the left piece and modifying the original Rect.
19    pub fn cut_left(&mut self, a: f32) -> Rect {
20        let minx: f32 = self.minx;
21        if self.maxx < self.minx + a {
22            self.minx = self.maxx;
23        } else {
24            self.minx = self.minx + a;
25        }
26        return Rect::new(minx, self.miny, self.minx, self.maxy);
27    }
28
29    /// Cut out the right of the rect, returning the right piece and modifying the original Rect.
30    pub fn cut_right(&mut self, a: f32) -> Rect {
31        let maxx: f32 = self.maxx;
32        if self.minx > self.maxx - a {
33            self.maxx = self.minx;
34        } else {
35            self.maxx = self.maxx - a;
36        }
37        return Rect::new(self.maxx, self.miny, maxx, self.maxy);
38    }
39
40    /// Cut out the top of the rect, returning the top piece and modifying the original Rect.
41    pub fn cut_top(&mut self, a: f32) -> Rect {
42        let miny: f32 = self.miny;
43        if self.maxy < self.miny + a {
44            self.miny = self.maxy;
45        } else {
46            self.miny = self.miny + a;
47        }
48        return Rect::new(self.minx, miny, self.maxx, self.miny);
49    }
50
51    /// Cut out the bottom of the rect, returning the bottom piece and modifying the original Rect.
52    pub fn cut_bottom(&mut self, a: f32) -> Rect {
53        let maxy: f32 = self.maxy;
54        if self.miny > self.maxy - a {
55            self.maxy = self.miny;
56        } else {
57            self.maxy = self.maxy - a;
58        }
59        return Rect::new(self.minx, self.maxy, self.maxx, maxy);
60    }
61
62    /// Cut out the left of the rect, leaving the original unmodified.
63    pub fn get_left(&self, a: f32) -> Rect {
64        let maxx;
65        if self.maxx < self.minx + a {
66            maxx = self.maxx;
67        } else {
68            maxx = self.minx + a;
69        }
70        return Rect::new(self.minx, self.miny, maxx, self.maxy);
71    }
72
73    /// Cut out the right of the rect, leaving the original unmodified.
74    pub fn get_right(&self, a: f32) -> Rect {
75        let minx;
76        if self.minx > self.maxx - a {
77            minx = self.minx;
78        } else {
79            minx = self.maxx - a;
80        }
81        return Rect::new(minx, self.miny, self.maxx, self.maxy);
82    }
83
84    /// Cut out the top of the rect, leaving the original unmodified.
85    pub fn get_top(&self, a: f32) -> Rect {
86        let maxy;
87        if self.maxy < self.miny + a {
88            maxy = self.maxy;
89        } else {
90            maxy = self.miny + a;
91        }
92        return Rect::new(self.minx, self.miny, self.maxx, maxy);
93    }
94
95    /// Cut out the bottom of the rect, leaving the original unmodified.
96    pub fn get_bottom(&self, a: f32) -> Rect {
97        let miny;
98        if self.miny > self.maxy - a {
99            miny = self.miny;
100        } else {
101            miny = self.maxy - a;
102        }
103        return Rect::new(self.minx, miny, self.maxx, self.maxy);
104    }
105
106    /// Create a rect that extends the given rect out to the left,
107    /// leaving the original unmodified.
108    pub fn add_left(&self, a: f32) -> Rect {
109        return Rect::new(self.minx - a, self.miny, self.minx, self.maxy);
110    }
111
112    /// Create a rect that extends the given rect out to the right,
113    /// leaving the original unmodified.
114    pub fn add_right(&self, a: f32) -> Rect {
115        return Rect::new(self.maxx, self.miny, self.maxx + a, self.maxy);
116    }
117
118    /// Create a rect that extends the given rect out to the top,
119    /// leaving the original unmodified.
120    pub fn add_top(&self, a: f32) -> Rect {
121        return Rect::new(self.minx, self.miny - a, self.maxx, self.miny);
122    }
123
124    /// Create a rect that extends the given rect out to the bottom,
125    /// leaving the original unmodified.
126    pub fn add_bottom(&self, a: f32) -> Rect {
127        return Rect::new(self.minx, self.maxy, self.maxx, self.maxy + a);
128    }
129
130    /// Extend the rect out in all directions, leaving the original unmodified.
131    pub fn extend(&self, a: f32) -> Rect {
132        return Rect::new(self.minx - a, self.miny - a, self.maxx + a, self.maxy + a);
133    }
134
135    /// Conctract the rect in all directions, leaving the original unmodified.
136    pub fn contract(&self, a: f32) -> Rect {
137        return Rect::new(self.minx + a, self.miny + a, self.maxx - a, self.maxy - a);
138    }
139}
140
141#[test]
142pub fn test_cut_left() {
143    let mut rect = Rect::new(0.0, 0.0, 10.0, 10.0);
144    let left = rect.cut_left(1.0);
145
146    assert_eq!(0.0, left.minx);
147    assert_eq!(1.0, left.maxx);
148    assert_eq!(rect.miny, left.miny);
149    assert_eq!(rect.maxy, left.maxy);
150
151    assert_eq!(1.0, rect.minx);
152    assert_eq!(10.0, rect.maxx);
153    assert_eq!(0.0, rect.miny);
154    assert_eq!(10.0, rect.maxy);
155}
156
157#[test]
158pub fn test_cut_right() {
159    let mut rect = Rect::new(0.0, 0.0, 10.0, 10.0);
160    let right = rect.cut_right(1.0);
161
162    assert_eq!(9.0, right.minx);
163    assert_eq!(10.0, right.maxy);
164    assert_eq!(rect.miny, right.miny);
165    assert_eq!(rect.maxy, right.maxy);
166
167    assert_eq!(0.0, rect.minx);
168    assert_eq!(9.0, rect.maxx);
169    assert_eq!(0.0, rect.miny);
170    assert_eq!(10.0, rect.maxy);
171}
172
173#[test]
174pub fn test_cut_top() {
175    let mut rect = Rect::new(0.0, 0.0, 10.0, 10.0);
176    let top = rect.cut_top(1.0);
177
178    assert_eq!(0.0, top.minx);
179    assert_eq!(10.0, top.maxx);
180    assert_eq!(0.0, top.miny);
181    assert_eq!(1.0, top.maxy);
182
183    assert_eq!(0.0, rect.minx);
184    assert_eq!(10.0, rect.maxx);
185    assert_eq!(1.0, rect.miny);
186    assert_eq!(10.0, rect.maxy);
187}
188
189#[test]
190pub fn test_cut_bottom() {
191    let mut rect = Rect::new(0.0, 0.0, 10.0, 10.0);
192    let bottom = rect.cut_bottom(1.0);
193
194    assert_eq!(0.0, bottom.minx);
195    assert_eq!(10.0, bottom.maxx);
196    assert_eq!(9.0, bottom.miny);
197    assert_eq!(10.0, bottom.maxy);
198
199    assert_eq!(0.0, rect.minx);
200    assert_eq!(10.0, rect.maxx);
201    assert_eq!(0.0, rect.miny);
202    assert_eq!(9.0, rect.maxy);
203}
204
205#[test]
206pub fn test_get_left() {
207    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
208    let left = rect.get_left(1.0);
209
210    assert_eq!(0.0, left.minx);
211    assert_eq!(1.0, left.maxx);
212    assert_eq!(0.0, left.miny);
213    assert_eq!(10.0, left.maxy);
214}
215
216#[test]
217pub fn test_get_right() {
218    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
219    let right = rect.get_right(1.0);
220
221    assert_eq!(9.0, right.minx);
222    assert_eq!(10.0, right.maxx);
223    assert_eq!(0.0, right.miny);
224    assert_eq!(10.0, right.maxy);
225}
226
227#[test]
228pub fn test_get_top() {
229    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
230    let top = rect.get_top(1.0);
231
232    assert_eq!(0.0, top.minx);
233    assert_eq!(10.0, top.maxx);
234    assert_eq!(0.0, top.miny);
235    assert_eq!(1.0, top.maxy);
236}
237
238#[test]
239pub fn test_get_bottom() {
240    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
241    let bottom = rect.get_bottom(1.0);
242
243    assert_eq!(0.0, bottom.minx);
244    assert_eq!(10.0, bottom.maxx);
245    assert_eq!(9.0, bottom.miny);
246    assert_eq!(10.0, bottom.maxy);
247}
248
249#[test]
250pub fn test_add_left() {
251    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
252    let left = rect.add_left(1.0);
253
254    assert_eq!(-1.0, left.minx);
255    assert_eq!(0.0, left.maxx);
256    assert_eq!(0.0, left.miny);
257    assert_eq!(10.0, left.maxy);
258}
259
260#[test]
261pub fn test_add_right() {
262    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
263    let right = rect.add_right(1.0);
264
265    assert_eq!(10.0, right.minx);
266    assert_eq!(11.0, right.maxx);
267    assert_eq!(0.0, right.miny);
268    assert_eq!(10.0, right.maxy);
269}
270
271#[test]
272pub fn test_add_top() {
273    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
274    let top = rect.add_top(1.0);
275
276    assert_eq!(0.0, top.minx);
277    assert_eq!(10.0, top.maxx);
278    assert_eq!(-1.0, top.miny);
279    assert_eq!(0.0, top.maxy);
280}
281
282#[test]
283pub fn test_add_bottom() {
284    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
285    let bottom = rect.add_bottom(1.0);
286
287    assert_eq!(0.0, bottom.minx);
288    assert_eq!(10.0, bottom.maxx);
289    assert_eq!(10.0, bottom.miny);
290    assert_eq!(11.0, bottom.maxy);
291}
292
293#[test]
294pub fn test_extend() {
295    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
296
297    let extended = rect.extend(1.0);
298
299    assert_eq!(-1.0, extended.minx);
300    assert_eq!(11.0, extended.maxx);
301    assert_eq!(-1.0, extended.miny);
302    assert_eq!(11.0, extended.maxy);
303}
304
305#[test]
306pub fn test_contract() {
307    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
308
309    let contract = rect.contract(1.0);
310
311    assert_eq!(1.0, contract.minx);
312    assert_eq!(9.0, contract.maxx);
313    assert_eq!(1.0, contract.miny);
314    assert_eq!(9.0, contract.maxy);
315}
316
317/// A RectCutSide represents a side of the rectangle. This allows
318/// the user to choose a side dynamically using a RectCut.
319#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
320pub enum RectCutSide {
321    Left,
322    Right,
323    Top,
324    Bottom,
325}
326
327/// A RectCut wraps a Rect along with a side. This allows the
328/// user to fix the side and pass the rect-and-side together
329/// into other code.
330#[derive(Copy, Clone, Debug)]
331struct RectCut {
332    pub rect: Rect,
333    pub side: RectCutSide,
334}
335
336impl RectCut {
337    /// Create a new RectCut.
338    pub fn new(rect: Rect, side: RectCutSide) -> RectCut {
339        return RectCut { rect, side };
340    }
341
342    /// Cut out from the RectCut, returning the new Rect
343    /// and modifying the internal Rect.
344    pub fn cut(&mut self, a: f32) -> Rect {
345        match self.side {
346            RectCutSide::Left =>   return self.rect.cut_left(a),
347            RectCutSide::Right =>  return self.rect.cut_right(a),
348            RectCutSide::Top =>    return self.rect.cut_top(a),
349            RectCutSide::Bottom => return self.rect.cut_bottom(a),
350        }
351    }
352}
353
354#[test]
355fn test_rectcut() {
356    let rect = Rect::new(0.0, 0.0, 10.0, 10.0);
357    let mut rectcut = RectCut::new(rect, RectCutSide::Left);
358    let left = rectcut.cut(1.0);
359    assert_eq!(0.0, left.minx);
360    assert_eq!(0.0, left.miny);
361    assert_eq!(1.0, left.maxx);
362    assert_eq!(10.0, left.maxy);
363
364    assert_eq!(1.0, rectcut.rect.minx);
365    assert_eq!(0.0, rectcut.rect.miny);
366    assert_eq!(10.0, rectcut.rect.maxx);
367    assert_eq!(10.0, rectcut.rect.maxy);
368}
369