diff --git a/Gui.py b/Gui.py index 79fd224..fd264eb 100644 --- a/Gui.py +++ b/Gui.py @@ -242,23 +242,29 @@ class Ui_fluencyCAD(object): self.gridLayout_2.setObjectName(u"gridLayout_2") self.pb_rectool = QPushButton(self.groupBox_2) self.pb_rectool.setObjectName(u"pb_rectool") + self.pb_rectool.setCheckable(True) + self.pb_rectool.setAutoExclusive(False) self.gridLayout_2.addWidget(self.pb_rectool, 1, 1, 1, 1, Qt.AlignTop) self.pb_circtool = QPushButton(self.groupBox_2) self.pb_circtool.setObjectName(u"pb_circtool") + self.pb_circtool.setCheckable(True) + self.pb_circtool.setAutoExclusive(False) self.gridLayout_2.addWidget(self.pb_circtool, 2, 0, 1, 1, Qt.AlignTop) self.pb_slotool = QPushButton(self.groupBox_2) self.pb_slotool.setObjectName(u"pb_slotool") + self.pb_slotool.setCheckable(True) + self.pb_slotool.setAutoExclusive(False) self.gridLayout_2.addWidget(self.pb_slotool, 2, 1, 1, 1, Qt.AlignTop) self.pb_linetool = QPushButton(self.groupBox_2) self.pb_linetool.setObjectName(u"pb_linetool") self.pb_linetool.setCheckable(True) - self.pb_linetool.setAutoExclusive(True) + self.pb_linetool.setAutoExclusive(False) self.gridLayout_2.addWidget(self.pb_linetool, 1, 0, 1, 1) @@ -274,25 +280,46 @@ class Ui_fluencyCAD(object): self.pb_con_line = QPushButton(self.groupBox_3) self.pb_con_line.setObjectName(u"pb_con_line") self.pb_con_line.setCheckable(True) + self.pb_con_line.setAutoExclusive(False) self.gridLayout_4.addWidget(self.pb_con_line, 0, 1, 1, 1) self.pb_con_ptpt = QPushButton(self.groupBox_3) self.pb_con_ptpt.setObjectName(u"pb_con_ptpt") self.pb_con_ptpt.setCheckable(True) + self.pb_con_ptpt.setAutoExclusive(False) self.gridLayout_4.addWidget(self.pb_con_ptpt, 0, 0, 1, 1) self.pb_con_horiz = QPushButton(self.groupBox_3) self.pb_con_horiz.setObjectName(u"pb_con_horiz") + self.pb_con_horiz.setCheckable(True) + self.pb_con_horiz.setAutoExclusive(False) self.gridLayout_4.addWidget(self.pb_con_horiz, 1, 0, 1, 1) self.pb_con_vert = QPushButton(self.groupBox_3) self.pb_con_vert.setObjectName(u"pb_con_vert") + self.pb_con_vert.setCheckable(True) + self.pb_con_vert.setAutoExclusive(False) self.gridLayout_4.addWidget(self.pb_con_vert, 1, 1, 1, 1) + self.pb_con_dist = QPushButton(self.groupBox_3) + self.pb_con_dist.setObjectName(u"pb_con_dist") + self.pb_con_dist.setCheckable(True) + self.pb_con_dist.setAutoExclusive(False) + self.pb_con_dist.setAutoRepeatDelay(297) + + self.gridLayout_4.addWidget(self.pb_con_dist, 2, 0, 1, 1) + + self.pb_con_sym = QPushButton(self.groupBox_3) + self.pb_con_sym.setObjectName(u"pb_con_sym") + self.pb_con_sym.setCheckable(True) + self.pb_con_sym.setAutoExclusive(False) + + self.gridLayout_4.addWidget(self.pb_con_sym, 2, 1, 1, 1) + self.gridLayout.addWidget(self.groupBox_3, 2, 0, 1, 1) @@ -352,5 +379,7 @@ class Ui_fluencyCAD(object): self.pb_con_ptpt.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Pt", None)) self.pb_con_horiz.setText(QCoreApplication.translate("fluencyCAD", u"Horiz", None)) self.pb_con_vert.setText(QCoreApplication.translate("fluencyCAD", u"Vert", None)) + self.pb_con_dist.setText(QCoreApplication.translate("fluencyCAD", u"Distnce", None)) + self.pb_con_sym.setText(QCoreApplication.translate("fluencyCAD", u"Symetrc", None)) # retranslateUi diff --git a/drawing_modules/draw_widget2d.py b/drawing_modules/draw_widget2d.py index d073778..e9fcc96 100644 --- a/drawing_modules/draw_widget2d.py +++ b/drawing_modules/draw_widget2d.py @@ -1,14 +1,21 @@ +import math import re from copy import copy -from PySide6.QtWidgets import QApplication, QWidget, QMessageBox +from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QInputDialog from PySide6.QtGui import QPainter, QPen, QColor -from PySide6.QtCore import Qt, QPoint +from PySide6.QtCore import Qt, QPoint, QPointF, Signal from python_solvespace import SolverSystem, ResultFlag class SketchWidget(QWidget): + constrain_done = Signal() + def __init__(self): super().__init__() + + self.zoom = 1 + self.selected_main_idx = None + self.pt_line_buffer = None self.hovered_point = None self.line_buffer = None self.pt_pt_buffer = None @@ -21,7 +28,12 @@ class SketchWidget(QWidget): self.wp = None self.solv = SolverSystem() - self.solventies = [] + self.slv_points_main = [] + self.slv_lines_main = [] + + def set_points(self, points: list): + self.points = points + #self.update() def create_worplane(self): self.wp = self.solv.create_2d_base() @@ -36,12 +48,10 @@ class SketchWidget(QWidget): if match: handle_number = int(match.group(1)) print(f"Handle number: {handle_number}") - return int(handle_number) else: print("Handle number not found.") - return 0 def get_keys(self, d: dict, target: QPoint) -> list: @@ -59,156 +69,539 @@ class SketchWidget(QWidget): return result + def distance(self, p1, p2): + return math.sqrt((p1.x() - p2.x())**2 + (p1.y() - p2.y())**2) + + def is_point_on_line(self, p, p1, p2, tolerance=5): + # Calculate the lengths of the sides of the triangle + a = self.distance(p, p1) + b = self.distance(p, p2) + c = self.distance(p1, p2) + + # Calculate the semi-perimeter + s = (a + b + c) / 2 + + # Calculate the area using Heron's formula + area = math.sqrt(s * (s - a) * (s - b) * (s - c)) + + # Calculate the height (perpendicular distance from the point to the line) + if c > 0: + height = (2 * area) / c + # Check if the height is within the tolerance distance to the line + if height > tolerance: + return False + + # Check if the projection of the point onto the line is within the line segment + dot_product = ((p.x() - p1.x()) * (p2.x() - p1.x()) + (p.y() - p1.y()) * (p2.y() - p1.y())) / (c ** 2) + + 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 mousePressEvent(self, event): - relation = { + 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)""" + + 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 + 'solv_handle': None, + 'ui_point': None, + 'part_of_entity': None + } + + relation_line = { + 'handle_nr': None, + 'solv_handle': None, + 'solv_entity_points': None, + 'ui_points': None } if event.button() == Qt.LeftButton and self.mouse_mode == "line": - clicked_pos = event.pos() + clicked_pos = local_event_pos # Paintline """self.points.append(clicked_pos) self.update()""" u = clicked_pos.x() v = clicked_pos.y() + point = self.solv.add_point_2d(u, v, self.wp) - #print(point) - #self.solv.dragged(point, self.wp) + + # Track Relationship + # Points + handle_nr = self.get_handle_nr(str(point)) + relation_point['handle_nr'] = handle_nr + relation_point['solv_handle'] = point + relation_point['ui_point'] = clicked_pos + + # List of points related to the current "figure" + self.points.append(clicked_pos) # Solverline if self.line_buffer: line = self.solv.add_line_2d(self.line_buffer, point, self.wp) - #print(line) + handle_nr_line = self.get_handle_nr(str(line)) + relation_line['handle_nr'] = handle_nr_line + relation_line['solv_handle'] = line + relation_line['solv_entity_points'] = (self.line_buffer, point) + relation_line['ui_points'] = [self.points[-2], self.points[-1]] + + #track relationship of point in line + relation_point['part_of_entity'] = handle_nr_line + + self.slv_lines_main.append(relation_line) + + self.slv_points_main.append(relation_point) self.line_buffer = point - # Track Relationship - handle_nr = self.get_handle_nr(str(point)) - relation['handle_nr'] = handle_nr - relation['solv_handle'] = point - relation['ui_point'] = clicked_pos - - self.solventies.append(relation) - - self.points.append(clicked_pos) - - print(self.points) + print("points", self.slv_points_main) + print("lines", self.slv_lines_main) if event.button() == Qt.LeftButton and self.mouse_mode == "pt_pt": - #point_solve_now = self.solventies[self.hovered_point]['solv_handle'] - - for new_id, entry in enumerate(self.solventies): - if self.hovered_point == entry['ui_point']: - point_solve_now = entry['solv_handle'] - print(point_solve_now) - target_id = new_id + point_solve_old = None + point_solve_now = None if self.pt_pt_buffer: - for old_id, entry in enumerate(self.solventies): - if self.pt_pt_buffer == entry['ui_point']: - point_solve_old = entry['solv_handle'] + for new_id, target_line in enumerate(self.slv_points_main): + if self.hovered_point == target_line['ui_point']: + point_solve_now = target_line['solv_handle'] + target_id = new_id + break + else: + point_solve_now = None + + for old_id, target_line in enumerate(self.slv_points_main): + if self.pt_pt_buffer == target_line['ui_point']: + point_solve_old = target_line['solv_handle'] move_id = old_id + break + else: + point_solve_old = None - #point_solve_old = self.solventies[self.pt_pt_buffer]['solv_handle'] - #self.solv.dragged(point_solve_now, self.wp) - self.solv.coincident(point_solve_now, point_solve_old, self.wp) + if point_solve_old and point_solve_now: + self.solv.coincident(point_solve_now, point_solve_old, self.wp) - if self.solv.solve() == ResultFlag.OKAY: - # Get the result (unpack from the entity or parameters) - # x and y are actually float type - dof = self.solv.dof() - print(dof) - print(self.solventies[move_id]['ui_point']) - print(self.solventies[target_id]['ui_point']) - x, y = self.solv.params(self.solventies[move_id]['solv_handle'].params) - self.solventies[move_id]['ui_point'] = QPoint(x, y) + if self.solv.solve() == ResultFlag.OKAY: - print(f"{x}, {y}") - print(self.solventies) #after adding the result + """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 - elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: - print("Solve_failed - Converge" ) + 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""" - elif self.solv.solve() == ResultFlag.TOO_MANY_UNKNOWNS: - print("Solve_failed - Unknowns" ) + self.pt_pt_buffer = [] + self.constrain_done.emit() + #print(dof) + self.update() - elif self.solv.solve() == ResultFlag.INCONSISTENT: - print("Solve_failed - Incons" ) + elif self.solv.solve() == ResultFlag.DIDNT_CONVERGE: + print("Solve_failed - Converge" ) - self.points = [] - for points_ui in self.solventies: - self.points.append(points_ui['ui_point']) - print(self.points) + elif self.solv.solve() == ResultFlag.TOO_MANY_UNKNOWNS: + print("Solve_failed - Unknowns" ) + + elif self.solv.solve() == ResultFlag.INCONSISTENT: + print("Solve_failed - Incons" ) + + self.points = [] + + #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 self.update() - + + if event.button() == Qt.LeftButton and self.mouse_mode == "pt_line": + print("ptline") + line_selected = None + + if self.hovered_point: + for nr, entry_point in enumerate(self.slv_points_main): + if self.hovered_point == entry_point['ui_point']: + self.pt_line_buffer = entry_point + self.selected_main_idx = nr + print("Point set", self.pt_line_buffer) + break + + if self.pt_line_buffer: + #Line selection target_line to constrain to + 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 + + #Update UI Line position ot the line of the selected point + for line_nr, move_line in enumerate(self.slv_lines_main): + #Test what point is going to be moved from the line + if move_line['ui_points'][0] == self.pt_line_buffer['ui_point']: + print("On line", line_nr) + idx = 0 + break + + elif move_line['ui_points'][1] == self.pt_line_buffer['ui_point']: + print("On line", line_nr) + idx = 1 + break + + # Contrain point to line + if line_selected: + self.solv.coincident(self.pt_line_buffer['solv_handle'], line_selected, self.wp) + print(f"1 : {self.pt_line_buffer['solv_handle']}, 2: {line_selected}") + + 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: + 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 == "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 + + 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: + 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 == "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 + + 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: + 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 == "distance": + print("distance") + + 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 + + self.solv.distance(e1, e2, length, 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: + 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") + + + points_need_update = check_all_points() + print("This", points_need_update) + update_ui_points(points_need_update) + + lines_need_update = check_all_lines_and_update(points_need_update) + print("This", lines_need_update) + + dof = self.solv.dof() + print(dof) + + self.update() + def mouseMoveEvent(self, event): + local_event_pos = self.viewport_to_local_coord(event.pos()) + closest_point = None min_distance = float('inf') threshold = 10 # Distance threshold for highlighting - for point in self.points: - distance = (event.pos() - point).manhattanLength() + for point in self.slv_points_main: + distance = (local_event_pos - point['ui_point']).manhattanLength() if distance < threshold and distance < min_distance: - closest_point = point + closest_point = point['ui_point'] min_distance = distance if closest_point != self.hovered_point: self.hovered_point = closest_point - self.update() + print(self.hovered_point) + + selected_points = [] + + for dic in self.slv_lines_main: + p1 = dic['ui_points'][0] + p2 = dic['ui_points'][1] + + if self.is_point_on_line(local_event_pos, p1, p2): + self.selected_line = p1, p2 + break + else: + self.selected_line = None + + self.update() def mouseDoubleClickEvent(self, event): pass - def distance(self, p1, p2): - return ((p1.x() - p2.x()) ** 2 + (p1.y() - p2.y()) ** 2) ** 0.5 + def drawBackgroundGrid(self, painter): + """Draw a background grid.""" + grid_spacing = 50 + pen = QPen(QColor(200, 200, 200), 1, Qt.SolidLine) + painter.setPen(pen) - def set_points(self, points: list): - self.points = points - #self.update() + # Draw vertical grid lines + for x in range(-self.width() // 2, self.width() // 2, grid_spacing): + painter.drawLine(x, -self.height() // 2, x, self.height() // 2) - def is_point_on_line(self, p, p1, p2): - distance1 = self.distance(p, p1) - distance2 = self.distance(p, p2) - total_distance = self.distance(p1, p2) + # Draw horizontal grid lines + for y in range(-self.height() // 2, self.height() // 2, grid_spacing): + painter.drawLine(-self.width() // 2, y, self.width() // 2, y) - return abs(distance1 + distance2 - total_distance) < 1 + def drawAxes(self, painter): + painter.setRenderHint(QPainter.Antialiasing) + + # Set up pen for dashed lines + pen = QPen(Qt.gray, 1, Qt.DashLine) + painter.setPen(pen) + + middle_x = self.width() // 2 + middle_y = self.height() // 2 + + # Draw X axis as dashed line + painter.drawLine(0, middle_y, self.width(), middle_y) + + # Draw Y axis as dashed line + painter.drawLine(middle_x, 0, middle_x, self.height()) + + # Draw tick marks + tick_length = 10 + tick_spacing = 50 + + pen = QPen(Qt.gray, 1, Qt.SolidLine) + painter.setPen(pen) + + # Draw tick marks on the X axis + for x in range(0, self.width(), tick_spacing): + painter.drawLine(x, middle_y - tick_length // 2, x, middle_y + tick_length // 2) + + # Draw tick marks on the Y axis + for y in range(0, self.height(), tick_spacing): + painter.drawLine(middle_x - tick_length // 2, y, middle_x + tick_length // 2, y) + + # Draw the origin point in red + 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 + center_y = self.height() // 2 + quadrant_x = point.x() - center_x + quadrant_y = point.y() - center_y + return QPoint(quadrant_x, quadrant_y) / self.zoom def paintEvent(self, event): painter = QPainter(self) + #self.drawBackgroundGrid(painter) + self.drawAxes(painter) + + # Translate the origin to the center of the widget + center = QPoint(self.width() // 2, self.height() // 2) + painter.translate(center) + + # Apply the zoom factor + painter.scale(self.zoom, self.zoom) + # Set the background color - painter.fillRect(self.rect(), QColor('black')) + #painter.fillRect(0, self.width(), 0, self.height(), QColor('black')) + + # Draw axes pen = QPen(Qt.gray) - pen.setWidth(2) + pen.setWidth(2 / self.zoom) painter.setPen(pen) # Draw points - for point in self.points: - painter.drawEllipse(point, 3, 3) + for point in self.slv_points_main: + painter.drawEllipse(point['ui_point'], 3 / self.zoom, 3 / self.zoom) - if len (self.points) > 0: - for i in range(len(self.points)-1): - painter.drawLine(self.points[i], self.points[i + 1]) + for dic in self.slv_lines_main: + painter.drawLine(dic['ui_points'][0] , dic['ui_points'][1]) + + 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) #Highlight point hovered if self.hovered_point: highlight_pen = QPen(QColor(255, 0, 0)) highlight_pen.setWidth(2) painter.setPen(highlight_pen) - painter.drawEllipse(self.hovered_point, 5, 5) + painter.drawEllipse(self.hovered_point, 5 / self.zoom, 5 / self.zoom) - """if self.selected_line is not None: - p1 = self.points[self.selected_line] - p2 = self.points[self.selected_line + 1] + if self.selected_line: + p1, p2 = self.selected_line painter.setPen(QPen(Qt.red, 2)) - painter.drawLine(p1, p2)""" + painter.drawLine(p1, p2) + painter.end() + def wheelEvent(self, event): + delta = event.angleDelta().y() + self.zoom += (delta / 200) * 0.1 + self.update() + + def aspect_ratio(self): + return self.width() / self.height() * (1.0 / abs(self.zoom)) + def clear_sketch(self): self.points = [] self.update() diff --git a/drawing_modules/gl_widget.py b/drawing_modules/gl_widget.py index e762cce..2a0ea4c 100644 --- a/drawing_modules/gl_widget.py +++ b/drawing_modules/gl_widget.py @@ -28,7 +28,6 @@ class OpenGLWidget(QOpenGLWidget): return mapped_value - def load_stl(self, filename: str) -> object: try: stl_mesh = mesh.Mesh.from_file(filename) @@ -76,12 +75,10 @@ class OpenGLWidget(QOpenGLWidget): def clear_mesh(self): self.mesh_loaded = None - def initializeGL(self): glClearColor(0, 0, 0, 1) glEnable(GL_DEPTH_TEST) - def resizeGL(self, width, height): glViewport(0, 0, width, height) glMatrixMode(GL_PROJECTION) diff --git a/gui.ui b/gui.ui index f55828b..417e23d 100644 --- a/gui.ui +++ b/gui.ui @@ -331,6 +331,12 @@ Rctgl + + true + + + false + @@ -338,6 +344,12 @@ Circle + + true + + + false + @@ -345,6 +357,12 @@ Slot + + true + + + false + @@ -356,7 +374,7 @@ true - true + false @@ -383,6 +401,9 @@ true + + false + @@ -393,6 +414,9 @@ true + + false + @@ -400,6 +424,12 @@ Horiz + + true + + + false + @@ -407,6 +437,41 @@ Vert + + true + + + false + + + + + + + Distnce + + + true + + + false + + + 297 + + + + + + + Symetrc + + + true + + + false + diff --git a/main.py b/main.py index 056f9e0..9d66abc 100644 --- a/main.py +++ b/main.py @@ -53,12 +53,19 @@ class MainWindow(QMainWindow): ###Modes self.ui.pb_linetool.pressed.connect(self.act_line_mode) self.ui.pb_con_ptpt.pressed.connect(self.act_constrain_pt_pt_mode) + self.ui.pb_con_line.pressed.connect(self.act_constrain_pt_line_mode) + self.ui.pb_con_horiz.pressed.connect(self.act_constrain_horiz_line_mode) + self.ui.pb_con_vert.pressed.connect(self.act_constrain_vert_line_mode) + self.ui.pb_con_dist.pressed.connect(self.act_constrain_distance_mode) ### Operations self.ui.pb_extrdop.pressed.connect(self.send_extrude) self.ui.pb_cutop.pressed.connect(self.send_cut) self.ui.pb_del_body.pressed.connect(self.del_body) + 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) @@ -70,14 +77,48 @@ class MainWindow(QMainWindow): #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_linetool.isChecked(): self.sketchWidget.mouse_mode = 'pt_pt' - #self.sketchWidget.points = [] else: self.sketchWidget.mouse_mode = None + self.sketchWidget.line_buffer = None + def act_constrain_pt_line_mode(self): + if not self.ui.pb_linetool.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_vert.isChecked(): + self.sketchWidget.mouse_mode = 'distance' + else: + self.sketchWidget.mouse_mode = None + self.sketchWidget.line_buffer = None + + def constrain_finished(self): + self.ui.pb_con_ptpt.setChecked(False) + self.ui.pb_con_line.setChecked(False) + self.ui.pb_con_dist.setChecked(False) def view_update(self): print("Update") @@ -192,6 +233,9 @@ class MainWindow(QMainWindow): # UI to mesh points = self.translate_points_tup(points) + if points[-1] == points[0]: + result = points.pop() + print("removed last point for mesh") length , ok = QInputDialog.getDouble(self, 'Extrude Length', 'Enter a mm value:', decimals=2) #TODO : Implement cancel @@ -310,4 +354,6 @@ if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() - app.exec() \ No newline at end of file + app.exec() + + #pyside6-uic gui.ui > Gui.py -g python \ No newline at end of file