- Extrude and cut

This commit is contained in:
bklronin 2024-06-15 00:18:32 +02:00
parent e35ff3e9a1
commit 055a90b62e
5 changed files with 377 additions and 240 deletions

166
Gui.py
View File

@ -16,15 +16,15 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QImage, QKeySequence, QLinearGradient, QPainter, QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform) QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QGridLayout, QGroupBox, QHBoxLayout, from PySide6.QtWidgets import (QApplication, QGridLayout, QGroupBox, QHBoxLayout,
QHeaderView, QMainWindow, QMenuBar, QPushButton, QListWidget, QListWidgetItem, QMainWindow, QMenuBar,
QSizePolicy, QStatusBar, QTabWidget, QTextEdit, QPushButton, QSizePolicy, QStatusBar, QTabWidget,
QTreeView, QVBoxLayout, QWidget) QTextEdit, QVBoxLayout, QWidget)
class Ui_fluencyCAD(object): class Ui_fluencyCAD(object):
def setupUi(self, fluencyCAD): def setupUi(self, fluencyCAD):
if not fluencyCAD.objectName(): if not fluencyCAD.objectName():
fluencyCAD.setObjectName(u"fluencyCAD") fluencyCAD.setObjectName(u"fluencyCAD")
fluencyCAD.resize(1755, 671) fluencyCAD.resize(1755, 685)
self.centralwidget = QWidget(fluencyCAD) self.centralwidget = QWidget(fluencyCAD)
self.centralwidget.setObjectName(u"centralwidget") self.centralwidget.setObjectName(u"centralwidget")
self.gridLayout = QGridLayout(self.centralwidget) self.gridLayout = QGridLayout(self.centralwidget)
@ -60,25 +60,25 @@ class Ui_fluencyCAD(object):
self.groupBox.setObjectName(u"groupBox") self.groupBox.setObjectName(u"groupBox")
self.gridLayout_3 = QGridLayout(self.groupBox) self.gridLayout_3 = QGridLayout(self.groupBox)
self.gridLayout_3.setObjectName(u"gridLayout_3") self.gridLayout_3.setObjectName(u"gridLayout_3")
self.pushButton_7 = QPushButton(self.groupBox) self.pb_extrdop = QPushButton(self.groupBox)
self.pushButton_7.setObjectName(u"pushButton_7") self.pb_extrdop.setObjectName(u"pb_extrdop")
self.gridLayout_3.addWidget(self.pushButton_7, 0, 0, 1, 1) self.gridLayout_3.addWidget(self.pb_extrdop, 0, 0, 1, 1)
self.pushButton_14 = QPushButton(self.groupBox) self.pb_cutop = QPushButton(self.groupBox)
self.pushButton_14.setObjectName(u"pushButton_14") self.pb_cutop.setObjectName(u"pb_cutop")
self.gridLayout_3.addWidget(self.pushButton_14, 0, 1, 1, 1) self.gridLayout_3.addWidget(self.pb_cutop, 0, 1, 1, 1)
self.pushButton_15 = QPushButton(self.groupBox) self.pb_arrayop = QPushButton(self.groupBox)
self.pushButton_15.setObjectName(u"pushButton_15") self.pb_arrayop.setObjectName(u"pb_arrayop")
self.gridLayout_3.addWidget(self.pushButton_15, 1, 1, 1, 1) self.gridLayout_3.addWidget(self.pb_arrayop, 1, 0, 1, 1)
self.pushButton_16 = QPushButton(self.groupBox) self.pb_revop = QPushButton(self.groupBox)
self.pushButton_16.setObjectName(u"pushButton_16") self.pb_revop.setObjectName(u"pb_revop")
self.gridLayout_3.addWidget(self.pushButton_16, 1, 0, 1, 1) self.gridLayout_3.addWidget(self.pb_revop, 1, 1, 1, 1)
self.gridLayout.addWidget(self.groupBox, 0, 5, 3, 1, Qt.AlignTop) self.gridLayout.addWidget(self.groupBox, 0, 5, 3, 1, Qt.AlignTop)
@ -92,16 +92,16 @@ class Ui_fluencyCAD(object):
self.verticalLayout_2.addWidget(self.pb_nw_sktch) self.verticalLayout_2.addWidget(self.pb_nw_sktch)
self.pb_edt_sktch = QPushButton(self.groupBox_6)
self.pb_edt_sktch.setObjectName(u"pb_edt_sktch")
self.verticalLayout_2.addWidget(self.pb_edt_sktch)
self.pb_del_sketch = QPushButton(self.groupBox_6) self.pb_del_sketch = QPushButton(self.groupBox_6)
self.pb_del_sketch.setObjectName(u"pb_del_sketch") self.pb_del_sketch.setObjectName(u"pb_del_sketch")
self.verticalLayout_2.addWidget(self.pb_del_sketch) self.verticalLayout_2.addWidget(self.pb_del_sketch)
self.pb_edt_sktch = QPushButton(self.groupBox_6)
self.pb_edt_sktch.setObjectName(u"pb_edt_sktch")
self.verticalLayout_2.addWidget(self.pb_edt_sktch)
self.pushButton_13 = QPushButton(self.groupBox_6) self.pushButton_13 = QPushButton(self.groupBox_6)
self.pushButton_13.setObjectName(u"pushButton_13") self.pushButton_13.setObjectName(u"pushButton_13")
@ -110,33 +110,6 @@ class Ui_fluencyCAD(object):
self.gridLayout.addWidget(self.groupBox_6, 0, 0, 1, 1) self.gridLayout.addWidget(self.groupBox_6, 0, 0, 1, 1)
self.groupBox_3 = QGroupBox(self.centralwidget)
self.groupBox_3.setObjectName(u"groupBox_3")
self.gridLayout_4 = QGridLayout(self.groupBox_3)
self.gridLayout_4.setObjectName(u"gridLayout_4")
self.pb_con_line = QPushButton(self.groupBox_3)
self.pb_con_line.setObjectName(u"pb_con_line")
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.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.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.gridLayout_4.addWidget(self.pb_con_vert, 1, 1, 1, 1)
self.gridLayout.addWidget(self.groupBox_3, 2, 0, 1, 1)
self.groupBox_7 = QGroupBox(self.centralwidget) self.groupBox_7 = QGroupBox(self.centralwidget)
self.groupBox_7.setObjectName(u"groupBox_7") self.groupBox_7.setObjectName(u"groupBox_7")
self.verticalLayout_5 = QVBoxLayout(self.groupBox_7) self.verticalLayout_5 = QVBoxLayout(self.groupBox_7)
@ -169,13 +142,58 @@ class Ui_fluencyCAD(object):
self.gridLayout.addWidget(self.groupBox_7, 3, 0, 1, 1) self.gridLayout.addWidget(self.groupBox_7, 3, 0, 1, 1)
self.InputTab = QTabWidget(self.centralwidget) self.groupBox_3 = QGroupBox(self.centralwidget)
self.InputTab.setObjectName(u"InputTab") self.groupBox_3.setObjectName(u"groupBox_3")
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred) self.gridLayout_4 = QGridLayout(self.groupBox_3)
self.gridLayout_4.setObjectName(u"gridLayout_4")
self.pb_con_line = QPushButton(self.groupBox_3)
self.pb_con_line.setObjectName(u"pb_con_line")
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.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.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.gridLayout_4.addWidget(self.pb_con_vert, 1, 1, 1, 1)
self.gridLayout.addWidget(self.groupBox_3, 2, 0, 1, 1)
self.groupBox_5 = QGroupBox(self.centralwidget)
self.groupBox_5.setObjectName(u"groupBox_5")
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
sizePolicy.setHorizontalStretch(0) sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0) sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.InputTab.sizePolicy().hasHeightForWidth()) sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth())
self.InputTab.setSizePolicy(sizePolicy) self.groupBox_5.setSizePolicy(sizePolicy)
self.groupBox_5.setMaximumSize(QSize(300, 16777215))
self.verticalLayout_3 = QVBoxLayout(self.groupBox_5)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.element_list = QListWidget(self.groupBox_5)
self.element_list.setObjectName(u"element_list")
self.verticalLayout_3.addWidget(self.element_list)
self.gridLayout.addWidget(self.groupBox_5, 0, 3, 4, 1)
self.InputTab = QTabWidget(self.centralwidget)
self.InputTab.setObjectName(u"InputTab")
sizePolicy1 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.InputTab.sizePolicy().hasHeightForWidth())
self.InputTab.setSizePolicy(sizePolicy1)
self.sketch_tab = QWidget() self.sketch_tab = QWidget()
self.sketch_tab.setObjectName(u"sketch_tab") self.sketch_tab.setObjectName(u"sketch_tab")
self.verticalLayout_4 = QVBoxLayout(self.sketch_tab) self.verticalLayout_4 = QVBoxLayout(self.sketch_tab)
@ -194,24 +212,6 @@ class Ui_fluencyCAD(object):
self.gridLayout.addWidget(self.InputTab, 0, 2, 4, 1) self.gridLayout.addWidget(self.InputTab, 0, 2, 4, 1)
self.groupBox_5 = QGroupBox(self.centralwidget)
self.groupBox_5.setObjectName(u"groupBox_5")
sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(0)
sizePolicy1.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth())
self.groupBox_5.setSizePolicy(sizePolicy1)
self.groupBox_5.setMaximumSize(QSize(300, 16777215))
self.verticalLayout_3 = QVBoxLayout(self.groupBox_5)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.comp_tree = QTreeView(self.groupBox_5)
self.comp_tree.setObjectName(u"comp_tree")
self.verticalLayout_3.addWidget(self.comp_tree)
self.gridLayout.addWidget(self.groupBox_5, 0, 3, 4, 1)
self.gl_box = QGroupBox(self.centralwidget) self.gl_box = QGroupBox(self.centralwidget)
self.gl_box.setObjectName(u"gl_box") self.gl_box.setObjectName(u"gl_box")
sizePolicy2 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) sizePolicy2 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
@ -256,29 +256,29 @@ class Ui_fluencyCAD(object):
self.pb_circtool.setText(QCoreApplication.translate("fluencyCAD", u"Circle", None)) self.pb_circtool.setText(QCoreApplication.translate("fluencyCAD", u"Circle", None))
self.pb_slotool.setText(QCoreApplication.translate("fluencyCAD", u"Slot", None)) self.pb_slotool.setText(QCoreApplication.translate("fluencyCAD", u"Slot", None))
self.groupBox.setTitle(QCoreApplication.translate("fluencyCAD", u"Modify", None)) self.groupBox.setTitle(QCoreApplication.translate("fluencyCAD", u"Modify", None))
self.pushButton_7.setText(QCoreApplication.translate("fluencyCAD", u"Cut", None)) self.pb_extrdop.setText(QCoreApplication.translate("fluencyCAD", u"Extrd", None))
self.pushButton_14.setText(QCoreApplication.translate("fluencyCAD", u"Arry", None)) self.pb_cutop.setText(QCoreApplication.translate("fluencyCAD", u"Cut", None))
self.pushButton_15.setText(QCoreApplication.translate("fluencyCAD", u"Extrd", None)) self.pb_arrayop.setText(QCoreApplication.translate("fluencyCAD", u"Arry", None))
self.pushButton_16.setText(QCoreApplication.translate("fluencyCAD", u"Rev", None)) self.pb_revop.setText(QCoreApplication.translate("fluencyCAD", u"Rev", None))
self.groupBox_6.setTitle(QCoreApplication.translate("fluencyCAD", u"Sketchtools", None)) self.groupBox_6.setTitle(QCoreApplication.translate("fluencyCAD", u"Sketchtools", None))
self.pb_nw_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Nw Sktch Wp", None)) self.pb_nw_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Add Sketch", None))
self.pb_edt_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Edt Sketch", None))
self.pb_del_sketch.setText(QCoreApplication.translate("fluencyCAD", u"Sktch del", None)) self.pb_del_sketch.setText(QCoreApplication.translate("fluencyCAD", u"Sktch del", None))
self.pb_edt_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Edt Sketch", None))
self.pushButton_13.setText(QCoreApplication.translate("fluencyCAD", u"PushButton", None)) self.pushButton_13.setText(QCoreApplication.translate("fluencyCAD", u"PushButton", None))
self.groupBox_3.setTitle(QCoreApplication.translate("fluencyCAD", u"Constrain", None))
self.pb_con_line.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Line", None))
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.groupBox_7.setTitle(QCoreApplication.translate("fluencyCAD", u"Executive", None)) self.groupBox_7.setTitle(QCoreApplication.translate("fluencyCAD", u"Executive", None))
self.pb_apply_code.setText(QCoreApplication.translate("fluencyCAD", u"Apply Code", None)) self.pb_apply_code.setText(QCoreApplication.translate("fluencyCAD", u"Apply Code", None))
self.pushButton.setText(QCoreApplication.translate("fluencyCAD", u"Delete Code", None)) self.pushButton.setText(QCoreApplication.translate("fluencyCAD", u"Delete Code", None))
self.pushButton_5.setText(QCoreApplication.translate("fluencyCAD", u"Load Code", None)) self.pushButton_5.setText(QCoreApplication.translate("fluencyCAD", u"Load Code", None))
self.pushButton_4.setText(QCoreApplication.translate("fluencyCAD", u"Save code", None)) self.pushButton_4.setText(QCoreApplication.translate("fluencyCAD", u"Save code", None))
self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"Export STL", None)) self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"Export STL", None))
self.groupBox_3.setTitle(QCoreApplication.translate("fluencyCAD", u"Constrain", None))
self.pb_con_line.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Line", None))
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.groupBox_5.setTitle(QCoreApplication.translate("fluencyCAD", u"Components", None))
self.InputTab.setTabText(self.InputTab.indexOf(self.sketch_tab), QCoreApplication.translate("fluencyCAD", u"Sketch", None)) self.InputTab.setTabText(self.InputTab.indexOf(self.sketch_tab), QCoreApplication.translate("fluencyCAD", u"Sketch", None))
self.InputTab.setTabText(self.InputTab.indexOf(self.code_tab), QCoreApplication.translate("fluencyCAD", u"Code", None)) self.InputTab.setTabText(self.InputTab.indexOf(self.code_tab), QCoreApplication.translate("fluencyCAD", u"Code", None))
self.groupBox_5.setTitle(QCoreApplication.translate("fluencyCAD", u"Components", None))
self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None)) self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
# retranslateUi # retranslateUi

View File

@ -10,12 +10,13 @@ class SnapLineWidget(QWidget):
self.selected_line = None self.selected_line = None
self.snapping_range = 20 # Range in pixels for snapping self.snapping_range = 20 # Range in pixels for snapping
def mousePressEvent(self, event): def mousePressEvent(self, event):
if event.button() == Qt.LeftButton: if event.button() == Qt.LeftButton :
self.points.append(event.pos()) self.points.append(event.pos())
self.update() self.update()
if event.button() == Qt.RightButton: elif event.button() == Qt.RightButton:
for i in range(len(self.points) - 1): for i in range(len(self.points) - 1):
if self.is_point_on_line(event.pos(), self.points[i], self.points[i + 1]): if self.is_point_on_line(event.pos(), self.points[i], self.points[i + 1]):
self.selected_line = i self.selected_line = i
@ -24,7 +25,7 @@ class SnapLineWidget(QWidget):
self.selected_line = None self.selected_line = None
def mouseMoveEvent(self, event): def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton: if event.buttons() & Qt.RightButton:
if self.selected_line is not None: if self.selected_line is not None:
self.points[self.selected_line] = event.pos() self.points[self.selected_line] = event.pos()
else: else:
@ -41,7 +42,8 @@ class SnapLineWidget(QWidget):
distance1 = self.distance(p, p1) distance1 = self.distance(p, p1)
distance2 = self.distance(p, p2) distance2 = self.distance(p, p2)
total_distance = self.distance(p1, p2) total_distance = self.distance(p1, p2)
return abs(distance1 + distance2 - total_distance) < 0.1
return abs(distance1 + distance2 - total_distance) < 1
def paintEvent(self, event): def paintEvent(self, event):
painter = QPainter(self) painter = QPainter(self)
@ -65,6 +67,11 @@ class SnapLineWidget(QWidget):
p2 = self.points[self.selected_line + 1] p2 = self.points[self.selected_line + 1]
painter.setPen(QPen(Qt.red, 2)) painter.setPen(QPen(Qt.red, 2))
painter.drawLine(p1, p2) painter.drawLine(p1, p2)
painter.end()
def clear_sketch(self):
self.points = []
self.update()
# Example usage # Example usage

View File

@ -8,13 +8,16 @@ from stl import mesh
class OpenGLWidget(QOpenGLWidget): class OpenGLWidget(QOpenGLWidget):
def __init__(self, parent=None): def __init__(self, parent=None):
super().__init__(parent) super().__init__(parent)
self.scale_factor = 0.001
self.mesh_loaded = None
self.centroid = None
self.stl_file = "out.stl" # Replace with your STL file path self.stl_file = "out.stl" # Replace with your STL file path
self.lastPos = QPoint() self.lastPos = QPoint()
self.startPos = None self.startPos = None
self.endPos = None self.endPos = None
self.xRot = 0 self.xRot = 0
self.yRot = 0 self.yRot = 0
self.zoom = -10.0 self.zoom = -2
self.sketch = [] self.sketch = []
self.gl_width = self.width() / 1000 self.gl_width = self.width() / 1000
self.gl_height = self.height() / 1000 self.gl_height = self.height() / 1000
@ -22,9 +25,11 @@ class OpenGLWidget(QOpenGLWidget):
def map_value_to_range(self, value, value_min=0, value_max=1920, range_min=-1, range_max=1): def map_value_to_range(self, value, value_min=0, value_max=1920, range_min=-1, range_max=1):
value = max(value_min, min(value_max, value)) value = max(value_min, min(value_max, value))
mapped_value = ((value - value_min) / (value_max - value_min)) * (range_max - range_min) + range_min mapped_value = ((value - value_min) / (value_max - value_min)) * (range_max - range_min) + range_min
return mapped_value return mapped_value
def load_stl(self, filename):
def load_stl(self, filename: str) -> object:
try: try:
stl_mesh = mesh.Mesh.from_file(filename) stl_mesh = mesh.Mesh.from_file(filename)
@ -40,17 +45,37 @@ class OpenGLWidget(QOpenGLWidget):
centroid_y = (min_y + max_y) / 2.0 centroid_y = (min_y + max_y) / 2.0
centroid_z = (min_z + max_z) / 2.0 centroid_z = (min_z + max_z) / 2.0
return stl_mesh.vectors, (centroid_x, centroid_y, centroid_z) self.mesh_loaded = stl_mesh.vectors
self.centroid = (centroid_x, centroid_y, centroid_z)
except FileNotFoundError: except FileNotFoundError:
print(f"Error: File {filename} not found.") print(f"Error: File {filename} not found.")
except Exception as e: except Exception as e:
print(f"Error loading {filename}: {e}") print(f"Error loading {filename}: {e}")
return None, (0, 0, 0) return None, (0, 0, 0)
def load_mesh_direct(self, mesh) -> object:
try:
stl_mesh = mesh
# Extract vertices
vertices = np.array(stl_mesh)
# Calculate centroid based on the average position of vertices
centroid = np.mean(vertices, axis=0)
self.mesh_loaded = vertices
self.centroid = tuple(centroid)
print(f"Centroid: {self.centroid}")
except Exception as e:
print(e)
def initializeGL(self): def initializeGL(self):
glClearColor(0, 0, 0, 1) glClearColor(0, 0, 0, 1)
glEnable(GL_DEPTH_TEST) glEnable(GL_DEPTH_TEST)
def resizeGL(self, width, height): def resizeGL(self, width, height):
glViewport(0, 0, width, height) glViewport(0, 0, width, height)
glMatrixMode(GL_PROJECTION) glMatrixMode(GL_PROJECTION)
@ -60,36 +85,33 @@ class OpenGLWidget(QOpenGLWidget):
self.gl_width = self.width() / 1000 self.gl_width = self.width() / 1000
self.gl_height = self.height() / 1000 self.gl_height = self.height() / 1000
gluPerspective(45.0, aspect, 1.0, 1000.0) gluPerspective(45.0, aspect, 1.0, 10000.0)
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_MODELVIEW)
def paintGL(self): def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity() glLoadIdentity()
mesh_loaded, centroid = self.load_stl(self.stl_file)
centroid_x, centroid_y, centroid_z = centroid
glTranslatef(0, 0, self.zoom) glTranslatef(0, 0, self.zoom)
glRotatef(self.xRot, 1.0, 0.0, 0.0) glRotatef(self.xRot, 0.0, 0.0, 0.0)
glRotatef(self.yRot, 0.0, 1.0, 0.0) glRotatef(self.yRot, 0.0, 0.0, 0.0)
glColor3f(1.0, 1.0, 1.0) glColor3f(1.0, 1.0, 1.0)
self.draw_area() self.draw_area()
if mesh is not None: if self.mesh_loaded is not None:
# Scale the object # Adjust the camera
scale_factor = 0.001 # Example scale factor (adjust as needed) if self.centroid:
glScalef(scale_factor, scale_factor, scale_factor) glScalef(self.scale_factor, self.scale_factor, self.scale_factor) # Apply scaling
# Translate to move the centroid of the object to the origin cx, cy, cz = self.centroid
glTranslatef(-centroid_x, -centroid_y, -centroid_z) gluLookAt(cx, cy, cz + 100, cx, cy, cz, 0, 1, 0)
self.draw_mesh_direct(self.mesh_loaded)
self.draw_stl(mesh_loaded)
def draw_stl(self, vertices): def draw_stl(self, vertices):
glEnable(GL_LIGHTING) glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0) glEnable(GL_LIGHT0)
@ -105,15 +127,24 @@ class OpenGLWidget(QOpenGLWidget):
for vertex in triangle: for vertex in triangle:
glVertex3fv(vertex) glVertex3fv(vertex)
glEnd() glEnd()
self.update()
"""# Draw outer vertices as points def draw_mesh_direct(self, points):
glDisable(GL_LIGHTING) glEnable(GL_LIGHTING)
glColor3f(1.0, 0.0, 0.0) # Set color to red glEnable(GL_LIGHT0)
glPointSize(5.0) # Set point size glEnable(GL_DEPTH_TEST)
glBegin(GL_POINTS) glEnable(GL_COLOR_MATERIAL)
for vertex in vertices: glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE)
glLightfv(GL_LIGHT0, GL_POSITION, (0, 1, 1, 0))
glLightfv(GL_LIGHT0, GL_DIFFUSE, (0.6, 0.6, 0.6, 1.0))
glBegin(GL_TRIANGLES)
for vertex in points:
glVertex3fv(vertex) glVertex3fv(vertex)
glEnd()""" glEnd()
self.update()
def draw_area(self): def draw_area(self):
glColor3f(0.5, 0.5, 0.5) # Gray color glColor3f(0.5, 0.5, 0.5) # Gray color

162
gui.ui
View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>1755</width> <width>1755</width>
<height>671</height> <height>685</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -59,28 +59,28 @@
</property> </property>
<layout class="QGridLayout" name="gridLayout_3"> <layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0"> <item row="0" column="0">
<widget class="QPushButton" name="pushButton_7"> <widget class="QPushButton" name="pb_extrdop">
<property name="text">
<string>Extrd</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pb_cutop">
<property name="text"> <property name="text">
<string>Cut</string> <string>Cut</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1"> <item row="1" column="0">
<widget class="QPushButton" name="pushButton_14"> <widget class="QPushButton" name="pb_arrayop">
<property name="text"> <property name="text">
<string>Arry</string> <string>Arry</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QPushButton" name="pushButton_15"> <widget class="QPushButton" name="pb_revop">
<property name="text">
<string>Extrd</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButton_16">
<property name="text"> <property name="text">
<string>Rev</string> <string>Rev</string>
</property> </property>
@ -98,14 +98,7 @@
<item> <item>
<widget class="QPushButton" name="pb_nw_sktch"> <widget class="QPushButton" name="pb_nw_sktch">
<property name="text"> <property name="text">
<string>Nw Sktch Wp</string> <string>Add Sketch</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_edt_sktch">
<property name="text">
<string>Edt Sketch</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -116,6 +109,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="pb_edt_sktch">
<property name="text">
<string>Edt Sketch</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QPushButton" name="pushButton_13"> <widget class="QPushButton" name="pushButton_13">
<property name="text"> <property name="text">
@ -126,43 +126,6 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Constrain</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1">
<widget class="QPushButton" name="pb_con_line">
<property name="text">
<string>Pt_Line</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pb_con_ptpt">
<property name="text">
<string>Pt_Pt</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pb_con_horiz">
<property name="text">
<string>Horiz</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pb_con_vert">
<property name="text">
<string>Vert</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="0"> <item row="3" column="0">
<widget class="QGroupBox" name="groupBox_7"> <widget class="QGroupBox" name="groupBox_7">
<property name="title"> <property name="title">
@ -207,6 +170,67 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Constrain</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1">
<widget class="QPushButton" name="pb_con_line">
<property name="text">
<string>Pt_Line</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="pb_con_ptpt">
<property name="text">
<string>Pt_Pt</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pb_con_horiz">
<property name="text">
<string>Horiz</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pb_con_vert">
<property name="text">
<string>Vert</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="3" rowspan="4">
<widget class="QGroupBox" name="groupBox_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Components</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QListWidget" name="element_list"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="2" rowspan="4"> <item row="0" column="2" rowspan="4">
<widget class="QTabWidget" name="InputTab"> <widget class="QTabWidget" name="InputTab">
<property name="sizePolicy"> <property name="sizePolicy">
@ -236,30 +260,6 @@
</widget> </widget>
</widget> </widget>
</item> </item>
<item row="0" column="3" rowspan="4">
<widget class="QGroupBox" name="groupBox_5">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>300</width>
<height>16777215</height>
</size>
</property>
<property name="title">
<string>Components</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QTreeView" name="comp_tree"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="4" rowspan="4"> <item row="0" column="4" rowspan="4">
<widget class="QGroupBox" name="gl_box"> <widget class="QGroupBox" name="gl_box">
<property name="sizePolicy"> <property name="sizePolicy">

195
main.py
View File

@ -1,3 +1,5 @@
import uuid
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy
from Gui import Ui_fluencyCAD # Import the generated GUI module from Gui import Ui_fluencyCAD # Import the generated GUI module
from drawing_modules.gl_widget import OpenGLWidget from drawing_modules.gl_widget import OpenGLWidget
@ -5,11 +7,17 @@ from drawing_modules.draw_widget2d import SnapLineWidget
from sdf import * from sdf import *
import python_solvespace import python_solvespace
# main, draw_widget, gl_widget
class MainWindow(QMainWindow): class MainWindow(QMainWindow):
def __init__(self): def __init__(self):
super().__init__() super().__init__()
# Set up the UI from the generated GUI module # Set up the UI from the generated GUI module
self.ui = Ui_fluencyCAD() self.ui = Ui_fluencyCAD()
self.ui.setupUi(self) self.ui.setupUi(self)
@ -24,21 +32,133 @@ class MainWindow(QMainWindow):
layout2.addWidget(self.sketchWidget) layout2.addWidget(self.sketchWidget)
size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding) size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
self.sketchWidget.setSizePolicy(size_policy) self.sketchWidget.setSizePolicy(size_policy)
self.sketchWidget.setStyleSheet("background-color: white; border: 1px solid red;")
self.ui.pb_apply_code.pressed.connect(self.check_current_tab) ### Main Model
self.model = {
'sketch': {},
'operations': {},
}
self.list_selected = []
def check_current_tab(self): #self.ui.pb_apply_code.pressed.connect(self.check_current_tab)
if self.ui.InputTab.currentIndex() == 0: self.ui.element_list.currentItemChanged.connect(self.on_item_changed)
self.generate_mesh_from_draw() self.ui.element_list.itemChanged.connect(self.view_update)
elif self.ui.InputTab.currentIndex() == 1:
self.generate_mesh_from_code()
def load_and_render(self, file, centroid): ### Sketches
self.openGLWidget.draw_stl(file) self.ui.pb_nw_sktch.pressed.connect(self.add_sketch)
self.ui.pb_del_sketch.pressed.connect(self.reset_pos_list)
### Operations
self.ui.pb_extrdop.pressed.connect(self.send_extrude)
self.ui.pb_cutop.pressed.connect(self.send_cut)
def view_update(self):
print("Update")
name = self.ui.element_list.currentItem().text()
print("selcted_for disp", name)
model = self.model['operations'][name]['sdf_object']
mesh = model.generate(samples=2**12)
self.openGLWidget.load_mesh_direct(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 add_sketch(self):
p_list = []
name = f"sketch-{str(uuid.uuid4())}"
points = self.sketchWidget.points
for ps in points:
p_list.append((ps.x(), ps.y()))
element = {
'id': name,
'type': 'polygon',
'sketch_points': p_list,
}
self.model['sketch'][element['id']] = element
print(self.model)
self.ui.element_list.addItem(name)
def send_extrude(self):
selected = self.ui.element_list.currentItem()
name = selected.text()
points = self.model['sketch'][name]['sketch_points']
geo = Geometry()
f = geo.extrude_shape(points)
element = {
'id': name,
'type': 'extrude',
'sdf_object': f,
}
name_op = f"extrd-{name}"
self.model['operations'][name_op] = element
self.ui.element_list.addItem(name_op)
items = self.ui.element_list.findItems(name_op, Qt.MatchExactly)
self.ui.element_list.setCurrentItem(items[0])
self.view_update()
def send_cut(self):
name = self.ui.element_list.currentItem().text()
points = self.model['operations'][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['operations'][name_op] = element
self.ui.element_list.addItem(name_op)
items = self.ui.element_list.findItems(name_op, Qt.MatchExactly)
self.ui.element_list.setCurrentItem(items[0])
self.view_update()
else:
print("mindestens 2!")
def load_and_render(self, file):
self.openGLWidget.load_stl(file)
self.openGLWidget.update() self.openGLWidget.update()
def reset_pos_list(self):
print("Deleting")
self.sketchWidget.clear_sketch()
""" def check_current_tab(self):
if self.ui.InputTab.currentIndex() == 0:
geo = Geometry()
geo.generate_mesh_from_draw(self.sketchWidget.points)
self.load_and_render("out.stl")
elif self.ui.InputTab.currentIndex() == 1:
code_bytes = self.ui.textEdit.toPlainText().encode('utf-8')
code_text = code_bytes.decode('utf-8')
save_string = "\nf.save('out.stl', samples=2**12)"
code_text += save_string
geo = Geometry()
geo.generate_mesh_from_code(code_text)
self.load_and_render("out.stl")"""
class Geometry: class Geometry:
def distance(self, p1, p2): def distance(self, p1, p2):
@ -47,13 +167,25 @@ class Geometry:
print("p2", p2) print("p2", p2)
return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2) return math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2)
def generate_mesh_from_code(self): def extrude_shape(self, points):
code_bytes = self.ui.textEdit.toPlainText().encode('utf-8') """2D to 3D sdf always first"""
code_text = code_bytes.decode('utf-8') f = polygon(points).extrude(100)
save_string = "\nf.save('out.stl', samples=2**12)"
code_text += save_string
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 = {} local_vars = {}
try: try:
print(code_text) print(code_text)
exec(code_text, globals(), local_vars) exec(code_text, globals(), local_vars)
@ -61,43 +193,10 @@ class Geometry:
# Retrieve the result from the captured local variables # Retrieve the result from the captured local variables
result = local_vars.get('result') result = local_vars.get('result')
print("Result:", result) print("Result:", result)
mesh = self.openGLWidget.load_stl("out.stl")
self.openGLWidget.draw_stl(mesh)
except Exception as e: except Exception as e:
print("Error executing code:", e) print("Error executing code:", e)
def generate_mesh_from_draw(self, points, ):
f = None
points = MainWindow().sketchWidget.points
print(points)
p_list = []
dimension = 0.001
for ps in points:
p_list.append((ps.x() , ps.y()))
#p_list.append(p_list[0])
print(p_list)
f = polygon(p_list).extrude(100)
"""if len(points) > 3:
p1 = [points[0].x(), points[0].y()]
p2 = [points[1].x(), points[1].y()]
dimension = self.distance(p1, p2)
scale = 0.001
f = box(dimension * scale)
elif len(points) < 3:
p1 = [points[0].x(), points[0].y()]
p2 = [points[1].x(), points[1].y()]
dimension = self.distance(p1, p2)
scale = 0.001
print(dimension * scale)
f = sphere(dimension * scale)"""
if f:
f.save('out.stl', samples=2**12, sparse=False)
if __name__ == "__main__": if __name__ == "__main__":
app = QApplication([]) app = QApplication([])