def make_rect_centered(center: Point, width: float, height: float): """ Computes a rectangle which center point is `center` and with a size of `width` and `height`. :param center: `Point` :param width: `float` :param height: `float` :return: """ origin = Point(center.x - width / 2, center.y - height / 2) return Rect(origin, Size(width, height))
def make_rect_containing_with_margin(points: List[Point], margin: float): """ Computes the smallest rectangle containing all the passed points, and adds a margin to all four sides. :param points: `[Point]` :param margin: `float` :return: `Rect` """ rect = make_rect_containing(points) return Rect( Point(rect.origin.x - margin, rect.origin.y - margin), Size(2 * margin + rect.size.width, 2 * margin + rect.size.height))
def apply_to_rect(self, rect: Rect): """ Computes a `Polygon` result of applying this affine transformation to the given `Rect`. After applying a generic affine transformation to a rectangle, this may not be a rectangle whose sides are aligned with the horizontal and vertical directions anymore, therefore, this method returns a `Polygon` and not a `Rect`. :param rect: source `Rect` :return: transformed `Polygon` """ return self.apply_to_polygon( rect.to_polygon() )
def make_rect_containing(points: List[Point]): """ Computes the smallest rectangle containing all the passed points. :param points: `[Point]` :return: `Rect` """ if not points: raise ValueError('Expected at least one point') first_point = points[0] min_x, max_x = first_point.x, first_point.x min_y, max_y = first_point.y, first_point.y for point in points[1:]: min_x, max_x = min(min_x, point.x), max(max_x, point.x) min_y, max_y = min(min_y, point.y), max(max_y, point.y) return Rect(Point(min_x, min_y), Size(max_x - min_x, max_y - min_x))
class TestRect(unittest.TestCase): origin = Point(0, 0) size = Size(10, 5) rect = Rect(origin, size) # --- CONTAINS --- # def test_contains_point(self): point = Point(5, 3) self.assertTrue(self.rect.contains_point(point)) def test_doesnt_contain_point(self): point = Point(50, 7) self.assertFalse(self.rect.contains_point(point)) # --- INTERSECTION --- # def test_no_intersection_horizontal_overlap(self): other = Rect(Point(50, 0), self.size) self.assertIsNone(self.rect.intersection_with(other)) def test_no_intersection_vertical_overlap(self): other = Rect(Point(0, 50), self.size) self.assertIsNone(self.rect.intersection_with(other)) def test_intersection(self): other = Rect(Point(5, 2), self.size) actual = self.rect.intersection_with(other) expected = Rect(other.origin, Size(5, 3)) self.assertEqual(expected, actual) # --- POLYGON --- # def test_to_polygon(self): actual = self.rect.to_polygon() expected = Polygon( [self.origin, Point(10, 0), Point(10, 5), Point(0, 5)]) self.assertEqual(expected, actual)
def test_intersection(self): other = Rect(Point(5, 2), self.size) actual = self.rect.intersection_with(other) expected = Rect(other.origin, Size(5, 3)) self.assertEqual(expected, actual)
def test_no_intersection_vertical_overlap(self): other = Rect(Point(0, 50), self.size) self.assertIsNone(self.rect.intersection_with(other))
def test_no_intersection_horizontal_overlap(self): other = Rect(Point(50, 0), self.size) self.assertIsNone(self.rect.intersection_with(other))