From 24e4d1028bb57a2578cdcae1d866d462c77273e3 Mon Sep 17 00:00:00 2001 From: bklronin Date: Fri, 28 Jun 2024 14:22:27 +0200 Subject: [PATCH] =?UTF-8?q?-=20Added=20p=C3=BCoint=20to=20line=20incl=20de?= =?UTF-8?q?tection=20-=20Added=20draggable=20points=20-=20added=20fhunctio?= =?UTF-8?q?ns=20for=20solv=20retreival?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- drawing_modules/draw_widget2d.py | 343 +++++++++++++++++-------------- main.py | 11 - 2 files changed, 188 insertions(+), 166 deletions(-) diff --git a/drawing_modules/draw_widget2d.py b/drawing_modules/draw_widget2d.py index 55c5502..75dafce 100644 --- a/drawing_modules/draw_widget2d.py +++ b/drawing_modules/draw_widget2d.py @@ -12,7 +12,12 @@ class SketchWidget(QWidget): def __init__(self): super().__init__() + self.main_buffer = [None, None] + self.distance_line = None + self.distance_point = None + self.point_for_mid = None + self.line_selected_mid = None self.zoom = 1 self.selected_main_idx = None self.pt_line_buffer = None @@ -69,6 +74,30 @@ class SketchWidget(QWidget): return result + def get_handle_from_ui_point(self, ui_point: QPoint): + """Input QPoint and you shall reveive a slvs entity handle!""" + for point in self.slv_points_main: + if ui_point == point['ui_point']: + slv_handle = point['solv_handle'] + + return slv_handle + + def get_line_handle_from_ui_point(self, ui_point: QPoint): + """Input Qpoint that is on a line and you shall receive the handle of the line!""" + for target_line_con in self.slv_lines_main: + if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): + slv_handle = target_line_con['solv_handle'] + + return slv_handle + + def get_point_line_handles_from_ui_point(self, ui_point: QPoint) -> tuple: + """Input Qpoint that is on a line and you shall receive the handles of the points of the line!""" + for target_line_con in self.slv_lines_main: + if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): + lines_to_cons = target_line_con['solv_entity_points'] + + return lines_to_cons + def distance(self, p1, p2): return math.sqrt((p1.x() - p2.x())**2 + (p1.y() - p2.y())**2) @@ -102,97 +131,87 @@ class SketchWidget(QWidget): return 0 <= dot_product <= 1 else: return None + def viewport_to_local_coord(self, qt_pos : QPoint) -> QPoint: self.to_quadrant_coords(qt_pos) return QPoint(self.to_quadrant_coords(qt_pos)) + def check_all_points(self,) -> list: + old_points_ui = [] + new_points_ui = [] + + for old_point_ui in self.slv_points_main: + old_points_ui.append(old_point_ui['ui_point']) + + for i in range(self.solv.entity_len()): + # Iterate though full length because mixed list from SS + entity = self.solv.entity(i) + if entity.is_point_2d() and self.solv.params(entity.params): + x_tbu, y_tbu = self.solv.params(entity.params) + point_solved = QPoint(x_tbu, y_tbu) + new_points_ui.append(point_solved) + + # Now we have old_points_ui and new_points_ui, let's compare them + differences = [] + + if len(old_points_ui) != len(new_points_ui): + print(f"Length mismatch {len(old_points_ui)} - {len(new_points_ui)}") + + for index, (old_point, new_point) in enumerate(zip(old_points_ui, new_points_ui)): + if old_point != new_point: + differences.append((index, old_point, new_point)) + + return differences + + def update_ui_points(self, point_list: list): + # Print initial state of slv_points_main + # print("Initial slv_points_main:", self.slv_points_main) + print("Change list:", point_list) + + if len(point_list) > 0: + for tbu_points_idx in point_list: + # Each tbu_points_idx is a tuple: (index, old_point, new_point) + index, old_point, new_point = tbu_points_idx + + # Update the point in slv_points_main + self.slv_points_main[index]['ui_point'] = new_point + + # Print updated state + # print("Updated slv_points_main:", self.slv_points_main) + + def check_all_lines_and_update(self,changed_points: list): + for tbu_points_idx in changed_points: + index, old_point, new_point = tbu_points_idx + for line_needs_update in self.slv_lines_main: + if old_point == line_needs_update['ui_points'][0]: + line_needs_update['ui_points'][0] = new_point + elif old_point == line_needs_update['ui_points'][1]: + line_needs_update['ui_points'][1] = new_point + + def mouseReleaseEvent(self, event): + local_event_pos = self.viewport_to_local_coord(event.pos()) + if event.button() == Qt.LeftButton and not self.mouse_mode: + self.main_buffer[1] = local_event_pos + + print("Le main buffer", self.main_buffer) + + if len(self.main_buffer) == 2: + + entry = self.main_buffer[0] + new_params = [self.main_buffer[1].x(), self.main_buffer[1].y()] + self.solv.set_params(entry.params, new_params ) + + self.solv.solve() + + points_need_update = self.check_all_points() + self.update_ui_points(points_need_update) + self.check_all_lines_and_update(points_need_update) + + self.update() + def mousePressEvent(self, event): local_event_pos = self.viewport_to_local_coord(event.pos()) - def check_all_points() -> list: - old_points_ui = [] - new_points_ui = [] - - for old_point_ui in self.slv_points_main: - old_points_ui.append(old_point_ui['ui_point']) - - for i in range(len(self.slv_points_main) + len(self.slv_lines_main)): - #Iterate though full length because mixed list from SS - entity = self.solv.entity(i) - if entity.is_point_2d() and self.solv.params(entity.params): - x_tbu, y_tbu = self.solv.params(entity.params) - point_solved = QPoint(x_tbu, y_tbu) - new_points_ui.append(point_solved) - - # Now we have old_points_ui and new_points_ui, let's compare them - differences = [] - - if len(old_points_ui) != len(new_points_ui) +1 : - differences.append(f"Length mismatch {len(old_points_ui)} - {len(new_points_ui)}") - return differences - - for index, (old_point, new_point) in enumerate(zip(old_points_ui, new_points_ui)): - if old_point != new_point: - differences.append((index, old_point, new_point)) - - return differences - - def update_ui_points(point_list: list): - # Print initial state of slv_points_main - """print("Initial slv_points_main:", self.slv_points_main) - print("Change list:", point_list)""" - - if len(point_list) > 0: - for tbu_points_idx in point_list: - # Each tbu_points_idx is a tuple: (index, old_point, new_point) - index, old_point, new_point = tbu_points_idx - """print("Updating index:", index) - print("Old point:", old_point) - print("New point:", new_point)""" - - # Update the point in slv_points_main - self.slv_points_main[index]['ui_point'] = new_point - - # Print updated state - #print("Updated slv_points_main:", self.slv_points_main) - - """# UPDATE UI POINTS with solver points - for i in range(len(self.slv_points_main) + len(self.slv_lines_main)): - entity = self.solv.entity(i) - if entity.is_point_2d() and self.solv.params(entity.params): - x_tbu, y_tbu = self.solv.params(entity.params) - point_solved = QPoint(x_tbu, y_tbu) - for point_to_be_updated in self.slv_points_main: - #print("Checking point:", point_to_be_updated) - # if the old ui point is present in the selected constrain line - # update the _ui_point with solver_point - - if point_to_be_updated['ui_point'] == target_line_con['ui_points'][0]: - print("that got updated", point_solved) - point_to_be_updated['ui_point'] = point_solved - - elif point_to_be_updated['ui_point'] == target_line_con['ui_points'][1]: - print("this got updated", point_solved) - point_to_be_updated['ui_point'] = point_solved - - if point_to_be_updated['ui_point'] == target_line_con['ui_points'][0]: - target_line_con['ui_points'][0] = point_solved - - elif point_to_be_updated['ui_point'] == target_line_con['ui_points'][1]: - target_line_con['ui_points'][1] = point_solved - - #TODO: All points ui and solve into lists and then check before afer for changes - # and update displayed points and then lines""" - - def check_all_lines_and_update(changed_points: list): - for tbu_points_idx in changed_points: - index, old_point, new_point = tbu_points_idx - for line_needs_update in self.slv_lines_main: - if old_point == line_needs_update['ui_points'][0]: - line_needs_update['ui_points'][0] = new_point - elif old_point == line_needs_update['ui_points'][1]: - line_needs_update['ui_points'][1] = new_point - relation_point = { 'handle_nr': None, 'solv_handle': None, @@ -207,11 +226,11 @@ class SketchWidget(QWidget): 'ui_points': None } + if event.button() == Qt.LeftButton and not self.mouse_mode: + self.main_buffer[0] = self.get_handle_from_ui_point(self.hovered_point) + if event.button() == Qt.LeftButton and self.mouse_mode == "line": clicked_pos = local_event_pos - # Paintline - """self.points.append(clicked_pos) - self.update()""" u = clicked_pos.x() v = clicked_pos.y() @@ -241,6 +260,7 @@ class SketchWidget(QWidget): relation_point['part_of_entity'] = handle_nr_line self.slv_lines_main.append(relation_line) + self.line_buffer = None self.slv_points_main.append(relation_point) @@ -250,8 +270,6 @@ class SketchWidget(QWidget): print("lines", self.slv_lines_main) if event.button() == Qt.LeftButton and self.mouse_mode == "pt_pt": - point_solve_old = None - point_solve_now = None if self.pt_pt_buffer: for new_id, target_line in enumerate(self.slv_points_main): @@ -274,19 +292,8 @@ class SketchWidget(QWidget): self.solv.coincident(point_solve_now, point_solve_old, self.wp) if self.solv.solve() == ResultFlag.OKAY: - - """x, y = self.solv.params(self.slv_points_main[move_id]['solv_handle'].params) - moved_point = QPoint(x, y) - self.slv_points_main[target_id]['ui_point'] = moved_point - - for ident, lines in enumerate(self.slv_lines_main): - if self.slv_points_main[target_id]['solv_handle'] == lines['solv_entity_points'][0]: - self.slv_lines_main[ident]['ui_points'][0] = moved_point""" - - self.pt_pt_buffer = [] self.constrain_done.emit() - #print(dof) - self.update() + print("Fuck yeah") elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: print("Solve_failed - Converge" ) @@ -298,10 +305,8 @@ class SketchWidget(QWidget): print("Solve_failed - Incons" ) self.points = [] + self.pt_pt_buffer = [] - #for points_ui in self.slv_points_main: - #self.points.append(points_ui['ui_point']) - print(self.points) print("Points_all", self.slv_points_main) self.pt_pt_buffer = self.hovered_point @@ -347,13 +352,6 @@ class SketchWidget(QWidget): if self.solv.solve() == ResultFlag.OKAY: print("Fuck yeah") - x, y = self.solv.params(self.pt_line_buffer['solv_handle'].params) - - #Update UI points to returned points from solver - self.slv_points_main[self.selected_main_idx]['ui_point'] = QPoint(x, y) - self.slv_lines_main[line_nr]['ui_points'][idx] = QPoint(x, y) - - self.pt_line_buffer = None self.constrain_done.emit() elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: @@ -365,20 +363,18 @@ class SketchWidget(QWidget): elif self.solv.solve() == ResultFlag.INCONSISTENT: print("Solve_failed - Incons") + # Clear saved_points after solve attempt + self.pt_line_buffer = None + if event.button() == Qt.LeftButton and self.mouse_mode == "horiz": - for target_line_con in self.slv_lines_main: - if self.is_point_on_line(local_event_pos, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): - line_selected = target_line_con['solv_handle'] - print(line_selected.params) - break + line_selected = self.get_line_handle_from_ui_point(local_event_pos) self.solv.horizontal(line_selected, self.wp) if self.solv.solve() == ResultFlag.OKAY: print("Fuck yeah") - self.pt_line_buffer = None self.constrain_done.emit() elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: @@ -390,20 +386,17 @@ class SketchWidget(QWidget): elif self.solv.solve() == ResultFlag.INCONSISTENT: print("Solve_failed - Incons") + + if event.button() == Qt.LeftButton and self.mouse_mode == "vert": - for target_line_con in self.slv_lines_main: - if self.is_point_on_line(local_event_pos, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): - line_selected = target_line_con['solv_handle'] - print(line_selected.params) - break + line_selected = self.get_line_handle_from_ui_point(local_event_pos) self.solv.vertical(line_selected, self.wp) if self.solv.solve() == ResultFlag.OKAY: print("Fuck yeah") - self.pt_line_buffer = None self.constrain_done.emit() elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: @@ -415,43 +408,82 @@ class SketchWidget(QWidget): elif self.solv.solve() == ResultFlag.INCONSISTENT: print("Solve_failed - Incons") + self.pt_line_buffer = None + if event.button() == Qt.LeftButton and self.mouse_mode == "distance": print("distance") + e1 = None + e2 = None - for target_line_con in self.slv_lines_main: - if self.is_point_on_line(local_event_pos, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): - lines_to_cons = target_line_con['solv_entity_points'] - break - length, ok = QInputDialog.getDouble(self, 'Distance', 'Enter a mm value:', decimals=2) - e1, e2 = lines_to_cons + if self.hovered_point: + self.distance_point = self.hovered_point - self.solv.distance(e1, e2, length, self.wp) + if self.selected_line: + self.distance_line = self.selected_line - if self.solv.solve() == ResultFlag.OKAY: - print("Fuck yeah") + if self.distance_point and self.distance_line: + e1 = self.get_handle_from_ui_point(self.distance_point) + e2 = self.get_line_handle_from_ui_point(local_event_pos) - self.pt_line_buffer = None - self.constrain_done.emit() + elif not self.distance_point: + e1, e2 = self.get_point_line_handles_from_ui_point(local_event_pos) - elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: - print("Solve_failed - Converge") + if e1 and e2: + length, ok = QInputDialog.getDouble(self, 'Distance', 'Enter a mm value:', value=100, decimals=2) + self.solv.distance(e1, e2, length, self.wp) - elif self.solv.solve() == ResultFlag.TOO_MANY_UNKNOWNS: - print("Solve_failed - Unknowns") + if self.solv.solve() == ResultFlag.OKAY: + print("Fuck yeah") + self.distance_point = None + self.distance_line = None + self.constrain_done.emit() - elif self.solv.solve() == ResultFlag.INCONSISTENT: - print("Solve_failed - Incons") + elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: + print("Solve_failed - Converge") + + elif self.solv.solve() == ResultFlag.TOO_MANY_UNKNOWNS: + print("Solve_failed - Unknowns") + + elif self.solv.solve() == ResultFlag.INCONSISTENT: + print("Solve_failed - Incons") if event.button() == Qt.LeftButton and self.mouse_mode == "pb_con_mid": + for entry_point_mid in self.slv_points_main: + if self.hovered_point == entry_point_mid['ui_point']: + self.point_for_mid = entry_point_mid['solv_handle'] + break + if self.point_for_mid: + for target_line_con in self.slv_lines_main: + if self.is_point_on_line(local_event_pos, target_line_con['ui_points'][0], target_line_con['ui_points'][1]): + self.line_selected_mid = target_line_con['solv_handle'] + break - points_need_update = check_all_points() - print("This", points_need_update) - update_ui_points(points_need_update) + print(f"{self.point_for_mid}, {self.line_selected_mid}") + if self.line_selected_mid and self.point_for_mid: + self.solv.midpoint(self.point_for_mid, self.line_selected_mid, self.wp) - lines_need_update = check_all_lines_and_update(points_need_update) - print("This", lines_need_update) + if self.solv.solve() == ResultFlag.OKAY: + print("Fuck yeah") + + self.constrain_done.emit() + + elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: + print("Solve_failed - Converge") + + elif self.solv.solve() == ResultFlag.TOO_MANY_UNKNOWNS: + print("Solve_failed - Unknowns") + + elif self.solv.solve() == ResultFlag.INCONSISTENT: + print("Solve_failed - Incons") + + self.point_for_mid = None + self.line_selected_mid = None + + points_need_update = self.check_all_points() + self.update_ui_points(points_need_update) + self.check_all_lines_and_update(points_need_update) dof = self.solv.dof() print(dof) @@ -475,8 +507,6 @@ class SketchWidget(QWidget): self.hovered_point = closest_point print(self.hovered_point) - selected_points = [] - for dic in self.slv_lines_main: p1 = dic['ui_points'][0] p2 = dic['ui_points'][1] @@ -543,6 +573,7 @@ class SketchWidget(QWidget): painter.setPen(QPen(Qt.red, 4)) painter.drawPoint(middle_x, middle_y) + def to_quadrant_coords(self, point): """Translate linear coordinates to quadrant coordinates.""" center_x = self.width() // 2 @@ -554,7 +585,6 @@ class SketchWidget(QWidget): def paintEvent(self, event): painter = QPainter(self) - #self.drawBackgroundGrid(painter) self.drawAxes(painter) # Translate the origin to the center of the widget @@ -579,19 +609,20 @@ class SketchWidget(QWidget): dis = self.distance(p1, p2) mid = self.calculate_midpoint(p1, p2) - painter.drawText(mid, str(round(dis, 2))) pen = QPen(Qt.green) pen.setWidth(2) painter.setPen(pen) - for i in range(len(self.slv_points_main) + len(self.slv_lines_main)): - entity = self.solv.entity(i) - if entity.is_point_2d() and self.solv.params(entity.params): - x,y = self.solv.params(entity.params) - point = QPoint(x, y) - painter.drawEllipse(point, 6 / self.zoom, 6 / self.zoom) + if self.solv.entity_len(): + for i in range(self.solv.entity_len()): + # 3 Entitys in the beginning of the workplane normal and point + entity = self.solv.entity(i) + if entity.is_point_2d() and self.solv.params(entity.params): + x, y = self.solv.params(entity.params) + point = QPoint(x, y) + painter.drawEllipse(point, 6 / self.zoom, 6 / self.zoom) #Highlight point hovered if self.hovered_point: @@ -600,11 +631,13 @@ class SketchWidget(QWidget): painter.setPen(highlight_pen) painter.drawEllipse(self.hovered_point, 5 / self.zoom, 5 / self.zoom) + # Highlight line hovered if self.selected_line and not self.hovered_point: p1, p2 = self.selected_line painter.setPen(QPen(Qt.red, 2)) painter.drawLine(p1, p2) + # self.drawBackgroundGrid(painter) painter.end() def wheelEvent(self, event): diff --git a/main.py b/main.py index 73fe02b..4934e13 100644 --- a/main.py +++ b/main.py @@ -66,60 +66,49 @@ class MainWindow(QMainWindow): self.sketchWidget.constrain_done.connect(self.constrain_finished) def add_wp_origin(self): - #Select orientation - #orientation, ok = Q .getDouble(self, 'Extrude Length', 'Enter a mm value:', decimals=2) self.sketchWidget.create_worplane() def act_line_mode(self): if not self.ui.pb_linetool.isChecked(): self.sketchWidget.mouse_mode = 'line' - #self.sketchWidget.points = [] else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None - self.sketchWidget.points = [] def act_constrain_pt_pt_mode(self): if not self.ui.pb_con_ptpt.isChecked(): self.sketchWidget.mouse_mode = 'pt_pt' else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None def act_constrain_pt_line_mode(self): if not self.ui.pb_con_line.isChecked(): self.sketchWidget.mouse_mode = 'pt_line' else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None def act_constrain_horiz_line_mode(self): if not self.ui.pb_con_horiz.isChecked(): self.sketchWidget.mouse_mode = 'horiz' else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None def act_constrain_vert_line_mode(self): if not self.ui.pb_con_vert.isChecked(): self.sketchWidget.mouse_mode = 'vert' else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None def act_constrain_distance_mode(self): if not self.ui.pb_con_dist.isChecked(): self.sketchWidget.mouse_mode = 'distance' else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None def act_constrain_mid_point_mode(self): if not self.ui.pb_con_mid.isChecked(): self.sketchWidget.mouse_mode = 'pb_con_mid' else: self.sketchWidget.mouse_mode = None - self.sketchWidget.line_buffer = None def constrain_finished(self): self.ui.pb_con_ptpt.setChecked(False)