-
Notifications
You must be signed in to change notification settings - Fork 9
/
exercise3.py
85 lines (67 loc) · 2.94 KB
/
exercise3.py
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
from exercise1 import Vector
from exercise2 import Point2D
class Rectangle:
def __init__(self, lower_left: Point2D, dx: float, dy: float) -> None:
self._lower_left = lower_left
self._dx = dx
self._dy = dy
def corner(self, i: int) -> Point2D:
assert i < 4
result = Point2D(self._lower_left.x, self._lower_left.y)
result += Vector([
self._dx if self._is_idx_on_right_edge(i) else 0.0,
self._dy if self._is_idx_on_upper_edge(i) else 0.0
])
return result
@property
def lower_left(self) -> Point2D:
return self._lower_left
@property
def upper_right(self) -> Point2D:
return self.corner(3)
# def contains(self, point: Point2D, tolerance: float = 0.0) -> bool: # Task B
def contains(self, point: Point2D) -> bool:
# Task A: remove duplication by defining a function
# that checks if a value is within an interval
# and reuse that here.
ll_px = point.x - self._lower_left.x
ll_py = point.y - self._lower_left.y
return ll_px >= 0 and ll_px <= self._dx \
and ll_py >= 0 and ll_py <= self._dy
def _is_idx_on_upper_edge(self, i: int) -> bool:
return i in [2, 3]
def _is_idx_on_right_edge(self, i: int) -> bool:
return i in [1, 3]
# def is_in_interval(...) -> bool: # Task A
def test_rectangle_contains_exact() -> None:
rectangle = Rectangle(lower_left=Point2D(1.0, 2.0), dx=2.5, dy=1.5)
for i in range(4):
assert rectangle.contains(rectangle.corner(i))
def test_rectangle_contains_tolerance() -> None:
rectangle = Rectangle(lower_left=Point2D(1.0, 2.0), dx=2.5, dy=1.5)
lower_left = rectangle.corner(0)
lower_right = rectangle.corner(1)
upper_left = rectangle.corner(2)
upper_right = rectangle.corner(3)
assert rectangle.contains(lower_left)
assert rectangle.contains(upper_left)
assert rectangle.contains(lower_right)
assert rectangle.contains(upper_right)
eps = 1e-10
lower_left -= Vector([eps, eps])
lower_right += Vector([eps, -eps])
upper_left += Vector([-eps, eps])
upper_right += Vector([eps, eps])
assert not rectangle.contains(lower_left)
assert not rectangle.contains(upper_left)
assert not rectangle.contains(lower_right)
assert not rectangle.contains(upper_right)
# Task B: make the tests below pass by adding optional tolerance argument to `contains`
assert not rectangle.contains(lower_left, tolerance=eps/2.0)
assert not rectangle.contains(upper_left, tolerance=eps/2.0)
assert not rectangle.contains(lower_right, tolerance=eps/2.0)
assert not rectangle.contains(upper_right, tolerance=eps/2.0)
assert rectangle.contains(lower_left, tolerance=eps*2.0)
assert rectangle.contains(upper_left, tolerance=eps*2.0)
assert rectangle.contains(lower_right, tolerance=eps*2.0)
assert rectangle.contains(upper_right, tolerance=eps*2.0)