-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathview.py
66 lines (51 loc) · 2.01 KB
/
view.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
from typing import Union
class View:
def __init__(self, left, top, right, bottom):
self.left = left
self.top = top
self.right = right
self.bottom = bottom
def intersection(self, other) -> Union["View", None]:
left = max(self.left, other.left)
top = max(self.top, other.top)
right = min(self.right, other.right)
bottom = min(self.bottom, other.bottom)
if left < right and top < bottom:
return View(left, top, right, bottom)
else:
return None
def translate(self, dx, dy) -> "View":
return View(self.left + dx, self.top + dy, self.right + dx, self.bottom + dy)
@staticmethod
def full():
return View(0, 0, 7930, 2808)
@property
def width(self):
return self.right - self.left
@property
def height(self):
return self.bottom - self.top
@staticmethod
def from_pts(pts: str) -> "View":
# Example: "4654,2127,4915,2322,pts"
tokens = pts.split(",")
assert len(tokens) == 5, "Invalid number of tokens"
assert tokens[-1] == "pts", "Invalid token"
left, top, right, bottom = map(float, tokens[:4])
return View(left, top, right, bottom)
def center(self):
return (self.right - self.left) // 2, (self.bottom - self.top) // 2
def expose(self) -> tuple[float, float, float, float]:
return self.left, self.top, self.right, self.bottom
def subsample(self, level) -> "View":
assert (level & (level - 1)) == 0, "Expected level to be power of 2."
return View(
int(round(self.left / level)),
int(round(self.top / level)),
int(round(self.right / level)),
int(round(self.bottom / level))
)
def to_pts(self):
return f"{','.join(map(str, [int(num) if num.is_integer() else num for num in self.expose()]))},pts"
def __repr__(self):
return f"View(left={self.left}, top={self.top}, right={self.right}, bottom={self.bottom})"