blob: e59286f735503b57199fdcb9003f9767c03271cc [file] [log] [blame]
Tabitha Jarvis1007a132018-12-12 21:47:54 -08001#!/usr/bin/python3
Tabitha Jarvis1007a132018-12-12 21:47:54 -08002from __future__ import print_function
3import os
Andrew Runke0f945fd2019-01-27 21:10:37 -08004import sys
Andrew Runke6842bf92019-01-26 15:38:25 -08005import copy
Tabitha Jarvis1007a132018-12-12 21:47:54 -08006import basic_window
7from color import Color, palette
8import random
9import gi
10import numpy as np
Andrew Runke6842bf92019-01-26 15:38:25 -080011from libspline import Spline
Tabitha Jarvis1007a132018-12-12 21:47:54 -080012import scipy.spatial.distance
13gi.require_version('Gtk', '3.0')
Andrew Runke6842bf92019-01-26 15:38:25 -080014from gi.repository import Gdk, Gtk, GLib
Tabitha Jarvis1007a132018-12-12 21:47:54 -080015import cairo
Tabitha Jarvis1007a132018-12-12 21:47:54 -080016import enum
Andrew Runke0f945fd2019-01-27 21:10:37 -080017import json # For writing to json files
Tabitha Jarvis1007a132018-12-12 21:47:54 -080018
19from basic_window import OverrideMatrix, identity, quit_main_loop, set_color
20
John Park13d3e282019-01-26 20:16:48 -080021WIDTH_OF_FIELD_IN_METERS = 8.258302
Tabitha Jarvis1007a132018-12-12 21:47:54 -080022PIXELS_ON_SCREEN = 300
23
Andrew Runke6842bf92019-01-26 15:38:25 -080024
John Park13d3e282019-01-26 20:16:48 -080025def pxToM(p):
26 return p * WIDTH_OF_FIELD_IN_METERS / PIXELS_ON_SCREEN
Andrew Runke6842bf92019-01-26 15:38:25 -080027
Tabitha Jarvis1007a132018-12-12 21:47:54 -080028
John Parka30a7782019-02-01 18:47:26 -080029def mToPx(m):
30 return (m*PIXELS_ON_SCREEN/WIDTH_OF_FIELD_IN_METERS)
Tabitha Jarvis1007a132018-12-12 21:47:54 -080031
32def px(cr):
33 return OverrideMatrix(cr, identity)
34
Andrew Runke6842bf92019-01-26 15:38:25 -080035
Tabitha Jarvis1007a132018-12-12 21:47:54 -080036def draw_px_cross(cr, x, y, length_px, color=palette["RED"]):
37 """Draws a cross with fixed dimensions in pixel space."""
38 set_color(cr, color)
39 cr.move_to(x, y - length_px)
40 cr.line_to(x, y + length_px)
41 cr.stroke()
42
43 cr.move_to(x - length_px, y)
44 cr.line_to(x + length_px, y)
45 cr.stroke()
46 set_color(cr, palette["LIGHT_GREY"])
47
Andrew Runke6842bf92019-01-26 15:38:25 -080048
Tabitha Jarvis1007a132018-12-12 21:47:54 -080049def draw_px_x(cr, x, y, length_px1, color=palette["BLACK"]):
50 """Draws a x with fixed dimensions in pixel space."""
51 length_px = length_px1 / np.sqrt(2)
52 set_color(cr, color)
53 cr.move_to(x - length_px, y - length_px)
54 cr.line_to(x + length_px, y + length_px)
55 cr.stroke()
56
57 cr.move_to(x - length_px, y + length_px)
58 cr.line_to(x + length_px, y - length_px)
59 cr.stroke()
60 set_color(cr, palette["LIGHT_GREY"])
61
Andrew Runke6842bf92019-01-26 15:38:25 -080062
Tabitha Jarvis1007a132018-12-12 21:47:54 -080063def draw_points(cr, p, size):
64 for i in range(0, len(p)):
Andrew Runke6842bf92019-01-26 15:38:25 -080065 draw_px_cross(cr, p[i][0], p[i][1], size, Color(
66 0, np.sqrt(0.2 * i), 0))
67
Tabitha Jarvis1007a132018-12-12 21:47:54 -080068
69class Mode(enum.Enum):
70 kViewing = 0
71 kPlacing = 1
72 kEditing = 2
73 kExporting = 3
74 kImporting = 4
Andrew Runke6842bf92019-01-26 15:38:25 -080075 kConstraint = 5
76
77
78class ConstraintType(enum.Enum):
79 kMaxSpeed = 0
80 kMaxAcceleration = 1
81
Tabitha Jarvis1007a132018-12-12 21:47:54 -080082
83def display_text(cr, text, widtha, heighta, widthb, heightb):
84 cr.scale(widtha, -heighta)
85 cr.show_text(text)
86 cr.scale(widthb, -heightb)
87
Andrew Runke6842bf92019-01-26 15:38:25 -080088
89def redraw(needs_redraw, window):
90 print("Redrew")
91 if not needs_redraw:
92 window.queue_draw()
93
94
95class Constraint():
96 def __init__(self, start, end, constraint, value):
97 self.start = start #Array with index and distance from start of spline
98 self.end = end #Array with index and distance from start of spline
99 self.constraint = constraint #INT
100 self.value = value #INT
101 if self.constraint == 0:
102 self.conName = "kMaxSpeed"
103 else:
104 self.conName = "kMaxAcceleration"
105
106 def toString(self):
107
108 return "START: " + str(self.start[0]) + ", " + str(
109 self.start[1]) + " | END: " + str(self.end[0]) + ", " + str(
110 self.end[1]) + " | " + str(self.conName) + ": " + str(
111 self.value)
112
113
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800114class GTK_Widget(basic_window.BaseWindow):
Andrew Runke6842bf92019-01-26 15:38:25 -0800115 """Create a GTK+ widget on which we will draw using Cairo"""
116
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800117 def __init__(self):
118 super(GTK_Widget, self).__init__()
119
120 # init field drawing
121 # add default spline for testing purposes
122 # init editing / viewing modes and pointer location
123 self.mode = Mode.kPlacing
124 self.x = 0
125 self.y = 0
126
Andrew Runke0f945fd2019-01-27 21:10:37 -0800127 module_path = os.path.dirname(os.path.realpath(sys.argv[0]))
128 self.path_to_export = os.path.join(module_path,
129 'points_for_pathedit.json')
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800130 # update list of control points
131 self.point_selected = False
132 # self.adding_spline = False
133 self.index_of_selected = -1
134 self.new_point = []
135
136 # For the editing mode
Andrew Runke6842bf92019-01-26 15:38:25 -0800137 self.index_of_edit = -1 # Can't be zero beause array starts at 0
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800138 self.held_x = 0
Andrew Runke6842bf92019-01-26 15:38:25 -0800139 self.spline_edit = -1
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800140
Andrew Runke6842bf92019-01-26 15:38:25 -0800141 self.curves = []
142
143 self.colors = []
144
145 for c in palette:
146 self.colors.append(palette[c])
147
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800148 self.selected_points = []
Andrew Runke6842bf92019-01-26 15:38:25 -0800149 self.splines = []
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800150 self.reinit_extents()
151
Andrew Runke6842bf92019-01-26 15:38:25 -0800152 self.inStart = None
153 self.inEnd = None
154 self.inConstraint = None
155 self.inValue = None
156 self.startSet = False
157
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800158 #John also wrote this
159 def add_point(self, x, y):
Andrew Runke6842bf92019-01-26 15:38:25 -0800160 if (len(self.selected_points) < 6):
John Park13d3e282019-01-26 20:16:48 -0800161 self.selected_points.append([pxToM(x), pxToM(y)])
Andrew Runke6842bf92019-01-26 15:38:25 -0800162 if (len(self.selected_points) == 6):
163 self.mode = Mode.kEditing
164 self.splines.append(np.array(self.selected_points))
165 self.selected_points = []
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800166
Andrew Runke6842bf92019-01-26 15:38:25 -0800167 """set extents on images"""
168
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800169 def reinit_extents(self):
170 self.extents_x_min = -800
171 self.extents_x_max = 800
172 self.extents_y_min = -800
173 self.extents_y_max = 800
174
175 # this needs to be rewritten with numpy, i dont think this ought to have
176 # SciPy as a dependecy
177 def get_index_of_nearest_point(self):
178 cur_p = [[self.x, self.y]]
179 distances = scipy.spatial.distance.cdist(cur_p, self.all_controls)
180
181 return np.argmin(distances)
182
183 # return the closest point to the loc of the click event
184 def get_nearest_point(self):
185 return self.all_controls[self.get_index_of_nearest_point()]
186
Andrew Runke6842bf92019-01-26 15:38:25 -0800187 def set_index_to_nearest_spline_point(self):
188 nearest = 50
189 index_of_closest = 0
190 self.spline_edit = 0
191 cur_p = [self.x, self.y]
192
193 for index_splines, points in enumerate(self.spline):
John Park13d3e282019-01-26 20:16:48 -0800194 for index_points, point in enumerate(points.curve):
Andrew Runke6842bf92019-01-26 15:38:25 -0800195 # pythagorean
John Park13d3e282019-01-26 20:16:48 -0800196 distance = np.sqrt((cur_p[0] - mToPx(point[0]))**2 +
197 (cur_p[1] - mToPx(point[1])**2))
Andrew Runke6842bf92019-01-26 15:38:25 -0800198 if distance < nearest:
199 nearest = distance
200 print("DISTANCE: ", distance, " | INDEX: ", index_points)
201 index_of_closest = index_points
202 self.index_of_edit = index_of_closest
203 self.spline_edit = index_splines
204 self.held_x = self.x
205 if self.startSet == False:
206 self.inStart = [self.index_of_edit, self.findDistance()]
207 self.startSet = True
208 else:
209 self.inEnd = [self.index_of_edit, self.findDistance()]
Andrew Runke6842bf92019-01-26 15:38:25 -0800210 self.startSet = False
211 self.mode = Mode.kEditing
212 self.spline_edit = -1
213 self.index_of_edit = -1
214
215 print("Nearest: " + str(nearest))
216 print("Spline: " + str(self.spline_edit))
217 print("Index: " + str(index_of_closest))
218
219 def findDistance(self):
220 """ findDistance goes through each point on the spline finding distance to that point from the point before.
221 It does this to find the the length of the spline to the point that is currently selected.
222 """
223 distance = 0
224 points = self.curves[self.spline_edit]
225 for index, point in enumerate(points):
226 if index > 0 and index <= self.index_of_edit:
227 distance += np.sqrt((points[index - 1][0] - point[0])**2 +
228 (points[index - 1][1] - point[1])**2)
John Park13d3e282019-01-26 20:16:48 -0800229 return distance
Andrew Runke6842bf92019-01-26 15:38:25 -0800230
John Parka30a7782019-02-01 18:47:26 -0800231 def draw_HAB(self, cr):
232 print("WENT IN")
233 # BASE Constants
234 X_BASE = -450+mToPx(2.41568)
235 Y_BASE = -150+mToPx(4.129151)
236
237 BACKWALL_X = -450
238
239 # HAB Levels 2 and 3 called in variables backhab
240
241 WIDTH_BACKHAB = mToPx(1.2192)
242
243 Y_TOP_BACKHAB_BOX = Y_BASE + mToPx(0.6096)
244 BACKHAB_LV2_LENGTH = mToPx(1.016)
245
246 BACKHAB_LV3_LENGTH = mToPx(1.2192)
247 Y_LV3_BOX = Y_TOP_BACKHAB_BOX - BACKHAB_LV3_LENGTH
248
249 Y_BOTTOM_BACKHAB_BOX = Y_LV3_BOX -BACKHAB_LV2_LENGTH
250
251 # HAB LEVEL 1
252 X_LV1_BOX = BACKWALL_X + WIDTH_BACKHAB
253
254 WIDTH_LV1_BOX = mToPx(0.90805)
255 LENGTH_LV1_BOX = mToPx(1.6256)
256
257 Y_BOTTOM_LV1_BOX = Y_BASE - LENGTH_LV1_BOX
258
259 # Ramp off Level 1
260 X_RAMP = X_LV1_BOX
261
262 Y_TOP_RAMP = Y_BASE + LENGTH_LV1_BOX
263 WIDTH_TOP_RAMP = mToPx(1.20015)
264 LENGTH_TOP_RAMP = Y_BASE + mToPx(0.28306)
265
266 X_MIDDLE_RAMP = X_RAMP + WIDTH_LV1_BOX
267 Y_MIDDLE_RAMP = Y_BOTTOM_LV1_BOX
268 LENGTH_MIDDLE_RAMP = 2*LENGTH_LV1_BOX
269 WIDTH_MIDDLE_RAMP = WIDTH_TOP_RAMP - WIDTH_LV1_BOX
270
271 Y_BOTTOM_RAMP = Y_BASE - LENGTH_LV1_BOX - LENGTH_TOP_RAMP
272
273 # Side Bars to Hold in balls
274 X_BARS = BACKWALL_X
275 WIDTH_BARS = WIDTH_BACKHAB
276 LENGTH_BARS = mToPx(0.574675)
277
278 Y_TOP_BAR = Y_TOP_BACKHAB_BOX + BACKHAB_LV2_LENGTH
279
280 Y_BOTTOM_BAR = Y_BOTTOM_BACKHAB_BOX - LENGTH_BARS
281
282 set_color(cr, palette["BLACK"])
283 cr.rectangle(BACKWALL_X, Y_TOP_BACKHAB_BOX, WIDTH_BACKHAB,
284 BACKHAB_LV2_LENGTH)
285 cr.rectangle(BACKWALL_X, Y_LV3_BOX, WIDTH_BACKHAB,
286 BACKHAB_LV3_LENGTH)
287 cr.rectangle(BACKWALL_X, Y_BOTTOM_BACKHAB_BOX, WIDTH_BACKHAB,
288 BACKHAB_LV2_LENGTH)
289 cr.rectangle(X_LV1_BOX, Y_BASE, WIDTH_LV1_BOX, LENGTH_LV1_BOX)
290 cr.rectangle(X_LV1_BOX, Y_BOTTOM_LV1_BOX, WIDTH_LV1_BOX,
291 LENGTH_LV1_BOX)
292 cr.rectangle(X_RAMP, Y_TOP_RAMP, WIDTH_TOP_RAMP, LENGTH_TOP_RAMP)
293 cr.rectangle(X_MIDDLE_RAMP, Y_MIDDLE_RAMP, WIDTH_MIDDLE_RAMP,
294 LENGTH_MIDDLE_RAMP)
295 cr.rectangle(X_RAMP, Y_BOTTOM_RAMP, WIDTH_TOP_RAMP, LENGTH_TOP_RAMP)
296 cr.rectangle(X_BARS, Y_TOP_BAR, WIDTH_BARS, LENGTH_BARS)
297 cr.rectangle(X_BARS, Y_BOTTOM_BAR, WIDTH_BARS, LENGTH_BARS)
298 cr.stroke()
299 #draw_px_x(cr, BACKWALL_X, 0, 10) # Midline Point
300 #draw_px_x(cr, X_BASE, Y_BASE, 10) # Bases
301 cr.set_line_join(cairo.LINE_JOIN_ROUND)
302
303 cr.stroke()
304
John Park9208ef92019-02-01 19:47:30 -0800305 def draw_rockets(self, cr):
306 # BASE Constants
307 X_BASE = -450+mToPx(2.41568)
308 Y_BASE = -150+mToPx(4.129151)
309
310 # Top Rocket
311
312 # Leftmost Line
313 cr.move_to(X_BASE + mToPx(2.89973), Y_BASE + mToPx(3.86305))
314 cr.line_to(X_BASE + mToPx(3.15642), Y_BASE + mToPx(3.39548))
315
316 # Top Line
317 cr.move_to(X_BASE + mToPx(3.15642), Y_BASE + mToPx(3.39548))
318 cr.line_to(X_BASE + mToPx(3.63473), Y_BASE + mToPx(3.39238))
319
320 #Rightmost Line
321 cr.move_to(X_BASE + mToPx(3.63473), Y_BASE + mToPx(3.39238))
322 cr.line_to(X_BASE + mToPx(3.89984), Y_BASE + mToPx(3.86305))
323
324 #Back Line
325 cr.move_to(X_BASE + mToPx(2.89973), Y_BASE + mToPx(3.86305))
326 cr.line_to(X_BASE + mToPx(3.89984), Y_BASE + mToPx(3.86305))
327
328 # Bottom Rocket
329
330 # Leftmost Line
331 cr.move_to(X_BASE + mToPx(2.89973), Y_BASE - mToPx(3.86305))
332 cr.line_to(X_BASE + mToPx(3.15642), Y_BASE - mToPx(3.39548))
333
334 # Top Line
335 cr.move_to(X_BASE + mToPx(3.15642), Y_BASE - mToPx(3.39548))
336 cr.line_to(X_BASE + mToPx(3.63473), Y_BASE - mToPx(3.39238))
337
338 #Rightmost Line
339 cr.move_to(X_BASE + mToPx(3.63473), Y_BASE - mToPx(3.39238))
340 cr.line_to(X_BASE + mToPx(3.89984), Y_BASE - mToPx(3.86305))
341
342 #Back Line
343 cr.move_to(X_BASE + mToPx(2.89973), Y_BASE - mToPx(3.86305))
344 cr.line_to(X_BASE + mToPx(3.89984), Y_BASE - mToPx(3.86305))
345
346 cr.stroke()
347
John Park9a25a232019-02-01 20:18:39 -0800348 def draw_cargo_ship(self, cr):
349 # BASE Constants
350 X_BASE = -450+mToPx(2.41568)
351 Y_BASE = -150+mToPx(4.129151)
352
353 cr.rectangle(X_BASE + mToPx(3.15912), Y_BASE - mToPx(0.72326),
354 mToPx(2.43205), mToPx(1.41605))
355
356 cr.stroke()
357
John Parka30a7782019-02-01 18:47:26 -0800358 def draw_field_elements(self, cr):
359 self.draw_HAB(cr)
John Park9208ef92019-02-01 19:47:30 -0800360 self.draw_rockets(cr)
John Park9a25a232019-02-01 20:18:39 -0800361 self.draw_cargo_ship(cr)
John Parka30a7782019-02-01 18:47:26 -0800362
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800363 def handle_draw(self, cr):
Andrew Runke6842bf92019-01-26 15:38:25 -0800364 # print(self.new_point)
365 # print("SELF.POINT_SELECTED: " + str(self.point_selected))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800366
367 # begin drawing
368 # Fill the background color of the window with grey
369 set_color(cr, palette["GREY"])
370 cr.paint()
Andrew Runkea9c8de52019-01-26 19:54:29 -0800371 #Scale the field to fit within drawing area
Andrew Runke6696bb82019-02-02 14:33:59 -0800372 cr.scale(0.5, 0.5)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800373
374 # Draw a extents rectangle
375 set_color(cr, palette["WHITE"])
376 cr.rectangle(self.extents_x_min, self.extents_y_min,
377 (self.extents_x_max - self.extents_x_min),
378 self.extents_y_max - self.extents_y_min)
379 cr.fill()
380
John Parka30a7782019-02-01 18:47:26 -0800381 #Drawing the field
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800382 cr.move_to(0, 50)
383 cr.show_text('Press "e" to export')
384 cr.show_text('Press "i" to import')
385
386 set_color(cr, Color(0.3, 0.3, 0.3))
Andrew Runke6842bf92019-01-26 15:38:25 -0800387 cr.rectangle(-450, -150, 300, 300)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800388 cr.fill()
389 set_color(cr, palette["BLACK"])
Andrew Runke6842bf92019-01-26 15:38:25 -0800390 cr.rectangle(-450, -150, 300, 300)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800391 cr.set_line_join(cairo.LINE_JOIN_ROUND)
392 cr.stroke()
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800393
John Parka30a7782019-02-01 18:47:26 -0800394 self.draw_field_elements(cr)
395
Andrew Runke6842bf92019-01-26 15:38:25 -0800396 y = 0
Andrew Runke6842bf92019-01-26 15:38:25 -0800397
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800398 # update all the things
399
400 if self.mode == Mode.kViewing:
401 set_color(cr, palette["BLACK"])
402 cr.move_to(-300, 170)
403 cr.show_text("VIEWING")
404 set_color(cr, palette["GREY"])
Andrew Runke6842bf92019-01-26 15:38:25 -0800405
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800406 if len(self.selected_points) > 0:
407 print("SELECTED_POINTS: " + str(len(self.selected_points)))
408 print("ITEMS:")
Andrew Runke6842bf92019-01-26 15:38:25 -0800409 # for item in self.selected_points:
410 # print(str(item))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800411 for i, point in enumerate(self.selected_points):
Andrew Runke6842bf92019-01-26 15:38:25 -0800412 # print("I: " + str(i))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800413 draw_px_x(cr, point[0], point[1], 10)
Andrew Runke6842bf92019-01-26 15:38:25 -0800414 cr.move_to(point[0], point[1] - 15)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800415 display_text(cr, str(i), 0.5, 0.5, 2, 2)
416
Andrew Runke6842bf92019-01-26 15:38:25 -0800417 elif self.mode == Mode.kPlacing:
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800418 set_color(cr, palette["BLACK"])
419 cr.move_to(-300, 170)
420 display_text(cr, "ADD", 1, 1, 1, 1)
421 set_color(cr, palette["GREY"])
Andrew Runke6842bf92019-01-26 15:38:25 -0800422
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800423 if len(self.selected_points) > 0:
424 print("SELECTED_POINTS: " + str(len(self.selected_points)))
425 print("ITEMS:")
426 for item in self.selected_points:
427 print(str(item))
428 for i, point in enumerate(self.selected_points):
429 print("I: " + str(i))
John Park13d3e282019-01-26 20:16:48 -0800430 draw_px_x(cr, mToPx(point[0]), mToPx(point[1]), 10)
431 cr.move_to(mToPx(point[0]), mToPx(point[1]) - 15)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800432 display_text(cr, str(i), 0.5, 0.5, 2, 2)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800433
434 elif self.mode == Mode.kEditing:
435 set_color(cr, palette["BLACK"])
436 cr.move_to(-300, 170)
437 display_text(cr, "EDITING", 1, 1, 1, 1)
Andrew Runke6842bf92019-01-26 15:38:25 -0800438 if len(self.splines) > 0:
Andrew Runke6842bf92019-01-26 15:38:25 -0800439 holder_spline = []
440 for i, points in enumerate(self.splines):
441 array = np.zeros(shape=(6, 2), dtype=float)
442 for j, point in enumerate(points):
John Park13d3e282019-01-26 20:16:48 -0800443 array[j, 0] = mToPx(point[0])
444 array[j, 1] = mToPx(point[1])
Andrew Runke6842bf92019-01-26 15:38:25 -0800445 spline = Spline(np.ascontiguousarray(np.transpose(array)))
446 for k in np.linspace(0.01, 1, 100):
Andrew Runke6842bf92019-01-26 15:38:25 -0800447 cr.move_to(
448 spline.Point(k - 0.01)[0],
449 spline.Point(k - 0.01)[1])
450 cr.line_to(spline.Point(k)[0], spline.Point(k)[1])
451 cr.stroke()
452 holding = [
453 spline.Point(k - 0.01)[0],
454 spline.Point(k - 0.01)[1]
455 ]
Andrew Runke6842bf92019-01-26 15:38:25 -0800456 holder_spline.append(holding)
457 self.curves.append(holder_spline)
458
459 for spline, points in enumerate(self.splines):
460 # for item in points:
461 # print(str(item))
462 for i, point in enumerate(points):
463 # print("I: " + str(i))
464 if spline == self.spline_edit and i == self.index_of_edit:
John Park13d3e282019-01-26 20:16:48 -0800465 draw_px_x(cr, mToPx(point[0]), mToPx(point[1]), 15,
Andrew Runke6842bf92019-01-26 15:38:25 -0800466 self.colors[spline])
467 elif (spline == 0 and not i == 5) or (not i == 0
468 and not i == 5):
John Park13d3e282019-01-26 20:16:48 -0800469 draw_px_x(cr, mToPx(point[0]), mToPx(point[1]), 10,
Andrew Runke6842bf92019-01-26 15:38:25 -0800470 self.colors[spline])
John Park13d3e282019-01-26 20:16:48 -0800471 cr.move_to(mToPx(point[0]), mToPx(point[1]) - 15)
Andrew Runke6842bf92019-01-26 15:38:25 -0800472 display_text(cr, str(i), 0.5, 0.5, 2, 2)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800473
Andrew Runke6842bf92019-01-26 15:38:25 -0800474 elif self.mode == Mode.kConstraint:
475 print("Drawn")
476 set_color(cr, palette["BLACK"])
477 cr.move_to(-300, 170)
478 display_text(cr, "Adding Constraint", 1, 1, 1, 1)
479 if len(self.splines) > 0:
480 # print("Splines: " + str(len(self.splines)))
481 # print("ITEMS:")
482 for s, points in enumerate(self.splines):
483 # for item in points:
484 # print(str(item))
485 for i, point in enumerate(points):
486 # print("I: " + str(i))
487 draw_px_x(cr, point[0], point[1], 10, self.colors[s])
488 cr.move_to(point[0], point[1] - 15)
489 display_text(cr, str(i), 0.5, 0.5, 2, 2)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800490
491 cr.paint_with_alpha(.65)
492
493 draw_px_cross(cr, self.x, self.y, 10)
494
495 def do_key_press(self, event):
496 keyval = Gdk.keyval_to_lower(event.keyval)
Andrew Runke6842bf92019-01-26 15:38:25 -0800497 # print("Gdk.KEY_" + Gdk.keyval_name(keyval))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800498 if keyval == Gdk.KEY_q:
499 print("Found q key and exiting.")
500 quit_main_loop()
501 if keyval == Gdk.KEY_e:
Andrew Runke0f945fd2019-01-27 21:10:37 -0800502 # Will export to json file
503 self.mode = Mode.kEditing
504 print(str(sys.argv))
505 print('out to: ', self.path_to_export)
506 exportList = [l.tolist() for l in self.splines]
507 with open(self.path_to_export, mode='w') as points_file:
508 json.dump(exportList, points_file)
509 print("Wrote: " + str(self.splines))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800510 if keyval == Gdk.KEY_i:
Andrew Runke0f945fd2019-01-27 21:10:37 -0800511 # import from json file
512 self.mode = Mode.kEditing
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800513 self.selected_points = []
Andrew Runke0f945fd2019-01-27 21:10:37 -0800514 self.splines = []
515 with open(self.path_to_export) as points_file:
516 self.splines = json.load(points_file)
517 print("Added: " + str(self.splines))
Andrew Runke6842bf92019-01-26 15:38:25 -0800518 if keyval == Gdk.KEY_p:
519 self.mode = Mode.kPlacing
520 # F0 = A1
521 # B1 = 2F0 - E0
522 # C1= d0 + 4F0 - 4E0
523 spline_index = len(self.splines) - 1
524 self.selected_points = []
525 f = self.splines[spline_index][5]
526 e = self.splines[spline_index][4]
527 d = self.splines[spline_index][3]
528 self.selected_points.append(f)
529 self.selected_points.append(f * 2 + e * -1)
530 self.selected_points.append(d + f * 4 + e * -4)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800531
Andrew Runke6842bf92019-01-26 15:38:25 -0800532 if keyval == Gdk.KEY_c:
533 self.mode = Mode.kConstraint
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800534
535 def button_press_action(self):
Andrew Runke6842bf92019-01-26 15:38:25 -0800536 if self.mode == Mode.kPlacing:
537 #Check that the point clicked is on the field
538 if (self.x < -150 and self.x > -450 and self.y < 150
539 and self.y > -150):
540 self.add_point(self.x, self.y)
541 elif self.mode == Mode.kEditing:
542 # Now after index_of_edit is not -1, the point is selected, so
543 # user can click for new point
544 if self.index_of_edit > -1 and self.held_x != self.x:
545 print("INDEX OF EDIT: " + str(self.index_of_edit))
546 self.splines[self.spline_edit][self.index_of_edit] = [
John Park13d3e282019-01-26 20:16:48 -0800547 pxToM(self.x), pxToM(self.y)
Andrew Runke6842bf92019-01-26 15:38:25 -0800548 ]
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800549
Andrew Runke6842bf92019-01-26 15:38:25 -0800550 if not self.spline_edit == len(self.splines) - 1:
551 spline_edit = self.spline_edit + 1
552 f = self.splines[self.spline_edit][5]
553 e = self.splines[self.spline_edit][4]
554 d = self.splines[self.spline_edit][3]
555 self.splines[spline_edit][0] = f
556 self.splines[spline_edit][1] = f * 2 + e * -1
557 self.splines[spline_edit][2] = d + f * 4 + e * -4
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800558
Andrew Runke6842bf92019-01-26 15:38:25 -0800559 if not self.spline_edit == 0:
560 spline_edit = self.spline_edit - 1
561 a = self.splines[self.spline_edit][0]
562 b = self.splines[self.spline_edit][1]
563 c = self.splines[self.spline_edit][2]
564 self.splines[spline_edit][5] = a
565 self.splines[spline_edit][4] = a * 2 + b * -1
566 self.splines[spline_edit][3] = c + a * 4 + b * -4
567
Andrew Runke6842bf92019-01-26 15:38:25 -0800568 self.index_of_edit = -1
569 self.spline_edit = -1
570 else:
571 print("mode == 2")
572 # Get clicked point
573 # Find nearest
574 # Move nearest to clicked
John Park13d3e282019-01-26 20:16:48 -0800575 cur_p = [pxToM(self.x), pxToM(self.y)]
Andrew Runke6842bf92019-01-26 15:38:25 -0800576 print("CUR_P: " + str(self.x) + " " + str(self.y))
577 # Get the distance between each for x and y
578 # Save the index of the point closest
John Park13d3e282019-01-26 20:16:48 -0800579 nearest = 1 # Max distance away a the selected point can be in meters
Andrew Runke6842bf92019-01-26 15:38:25 -0800580 index_of_closest = 0
581 for index_splines, points in enumerate(self.splines):
582 for index_points, val in enumerate(points):
583 # pythagorean
584 distance = np.sqrt((cur_p[0] - val[0])**2 +
585 (cur_p[1] - val[1])**2)
586 if distance < nearest:
587 nearest = distance
588 index_of_closest = index_points
589 print("Nearest: " + str(nearest))
590 print("Index: " + str(index_of_closest))
591 self.index_of_edit = index_of_closest
592 self.spline_edit = index_splines
593 self.held_x = self.x
594 elif self.mode == Mode.kConstraint:
595 print("RAN")
596 self.set_index_to_nearest_spline_point()
597 print("FINISHED")
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800598
599 def do_button_press(self, event):
600 print("button press activated")
John Park13d3e282019-01-26 20:16:48 -0800601 # Be consistent with the scaling in the drawing_area
Andrew Runkea9c8de52019-01-26 19:54:29 -0800602 self.x = event.x * 2
603 self.y = event.y * 2
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800604 self.button_press_action()
605
606
Andrew Runke6842bf92019-01-26 15:38:25 -0800607class GridWindow(Gtk.Window):
608 def method_connect(self, event, cb):
609 def handler(obj, *args):
610 cb(*args)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800611
Andrew Runke6842bf92019-01-26 15:38:25 -0800612 print("Method_connect ran")
613 self.connect(event, handler)
614
615 def button_press(self, event):
616 print("button press activated")
617 o_x = event.x
618 o_y = event.y
619 x = event.x - self.drawing_area.window_shape[0] / 2
620 y = self.drawing_area.window_shape[1] / 2 - event.y
621 scale = self.drawing_area.get_current_scale()
622 event.x = x / scale + self.drawing_area.center[0]
623 event.y = y / scale + self.drawing_area.center[1]
624 self.drawing_area.do_button_press(event)
625 event.x = o_x
626 event.y = o_y
627
628 def key_press(self, event):
629 print("key press activated")
630 self.drawing_area.do_key_press(event)
631 self.queue_draw()
632
633 def configure(self, event):
634 print("configure activated")
635 self.drawing_area.window_shape = (event.width, event.height)
636
637 def on_submit_click(self, widget):
638 self.drawing_area.inConstraint = int(self.constraint_box.get_text())
639 self.drawing_area.inValue = int(self.value_box.get_text())
640
641 def __init__(self):
642 Gtk.Window.__init__(self)
643
644 self.set_default_size(1366, 738)
645
646 flowBox = Gtk.FlowBox()
647 flowBox.set_valign(Gtk.Align.START)
648 flowBox.set_selection_mode(Gtk.SelectionMode.NONE)
649
650 flowBox.set_valign(Gtk.Align.START)
651
652 self.add(flowBox)
653
654 container = Gtk.Fixed()
655 flowBox.add(container)
656
657 self.eventBox = Gtk.EventBox()
658 container.add(self.eventBox)
659
660 self.eventBox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK
661 | Gdk.EventMask.BUTTON_RELEASE_MASK
662 | Gdk.EventMask.POINTER_MOTION_MASK
663 | Gdk.EventMask.SCROLL_MASK
664 | Gdk.EventMask.KEY_PRESS_MASK)
665
666 self.drawing_area = GTK_Widget()
667 self.eventBox.add(self.drawing_area)
668
669 self.method_connect("key-release-event", self.key_press)
670 self.method_connect("button-release-event", self.button_press)
671 self.method_connect("configure-event", self.configure)
672
673 # Constraint Boxes
674
675 self.start_box = Gtk.Entry()
676 self.start_box.set_size_request(100, 20)
677
678 self.constraint_box = Gtk.Entry()
679 self.constraint_box.set_size_request(100, 20)
680
681 self.constraint_box.set_text("Constraint")
682 self.constraint_box.set_editable(True)
683
684 container.put(self.constraint_box, 700, 0)
685
686 self.value_box = Gtk.Entry()
687 self.value_box.set_size_request(100, 20)
688
689 self.value_box.set_text("Value")
690 self.value_box.set_editable(True)
691
692 container.put(self.value_box, 700, 40)
693
694 self.submit_button = Gtk.Button("Submit")
695 self.submit_button.connect('clicked', self.on_submit_click)
696
697 container.put(self.submit_button, 880, 0)
698
699 self.show_all()
700
701
702window = GridWindow()
John Park13d3e282019-01-26 20:16:48 -0800703basic_window.RunApp()