-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgui.py
More file actions
297 lines (231 loc) · 12.5 KB
/
Copy pathgui.py
File metadata and controls
297 lines (231 loc) · 12.5 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
from tkinter import *
from PIL import ImageTk, Image
from vectors import Vector, radiansToDegrees
import numpy as np
def abs(a):
return (a >= 0) * a + (a < 0) * (-1) * a
class App(Frame):
def __init__(self, master=Tk(), width=500, height=500, x_axis_scale=100, y_axis_scale=100, drag_scale=0.01, scroll_scale = 0.1,
markings_space = 1, lower_bound = -1, upper_bound = 1, small_step = 0.05,
generate_axis = False, generate_markings = False, x_marking = True, y_marking = True, z_marking = True,
x_color = "red", y_color = "blue", z_color = "green", title="3D viewer - tkinter and numpy"
):
#App and windows settings
Frame.__init__(self, master)
self.master = master
master.title(title)
self.width = width
self.height = height
self.x_color = x_color
self.y_color = y_color
self.z_color = z_color
self.lower_bound = lower_bound # of axis
self.upper_bound = upper_bound # of axis
self.small_step = small_step # defult value of dx/dy/dz
self.generate_axis = generate_axis
self.generate_markings = generate_markings
self.markings_space = markings_space
self.x_marking = x_marking
self.y_marking = y_marking
self.z_marking = z_marking
#Bind Actions to keys
self.master.bind('<Key>', lambda e: self.keyPress(e))
self.master.bind('<KeyRelease>', lambda e: self.keyRelease(e))
self.master.bind('<Button-1>', lambda e: self.clickScreen(e))
self.master.bind('<B1-Motion>', lambda e: self.dragScreen(e))
self.master.bind('<MouseWheel>', lambda e: self.scrollScreen(e))
self.master.bind("<Escape>", lambda x: master.destroy())
#Create canvas for 3d
self.app_canvas = Canvas(master, height=self.height, width=self.width, bg='grey')
self.all_vectors = []
#3d person viewing settings
self.x_axis_scale = x_axis_scale #How much to scale the screen X axis
self.y_axis_scale = y_axis_scale #How much to scale the screen Y axis
self.root_point = np.array([self.width / 2, self.height / 2]) #Where the (0,0) of the screen X and Y axis is located
self.drag_scale = drag_scale #How Sensitive the changes to the mouse drag
self.scroll_scale = scroll_scale
#Where camera is located in the app world
self.camera_vector = Vector([0,0,0],[0,0,1], display_on_screen=False, color='Blue')
#Where player clicks on the screen canvas
self.screen_x = 0
self.screen_y = 0
#What the X and Y vectors on the screen represent in the app
self.screen_x_vector = Vector([0,0,0],[1,0,0], display_on_screen=False) #What the X axis of the monitor represents
self.screen_y_vector = Vector([0,0,0],[0,1,0], display_on_screen=False) #What the Y axis of the monitor represents
#Create Axis Lines X/Y/Z
if (self.generate_axis == True):
self.generateAxis()
#Create Ticks on X/Y/Z
if (self.generate_markings == True):
self.generateMarkLines()
def clickScreen(self, e):
self.screen_x = e.x
self.screen_y = e.y
def scrollScreen(self, e):
delta = e.delta / 120
self.modifyVectors(scale= 1 + delta * self.scroll_scale)
def dragScreen(self, e):
diff_x = e.x - self.screen_x
diff_y = e.y - self.screen_y
#The camera vector rotates around the screen_x_vector with diff_y and around the screen_y_vector with diff_x
#The camera is perpendicular to the XY plane
self.camera_vector.vector = np.cross(self.screen_x_vector.vector, self.screen_y_vector.vector)
#Modify all vectors according to the screen drage
self.modifyVectors(diff_x, diff_y)
#Assign current x, y to where the player last clicked
self.screen_x = e.x
self.screen_y = e.y
def changeCameraAngle(self, x_vector, y_vector, camera_vector):
if x_vector != [0,0,0]:
self.screen_x_vector.end_point[0] = x_vector[0]
self.screen_x_vector.end_point[1] = x_vector[1]
self.screen_x_vector.end_point[2] = x_vector[2]
if y_vector != [0,0,0]:
self.screen_y_vector.end_point[0] = y_vector[0]
self.screen_y_vector.end_point[1] = y_vector[1]
self.screen_y_vector.end_point[2] = y_vector[2]
if camera_vector != [0,0,0]:
self.camera_vector.end_point[0] = camera_vector[0]
self.camera_vector.end_point[1] = camera_vector[1]
self.camera_vector.end_point[2] = camera_vector[2]
screen_vectors = [self.screen_x_vector, self.screen_y_vector, self.camera_vector]
for v in Vector.all_vectors:
if v not in screen_vectors:
pass
def keyPress(self, e):
#Walk Down
if e.char == 's' or e.char == 'S':
self.modifyVectors(move_y=1)
#Walk Up
elif e.char == 'w' or e.char == 'W':
self.modifyVectors(move_y=-1)
#Walk left
elif e.char == 'a' or e.char == 'A':
self.modifyVectors(move_x=1)
#Walk right
elif e.char == 'd' or e.char == 'D':
self.modifyVectors(move_x=-1)
elif e.char == 'z' or e.char == 'Z':
self.changeCameraAngle([1,0,0], [0,1,0], [0,0,1])
def keyRelease(self, e):
#print (e.char, 'KeyRelease')
pass
def packObjects(self):
self.app_canvas.pack(fill="both", expand=True)
def modifyVectors(self, diff_x=0, diff_y=0, move_x=0, move_y=0, move_z=0, scale=1):
screen_vectors = [self.screen_x_vector, self.screen_y_vector, self.camera_vector]
#Start with screen_vectors
for v in screen_vectors:
self.modifySingleVector(v=v, diff_x=diff_x, diff_y=diff_y, move_x=move_x, move_y=move_y, move_z=move_z, screen_vectors=screen_vectors, scale=scale)
#Then on to all other vectors
for v in self.all_vectors:
if v not in screen_vectors:
self.modifySingleVector(v=v, diff_x=diff_x, diff_y=diff_y, move_x=move_x, move_y=move_y, move_z=move_z, screen_vectors=screen_vectors, scale=scale)
def modifySingleVector(self, v=Vector([0,0,0], [0,0,0]), diff_x=0, diff_y=0, move_x=0, move_y=0, move_z=0, screen_vectors=[], scale = 1):
#Scale vector if user scrolled mouse
v.start_point[0] *= scale
v.start_point[1] *= scale
v.start_point[2] *= scale
v.end_point[0] *= scale
v.end_point[1] *= scale
v.end_point[2] *= scale
# Rotate Vector according to the current screen_x/y axis
if diff_x != 0:
v.rotateAroundAnotherVector(axis_vector=self.screen_y_vector, angle_of_rotation=diff_x)
if diff_y != 0:
v.rotateAroundAnotherVector(axis_vector=self.screen_x_vector, angle_of_rotation=diff_y)
if v not in screen_vectors:
#If objects are moving
if move_x != 0:
v.start_point += self.screen_x_vector.vector * move_x
v.end_point += self.screen_x_vector.vector * move_x
if move_y != 0:
v.start_point += self.screen_y_vector.vector * move_y
v.end_point += self.screen_y_vector.vector * move_y
#Modify the 2d representation of the vector in a 3d space
#Set start point and end point Vectors
start_point_vector = Vector(end_point=v.start_point, temp_vector=True)
end_point_vector = Vector(end_point=v.end_point, temp_vector=True)
#Get 2d coordinates of the start and the end of the 2d vector on that plane
v.screen_start_point = start_point_vector.get2dCoordinates(self.screen_x_vector, self.screen_y_vector)
v.screen_end_point = end_point_vector.get2dCoordinates(self.screen_x_vector, self.screen_y_vector)
scale_x = self.x_axis_scale
scale_y = self.y_axis_scale
root_point_x = self.root_point[0]
root_point_y = self.root_point[1]
x1 = -1 * v.screen_start_point [0]
y1 = v.screen_start_point[1]
x2 = -1 * v.screen_end_point[0]
y2 = v.screen_end_point[1]
self.app_canvas.coords(v.canvas_object,
#X1, Y1
root_point_x - x1 * scale_x, root_point_y - y1 * scale_y,
#X2, Y2
root_point_x - x2 * scale_x, root_point_y - y2 * scale_y
)
#Vector.deleteAllTempVecotrs(Vector)
def generateVectors(self):
for v in Vector.all_vectors:
if v.display_on_screen == True:
scale_x = self.x_axis_scale
scale_y = self.y_axis_scale
root_point_x = self.root_point[0]
root_point_y = self.root_point[1]
x1 = v.screen_start_point[0]
y1 = v.screen_start_point[1]
x2 = v.screen_end_point[0]
y2 = v.screen_end_point[1]
arrow_option = NONE
if (v.arrow == True):
arrow_option = LAST
#If the vector on this plane equals 0 create a little line
if (x2 != x1 or y2 != y2):
v.canvas_object = self.app_canvas.create_line(
# X1, Y1
root_point_x - x1 * scale_x, root_point_y - y1 * scale_y,
# X2, Y2
root_point_x - x2 * scale_x, root_point_y - y2 * scale_y,
fill=v.color, arrow=arrow_option, width=v.line_width
)
else:
v.canvas_object = self.app_canvas.create_line(0, 0, 1, 1, fill=v.color, arrow=arrow_option)
self.all_vectors.append(v)
def generateAxis(self):
x_axis = Vector([self.lower_bound, 0, 0], [self.upper_bound, 0, 0], color=self.x_color, arrow=True)
y_axis = Vector([0, self.lower_bound, 0], [0, self.upper_bound, 0], color=self.y_color, arrow=True)
z_axis = Vector([0, 0, self.lower_bound], [0, 0, self.upper_bound], color=self.z_color, arrow=True)
def generateMarkLines(self):
small_step = self.small_step
lower_bound = self.lower_bound
upper_bound = self.upper_bound
x = lower_bound
y = lower_bound
z = lower_bound
smaller_axis_scaler = 1.5
while (x != upper_bound and self.x_marking):
if x != 0:
if (x % 1 == 0):
Vector([x, small_step, 0], [x, (-1) * small_step, 0], color=self.x_color)
Vector([x, 0, small_step], [x, 0, (-1) * small_step], color=self.x_color)
else:
Vector([x, small_step * smaller_axis_scaler, 0], [x, (-1) * small_step * smaller_axis_scaler , 0], color=self.x_color)
Vector([x, 0, small_step * smaller_axis_scaler], [x, 0, (-1) * small_step * smaller_axis_scaler ], color=self.x_color)
x += self.markings_space
while (y != upper_bound and self.y_marking):
if y != 0:
if (y % 1 == 0):
Vector([small_step, y, 0], [(-1) * small_step, y, 0], color=self.y_color)
Vector([0, y, small_step], [0, y, (-1) * small_step], color=self.y_color)
else:
Vector([small_step * smaller_axis_scaler, y, 0], [(-1) * small_step * smaller_axis_scaler, y, 0], color=self.y_color)
Vector([0, y, small_step * smaller_axis_scaler], [0, y, (-1) * small_step * smaller_axis_scaler], color=self.y_color)
y += self.markings_space
while (z != upper_bound and self.z_marking):
if z != 0:
if (z % 1 == 0):
Vector([small_step, 0, z], [(-1) * small_step, 0, z], color=self.z_color)
Vector([0, small_step, z], [0, (-1) * small_step, z], color=self.z_color)
else:
Vector([small_step * smaller_axis_scaler, 0, z], [(-1) * small_step * smaller_axis_scaler, 0, z], color=self.z_color)
Vector([0, small_step * smaller_axis_scaler, z], [0, (-1) * small_step * smaller_axis_scaler, z], color=self.z_color)
z += self.markings_space