def loadData(): dirs = os.listdir(dataFilePath) for classPathName, classIndex in zip(dirs, range(len(dirs))): for graphPathName in os.listdir(dataFilePath + classPathName): graph = Graph(dataFilePath + classPathName + "/" + graphPathName, priorList, "#") graphList.append(graph) labelList.append(classIndex)
def __init__(self, parent=None): super(AppWidget, self).__init__(parent) self.graph = Graph() self.mode = '+ .' self._next_label = 1 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.searchLoop) self.nodeR = 5 self.nodeDetectPadding = 7 self.nodeSpacing = 30 self.edgeDetectPadding = 3 self.clearSearchVars() self.setupUi()
def __init__(self, width=640, height=400, node_r=5, node_padding=5, node_spacing=30, edge_padding=5): self._running = True self.screen = None self.node1 = None self.size = self.width, self.height = width, height self.node_r = node_r self.node_padding = node_padding self.node_spacing = node_spacing self.edge_padding = edge_padding self.graph = Graph() self.pen_mode = 1 self.prev_pen_mode = 1 self._node_label_index = 1 self.search_clear() print("1 - Add nodes") print("2 - Add undirected edges") print("3 - Add directed edges") print("4 - Delete nodes") print("5 - Delete edges") print("6 - Select Start") print("7 - Select Goal") print("8 - Begin Search") print("9 - Clear Search") print("Keypad - change search settings") print("0 - Clear")
class App: def __init__(self, width=640, height=400, node_r=5, node_padding=5, node_spacing=30, edge_padding=5): self._running = True self.screen = None self.node1 = None self.size = self.width, self.height = width, height self.node_r = node_r self.node_padding = node_padding self.node_spacing = node_spacing self.edge_padding = edge_padding self.graph = Graph() self.pen_mode = 1 self.prev_pen_mode = 1 self._node_label_index = 1 self.search_clear() print("1 - Add nodes") print("2 - Add undirected edges") print("3 - Add directed edges") print("4 - Delete nodes") print("5 - Delete edges") print("6 - Select Start") print("7 - Select Goal") print("8 - Begin Search") print("9 - Clear Search") print("Keypad - change search settings") print("0 - Clear") def search_clear(self, target_clear=True): if target_clear: self.start = None self.goal = None self.queue = [] self.search_type = None self.enqueue_filter = None self.slow_mode = None self.expanded_nodes = set() self.cur_path = [Path()] self.goal_path = Path() self.count = 0 self.w = None self.admis_heur = None self.searching = False self.done = False def on_init(self): pygame.init() self.clock = pygame.time.Clock() # Set logo and Title logo = pygame.image.load("logo.png") pygame.display.set_icon(logo) pygame.display.set_caption("Search Algorithms") self.screen = pygame.display.set_mode( self.size, pygame.HWSURFACE | pygame.DOUBLEBUF) self.surface = pygame.Surface(self.screen.get_size()) self._running = True def on_event(self, event): if event.type == pygame.QUIT: self._running = False if (not self.searching) or self.done: if event.type == pygame.KEYDOWN: if pygame.key.get_pressed()[pygame.K_0]: self.pen_mode = 0 self.prev_pen_mode = 1 self._node_label_index = 1 nodes = self.graph.get_nodes().copy() for node in nodes: self.graph.delete_node(node) self.search_clear() elif pygame.key.get_pressed()[pygame.K_1]: self.node1 = None self.pen_mode = 1 elif pygame.key.get_pressed()[pygame.K_2]: self.pen_mode = 2 elif pygame.key.get_pressed()[pygame.K_3]: self.pen_mode = 3 elif pygame.key.get_pressed()[pygame.K_4]: self.pen_mode = 4 elif pygame.key.get_pressed()[pygame.K_5]: self.pen_mode = 5 elif pygame.key.get_pressed()[pygame.K_6]: self.pen_mode = 6 elif pygame.key.get_pressed()[pygame.K_7]: self.pen_mode = 7 elif pygame.key.get_pressed()[pygame.K_8]: self.pen_mode = 8 self.searching = True elif pygame.key.get_pressed()[pygame.K_9]: self.pen_mode = 9 self.search_clear(False) elif pygame.key.get_pressed()[pygame.K_KP0]: self.enqueue_filter = not self.enqueue_filter print("enqueue filter : %s" % (self.enqueue_filter)) elif pygame.key.get_pressed()[pygame.K_KP1]: self.slow_mode = not self.slow_mode print("slow mode : %s" % (self.slow_mode)) elif pygame.key.get_pressed()[pygame.K_KP2]: self.admis_heur = not self.admis_heur print("admissable heuristic : %s" % (self.admis_heur)) elif pygame.key.get_pressed()[pygame.K_KP7]: self.search_type = 'Breadth' print("search type : %s" % (self.search_type)) elif pygame.key.get_pressed()[pygame.K_KP8]: self.search_type = 'Depth' print("search type : %s" % (self.search_type)) elif pygame.key.get_pressed()[pygame.K_KP4]: self.search_type = 'Hill' print("search type : %s" % (self.search_type)) elif pygame.key.get_pressed()[pygame.K_KP5]: self.search_type = 'Beam' print("search type : %s" % (self.search_type)) elif pygame.key.get_pressed()[pygame.K_KP6]: self.search_type = 'B & B' print("search type : %s" % (self.search_type)) elif pygame.key.get_pressed()[pygame.K_KP_PLUS]: if self.w == None: self.w = 1 else: self.w += 1 print("Beam width: %s" % (self.w)) elif pygame.key.get_pressed()[pygame.K_KP_MINUS]: if self.w == None: self.w = 1 else: self.w = max(1, self.w - 1) print("Beam width: %s" % (self.w)) if self.prev_pen_mode != self.pen_mode: self.node1 = None if event.type == pygame.MOUSEBUTTONDOWN: if self.pen_mode == 1: if self.get_cur_mouse_node(self.node_spacing) == None: self.graph.add_node( Node(self._node_label_index, pygame.mouse.get_pos())) self._node_label_index += 1 if self.pen_mode == 2: if self.node1 != None: node2 = self.get_cur_mouse_node(self.node_padding) if node2 != None: pre_existing_edges = set.intersection( self.node1.get_connected_edges(), node2.get_connected_edges()) if self.node1 != node2 and len( pre_existing_edges) == 0: dist = sqr_dist(self.node1, node2) weight = dist**0.5 self.graph.add_edge( UndirectedEdge(self.node1, node2, weight)) else: print("No no, not allowed") self.node1 = None else: self.node1 = self.get_cur_mouse_node() if self.pen_mode == 3: if self.node1 != None: node2 = self.get_cur_mouse_node(self.node_padding) if node2 != None: pre_existing_edges = set.intersection( self.node1.get_connected_edges(), node2.get_connected_edges()) pre_existing_edges = {edge for edge in pre_existing_edges if \ edge.get_node2() == node2 or edge.__class__ == UndirectedEdge} if self.node1 != node2 and len( pre_existing_edges) == 0: dist = sqr_dist(self.node1, node2) weight = dist**0.5 self.graph.add_edge( DirectedEdge(self.node1, node2, weight)) else: print("No no, not allowed") self.node1 = None else: self.node1 = self.get_cur_mouse_node() if self.pen_mode == 4: node = self.get_cur_mouse_node(self.node_padding) if node != None: if node == self.goal: self.goal = None if node == self.start: self.start = None self.graph.delete_node(node) if self.pen_mode == 5: edge = self.get_cur_mouse_edge(self.edge_padding) if edge != None: if edge in self.goal_path.get_edges(): self.search_clear(False) self.graph.delete_edge(edge) if self.pen_mode == 6: node = self.get_cur_mouse_node(self.node_padding) if node and node != self.goal: self.start = node if self.pen_mode == 7: node = self.get_cur_mouse_node(self.node_padding) if node and node != self.start: self.goal = node if self.pen_mode == 8: print(self.get_cur_mouse_edge(self.edge_padding)) self.prev_pen_mode = self.pen_mode def get_cur_mouse_node(self, padding=0): cur_mouse_node = None mouse_pos = pygame.mouse.get_pos() for node in self.graph.get_nodes(): node_pos = node.get_coords() x_dif = node_pos[0] - mouse_pos[0] y_dif = node_pos[1] - mouse_pos[1] if x_dif * x_dif + y_dif * y_dif < (self.node_r + padding) * ( self.node_r + padding): cur_mouse_node = node break return cur_mouse_node def get_cur_mouse_edge(self, padding=0): cur_mouse_edge = None mouse_pos = pygame.mouse.get_pos() for edge in self.graph.get_edges(): mult = 0 pre_existing_edges = set.intersection( edge.get_node1().get_connected_edges(), edge.get_node2().get_connected_edges()) if len(pre_existing_edges) == 2: mult = 1 node1 = edge.get_node1().get_coords() node2 = edge.get_node2().get_coords() v0_x = node1[1] - node2[1] v0_y = -(node1[0] - node2[0]) v0_mag = float(v0_x * v0_x + v0_y * v0_y)**0.5 LHS = (mouse_pos[0] - node1[0])*v0_x\ + (mouse_pos[1] - node1[1])*v0_y\ + mult*self.node_r*v0_mag RHS = padding * v0_mag condition1 = min(node1[0],node2[0]) - self.node_r < mouse_pos[0] and \ mouse_pos[0] < max(node1[0],node2[0]) + self.node_r condition2 = min(node1[1],node2[1]) - self.node_r < mouse_pos[1] and \ mouse_pos[1] < max(node1[1],node2[1]) + self.node_r condition = abs(LHS) < abs(RHS) and condition1 and condition2 if condition: cur_mouse_edge = edge break return cur_mouse_edge def on_loop(self): if self.searching and not self.done: if self.start == None: print("Please define a start") self.searching = False return if self.goal == None: print("Please define a goal") self.searching = False return if self.search_type == None: print("Please select a search type") self.searching = False return if self.enqueue_filter == None: print("please toggle enqueue filter") self.searching = False return if self.slow_mode == None: print("please toggle slow mode") self.searching = False return if self.search_type == "Beam" and self.w == None: print("please define the beam width") self.searching = False return if self.search_type == "B & B" and self.admis_heur == None: print("please Toggle admissable heuristic") self.searching = False return if len(self.cur_path[0]) == 0 and len(self.queue) == 0: self.queue = [Path([self.start])] self.count += 1 return if self.slow_mode == False or (self.slow_mode == True and self.count == 0): if len(self.queue) == 0: self.done = True print("No path found") return if self.search_type == 'Beam': self.cur_path = [] extensions = [] for path in self.queue: if path[-1] == self.goal: self.done = True self.goal_path = path print(path.get_length()) return self.cur_path.append(path) extensions += path.extend() if self.enqueue_filter: self.expanded_nodes.add(path[-1]) extensions = sorted( extensions, key=lambda path: sqr_dist(path[-1], self.goal)) self.queue = [] else: cur_path = self.queue.pop() if cur_path[-1] == self.goal: self.done = True self.goal_path = cur_path print(cur_path.get_length()) return self.cur_path = [cur_path] if self.enqueue_filter: self.expanded_nodes.add(cur_path[-1]) extensions = cur_path.extend() if self.search_type == 'Hill': extensions = sorted( extensions, key=lambda path: sqr_dist(path[-1], self.goal), reverse=True) print(self.cur_path) for path in extensions: if self.enqueue_filter and path[-1] in self.expanded_nodes: continue elif self.search_type == 'Breadth': self.queue.insert(0, path) elif self.search_type == 'Depth': self.queue.append(path) elif self.search_type == 'Hill': self.queue.append(path) elif self.search_type == 'Beam': self.queue.append(path) elif self.search_type == 'B & B': self.queue.append(path) if self.search_type == 'Beam': self.queue = self.queue[:self.w] if self.search_type == 'B & B': if self.admis_heur: key = lambda path: path.get_length() + sqr_dist( path[-1], self.goal)**0.5 else: key = lambda path: path.get_length() self.queue = sorted(self.queue, key=key, reverse=True) self.count += 1 self.count = self.count % 15 def on_render(self): # Draw background pygame.draw.rect(self.surface, (255, 255, 255), (0, 0, self.width, self.height)) # Draw all the edges for edge in self.graph.get_edges(): conditions = [ True if edge in path.get_edges() else False for path in self.cur_path ] if self.searching and not self.done and True in conditions: colour = (255, 100, 100) width = 3 elif self.done and (edge in self.goal_path.get_edges()): colour = (0, 255, 0) width = 3 else: colour = (0, 0, 0) width = 2 node1_coords = edge.get_node1().get_coords() node2_coords = edge.get_node2().get_coords() if edge.__class__ == DirectedEdge: mult = 0 pre_existing_edges = set.intersection( edge.get_node1().get_connected_edges(), edge.get_node2().get_connected_edges()) if len(pre_existing_edges) == 2: mult = 1 midpoint = ((node1_coords[0] + node2_coords[0]) / 2, (node1_coords[1] + node2_coords[1]) / 2) grad_vec = (node2_coords[0] - node1_coords[0], node2_coords[1] - node1_coords[1]) grad_vec_mag = (grad_vec[0] * grad_vec[0] + grad_vec[1] * grad_vec[1])**(0.5) norm_grad_vec = (grad_vec[0] / grad_vec_mag, grad_vec[1] / grad_vec_mag) norm_perp_vec = (norm_grad_vec[1], -norm_grad_vec[0]) midpoint = (midpoint[0] + mult * self.node_r * norm_perp_vec[0], midpoint[1] + mult * self.node_r * norm_perp_vec[1]) head_1_grad = (10 * (0.8660254037844386 * norm_grad_vec[0] - 0.5 * norm_grad_vec[1]), 10 * (0.5 * norm_grad_vec[0] + 0.8660254037844386 * norm_grad_vec[1])) head_2_grad = (10 * (0.8660254037844386 * norm_grad_vec[0] + 0.5 * norm_grad_vec[1]), 10 * (-0.5 * norm_grad_vec[0] + 0.8660254037844386 * norm_grad_vec[1])) pygame.draw.line(self.surface, colour, midpoint, (midpoint[0] - head_1_grad[0], midpoint[1] - head_1_grad[1]), max(width / 2, 1)) pygame.draw.line(self.surface, colour, midpoint, (midpoint[0] - head_2_grad[0], midpoint[1] - head_2_grad[1]), max(width / 2, 1)) node1_coords = (node1_coords[0] + mult * self.node_r * norm_perp_vec[0], node1_coords[1] + mult * self.node_r * norm_perp_vec[1]) node2_coords = (node2_coords[0] + mult * self.node_r * norm_perp_vec[0], node2_coords[1] + mult * self.node_r * norm_perp_vec[1]) pygame.draw.line(self.surface, colour, node1_coords, node2_coords, width) # Draw a line between node and mouse when drawing edges if self.node1 != None: pygame.draw.line(self.surface, (0, 0, 0), self.node1.get_coords(), pygame.mouse.get_pos()) # Draw nodes for node in self.graph.get_nodes(): if node == self.start: colour = (0, 255, 0) elif node == self.goal: colour = (255, 0, 0) elif node in self.expanded_nodes: colour = (0, 0, 255) else: colour = (0, 0, 0) pygame.draw.circle(self.surface, colour, node.get_coords(), self.node_r) self.screen.blit(self.surface, (0, 0)) pygame.display.flip() def on_cleanup(self): pygame.quit() def on_execute(self): if self.on_init() == False: self._running = False while (self._running): for event in pygame.event.get(): self.on_event(event) self.on_loop() self.on_render() self.clock.tick(60) self.on_cleanup()
print("Result length of the path: ", length) return length, path def sort_closest_bars(adjacency_matrix): result = {} for key, value in adjacency_matrix.items(): result[key] = { k: v for k, v in sorted(value.items(), key=lambda item: item[1]) } return result def find_next_bar(current, adjacency_matrix, visited): for key, value in adjacency_matrix[current].items(): next_bar = key if next_bar not in visited: return next_bar return 0 if __name__ == '__main__': graph = graph.Graph() graph.build_graph() christofides(graph, 0, 5)
class AppWidget(QtWidgets.QWidget): def __init__(self, parent=None): super(AppWidget, self).__init__(parent) self.graph = Graph() self.mode = '+ .' self._next_label = 1 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.searchLoop) self.nodeR = 5 self.nodeDetectPadding = 7 self.nodeSpacing = 30 self.edgeDetectPadding = 3 self.clearSearchVars() self.setupUi() def setupUi(self): self.setMouseTracking(True) pal = self.palette() pal.setColor(QtGui.QPalette.Background, QtCore.Qt.white) self.setAutoFillBackground(True) self.setPalette(pal) def clearSearchVars(self, clear_target=True): if clear_target: self.start = None self.goal = None self.node1 = None self.queue = [] self.searchAlgo = None self.listFilter = None self.speed = 0 self.expandedNodes = set() self.curPaths = [Path()] self.goalPath = Path() self.w = 1 self.admisHeur = None self.searching = False self.done = False self.changeSpeed() def changeSpeed(self): self.timer.setInterval(self.speed) def startTimer(self): if self.searchAlgo != None: self.timer.start(self.speed) def searchLoop(self): if self.done: self.searching = False self.timer.stop() self.repaint() return if len(self.curPaths[0]) == 0 and len(self.queue) == 0: self.searching = True self.queue = [Path([self.start])] return if len(self.queue) == 0: self.done = True print("No path found") return if self.searchAlgo == 'Beam': self.curPaths = [] extensions = [] for path in self.queue: if path[-1] == self.goal: self.done = True self.goalPath = path print(path.get_length()) return self.curPaths.append(path) extensions += path.extend() if self.listFilter: self.expandedNodes.add(path[-1]) extensions = sorted(extensions, key=lambda path: sqr_dist(path[-1], self.goal)) self.queue = [] else: cur_path = self.queue.pop() if cur_path[-1] == self.goal: self.done = True self.goalPath = cur_path print(cur_path.get_length()) return self.curPaths = [cur_path] if self.listFilter: self.expandedNodes.add(cur_path[-1]) extensions = cur_path.extend() if self.searchAlgo == 'Hill': extensions = sorted( extensions, key=lambda path: sqr_dist(path[-1], self.goal), reverse=True) print(self.curPaths) for path in extensions: if self.listFilter and path[-1] in self.expandedNodes: continue elif self.searchAlgo == 'Breadth': self.queue.insert(0, path) elif self.searchAlgo == 'Depth': self.queue.append(path) elif self.searchAlgo == 'Hill': self.queue.append(path) elif self.searchAlgo == 'Beam': self.queue.append(path) elif self.searchAlgo == 'BnB': self.queue.append(path) if self.searchAlgo == 'Beam': self.queue = self.queue[:self.w] if self.searchAlgo == 'BnB': if self.admisHeur: key = lambda path: path.get_length() + sqr_dist( path[-1], self.goal)**0.5 else: key = lambda path: path.get_length() self.queue = sorted(self.queue, key=key, reverse=True) self.repaint() def paintEvent(self, event): painter = QtGui.QPainter() painter.setRenderHint(QtGui.QPainter.Antialiasing, True) painter.begin(self) self.draw_edges(painter) if self.node1 != None and self.mouse_pos != None: self.draw_new_edge(painter) self.draw_nodes(painter) painter.end() def draw_nodes(self, painter): pen = QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.SolidLine) brush = QtGui.QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern) nodes = self.graph.get_nodes() for node in nodes: if self.start == node: pen.setColor(QtCore.Qt.green) brush.setColor(QtCore.Qt.green) elif self.goal == node: pen.setColor(QtCore.Qt.red) brush.setColor(QtCore.Qt.red) elif node in self.expandedNodes: pen.setColor(QtCore.Qt.blue) brush.setColor(QtCore.Qt.blue) else: pen.setColor(QtCore.Qt.black) brush.setColor(QtCore.Qt.black) painter.setPen(pen) painter.setBrush(brush) pos = node.get_coords() painter.drawEllipse(pos[0] - self.nodeR, pos[1] - self.nodeR, 2 * self.nodeR, 2 * self.nodeR) def draw_edges(self, painter): pen = QtGui.QPen(QtCore.Qt.black, 3, QtCore.Qt.SolidLine) brush = QtGui.QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern) edges = self.graph.get_edges() for edge in edges: conditions = [ True if edge in path.get_edges() else False for path in self.curPaths ] if self.searching and not self.done and True in conditions: pen.setColor(QtCore.Qt.red) pen.setWidth(3) elif self.done and (edge in self.goalPath.get_edges()): pen.setColor(QtCore.Qt.green) pen.setWidth(3) else: pen.setColor(QtCore.Qt.black) pen.setWidth(2) painter.setPen(pen) painter.setBrush(brush) node1 = edge.get_node1() node2 = edge.get_node2() pos1 = node1.get_coords() pos2 = node2.get_coords() if edge.__class__ == DirectedEdge: mult = 0 pre_existing_edges = set.intersection( edge.get_node1().get_connected_edges(), edge.get_node2().get_connected_edges()) if len(pre_existing_edges) == 2: mult = 1 midpoint = ((pos1[0] + pos2[0]) / 2, (pos1[1] + pos2[1]) / 2) grad_vec = (pos2[0] - pos1[0], pos2[1] - pos1[1]) grad_vec_mag = (grad_vec[0] * grad_vec[0] + grad_vec[1] * grad_vec[1])**(0.5) norm_grad_vec = (grad_vec[0] / grad_vec_mag, grad_vec[1] / grad_vec_mag) norm_perp_vec = (norm_grad_vec[1], -norm_grad_vec[0]) midpoint = (midpoint[0] + mult * self.nodeR * norm_perp_vec[0], midpoint[1] + mult * self.nodeR * norm_perp_vec[1]) pen.setWidth(1) painter.setPen(pen) head_1_grad = (10 * (0.8660254037844386 * norm_grad_vec[0] - 0.5 * norm_grad_vec[1]), 10 * (0.5 * norm_grad_vec[0] + 0.8660254037844386 * norm_grad_vec[1])) head_2_grad = (10 * (0.8660254037844386 * norm_grad_vec[0] + 0.5 * norm_grad_vec[1]), 10 * (-0.5 * norm_grad_vec[0] + 0.8660254037844386 * norm_grad_vec[1])) pen.setWidth(3) painter.setPen(pen) painter.drawLine(midpoint[0], midpoint[1], midpoint[0] - head_1_grad[0], midpoint[1] - head_1_grad[1]) painter.drawLine(midpoint[0], midpoint[1], midpoint[0] - head_2_grad[0], midpoint[1] - head_2_grad[1]) pos1 = (pos1[0] + mult * self.nodeR * norm_perp_vec[0], pos1[1] + mult * self.nodeR * norm_perp_vec[1]) pos2 = (pos2[0] + mult * self.nodeR * norm_perp_vec[0], pos2[1] + mult * self.nodeR * norm_perp_vec[1]) painter.drawLine(pos1[0], pos1[1], pos2[0], pos2[1]) def draw_new_edge(self, painter): pen = QtGui.QPen(QtCore.Qt.black, 2, QtCore.Qt.SolidLine) brush = QtGui.QBrush(QtCore.Qt.black, QtCore.Qt.SolidPattern) painter.setPen(pen) painter.setBrush(brush) node1 = self.node1 pos1 = node1.get_coords() pos2 = self.mouse_pos painter.drawLine(pos1[0], pos1[1], pos2[0], pos2[1]) self.mouse_pos = None def mouseMoveEvent(self, event): if self.node1 != None: pos = event.pos() self.mouse_pos = (pos.x(), pos.y()) self.repaint() def mousePressEvent(self, event): if not self.searching: if self.mode == '+ .': pos = event.pos() pos = (pos.x(), pos.y()) if self.getNodeAtPos(pos, self.nodeSpacing) == None: node = Node(self._next_label, pos) self.graph.add_node(node) self._next_label += 1 self.repaint() else: # TODO send message to status bar saying not allowed pass if self.mode == '+ ---': pos = event.pos() pos = (pos.x(), pos.y()) self.mouse_pos = pos node = self.getNodeAtPos(pos, padding=self.nodeDetectPadding) if node == None: self.node1 = None elif self.node1 == None: self.node1 = node elif self.node1 != node: node1 = self.node1 node2 = node pre_existing_edges = set.intersection( self.node1.get_connected_edges(), node2.get_connected_edges()) if len(pre_existing_edges) == 0: weight = sqr_dist(node1, node2)**0.5 self.graph.add_edge( UndirectedEdge(node1, node2, weight)) else: # TODO send message to status bar saying not allowed pass self.node1 = None else: # TODO send message to status bar saying not allowed pass self.repaint() if self.mode == '+ -->': pos = event.pos() pos = (pos.x(), pos.y()) self.mouse_pos = pos node = self.getNodeAtPos(pos, padding=self.nodeDetectPadding) if node == None: self.node1 = None elif self.node1 == None: self.node1 = node elif self.node1 != node: node1 = self.node1 node2 = node pre_existing_edges = set.intersection( self.node1.get_connected_edges(), node2.get_connected_edges()) pre_existing_edges = {edge for edge in pre_existing_edges if \ edge.get_node2() == node2 or edge.__class__ == UndirectedEdge} if len(pre_existing_edges) == 0: weight = sqr_dist(node1, node2)**0.5 self.graph.add_edge(DirectedEdge(node1, node2, weight)) else: # TODO send message to status bar saying not allowed pass self.node1 = None else: # TODO send message to status bar saying not allowed pass self.repaint() if self.mode == '- .': pos = event.pos() pos = (pos.x(), pos.y()) node = self.getNodeAtPos(pos, self.nodeDetectPadding) if node != None: if node == self.start: self.start = None if node == self.goal: self.goal = None if node in self.goalPath: self.clearSearchVars() self.graph.delete_node(node) self.repaint() if self.mode == '- ---': pos = event.pos() pos = (pos.x(), pos.y()) edge = self.getEdgeAtPos(pos, self.edgeDetectPadding) print(edge) if edge != None: if edge in self.goalPath.get_edges(): self.clearSearchVars(False) self.graph.delete_edge(edge) self.repaint() if self.mode == '+ S': pos = event.pos() pos = (pos.x(), pos.y()) node = self.getNodeAtPos(pos, self.nodeDetectPadding) if node != self.goal: self.start = node self.repaint() if self.mode == '+ G': pos = event.pos() pos = (pos.x(), pos.y()) node = self.getNodeAtPos(pos, self.nodeDetectPadding) if node != self.start: self.goal = node self.repaint() def getNodeAtPos(self, pos, padding=0): cur_mouse_node = None for node in self.graph.get_nodes(): node_pos = node.get_coords() x_dif = node_pos[0] - pos[0] y_dif = node_pos[1] - pos[1] if x_dif * x_dif + y_dif * y_dif < (self.nodeR + padding) * ( self.nodeR + padding): cur_mouse_node = node break return cur_mouse_node def getEdgeAtPos(self, pos, padding=0): cur_mouse_edge = None for edge in self.graph.get_edges(): pos1 = edge.get_node1().get_coords() pos2 = edge.get_node2().get_coords() m = (pos1[0] - pos2[0]) * (pos1[0] - pos2[0]) + ( pos1[1] - pos2[1]) * (pos1[1] - pos2[1]) px = (pos[0] - pos1[0]) * (pos2[0] - pos1[0]) + ( pos[1] - pos1[1]) * (pos2[1] - pos1[1]) py = (pos[1] - pos1[1]) * (pos2[0] - pos1[0]) - ( pos[0] - pos1[0]) * (pos2[1] - pos1[1]) p2 = (pos[0] - pos2[0]) * (pos[0] - pos2[0]) + ( pos[1] - pos2[1]) * (pos[1] - pos2[1]) condition1 = 0 < px and px < m and py * py < padding * padding * m condition2 = px < 0 and px * px + py * py < padding * padding condition3 = px > m and p2 < padding * padding if condition1 or condition2 or condition3: cur_mouse_edge = edge break return cur_mouse_edge