-
Notifications
You must be signed in to change notification settings - Fork 0
/
Drawing.py
142 lines (112 loc) · 3.77 KB
/
Drawing.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
from pygame import Color, Rect
from typing import Union
class DrawingObject():
"""
To be inherited from
"""
def __init__(self) -> None:
pass
class DrawingLine():
"""
To store lines with color, start pos, end pos, and thickness
"""
color: Union[tuple[int, int, int, int], Color]
start: tuple[int, int]
end: tuple[int, int]
thickness: int
def __init__(self, color: Union[tuple[int, int, int, int], Color], start: tuple[int, int], end: tuple[int, int], thickness: int) -> None:
self.color = color
self.start = start
self.end = end
self.thickness = thickness
def __repr__(self) -> str:
return f"Line from {self.start} to {self.end}"
# class DrawingDot():
# """
# To store dots with color, radius, center
# """
# color: tuple[int, int, int, int]
# center: tuple[int, int]
# radius: int
# def __init__(self, color: tuple[int, int, int, int], center: tuple[int, int], radius: int) -> None:
# self.color = color
# self.center = center
# self.radius = radius
# def __repr__(self) -> str:
# return f"Dot at {self.center}"
class DrawingClipboard():
"""
Stores drawing rects to be rendered and erased.
Singleton object, stores ALL drawingObjects
"""
objs: list[DrawingLine]
def __init__(self) -> None:
self.objs = []
def addLines(self, line: DrawingLine) -> None:
self.objs.append(line)
def check_collision_line(self, line: DrawingLine, rect: Rect) -> bool:
"""
Check if <rect> collides with any lines
"""
if line.start[0] < line.end[0]:
x1, y1 = line.start[0], line.start[1]
x2, y2 = line.end[0], line.end[1]
else:
x1, y1 = line.end[0], line.end[1]
x2, y2 = line.start[0], line.start[1]
try:
slope = (y2 - y1) / (x2 - x1)
b = y1 - (slope * x1)
while x1 < x2:
y = (slope * x1) + b
if rect.collidepoint(x1, y):
return True
x1 += 1
except ZeroDivisionError: # Horizontal line
if y1 < y2:
start, end = y1, y2
else:
start, end = y2, y1
while start < end:
if rect.collidepoint(x1, start):
return True
start += 1
return False
# def check_collision_dot(self, dot: DrawingDot, rect: Rect) -> bool:
# """
# Check if rect collides with <dot>
# """
# h, k = dot.center
# r = dot.radius
# for x in range(h - r, h + r + 1):
# for y in range(k - r, k + r + 1):
# if rect.collidepoint(x, y):
# return True
# return False
def find_collision(self, obj, rect: Rect) -> bool:
if isinstance(obj, DrawingLine):
return self.check_collision_line(obj, rect)
# elif isinstance(obj, DrawingDot):
# return self.check_collision_dot(obj, rect)
return False
def findLine(self, rect: Rect) -> list[DrawingLine]:
"""
Find the lines that collide with <rect>
"""
to_return = []
for obj in self.objs:
if self.find_collision(obj, rect):
to_return.append(obj)
return to_return
def eraseAt(self, rect: Rect) -> None:
"""
Erases the lines that collide with <rect>
"""
for obj in self.objs:
if self.find_collision(obj, rect):
self.objs.remove(obj)
def clearBoard(self) -> None:
"""
Clears all lines
"""
self.objs = []