From e9383f76a227b5cf6edf711709c0145dd5fbd056 Mon Sep 17 00:00:00 2001 From: bklronin Date: Wed, 1 Jan 2025 21:35:43 +0100 Subject: [PATCH] - delete sketch working - added mid point snap - added hovering line with distance --- drawing_modules/draw_widget_solve.py | 50 +++++++++++++++---- main.py | 75 +++++++++++++--------------- 2 files changed, 75 insertions(+), 50 deletions(-) diff --git a/drawing_modules/draw_widget_solve.py b/drawing_modules/draw_widget_solve.py index 4a1d8e4..a1058da 100644 --- a/drawing_modules/draw_widget_solve.py +++ b/drawing_modules/draw_widget_solve.py @@ -19,6 +19,7 @@ class SketchWidget(QWidget): self.line_draw_buffer = [None, None] self.drag_buffer = [None, None] self.main_buffer = [None, None] + self.dynamic_line_end = None # Cursor position for dynamic drawing self.hovered_point = None self.selected_line = None @@ -186,7 +187,7 @@ class SketchWidget(QWidget): 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.sketch.slv_lines: + for target_line_con in self.sketch.lines: if self.is_point_on_line(ui_point, target_line_con.crd1.ui_point, target_line_con.crd2.ui_point): lines_to_cons = target_line_con.crd1.handle, target_line_con.crd2.handle @@ -535,13 +536,18 @@ class SketchWidget(QWidget): def mouseMoveEvent(self, event): local_event_pos = self.viewport_to_local_coord(event.pos()) + #print(local_event_pos) closest_point = None min_distance = float('inf') threshold = 10 # Distance threshold for highlighting - if len(self.sketch.points) > 0: + if self.mouse_mode == "line" and self.line_draw_buffer[0]: + # Update the current cursor position as the second point + self.dynamic_line_end = self.viewport_to_local_coord(event.pos()) + self.update() # Trigger a repaint + if self.sketch.points is not None and len(self.sketch.points) > 0: for point in self.sketch.points: distance = (local_event_pos - point.ui_point).manhattanLength() if distance < threshold and distance < min_distance: @@ -564,6 +570,10 @@ class SketchWidget(QWidget): if self.is_point_on_line(local_event_pos, p1, p2): self.selected_line = p1, p2 + mid = self.calculate_midpoint(p1, p2) + distance = (local_event_pos - mid).manhattanLength() + if distance < threshold and distance < min_distance: + self.hovered_point = mid break else: self.selected_line = None @@ -695,7 +705,10 @@ class SketchWidget(QWidget): pen_solver = QPen(Qt.green) pen_solver.setWidthF(2 / self.zoom) - # Draw points + pen_text = QPen(Qt.white) + pen_text.setWidthF(1 / self.zoom) + + # Draw points and lines if self.sketch: painter.setPen(pen_normal) for point in self.sketch.points: @@ -703,10 +716,34 @@ class SketchWidget(QWidget): painter.setPen(pen_construct) painter.drawEllipse(point.ui_point, 10 / self.zoom, 10 / self.zoom) else: - #Normal point + # Normal point painter.setPen(pen_normal) painter.drawEllipse(point.ui_point, 3 / self.zoom, 3 / self.zoom) + # Draw the dynamic line + if self.mouse_mode == "line" and self.line_draw_buffer[0] and self.dynamic_line_end is not None: + start_point = self.line_draw_buffer[0].ui_point + end_point = self.dynamic_line_end + painter.setPen(Qt.red) # Use a different color for the dynamic line + painter.drawLine(start_point, end_point) + + # Save painter state + painter.save() + painter.setPen(pen_text) + + # Calculate the distance and midpoint + dis = self.distance(start_point, end_point) + mid = self.calculate_midpoint(start_point, end_point) + + # Transform for text + painter.translate(mid.x(), mid.y()) # Move to the midpoint + painter.scale(1, -1) # Flip y-axis back to make text readable + + # Draw the text + painter.drawText(0, 0, str(round(dis, 2))) # Draw text at transformed position + + # Restore painter state + painter.restore() for line in self.sketch.lines: if line.is_helper: @@ -720,11 +757,6 @@ class SketchWidget(QWidget): p2 = line.crd2.ui_point painter.drawLine(p1, p2) - dis = self.distance(p1, p2) - mid = self.calculate_midpoint(p1, p2) - painter.drawText(mid, str(round(dis, 2))) - - # Draw all solver points if self.sketch.entity_len(): painter.setPen(pen_solver) diff --git a/main.py b/main.py index fc05fd5..2b5588a 100644 --- a/main.py +++ b/main.py @@ -6,7 +6,7 @@ import uuid import names from PySide6.QtCore import Qt, QPoint, Signal, QSize -from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy, QInputDialog, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox, QCheckBox, QPushButton +from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy, QInputDialog, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox, QCheckBox, QPushButton, QButtonGroup from Gui import Ui_fluencyCAD # Import the generated GUI module from drawing_modules.vtk_widget import VTKWidget from drawing_modules.vysta_widget import PyVistaWidget @@ -156,6 +156,7 @@ class MainWindow(QMainWindow): self.project.timeline = timeline self.new_component() + def new_component(self): print("Creating a new component...") @@ -164,6 +165,10 @@ class MainWindow(QMainWindow): print("Initializing compo_layout...") self.compo_layout = QHBoxLayout() + # Create a button group + self.compo_group = QButtonGroup(self) + self.compo_group.setExclusive(True) # Ensure exclusivity + # Ensure the QGroupBox has a layout if not self.ui.compo_box.layout(): self.ui.compo_box.setLayout(QVBoxLayout()) # Set a default layout for QGroupBox @@ -188,13 +193,19 @@ class MainWindow(QMainWindow): button.setText(str(len(self.project.timeline))) button.setFixedSize(QSize(40, 40)) # Set button size button.setCheckable(True) - button.setAutoExclusive(True) - button.setChecked(False) + #button.setAutoExclusive(True) button.released.connect(self.on_compo_change) + button.setChecked(True) + + # Add button to the group + self.compo_group.addButton(button) # Add the button to the layout self.compo_layout.addWidget(button) + # We automatically switch to the new compo hence, refresh + self.on_compo_change() + print(f"Added component {compo.id} to the layout.") def get_activated_compo(self): @@ -285,6 +296,7 @@ class MainWindow(QMainWindow): def on_compo_change(self): self.custom_3D_Widget.clear_body_actors() self.custom_3D_Widget.clear_actors_interactor() + self.custom_3D_Widget.clear_actors_projection() compo_id = self.get_activated_compo() if compo_id is not None: @@ -301,16 +313,17 @@ class MainWindow(QMainWindow): for body in self.project.timeline[compo_id].bodies: self.ui.body_list.addItem(body) - item = self.ui.body_list.findItems(body , Qt.MatchExactly)[0] - self.ui.body_list.setCurrentItem(item) - self.draw_mesh() + if self.project.timeline[compo_id].bodies: + item = self.ui.body_list.findItems(body , Qt.MatchExactly)[0] + self.ui.body_list.setCurrentItem(item) + self.draw_mesh() - selected = self.ui.body_list.currentItem() - name = selected.text() + selected = self.ui.body_list.currentItem() + name = selected.text() - edges = self.project.timeline[compo_id].bodies[name].interactor.edges - offset_vec = self.project.timeline[compo_id].bodies[name].interactor.offset_vector - self.custom_3D_Widget.load_interactor_mesh(edges, offset_vec) + edges = self.project.timeline[compo_id].bodies[name].interactor.edges + offset_vec = self.project.timeline[compo_id].bodies[name].interactor.offset_vector + self.custom_3D_Widget.load_interactor_mesh(edges, offset_vec) def edit_sketch(self): selected = self.ui.sketch_list.currentItem() @@ -323,40 +336,20 @@ class MainWindow(QMainWindow): self.sketchWidget.update() def del_sketch(self): - # Old - print("Deleting") - name = self.ui.sketch_list.currentItem() # Get the current item + selected = self.ui.sketch_list.currentItem() + name = selected.text() + sel_compo = self.project.timeline[self.get_activated_compo()] + sketch = sel_compo.sketches[name] - print(self.model) - - if name is not None: - item_name = name.text() - print("obj_name", item_name) - - # Check if the 'sketches' key exists in the model dictionary - if 'sketches' in self.model and item_name in self.model['sketches']: - if self.model['sketches'][item_name]['id'] == item_name: - row = self.ui.sketch_list.row(name) # Get the row of the current item - self.ui.sketch_list.takeItem(row) # Remove the item from the list widget - self.sketchWidget.clear_sketch() - self.model['sketches'].pop(item_name) # Remove the item from the sketches dictionary - print(f"Removed sketches: {item_name}") - - # Check if the 'operation' key exists in the model dictionary - elif 'operation' in self.model and item_name in self.model['operation']: - if self.model['operation'][item_name]['id'] == item_name: - row = self.ui.sketch_list.row(name) # Get the row of the current item - self.ui.sketch_list.takeItem(row) # Remove the item from the list widget - self.sketchWidget.clear_sketch() - self.model['operation'].pop(item_name) # Remove the item from the operation dictionary - print(f"Removed operation: {item_name}") - - else: - print(f"Item '{item_name}' not found in either 'sketches' or 'operation' dictionary.") + if sketch is not None: + sel_compo.sketches.pop(name) + row = self.ui.sketch_list.row(selected) # Get the row of the current item + self.ui.sketch_list.takeItem(row) # Remove the item from the list widget + self.sketchWidget.sketch = None + print(sketch) else: print("No item selected.") - def on_flip_face(self): self.send_command.emit("flip")