blob: da16ad46e8e74d2c03f5c5fa114ff64901e9120f [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
305 def draw_field_elements(self, cr):
306 self.draw_HAB(cr)
307
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800308 def handle_draw(self, cr):
Andrew Runke6842bf92019-01-26 15:38:25 -0800309 # print(self.new_point)
310 # print("SELF.POINT_SELECTED: " + str(self.point_selected))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800311
312 # begin drawing
313 # Fill the background color of the window with grey
314 set_color(cr, palette["GREY"])
315 cr.paint()
Andrew Runkea9c8de52019-01-26 19:54:29 -0800316 #Scale the field to fit within drawing area
Andrew Runke6696bb82019-02-02 14:33:59 -0800317 cr.scale(0.5, 0.5)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800318
319 # Draw a extents rectangle
320 set_color(cr, palette["WHITE"])
321 cr.rectangle(self.extents_x_min, self.extents_y_min,
322 (self.extents_x_max - self.extents_x_min),
323 self.extents_y_max - self.extents_y_min)
324 cr.fill()
325
John Parka30a7782019-02-01 18:47:26 -0800326 #Drawing the field
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800327 cr.move_to(0, 50)
328 cr.show_text('Press "e" to export')
329 cr.show_text('Press "i" to import')
330
331 set_color(cr, Color(0.3, 0.3, 0.3))
Andrew Runke6842bf92019-01-26 15:38:25 -0800332 cr.rectangle(-450, -150, 300, 300)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800333 cr.fill()
334 set_color(cr, palette["BLACK"])
Andrew Runke6842bf92019-01-26 15:38:25 -0800335 cr.rectangle(-450, -150, 300, 300)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800336 cr.set_line_join(cairo.LINE_JOIN_ROUND)
337 cr.stroke()
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800338
John Parka30a7782019-02-01 18:47:26 -0800339 self.draw_field_elements(cr)
340
Andrew Runke6842bf92019-01-26 15:38:25 -0800341 y = 0
Andrew Runke6842bf92019-01-26 15:38:25 -0800342
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800343 # update all the things
344
345 if self.mode == Mode.kViewing:
346 set_color(cr, palette["BLACK"])
347 cr.move_to(-300, 170)
348 cr.show_text("VIEWING")
349 set_color(cr, palette["GREY"])
Andrew Runke6842bf92019-01-26 15:38:25 -0800350
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800351 if len(self.selected_points) > 0:
352 print("SELECTED_POINTS: " + str(len(self.selected_points)))
353 print("ITEMS:")
Andrew Runke6842bf92019-01-26 15:38:25 -0800354 # for item in self.selected_points:
355 # print(str(item))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800356 for i, point in enumerate(self.selected_points):
Andrew Runke6842bf92019-01-26 15:38:25 -0800357 # print("I: " + str(i))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800358 draw_px_x(cr, point[0], point[1], 10)
Andrew Runke6842bf92019-01-26 15:38:25 -0800359 cr.move_to(point[0], point[1] - 15)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800360 display_text(cr, str(i), 0.5, 0.5, 2, 2)
361
Andrew Runke6842bf92019-01-26 15:38:25 -0800362 elif self.mode == Mode.kPlacing:
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800363 set_color(cr, palette["BLACK"])
364 cr.move_to(-300, 170)
365 display_text(cr, "ADD", 1, 1, 1, 1)
366 set_color(cr, palette["GREY"])
Andrew Runke6842bf92019-01-26 15:38:25 -0800367
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800368 if len(self.selected_points) > 0:
369 print("SELECTED_POINTS: " + str(len(self.selected_points)))
370 print("ITEMS:")
371 for item in self.selected_points:
372 print(str(item))
373 for i, point in enumerate(self.selected_points):
374 print("I: " + str(i))
John Park13d3e282019-01-26 20:16:48 -0800375 draw_px_x(cr, mToPx(point[0]), mToPx(point[1]), 10)
376 cr.move_to(mToPx(point[0]), mToPx(point[1]) - 15)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800377 display_text(cr, str(i), 0.5, 0.5, 2, 2)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800378
379 elif self.mode == Mode.kEditing:
380 set_color(cr, palette["BLACK"])
381 cr.move_to(-300, 170)
382 display_text(cr, "EDITING", 1, 1, 1, 1)
Andrew Runke6842bf92019-01-26 15:38:25 -0800383 if len(self.splines) > 0:
Andrew Runke6842bf92019-01-26 15:38:25 -0800384 holder_spline = []
385 for i, points in enumerate(self.splines):
386 array = np.zeros(shape=(6, 2), dtype=float)
387 for j, point in enumerate(points):
John Park13d3e282019-01-26 20:16:48 -0800388 array[j, 0] = mToPx(point[0])
389 array[j, 1] = mToPx(point[1])
Andrew Runke6842bf92019-01-26 15:38:25 -0800390 spline = Spline(np.ascontiguousarray(np.transpose(array)))
391 for k in np.linspace(0.01, 1, 100):
Andrew Runke6842bf92019-01-26 15:38:25 -0800392 cr.move_to(
393 spline.Point(k - 0.01)[0],
394 spline.Point(k - 0.01)[1])
395 cr.line_to(spline.Point(k)[0], spline.Point(k)[1])
396 cr.stroke()
397 holding = [
398 spline.Point(k - 0.01)[0],
399 spline.Point(k - 0.01)[1]
400 ]
Andrew Runke6842bf92019-01-26 15:38:25 -0800401 holder_spline.append(holding)
402 self.curves.append(holder_spline)
403
404 for spline, points in enumerate(self.splines):
405 # for item in points:
406 # print(str(item))
407 for i, point in enumerate(points):
408 # print("I: " + str(i))
409 if spline == self.spline_edit and i == self.index_of_edit:
John Park13d3e282019-01-26 20:16:48 -0800410 draw_px_x(cr, mToPx(point[0]), mToPx(point[1]), 15,
Andrew Runke6842bf92019-01-26 15:38:25 -0800411 self.colors[spline])
412 elif (spline == 0 and not i == 5) or (not i == 0
413 and not i == 5):
John Park13d3e282019-01-26 20:16:48 -0800414 draw_px_x(cr, mToPx(point[0]), mToPx(point[1]), 10,
Andrew Runke6842bf92019-01-26 15:38:25 -0800415 self.colors[spline])
John Park13d3e282019-01-26 20:16:48 -0800416 cr.move_to(mToPx(point[0]), mToPx(point[1]) - 15)
Andrew Runke6842bf92019-01-26 15:38:25 -0800417 display_text(cr, str(i), 0.5, 0.5, 2, 2)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800418
Andrew Runke6842bf92019-01-26 15:38:25 -0800419 elif self.mode == Mode.kConstraint:
420 print("Drawn")
421 set_color(cr, palette["BLACK"])
422 cr.move_to(-300, 170)
423 display_text(cr, "Adding Constraint", 1, 1, 1, 1)
424 if len(self.splines) > 0:
425 # print("Splines: " + str(len(self.splines)))
426 # print("ITEMS:")
427 for s, points in enumerate(self.splines):
428 # for item in points:
429 # print(str(item))
430 for i, point in enumerate(points):
431 # print("I: " + str(i))
432 draw_px_x(cr, point[0], point[1], 10, self.colors[s])
433 cr.move_to(point[0], point[1] - 15)
434 display_text(cr, str(i), 0.5, 0.5, 2, 2)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800435
436 cr.paint_with_alpha(.65)
437
438 draw_px_cross(cr, self.x, self.y, 10)
439
440 def do_key_press(self, event):
441 keyval = Gdk.keyval_to_lower(event.keyval)
Andrew Runke6842bf92019-01-26 15:38:25 -0800442 # print("Gdk.KEY_" + Gdk.keyval_name(keyval))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800443 if keyval == Gdk.KEY_q:
444 print("Found q key and exiting.")
445 quit_main_loop()
446 if keyval == Gdk.KEY_e:
Andrew Runke0f945fd2019-01-27 21:10:37 -0800447 # Will export to json file
448 self.mode = Mode.kEditing
449 print(str(sys.argv))
450 print('out to: ', self.path_to_export)
451 exportList = [l.tolist() for l in self.splines]
452 with open(self.path_to_export, mode='w') as points_file:
453 json.dump(exportList, points_file)
454 print("Wrote: " + str(self.splines))
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800455 if keyval == Gdk.KEY_i:
Andrew Runke0f945fd2019-01-27 21:10:37 -0800456 # import from json file
457 self.mode = Mode.kEditing
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800458 self.selected_points = []
Andrew Runke0f945fd2019-01-27 21:10:37 -0800459 self.splines = []
460 with open(self.path_to_export) as points_file:
461 self.splines = json.load(points_file)
462 print("Added: " + str(self.splines))
Andrew Runke6842bf92019-01-26 15:38:25 -0800463 if keyval == Gdk.KEY_p:
464 self.mode = Mode.kPlacing
465 # F0 = A1
466 # B1 = 2F0 - E0
467 # C1= d0 + 4F0 - 4E0
468 spline_index = len(self.splines) - 1
469 self.selected_points = []
470 f = self.splines[spline_index][5]
471 e = self.splines[spline_index][4]
472 d = self.splines[spline_index][3]
473 self.selected_points.append(f)
474 self.selected_points.append(f * 2 + e * -1)
475 self.selected_points.append(d + f * 4 + e * -4)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800476
Andrew Runke6842bf92019-01-26 15:38:25 -0800477 if keyval == Gdk.KEY_c:
478 self.mode = Mode.kConstraint
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800479
480 def button_press_action(self):
Andrew Runke6842bf92019-01-26 15:38:25 -0800481 if self.mode == Mode.kPlacing:
482 #Check that the point clicked is on the field
483 if (self.x < -150 and self.x > -450 and self.y < 150
484 and self.y > -150):
485 self.add_point(self.x, self.y)
486 elif self.mode == Mode.kEditing:
487 # Now after index_of_edit is not -1, the point is selected, so
488 # user can click for new point
489 if self.index_of_edit > -1 and self.held_x != self.x:
490 print("INDEX OF EDIT: " + str(self.index_of_edit))
491 self.splines[self.spline_edit][self.index_of_edit] = [
John Park13d3e282019-01-26 20:16:48 -0800492 pxToM(self.x), pxToM(self.y)
Andrew Runke6842bf92019-01-26 15:38:25 -0800493 ]
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800494
Andrew Runke6842bf92019-01-26 15:38:25 -0800495 if not self.spline_edit == len(self.splines) - 1:
496 spline_edit = self.spline_edit + 1
497 f = self.splines[self.spline_edit][5]
498 e = self.splines[self.spline_edit][4]
499 d = self.splines[self.spline_edit][3]
500 self.splines[spline_edit][0] = f
501 self.splines[spline_edit][1] = f * 2 + e * -1
502 self.splines[spline_edit][2] = d + f * 4 + e * -4
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800503
Andrew Runke6842bf92019-01-26 15:38:25 -0800504 if not self.spline_edit == 0:
505 spline_edit = self.spline_edit - 1
506 a = self.splines[self.spline_edit][0]
507 b = self.splines[self.spline_edit][1]
508 c = self.splines[self.spline_edit][2]
509 self.splines[spline_edit][5] = a
510 self.splines[spline_edit][4] = a * 2 + b * -1
511 self.splines[spline_edit][3] = c + a * 4 + b * -4
512
Andrew Runke6842bf92019-01-26 15:38:25 -0800513 self.index_of_edit = -1
514 self.spline_edit = -1
515 else:
516 print("mode == 2")
517 # Get clicked point
518 # Find nearest
519 # Move nearest to clicked
John Park13d3e282019-01-26 20:16:48 -0800520 cur_p = [pxToM(self.x), pxToM(self.y)]
Andrew Runke6842bf92019-01-26 15:38:25 -0800521 print("CUR_P: " + str(self.x) + " " + str(self.y))
522 # Get the distance between each for x and y
523 # Save the index of the point closest
John Park13d3e282019-01-26 20:16:48 -0800524 nearest = 1 # Max distance away a the selected point can be in meters
Andrew Runke6842bf92019-01-26 15:38:25 -0800525 index_of_closest = 0
526 for index_splines, points in enumerate(self.splines):
527 for index_points, val in enumerate(points):
528 # pythagorean
529 distance = np.sqrt((cur_p[0] - val[0])**2 +
530 (cur_p[1] - val[1])**2)
531 if distance < nearest:
532 nearest = distance
533 index_of_closest = index_points
534 print("Nearest: " + str(nearest))
535 print("Index: " + str(index_of_closest))
536 self.index_of_edit = index_of_closest
537 self.spline_edit = index_splines
538 self.held_x = self.x
539 elif self.mode == Mode.kConstraint:
540 print("RAN")
541 self.set_index_to_nearest_spline_point()
542 print("FINISHED")
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800543
544 def do_button_press(self, event):
545 print("button press activated")
John Park13d3e282019-01-26 20:16:48 -0800546 # Be consistent with the scaling in the drawing_area
Andrew Runkea9c8de52019-01-26 19:54:29 -0800547 self.x = event.x * 2
548 self.y = event.y * 2
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800549 self.button_press_action()
550
551
Andrew Runke6842bf92019-01-26 15:38:25 -0800552class GridWindow(Gtk.Window):
553 def method_connect(self, event, cb):
554 def handler(obj, *args):
555 cb(*args)
Tabitha Jarvis1007a132018-12-12 21:47:54 -0800556
Andrew Runke6842bf92019-01-26 15:38:25 -0800557 print("Method_connect ran")
558 self.connect(event, handler)
559
560 def button_press(self, event):
561 print("button press activated")
562 o_x = event.x
563 o_y = event.y
564 x = event.x - self.drawing_area.window_shape[0] / 2
565 y = self.drawing_area.window_shape[1] / 2 - event.y
566 scale = self.drawing_area.get_current_scale()
567 event.x = x / scale + self.drawing_area.center[0]
568 event.y = y / scale + self.drawing_area.center[1]
569 self.drawing_area.do_button_press(event)
570 event.x = o_x
571 event.y = o_y
572
573 def key_press(self, event):
574 print("key press activated")
575 self.drawing_area.do_key_press(event)
576 self.queue_draw()
577
578 def configure(self, event):
579 print("configure activated")
580 self.drawing_area.window_shape = (event.width, event.height)
581
582 def on_submit_click(self, widget):
583 self.drawing_area.inConstraint = int(self.constraint_box.get_text())
584 self.drawing_area.inValue = int(self.value_box.get_text())
585
586 def __init__(self):
587 Gtk.Window.__init__(self)
588
589 self.set_default_size(1366, 738)
590
591 flowBox = Gtk.FlowBox()
592 flowBox.set_valign(Gtk.Align.START)
593 flowBox.set_selection_mode(Gtk.SelectionMode.NONE)
594
595 flowBox.set_valign(Gtk.Align.START)
596
597 self.add(flowBox)
598
599 container = Gtk.Fixed()
600 flowBox.add(container)
601
602 self.eventBox = Gtk.EventBox()
603 container.add(self.eventBox)
604
605 self.eventBox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK
606 | Gdk.EventMask.BUTTON_RELEASE_MASK
607 | Gdk.EventMask.POINTER_MOTION_MASK
608 | Gdk.EventMask.SCROLL_MASK
609 | Gdk.EventMask.KEY_PRESS_MASK)
610
611 self.drawing_area = GTK_Widget()
612 self.eventBox.add(self.drawing_area)
613
614 self.method_connect("key-release-event", self.key_press)
615 self.method_connect("button-release-event", self.button_press)
616 self.method_connect("configure-event", self.configure)
617
618 # Constraint Boxes
619
620 self.start_box = Gtk.Entry()
621 self.start_box.set_size_request(100, 20)
622
623 self.constraint_box = Gtk.Entry()
624 self.constraint_box.set_size_request(100, 20)
625
626 self.constraint_box.set_text("Constraint")
627 self.constraint_box.set_editable(True)
628
629 container.put(self.constraint_box, 700, 0)
630
631 self.value_box = Gtk.Entry()
632 self.value_box.set_size_request(100, 20)
633
634 self.value_box.set_text("Value")
635 self.value_box.set_editable(True)
636
637 container.put(self.value_box, 700, 40)
638
639 self.submit_button = Gtk.Button("Submit")
640 self.submit_button.connect('clicked', self.on_submit_click)
641
642 container.put(self.submit_button, 880, 0)
643
644 self.show_all()
645
646
647window = GridWindow()
John Park13d3e282019-01-26 20:16:48 -0800648basic_window.RunApp()