Do intersect_all

master
expectocode 2019-12-31 02:06:23 +00:00
parent ade8859701
commit 6d8852260e
2 changed files with 92 additions and 0 deletions

View File

@ -152,6 +152,43 @@ impl Rectangle {
|| self.top_right().left_of(&other.top_left())
|| self.bottom_left().above(&other.top_left()))
}
pub fn intersection(&self, other: &Rectangle) -> Option<Rectangle> {
if !self.intersects(other) {
return None;
}
// idk wtf this is lol
let in_top_left;
let in_bottom_right;
if self.top_left().right_of(&other.top_left()) {
if self.top_left().below(&other.top_left()) {
in_top_left = self.top_left();
} else {
in_top_left = Point::new(self.top_left().x(), other.top_left().y());
}
} else {
if self.top_left().below(&other.top_left()) {
in_top_left = Point::new(other.top_left().x(), self.top_left().y());
} else {
in_top_left = other.top_left();
}
}
if self.bottom_right().left_of(&other.bottom_right()) {
if self.bottom_right().below(&other.bottom_right()) {
in_bottom_right = Point::new(self.bottom_right().x(), other.bottom_right().y());
} else {
in_bottom_right = self.bottom_right();
}
} else {
if self.bottom_right().below(&other.bottom_right()) {
in_bottom_right = other.bottom_right();
} else {
in_bottom_right = Point::new(other.bottom_right().x(), self.bottom_right().y());
}
}
Some(Rectangle::from_corners(in_top_left, in_bottom_right))
}
}
#[cfg(test)]

View File

@ -88,3 +88,58 @@ where
// The type of the collect() function is chosen based on the return type that it's meant to fit
rects.map(|r| (r, r.area())).collect()
}
pub fn intersect_all<T>(mut rects: T) -> Option<Rectangle>
where
T: Iterator<Item = Rectangle>,
{
let first = rects.next();
if let None = first {
// Can't do intersection if no items.
return None;
}
fn intersect_helper(acc: Option<Rectangle>, rect: Rectangle) -> Option<Rectangle> {
match acc {
None => None,
Some(a) => a.intersection(&rect),
}
}
rects.fold(first, intersect_helper)
}
#[cfg(test)]
mod tests {
use super::*;
const INCREASING_ENCLOSING: [Rectangle; 5] = [
Rectangle::at_origin_with_size(1, 1),
Rectangle::at_origin_with_size(2, 2),
Rectangle::at_origin_with_size(3, 3),
Rectangle::at_origin_with_size(4, 4),
Rectangle::at_origin_with_size(5, 5),
];
#[test]
fn test_intersect_all_1() {
let mut v = Vec::new();
v.extend(INCREASING_ENCLOSING.iter());
// Drain is a bit different to iter in that it releases ownership of each object,
// instead of just giving a reference.
assert_eq!(Some(INCREASING_ENCLOSING[0]), intersect_all(v.drain(0..)));
}
#[test]
fn test_intersect_all_2() {
// Deliberately inconsistent with above code to show a different way of doing things.
let mut various_rects = vec![
Rectangle::from_corner_width_height(Point::new(20, 110), 10, 10),
Rectangle::from_corner_width_height(Point::new(25, 115), 10, 10),
Rectangle::from_corner_width_height(Point::new(10, 100), 1000, 1000),
Rectangle::from_corner_width_height(Point::new(2010, 2100), 1, 1),
];
assert_eq!(None, intersect_all(various_rects.drain(0..)));
}
}