import uuid import names from PySide6.QtCore import Qt, QPoint from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy, QInputDialog from Gui import Ui_fluencyCAD # Import the generated GUI module from drawing_modules.vtk_widget import VTKWidget from drawing_modules.vysta_widget import PyVistaWidget from drawing_modules.draw_widget2d import SketchWidget from sdf import * from python_solvespace import SolverSystem, ResultFlag from mesh_modules import simple_mesh # main, draw_widget, gl_widget class MainWindow(QMainWindow): def __init__(self): super().__init__() # Set up the UI from the generated GUI module self.ui = Ui_fluencyCAD() self.ui.setupUi(self) self.custom_3D_Widget = VTKWidget() layout = self.ui.gl_box.layout() layout.addWidget(self.custom_3D_Widget) size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) #self.custom_3D_Widget.setSizePolicy(size_policy) self.sketchWidget = SketchWidget() layout2 = self.ui.sketch_tab.layout() # Get the layout of self.ui.gl_canvas layout2.addWidget(self.sketchWidget) size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) self.sketchWidget.setSizePolicy(size_policy) ### Main Model self.model = { 'sketch': {}, 'operation': {}, } self.list_selected = [] #self.ui.pb_apply_code.pressed.connect(self.check_current_tab) self.ui.sketch_list.currentItemChanged.connect(self.on_item_changed) self.ui.sketch_list.itemChanged.connect(self.draw_mesh) ### Sketches self.ui.pb_origin_wp.pressed.connect(self.add_new_sketch) self.ui.pb_nw_sktch.pressed.connect(self.add_sketch) self.ui.pb_del_sketch.pressed.connect(self.del_sketch) self.ui.pb_edt_sktch.pressed.connect(self.edit_sketch) ###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) self.ui.pb_con_mid.pressed.connect(self.act_constrain_mid_point_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.draw_op_complete) def add_new_sketch(self): self.sketchWidget.clear_sketch() self.sketchWidget.create_workplane() def act_line_mode(self): if not self.ui.pb_linetool.isChecked(): self.sketchWidget.mouse_mode = 'line' else: self.sketchWidget.mouse_mode = None self.sketchWidget.line_draw_buffer = [None, None] 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 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 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 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 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 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 def draw_op_complete(self): # safely disable the line modes self.ui.pb_linetool.setChecked(False) self.ui.pb_con_ptpt.setChecked(False) self.ui.pb_con_line.setChecked(False) self.ui.pb_con_dist.setChecked(False) self.ui.pb_con_mid.setChecked(False) self.ui.pb_con_perp.setChecked(False) self.sketchWidget.mouse_mode = None self.sketchWidget.reset_buffers() def calc_sketch_projection_3d(self, depth): name = self.ui.sketch_list.currentItem().text() #print("selected_for disp", name) model = self.model['sketch'][name]['sketch_points'] #print("sketch points from model", model) simp_mesh = simple_mesh.generate_mesh(model, depth) print("Generated model", simp_mesh) self.custom_3D_Widget. load_interactor_mesh(simp_mesh) #draw_interactor(simp_mesh) def draw_mesh(self): #print("Update") name = self.ui.body_list.currentItem().text() #print("selected_for disp", name) model = self.model['operation'][name]['sdf_object'] mesh = model.generate() #print("Mesh sdf", mesh) #self.custom_3D_Widget.render_from_points_direct_with_faces(mesh) self.custom_3D_Widget.render_from_points_direct_with_faces(mesh) def on_item_changed(self, current_item, previous_item): if current_item: name = current_item.text() #self.view_update() print(f"Selected item: {name}") def convert_points_for_sdf(self): points_for_sdf = [] for point_to_poly in self.sketchWidget.slv_points_main: points_for_sdf.append(self.translate_points_tup(point_to_poly['ui_point'])) return points_for_sdf def add_sketch(self): name = f"sketch-{str(names.get_first_name())}" points_for_sdf = self.convert_points_for_sdf() element = { 'id': name, 'type': 'sketch', 'point_list': self.sketchWidget.slv_points_main, 'line_list': self.sketchWidget.slv_lines_main, 'sketch_points': points_for_sdf, 'solver': self.sketchWidget.solv } self.model['sketch'][element['id']] = element print(self.model) self.ui.sketch_list.addItem(name) self.ui.pb_linetool.setChecked(False) self.sketchWidget.line_mode = False items = self.ui.sketch_list.findItems(name, Qt.MatchExactly)[0] self.ui.sketch_list.setCurrentItem(items) def edit_sketch(self): name = self.ui.sketch_list.currentItem().text() #self.sketchWidget.clear_sketch() self.sketchWidget.slv_points_main = self.model['sketch'][name]['point_list'] self.sketchWidget.slv_lines_main = self.model['sketch'][name]['line_list'] self.sketchWidget.solv = self.model['sketch'][name]['solver'] self.sketchWidget.update() print("model",self.model) print("widget", self.sketchWidget.slv_points_main) def del_sketch(self): print("Deleting") name = self.ui.sketch_list.currentItem() # Get the current item print(self.model) if name is not None: item_name = name.text() print("obj_name", item_name) # Check if the 'sketch' key exists in the model dictionary if 'sketch' in self.model and item_name in self.model['sketch']: if self.model['sketch'][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['sketch'].pop(item_name) # Remove the item from the sketch dictionary print(f"Removed sketch: {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 'sketch' or 'operation' dictionary.") else: print("No item selected.") def update_body(self): pass def del_body(self): print("Deleting") name = self.ui.body_list.currentItem() # Get the current item if name is not None: item_name = name.text() print("obj_name", item_name) # Check if the 'operation' key exists in the model dictionary if 'operation' in self.model and item_name in self.model['operation']: if self.model['operation'][item_name]['id'] == item_name: row = self.ui.body_list.row(name) # Get the row of the current item self.ui.body_list.takeItem(row) # Remove the item from the list widget self.model['operation'].pop(item_name) # Remove the item from the operation dictionary print(f"Removed operation: {item_name}") self.custom_3D_Widget.clear_mesh() def translate_points_tup(self, point: QPoint): """QPoints from Display to mesh data input: Qpoints output: Tuple X,Y """ if isinstance(point, QPoint): return point.x(), point.y() def send_extrude(self): selected = self.ui.sketch_list.currentItem() name = selected.text() points = self.model['sketch'][name]['sketch_points'] if points[-1] == points[0]: #detect loop that causes problems in mesh generation del points[-1] print(points) length, ok = QInputDialog.getDouble(self, 'Extrude Length', 'Enter a mm value:', decimals=2) #TODO : Implement cancel #Create and draw Interactor geo = Geometry() f = geo.extrude_shape(points, length) name_op = f"extrd-{name}" element = { 'id': name_op, 'type': 'extrude', 'sdf_object': f, } print(element) self.model['operation'][name_op] = element self.ui.body_list.addItem(name_op) items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)[0] self.ui.body_list.setCurrentItem(items) self.draw_mesh() #self.calc_sketch_projection_3d(length) def send_cut(self): name = self.ui.body_list.currentItem().text() points = self.model['operation'][name]['sdf_object'] self.list_selected.append(points) print(self.list_selected) if len(self.list_selected) > 1: geo = Geometry() f = geo.cut_shapes(self.list_selected[0], self.list_selected[1] ) element = { 'id': name, 'type': 'cut', 'sdf_object': f, } name_op = f"cut-{name}" self.model['operation'][name_op] = element self.ui.body_list.addItem(name_op) items = self.ui.sketch_list.findItems(name_op, Qt.MatchExactly) self.ui.body_list.setCurrentItem(items[-1]) self.draw_mesh() else: print("mindestens 2!") def load_and_render(self, file): self.custom_3D_Widget.load_stl(file) self.custom_3D_Widget.update() class Geometry: def distance(self, p1, p2): """Calculate the distance between two points.""" print("p1", p1) print("p2", p2) return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) def extrude_shape(self, points, length: float): """2D to 3D sdf always first""" f = polygon(points).extrude(length) return f def cut_shapes(self, sdf_object1, sdf_object2): f = difference(sdf_object1, sdf_object2) # equivalent return f def export_mesh(self, sdf_object): """FINAL EXPORT""" result_points = sdf_object.generate() write_binary_stl('out.stl', result_points) def generate_mesh_from_code(self, code_text: str): local_vars = {} try: print(code_text) exec(code_text, globals(), local_vars) # Retrieve the result from the captured local variables result = local_vars.get('result') print("Result:", result) except Exception as e: print("Error executing code:", e) if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() app.exec() #pyside6-uic gui.ui > Gui.py -g python