- Basic polygon to body

This commit is contained in:
bklronin 2024-06-14 14:38:11 +02:00
parent 24f569ebc1
commit e35ff3e9a1
6 changed files with 772 additions and 405 deletions

321
Gui.py
View File

@ -15,118 +15,226 @@ from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
QFont, QFontDatabase, QGradient, QIcon,
QImage, QKeySequence, QLinearGradient, QPainter,
QPalette, QPixmap, QRadialGradient, QTransform)
from PySide6.QtWidgets import (QApplication, QGroupBox, QHBoxLayout, QMainWindow,
QMenuBar, QPushButton, QSizePolicy, QStatusBar,
QTextEdit, QVBoxLayout, QWidget)
from PySide6.QtWidgets import (QApplication, QGridLayout, QGroupBox, QHBoxLayout,
QHeaderView, QMainWindow, QMenuBar, QPushButton,
QSizePolicy, QStatusBar, QTabWidget, QTextEdit,
QTreeView, QVBoxLayout, QWidget)
class Ui_fluencyCAD(object):
def setupUi(self, fluencyCAD):
if not fluencyCAD.objectName():
fluencyCAD.setObjectName(u"fluencyCAD")
fluencyCAD.resize(892, 600)
fluencyCAD.resize(1755, 671)
self.centralwidget = QWidget(fluencyCAD)
self.centralwidget.setObjectName(u"centralwidget")
self.horizontalLayout_2 = QHBoxLayout(self.centralwidget)
self.horizontalLayout_2.setObjectName(u"horizontalLayout_2")
self.gridLayout = QGridLayout(self.centralwidget)
self.gridLayout.setObjectName(u"gridLayout")
self.groupBox_2 = QGroupBox(self.centralwidget)
self.groupBox_2.setObjectName(u"groupBox_2")
self.verticalLayout_2 = QVBoxLayout(self.groupBox_2)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.pushButton_6 = QPushButton(self.groupBox_2)
self.pushButton_6.setObjectName(u"pushButton_6")
self.gridLayout_2 = QGridLayout(self.groupBox_2)
self.gridLayout_2.setObjectName(u"gridLayout_2")
self.pb_rectool = QPushButton(self.groupBox_2)
self.pb_rectool.setObjectName(u"pb_rectool")
self.verticalLayout_2.addWidget(self.pushButton_6)
self.gridLayout_2.addWidget(self.pb_rectool, 0, 1, 1, 1, Qt.AlignTop)
self.pb_linetool = QPushButton(self.groupBox_2)
self.pb_linetool.setObjectName(u"pb_linetool")
self.gridLayout_2.addWidget(self.pb_linetool, 0, 0, 1, 1, Qt.AlignTop)
self.pb_circtool = QPushButton(self.groupBox_2)
self.pb_circtool.setObjectName(u"pb_circtool")
self.gridLayout_2.addWidget(self.pb_circtool, 1, 0, 1, 1, Qt.AlignTop)
self.pb_slotool = QPushButton(self.groupBox_2)
self.pb_slotool.setObjectName(u"pb_slotool")
self.gridLayout_2.addWidget(self.pb_slotool, 1, 1, 1, 1, Qt.AlignTop)
self.horizontalLayout_2.addWidget(self.groupBox_2)
self.verticalLayout = QVBoxLayout()
self.verticalLayout.setObjectName(u"verticalLayout")
self.gl_box = QGroupBox(self.centralwidget)
self.gl_box.setObjectName(u"gl_box")
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(4)
sizePolicy.setHeightForWidth(self.gl_box.sizePolicy().hasHeightForWidth())
self.gl_box.setSizePolicy(sizePolicy)
self.horizontalLayout_4 = QHBoxLayout(self.gl_box)
self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
self.gl_canvas = QWidget(self.gl_box)
self.gl_canvas.setObjectName(u"gl_canvas")
self.horizontalLayout_4.addWidget(self.gl_canvas)
self.verticalLayout.addWidget(self.gl_box)
self.groupBox_3 = QGroupBox(self.centralwidget)
self.groupBox_3.setObjectName(u"groupBox_3")
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
sizePolicy1.setHorizontalStretch(0)
sizePolicy1.setVerticalStretch(1)
sizePolicy1.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
self.groupBox_3.setSizePolicy(sizePolicy1)
self.horizontalLayout_3 = QHBoxLayout(self.groupBox_3)
self.horizontalLayout_3.setObjectName(u"horizontalLayout_3")
self.textEdit = QTextEdit(self.groupBox_3)
self.textEdit.setObjectName(u"textEdit")
self.horizontalLayout_3.addWidget(self.textEdit)
self.verticalLayout.addWidget(self.groupBox_3)
self.groupBox_4 = QGroupBox(self.centralwidget)
self.groupBox_4.setObjectName(u"groupBox_4")
self.horizontalLayout = QHBoxLayout(self.groupBox_4)
self.horizontalLayout.setObjectName(u"horizontalLayout")
self.pb_apply_code = QPushButton(self.groupBox_4)
self.pb_apply_code.setObjectName(u"pb_apply_code")
self.horizontalLayout.addWidget(self.pb_apply_code)
self.pushButton = QPushButton(self.groupBox_4)
self.pushButton.setObjectName(u"pushButton")
self.horizontalLayout.addWidget(self.pushButton)
self.pushButton_2 = QPushButton(self.groupBox_4)
self.pushButton_2.setObjectName(u"pushButton_2")
self.horizontalLayout.addWidget(self.pushButton_2)
self.pushButton_4 = QPushButton(self.groupBox_4)
self.pushButton_4.setObjectName(u"pushButton_4")
self.horizontalLayout.addWidget(self.pushButton_4)
self.pushButton_5 = QPushButton(self.groupBox_4)
self.pushButton_5.setObjectName(u"pushButton_5")
self.horizontalLayout.addWidget(self.pushButton_5)
self.verticalLayout.addWidget(self.groupBox_4)
self.horizontalLayout_2.addLayout(self.verticalLayout)
self.gridLayout.addWidget(self.groupBox_2, 1, 0, 1, 1)
self.groupBox = QGroupBox(self.centralwidget)
self.groupBox.setObjectName(u"groupBox")
self.verticalLayout_3 = QVBoxLayout(self.groupBox)
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
self.gridLayout_3 = QGridLayout(self.groupBox)
self.gridLayout_3.setObjectName(u"gridLayout_3")
self.pushButton_7 = QPushButton(self.groupBox)
self.pushButton_7.setObjectName(u"pushButton_7")
self.verticalLayout_3.addWidget(self.pushButton_7)
self.gridLayout_3.addWidget(self.pushButton_7, 0, 0, 1, 1)
self.pushButton_14 = QPushButton(self.groupBox)
self.pushButton_14.setObjectName(u"pushButton_14")
self.gridLayout_3.addWidget(self.pushButton_14, 0, 1, 1, 1)
self.pushButton_15 = QPushButton(self.groupBox)
self.pushButton_15.setObjectName(u"pushButton_15")
self.gridLayout_3.addWidget(self.pushButton_15, 1, 1, 1, 1)
self.pushButton_16 = QPushButton(self.groupBox)
self.pushButton_16.setObjectName(u"pushButton_16")
self.gridLayout_3.addWidget(self.pushButton_16, 1, 0, 1, 1)
self.horizontalLayout_2.addWidget(self.groupBox)
self.gridLayout.addWidget(self.groupBox, 0, 5, 3, 1, Qt.AlignTop)
self.groupBox_6 = QGroupBox(self.centralwidget)
self.groupBox_6.setObjectName(u"groupBox_6")
self.verticalLayout_2 = QVBoxLayout(self.groupBox_6)
self.verticalLayout_2.setObjectName(u"verticalLayout_2")
self.pb_nw_sktch = QPushButton(self.groupBox_6)
self.pb_nw_sktch.setObjectName(u"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.setObjectName(u"pb_del_sketch")
self.verticalLayout_2.addWidget(self.pb_del_sketch)
self.pushButton_13 = QPushButton(self.groupBox_6)
self.pushButton_13.setObjectName(u"pushButton_13")
self.verticalLayout_2.addWidget(self.pushButton_13)
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.setObjectName(u"groupBox_7")
self.verticalLayout_5 = QVBoxLayout(self.groupBox_7)
self.verticalLayout_5.setObjectName(u"verticalLayout_5")
self.pb_apply_code = QPushButton(self.groupBox_7)
self.pb_apply_code.setObjectName(u"pb_apply_code")
self.verticalLayout_5.addWidget(self.pb_apply_code)
self.pushButton = QPushButton(self.groupBox_7)
self.pushButton.setObjectName(u"pushButton")
self.verticalLayout_5.addWidget(self.pushButton)
self.pushButton_5 = QPushButton(self.groupBox_7)
self.pushButton_5.setObjectName(u"pushButton_5")
self.verticalLayout_5.addWidget(self.pushButton_5)
self.pushButton_4 = QPushButton(self.groupBox_7)
self.pushButton_4.setObjectName(u"pushButton_4")
self.verticalLayout_5.addWidget(self.pushButton_4)
self.pushButton_2 = QPushButton(self.groupBox_7)
self.pushButton_2.setObjectName(u"pushButton_2")
self.verticalLayout_5.addWidget(self.pushButton_2)
self.gridLayout.addWidget(self.groupBox_7, 3, 0, 1, 1)
self.InputTab = QTabWidget(self.centralwidget)
self.InputTab.setObjectName(u"InputTab")
sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred)
sizePolicy.setHorizontalStretch(0)
sizePolicy.setVerticalStretch(0)
sizePolicy.setHeightForWidth(self.InputTab.sizePolicy().hasHeightForWidth())
self.InputTab.setSizePolicy(sizePolicy)
self.sketch_tab = QWidget()
self.sketch_tab.setObjectName(u"sketch_tab")
self.verticalLayout_4 = QVBoxLayout(self.sketch_tab)
self.verticalLayout_4.setObjectName(u"verticalLayout_4")
self.InputTab.addTab(self.sketch_tab, "")
self.code_tab = QWidget()
self.code_tab.setObjectName(u"code_tab")
self.verticalLayout = QVBoxLayout(self.code_tab)
self.verticalLayout.setObjectName(u"verticalLayout")
self.textEdit = QTextEdit(self.code_tab)
self.textEdit.setObjectName(u"textEdit")
self.verticalLayout.addWidget(self.textEdit)
self.InputTab.addTab(self.code_tab, "")
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.setObjectName(u"gl_box")
sizePolicy2 = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
sizePolicy2.setHorizontalStretch(0)
sizePolicy2.setVerticalStretch(4)
sizePolicy2.setHeightForWidth(self.gl_box.sizePolicy().hasHeightForWidth())
self.gl_box.setSizePolicy(sizePolicy2)
font = QFont()
font.setPointSize(12)
self.gl_box.setFont(font)
self.horizontalLayout_4 = QHBoxLayout(self.gl_box)
#ifndef Q_OS_MAC
self.horizontalLayout_4.setSpacing(-1)
#endif
self.horizontalLayout_4.setObjectName(u"horizontalLayout_4")
self.horizontalLayout_4.setContentsMargins(12, -1, -1, -1)
self.gridLayout.addWidget(self.gl_box, 0, 4, 4, 1)
fluencyCAD.setCentralWidget(self.centralwidget)
self.menubar = QMenuBar(fluencyCAD)
self.menubar.setObjectName(u"menubar")
self.menubar.setGeometry(QRect(0, 0, 892, 24))
self.menubar.setGeometry(QRect(0, 0, 1755, 24))
fluencyCAD.setMenuBar(self.menubar)
self.statusbar = QStatusBar(fluencyCAD)
self.statusbar.setObjectName(u"statusbar")
@ -134,22 +242,43 @@ class Ui_fluencyCAD(object):
self.retranslateUi(fluencyCAD)
self.InputTab.setCurrentIndex(0)
QMetaObject.connectSlotsByName(fluencyCAD)
# setupUi
def retranslateUi(self, fluencyCAD):
fluencyCAD.setWindowTitle(QCoreApplication.translate("fluencyCAD", u"fluencyCAD", None))
self.groupBox_2.setTitle(QCoreApplication.translate("fluencyCAD", u"Drawing", None))
self.pushButton_6.setText(QCoreApplication.translate("fluencyCAD", u"PushButton", None))
self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
self.groupBox_3.setTitle(QCoreApplication.translate("fluencyCAD", u"Code Editor", None))
self.groupBox_4.setTitle(QCoreApplication.translate("fluencyCAD", u"Code Tools", None))
self.pb_rectool.setText(QCoreApplication.translate("fluencyCAD", u"Rctgl", None))
self.pb_linetool.setText(QCoreApplication.translate("fluencyCAD", u"Line", None))
self.pb_circtool.setText(QCoreApplication.translate("fluencyCAD", u"Circle", None))
self.pb_slotool.setText(QCoreApplication.translate("fluencyCAD", u"Slot", None))
self.groupBox.setTitle(QCoreApplication.translate("fluencyCAD", u"Modify", None))
self.pushButton_7.setText(QCoreApplication.translate("fluencyCAD", u"Cut", None))
self.pushButton_14.setText(QCoreApplication.translate("fluencyCAD", u"Arry", None))
self.pushButton_15.setText(QCoreApplication.translate("fluencyCAD", u"Extrd", None))
self.pushButton_16.setText(QCoreApplication.translate("fluencyCAD", u"Rev", 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_edt_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Edt Sketch", None))
self.pb_del_sketch.setText(QCoreApplication.translate("fluencyCAD", u"Sktch del", 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.pb_apply_code.setText(QCoreApplication.translate("fluencyCAD", u"Apply Code", None))
self.pushButton.setText(QCoreApplication.translate("fluencyCAD", u"Delete Code", None))
self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"Export STL", None))
self.pushButton_4.setText(QCoreApplication.translate("fluencyCAD", u"Save code", None))
self.pushButton_5.setText(QCoreApplication.translate("fluencyCAD", u"Load Code", None))
self.groupBox.setTitle(QCoreApplication.translate("fluencyCAD", u"Modify", None))
self.pushButton_7.setText(QCoreApplication.translate("fluencyCAD", u"PushButton", None))
self.pushButton_4.setText(QCoreApplication.translate("fluencyCAD", u"Save code", None))
self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"Export STL", 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.groupBox_5.setTitle(QCoreApplication.translate("fluencyCAD", u"Components", None))
self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
# retranslateUi

View File

@ -0,0 +1,79 @@
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox
from PySide6.QtGui import QPainter, QPen, QColor
from PySide6.QtCore import Qt, QPoint
class SnapLineWidget(QWidget):
def __init__(self):
super().__init__()
self.points = []
self.selected_line = None
self.snapping_range = 20 # Range in pixels for snapping
def mousePressEvent(self, event):
if event.button() == Qt.LeftButton:
self.points.append(event.pos())
self.update()
if event.button() == Qt.RightButton:
for i in range(len(self.points) - 1):
if self.is_point_on_line(event.pos(), self.points[i], self.points[i + 1]):
self.selected_line = i
break
else:
self.selected_line = None
def mouseMoveEvent(self, event):
if event.buttons() & Qt.LeftButton:
if self.selected_line is not None:
self.points[self.selected_line] = event.pos()
else:
self.points[-1] = event.pos()
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 is_point_on_line(self, p, p1, p2):
distance1 = self.distance(p, p1)
distance2 = self.distance(p, p2)
total_distance = self.distance(p1, p2)
return abs(distance1 + distance2 - total_distance) < 0.1
def paintEvent(self, event):
painter = QPainter(self)
# Set the background color
painter.fillRect(self.rect(), QColor('white'))
pen = QPen(Qt.black)
pen.setWidth(1)
painter.setPen(pen)
for i in range(len(self.points) - 1):
painter.drawLine(self.points[i], self.points[i + 1])
# Draw points
for point in self.points:
painter.drawEllipse(point, 3, 3)
if self.selected_line is not None:
p1 = self.points[self.selected_line]
p2 = self.points[self.selected_line + 1]
painter.setPen(QPen(Qt.red, 2))
painter.drawLine(p1, p2)
# Example usage
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
window = SnapLineWidget()
window.setWindowTitle("Snap Line Widget")
window.resize(800, 600)
window.show()
sys.exit(app.exec())

View File

@ -0,0 +1,151 @@
import numpy as np
from PySide6.QtOpenGLWidgets import QOpenGLWidget
from PySide6.QtCore import Qt, QPoint
from OpenGL.GL import *
from OpenGL.GLU import *
from stl import mesh
class OpenGLWidget(QOpenGLWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.stl_file = "out.stl" # Replace with your STL file path
self.lastPos = QPoint()
self.startPos = None
self.endPos = None
self.xRot = 0
self.yRot = 0
self.zoom = -10.0
self.sketch = []
self.gl_width = self.width() / 1000
self.gl_height = self.height() / 1000
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))
mapped_value = ((value - value_min) / (value_max - value_min)) * (range_max - range_min) + range_min
return mapped_value
def load_stl(self, filename):
try:
stl_mesh = mesh.Mesh.from_file(filename)
# Extract vertices
vertices = np.concatenate([stl_mesh.v0, stl_mesh.v1, stl_mesh.v2])
# Calculate bounding box
min_x, min_y, min_z = vertices.min(axis=0)
max_x, max_y, max_z = vertices.max(axis=0)
# Calculate centroid
centroid_x = (min_x + max_x) / 2.0
centroid_y = (min_y + max_y) / 2.0
centroid_z = (min_z + max_z) / 2.0
return stl_mesh.vectors, (centroid_x, centroid_y, centroid_z)
except FileNotFoundError:
print(f"Error: File {filename} not found.")
except Exception as e:
print(f"Error loading {filename}: {e}")
return None, (0, 0, 0)
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)
glLoadIdentity()
aspect = width / float(height)
self.gl_width = self.width() / 1000
self.gl_height = self.height() / 1000
gluPerspective(45.0, aspect, 1.0, 1000.0)
glMatrixMode(GL_MODELVIEW)
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
mesh_loaded, centroid = self.load_stl(self.stl_file)
centroid_x, centroid_y, centroid_z = centroid
glTranslatef(0, 0, self.zoom)
glRotatef(self.xRot, 1.0, 0.0, 0.0)
glRotatef(self.yRot, 0.0, 1.0, 0.0)
glColor3f(1.0, 1.0, 1.0)
self.draw_area()
if mesh is not None:
# Scale the object
scale_factor = 0.001 # Example scale factor (adjust as needed)
glScalef(scale_factor, scale_factor, scale_factor)
# Translate to move the centroid of the object to the origin
glTranslatef(-centroid_x, -centroid_y, -centroid_z)
self.draw_stl(mesh_loaded)
def draw_stl(self, vertices):
glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0)
glEnable(GL_DEPTH_TEST)
glEnable(GL_COLOR_MATERIAL)
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 triangle in vertices:
for vertex in triangle:
glVertex3fv(vertex)
glEnd()
"""# Draw outer vertices as points
glDisable(GL_LIGHTING)
glColor3f(1.0, 0.0, 0.0) # Set color to red
glPointSize(5.0) # Set point size
glBegin(GL_POINTS)
for vertex in vertices:
glVertex3fv(vertex)
glEnd()"""
def draw_area(self):
glColor3f(0.5, 0.5, 0.5) # Gray color
glBegin(GL_LINES)
for x in range(0, self.width(), 20):
x_ndc = self.map_value_to_range(x, 0, value_max=self.width(), range_min=-self.gl_width, range_max=self.gl_width)
glVertex2f(x_ndc, -self.gl_height) # Start from y = -1
glVertex2f(x_ndc, self.gl_height) # End at y = 1
for y in range(0, self.height(), 20):
y_ndc = self.map_value_to_range(y, 0, value_max=self.height(), range_min=-self.gl_height, range_max=self.gl_height)
glVertex2f(-self.gl_width, y_ndc) # Start from x = -1
glVertex2f(self.gl_width, y_ndc) # End at x = 1
glEnd()
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & Qt.MouseButton.LeftButton :
self.xRot += 0.5 * dy
self.yRot += 0.5 * dx
self.lastPos = event.pos()
self.update()
def wheelEvent(self, event):
delta = event.angleDelta().y()
self.zoom += delta / 120
self.update()
def aspect_ratio(self):
return self.width() / self.height() * (1.0 / abs(self.zoom))

349
gui.ui
View File

@ -6,23 +6,118 @@
<rect>
<x>0</x>
<y>0</y>
<width>892</width>
<height>600</height>
<width>1755</width>
<height>671</height>
</rect>
</property>
<property name="windowTitle">
<string>fluencyCAD</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Drawing</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="1" alignment="Qt::AlignTop">
<widget class="QPushButton" name="pb_rectool">
<property name="text">
<string>Rctgl</string>
</property>
</widget>
</item>
<item row="0" column="0" alignment="Qt::AlignTop">
<widget class="QPushButton" name="pb_linetool">
<property name="text">
<string>Line</string>
</property>
</widget>
</item>
<item row="1" column="0" alignment="Qt::AlignTop">
<widget class="QPushButton" name="pb_circtool">
<property name="text">
<string>Circle</string>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignTop">
<widget class="QPushButton" name="pb_slotool">
<property name="text">
<string>Slot</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="5" rowspan="3" alignment="Qt::AlignTop">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Modify</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QPushButton" name="pushButton_7">
<property name="text">
<string>Cut</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="pushButton_14">
<property name="text">
<string>Arry</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="pushButton_15">
<property name="text">
<string>Extrd</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="pushButton_16">
<property name="text">
<string>Rev</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox_6">
<property name="title">
<string>Sketchtools</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QPushButton" name="pushButton_6">
<widget class="QPushButton" name="pb_nw_sktch">
<property name="text">
<string>Nw Sktch Wp</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_edt_sktch">
<property name="text">
<string>Edt Sketch</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pb_del_sketch">
<property name="text">
<string>Sktch del</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_13">
<property name="text">
<string>PushButton</string>
</property>
@ -31,103 +126,163 @@
</layout>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="gl_box">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>4</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Model Viewer</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<widget class="QWidget" name="gl_canvas" native="true"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>1</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Code Editor</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>Code Tools</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pb_apply_code">
<property name="text">
<string>Apply Code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Delete Code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Export STL</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>Save code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<property name="text">
<string>Load Code</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<item row="2" column="0">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Modify</string>
<string>Constrain</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="pushButton_7">
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="1">
<widget class="QPushButton" name="pb_con_line">
<property name="text">
<string>PushButton</string>
<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">
<widget class="QGroupBox" name="groupBox_7">
<property name="title">
<string>Executive</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QPushButton" name="pb_apply_code">
<property name="text">
<string>Apply Code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Delete Code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<property name="text">
<string>Load Code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>Save code</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="text">
<string>Export STL</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="2" rowspan="4">
<widget class="QTabWidget" name="InputTab">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="sketch_tab">
<attribute name="title">
<string>Sketch</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_4"/>
</widget>
<widget class="QWidget" name="code_tab">
<attribute name="title">
<string>Code</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="textEdit"/>
</item>
</layout>
</widget>
</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="QTreeView" name="comp_tree"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="4" rowspan="4">
<widget class="QGroupBox" name="gl_box">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>4</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="title">
<string>Model Viewer</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>-1</number>
</property>
<property name="leftMargin">
<number>12</number>
</property>
</layout>
</widget>
</item>
@ -138,7 +293,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>892</width>
<width>1755</width>
<height>24</height>
</rect>
</property>

77
main.py
View File

@ -1,8 +1,9 @@
from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy
from Gui import Ui_fluencyCAD # Import the generated GUI module
from modules.gl_widget import OpenGLWidget
from drawing_modules.gl_widget import OpenGLWidget
from drawing_modules.draw_widget2d import SnapLineWidget
from sdf import *
import python_solvespace
class MainWindow(QMainWindow):
def __init__(self):
@ -13,14 +14,40 @@ class MainWindow(QMainWindow):
self.ui.setupUi(self)
self.openGLWidget = OpenGLWidget()
self.openGLWidget.setParent(self.ui.gl_canvas)
# Connect the resizeEvent of the parent widget to a function
self.ui.gl_canvas.resizeEvent = self.glCanvasResized
layout = self.ui.gl_box.layout()
layout.addWidget(self.openGLWidget)
size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
#self.openGLWidget.setSizePolicy(size_policy)
self.ui.pb_apply_code.pressed.connect(self.generate_mesh)
self.sketchWidget = SnapLineWidget()
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)
self.sketchWidget.setStyleSheet("background-color: white; border: 1px solid red;")
self.ui.pb_apply_code.pressed.connect(self.check_current_tab)
def check_current_tab(self):
if self.ui.InputTab.currentIndex() == 0:
self.generate_mesh_from_draw()
elif self.ui.InputTab.currentIndex() == 1:
self.generate_mesh_from_code()
def load_and_render(self, file, centroid):
self.openGLWidget.draw_stl(file)
self.openGLWidget.update()
def generate_mesh(self):
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 generate_mesh_from_code(self):
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)"
@ -39,12 +66,38 @@ class MainWindow(QMainWindow):
except Exception as 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)
def glCanvasResized(self, event):
# Get the size of the gl_canvas
canvas_size = self.ui.gl_canvas.size()
# Resize the OpenGL widget to match the size of the gl_canvas
self.openGLWidget.resize(canvas_size)
if __name__ == "__main__":
app = QApplication([])

View File

@ -1,200 +0,0 @@
from PySide6.QtOpenGLWidgets import QOpenGLWidget
from PySide6.QtCore import Qt, QPoint
from OpenGL.GL import *
from OpenGL.GLU import *
from stl import mesh
class OpenGLWidget(QOpenGLWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.stl_file = "out.stl" # Replace with your STL file path
self.lastPos = QPoint()
self.startPos = None
self.endPos = None
self.xRot = 0
self.yRot = 0
self.zoom = -10.0
self.sketch = []
self.gl_width = self.width() / 1000
self.gl_height = self.height() / 1000
print(self.gl_height)
print(self.gl_width)
def map_value_to_range(self, value, value_min: int = 0, value_max: int= 1920, range_min=-1, range_max=1):
"""
Maps a value from one range to another.
Parameters:
value (float): The value to be mapped.
value_min (float): The minimum value of the input range.
value_max (float): The maximum value of the input range.
range_min (float, optional): The minimum value of the output range. Default is -1.
range_max (float, optional): The maximum value of the output range. Default is 1.
Returns:
float: The mapped value in the output range.
"""
# Ensure value is within the input range
value = max(value_min, min(value_max, value))
# Map the value to the output range
mapped_value = ((value - value_min) / (value_max - value_min)) * (range_max - range_min) + range_min
return mapped_value
def load_stl(self, filename):
try:
stl_mesh = mesh.Mesh.from_file(filename)
return stl_mesh.vectors
except FileNotFoundError:
print(f"Error: File {filename} not found.")
except Exception as e:
print(f"Error loading {filename}: {e}")
return []
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)
glLoadIdentity()
aspect = width / float(height)
self.gl_width = self.width() / 1000
self.gl_height = self.height() / 1000
gluPerspective(45.0, aspect, 1.0, 100.0)
glMatrixMode(GL_MODELVIEW)
def paintGL(self):
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
glLoadIdentity()
glTranslatef(0.0, 0.0, self.zoom)
glRotatef(self.xRot, 1.0, 0.0, 0.0)
glRotatef(self.yRot, 0.0, 1.0, 0.0)
glColor3f(1.0, 1.0, 1.0)
# Draw the rectangle if start and end positions are defined
self.draw_area()
if self.sketch:
self.draw_lines_between_points(self.sketch)
def draw_area(self):
# Set line color
glColor3f(0.5, 0.5, 0.5) # Gray color
# Draw vertical lines
glBegin(GL_LINES)
for x in range(0, self.width(), 20):
x_ndc = self.map_value_to_range(x, 0, value_max=self.width(), range_min=-self.gl_width, range_max=self.gl_width)
glVertex2f(x_ndc, -self.gl_height) # Start from y = -1
glVertex2f(x_ndc, self.gl_height) # End at y = 1
# Draw horizontal lines
for y in range(0, self.height(), 20):
y_ndc = self.map_value_to_range(y, 0, value_max=self.height(), range_min=-self.gl_height, range_max=self.gl_height)
glVertex2f(-self.gl_width, y_ndc) # Start from x = -1
glVertex2f(self.gl_width, y_ndc) # End at x = 1
glEnd()
def draw_line(self, startPos, endPos):
# Get normalized mouse coordinates
print("start", startPos)
print("end", endPos)
x1, y1 = startPos
x2, y2 = endPos
# Adjust line width based on zoom level
line_width = abs(2.0 / self.zoom) # Adjust line width inversely proportional to zoom
glLineWidth(line_width)
# Adjust line color
glColor3f(1.0, 1.0, 0.0) # Yellow color
# Draw the line
glBegin(GL_LINES)
glVertex2f(x1, y1)
glVertex2f(x2, y2)
glEnd()
def draw_lines_between_points(self, points):
glBegin(GL_LINES)
glColor3f(1.0, 1.0, 1.0) # Set line color to white
num_points = len(points)
for i in range(num_points - 1):
x1, y1 = points[i]
x2, y2 = points[i + 1]
glVertex2f(x1, y1)
glVertex2f(x2, y2)
# Connect the last point to the first point
x1, y1 = points[num_points - 1]
x2, y2 = points[0]
glVertex2f(x1, y1)
glVertex2f(x2, y2)
glEnd()
glPointSize(8)
glBegin(GL_POINTS)
glColor3f(1.0, 0.2, 1.0) # Set dot color to white
for point in points:
glVertex2f(point[0], point[1])
glEnd()
def mousePressEvent(self, event):
if event.buttons() & Qt.MouseButton.RightButton:
# Get mouse position in widget coordinates
mouse_pos = event.pos()
# Map mouse position to normalized device coordinates
normalized_x = self.map_value_to_range(mouse_pos.x(), 0, value_max=self.width(),range_min=-self.gl_width, range_max=self.gl_width)
normalized_y = self.map_value_to_range(mouse_pos.y(), 0, value_max=self.height(),range_min=-self.gl_height, range_max=self.gl_height)
self.startPos = [normalized_x * -self.zoom, -normalized_y * -self.zoom]
# Now you have the mouse position in normalized coordinates
print("Right mouse button pressed - Mouse position (normalized):", normalized_x, normalized_y)
def mouseReleaseEvent(self, event):
if event.button() == Qt.MouseButton.RightButton:
mouse_pos = event.pos()
# Map mouse position to normalized device coordinates
normalized_x = self.map_value_to_range(mouse_pos.x(), 0, value_max=self.width(), range_min=-self.gl_width, range_max=self.gl_width)
normalized_y = self.map_value_to_range(mouse_pos.y(), 0, value_max=self.height(), range_min=-self.gl_height, range_max=self.gl_height)
self.endPos = [normalized_x * -self.zoom, -normalized_y * -self.zoom]
self.add_to_sketch(self.startPos)
self.add_to_sketch(self.endPos)
self.update()
print("releaseonly")
# Now you have the mouse position in normalized coordinates
print("Right mouse button pressed - Mouse position (normalized):", normalized_x, normalized_y)
def mouseMoveEvent(self, event):
dx = event.x() - self.lastPos.x()
dy = event.y() - self.lastPos.y()
if event.buttons() & Qt.MouseButton.LeftButton :
self.xRot += 0.5 * dy
self.yRot += 0.5 * dx
self.lastPos = event.pos()
self.update()
def add_to_sketch(self, pos):
self.sketch.append(pos)
print(self.sketch)
def wheelEvent(self, event):
delta = event.angleDelta().y()
self.zoom += delta / 120
self.update()