Merge pull request 'structure' (#6) from structure into master
Reviewed-on: BKLronin/fluency#6
This commit is contained in:
commit
15cc30edac
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.xml
|
||||||
|
*.iml
|
||||||
|
.idea
|
833
Gui.py
833
Gui.py
@ -11,238 +11,39 @@
|
|||||||
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale,
|
||||||
QMetaObject, QObject, QPoint, QRect,
|
QMetaObject, QObject, QPoint, QRect,
|
||||||
QSize, QTime, QUrl, Qt)
|
QSize, QTime, QUrl, Qt)
|
||||||
from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor,
|
from PySide6.QtGui import (QAction, QBrush, QColor, QConicalGradient,
|
||||||
QFont, QFontDatabase, QGradient, QIcon,
|
QCursor, QFont, QFontDatabase, QGradient,
|
||||||
QImage, QKeySequence, QLinearGradient, QPainter,
|
QIcon, QImage, QKeySequence, QLinearGradient,
|
||||||
QPalette, QPixmap, QRadialGradient, QTransform)
|
QPainter, QPalette, QPixmap, QRadialGradient,
|
||||||
from PySide6.QtWidgets import (QApplication, QGridLayout, QGroupBox, QHBoxLayout,
|
QTransform)
|
||||||
QListWidget, QListWidgetItem, QMainWindow, QMenuBar,
|
from PySide6.QtWidgets import (QApplication, QFrame, QGridLayout, QGroupBox,
|
||||||
QPushButton, QSizePolicy, QStatusBar, QTabWidget,
|
QHBoxLayout, QLabel, QListWidget, QListWidgetItem,
|
||||||
|
QMainWindow, QMenu, QMenuBar, QPushButton,
|
||||||
|
QSizePolicy, QSpinBox, QStatusBar, QTabWidget,
|
||||||
QTextEdit, 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(2214, 803)
|
fluencyCAD.resize(2192, 1109)
|
||||||
|
self.actionNew_Project = QAction(fluencyCAD)
|
||||||
|
self.actionNew_Project.setObjectName(u"actionNew_Project")
|
||||||
|
self.actionLoad_Project = QAction(fluencyCAD)
|
||||||
|
self.actionLoad_Project.setObjectName(u"actionLoad_Project")
|
||||||
|
self.actionRecent = QAction(fluencyCAD)
|
||||||
|
self.actionRecent.setObjectName(u"actionRecent")
|
||||||
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)
|
||||||
self.gridLayout.setObjectName(u"gridLayout")
|
self.gridLayout.setObjectName(u"gridLayout")
|
||||||
self.groupBox = QGroupBox(self.centralwidget)
|
|
||||||
self.groupBox.setObjectName(u"groupBox")
|
|
||||||
self.gridLayout_3 = QGridLayout(self.groupBox)
|
|
||||||
self.gridLayout_3.setObjectName(u"gridLayout_3")
|
|
||||||
self.pb_revop = QPushButton(self.groupBox)
|
|
||||||
self.pb_revop.setObjectName(u"pb_revop")
|
|
||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_revop, 2, 1, 1, 1)
|
|
||||||
|
|
||||||
self.pb_extrdop = QPushButton(self.groupBox)
|
|
||||||
self.pb_extrdop.setObjectName(u"pb_extrdop")
|
|
||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_extrdop, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_arrayop = QPushButton(self.groupBox)
|
|
||||||
self.pb_arrayop.setObjectName(u"pb_arrayop")
|
|
||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_arrayop, 2, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_cutop = QPushButton(self.groupBox)
|
|
||||||
self.pb_cutop.setObjectName(u"pb_cutop")
|
|
||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_cutop, 0, 1, 1, 1)
|
|
||||||
|
|
||||||
self.pb_combop = QPushButton(self.groupBox)
|
|
||||||
self.pb_combop.setObjectName(u"pb_combop")
|
|
||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_combop, 1, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_moveop = QPushButton(self.groupBox)
|
|
||||||
self.pb_moveop.setObjectName(u"pb_moveop")
|
|
||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_moveop, 1, 1, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox, 0, 5, 10, 1, Qt.AlignTop)
|
|
||||||
|
|
||||||
self.groupBox_5 = QGroupBox(self.centralwidget)
|
|
||||||
self.groupBox_5.setObjectName(u"groupBox_5")
|
|
||||||
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
||||||
sizePolicy.setHorizontalStretch(0)
|
|
||||||
sizePolicy.setVerticalStretch(0)
|
|
||||||
sizePolicy.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth())
|
|
||||||
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.sketch_list = QListWidget(self.groupBox_5)
|
|
||||||
self.sketch_list.setObjectName(u"sketch_list")
|
|
||||||
self.sketch_list.setSelectionRectVisible(True)
|
|
||||||
|
|
||||||
self.verticalLayout_3.addWidget(self.sketch_list)
|
|
||||||
|
|
||||||
self.groupBox_6 = QGroupBox(self.groupBox_5)
|
|
||||||
self.groupBox_6.setObjectName(u"groupBox_6")
|
|
||||||
sizePolicy1 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
|
||||||
sizePolicy1.setHorizontalStretch(0)
|
|
||||||
sizePolicy1.setVerticalStretch(0)
|
|
||||||
sizePolicy1.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth())
|
|
||||||
self.groupBox_6.setSizePolicy(sizePolicy1)
|
|
||||||
self.gridLayout_6 = QGridLayout(self.groupBox_6)
|
|
||||||
self.gridLayout_6.setObjectName(u"gridLayout_6")
|
|
||||||
self.gridLayout_6.setContentsMargins(2, 2, 2, 2)
|
|
||||||
self.pb_del_sketch = QPushButton(self.groupBox_6)
|
|
||||||
self.pb_del_sketch.setObjectName(u"pb_del_sketch")
|
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.pb_del_sketch, 0, 2, 1, 1)
|
|
||||||
|
|
||||||
self.pb_nw_sktch = QPushButton(self.groupBox_6)
|
|
||||||
self.pb_nw_sktch.setObjectName(u"pb_nw_sktch")
|
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.pb_nw_sktch, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_edt_sktch = QPushButton(self.groupBox_6)
|
|
||||||
self.pb_edt_sktch.setObjectName(u"pb_edt_sktch")
|
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.pb_edt_sktch, 0, 1, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
self.verticalLayout_3.addWidget(self.groupBox_6)
|
|
||||||
|
|
||||||
self.body_list = QListWidget(self.groupBox_5)
|
|
||||||
self.body_list.setObjectName(u"body_list")
|
|
||||||
self.body_list.setSelectionRectVisible(True)
|
|
||||||
|
|
||||||
self.verticalLayout_3.addWidget(self.body_list)
|
|
||||||
|
|
||||||
self.groupBox_8 = QGroupBox(self.groupBox_5)
|
|
||||||
self.groupBox_8.setObjectName(u"groupBox_8")
|
|
||||||
sizePolicy1.setHeightForWidth(self.groupBox_8.sizePolicy().hasHeightForWidth())
|
|
||||||
self.groupBox_8.setSizePolicy(sizePolicy1)
|
|
||||||
self.gridLayout_8 = QGridLayout(self.groupBox_8)
|
|
||||||
self.gridLayout_8.setObjectName(u"gridLayout_8")
|
|
||||||
self.gridLayout_8.setContentsMargins(2, 2, 2, 2)
|
|
||||||
self.pb_del_body = QPushButton(self.groupBox_8)
|
|
||||||
self.pb_del_body.setObjectName(u"pb_del_body")
|
|
||||||
|
|
||||||
self.gridLayout_8.addWidget(self.pb_del_body, 0, 2, 1, 1)
|
|
||||||
|
|
||||||
self.pb_update_body = QPushButton(self.groupBox_8)
|
|
||||||
self.pb_update_body.setObjectName(u"pb_update_body")
|
|
||||||
|
|
||||||
self.gridLayout_8.addWidget(self.pb_update_body, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_edt_sktch_3 = QPushButton(self.groupBox_8)
|
|
||||||
self.pb_edt_sktch_3.setObjectName(u"pb_edt_sktch_3")
|
|
||||||
|
|
||||||
self.gridLayout_8.addWidget(self.pb_edt_sktch_3, 0, 1, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
self.verticalLayout_3.addWidget(self.groupBox_8)
|
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox_5, 0, 3, 12, 1)
|
|
||||||
|
|
||||||
self.groupBox_9 = QGroupBox(self.centralwidget)
|
|
||||||
self.groupBox_9.setObjectName(u"groupBox_9")
|
|
||||||
self.gridLayout_7 = QGridLayout(self.groupBox_9)
|
|
||||||
self.gridLayout_7.setObjectName(u"gridLayout_7")
|
|
||||||
self.pb_origin_wp = QPushButton(self.groupBox_9)
|
|
||||||
self.pb_origin_wp.setObjectName(u"pb_origin_wp")
|
|
||||||
|
|
||||||
self.gridLayout_7.addWidget(self.pb_origin_wp, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_origin_face = QPushButton(self.groupBox_9)
|
|
||||||
self.pb_origin_face.setObjectName(u"pb_origin_face")
|
|
||||||
|
|
||||||
self.gridLayout_7.addWidget(self.pb_origin_face, 0, 1, 1, 1)
|
|
||||||
|
|
||||||
self.pb_flip_face = QPushButton(self.groupBox_9)
|
|
||||||
self.pb_flip_face.setObjectName(u"pb_flip_face")
|
|
||||||
|
|
||||||
self.gridLayout_7.addWidget(self.pb_flip_face, 1, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_move_wp = QPushButton(self.groupBox_9)
|
|
||||||
self.pb_move_wp.setObjectName(u"pb_move_wp")
|
|
||||||
|
|
||||||
self.gridLayout_7.addWidget(self.pb_move_wp, 1, 1, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox_9, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
self.groupBox_3 = QGroupBox(self.centralwidget)
|
|
||||||
self.groupBox_3.setObjectName(u"groupBox_3")
|
|
||||||
sizePolicy1.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
|
|
||||||
self.groupBox_3.setSizePolicy(sizePolicy1)
|
|
||||||
self.groupBox_3.setMaximumSize(QSize(16777214, 16777213))
|
|
||||||
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.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, 2, 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, 2, 1, 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, 3, 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, 3, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_con_mid = QPushButton(self.groupBox_3)
|
|
||||||
self.pb_con_mid.setObjectName(u"pb_con_mid")
|
|
||||||
self.pb_con_mid.setCheckable(True)
|
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.pb_con_mid, 1, 0, 1, 1)
|
|
||||||
|
|
||||||
self.pb_con_perp = QPushButton(self.groupBox_3)
|
|
||||||
self.pb_con_perp.setObjectName(u"pb_con_perp")
|
|
||||||
self.pb_con_perp.setCheckable(True)
|
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.pb_con_perp, 1, 1, 1, 1)
|
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox_3, 2, 0, 1, 1)
|
|
||||||
|
|
||||||
self.InputTab = QTabWidget(self.centralwidget)
|
self.InputTab = QTabWidget(self.centralwidget)
|
||||||
self.InputTab.setObjectName(u"InputTab")
|
self.InputTab.setObjectName(u"InputTab")
|
||||||
sizePolicy2 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
|
||||||
sizePolicy2.setHorizontalStretch(0)
|
sizePolicy.setHorizontalStretch(0)
|
||||||
sizePolicy2.setVerticalStretch(0)
|
sizePolicy.setVerticalStretch(0)
|
||||||
sizePolicy2.setHeightForWidth(self.InputTab.sizePolicy().hasHeightForWidth())
|
sizePolicy.setHeightForWidth(self.InputTab.sizePolicy().hasHeightForWidth())
|
||||||
self.InputTab.setSizePolicy(sizePolicy2)
|
self.InputTab.setSizePolicy(sizePolicy)
|
||||||
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)
|
||||||
@ -286,7 +87,187 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
self.InputTab.addTab(self.code_tab, "")
|
self.InputTab.addTab(self.code_tab, "")
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.InputTab, 0, 2, 12, 1)
|
self.gridLayout.addWidget(self.InputTab, 0, 1, 9, 1)
|
||||||
|
|
||||||
|
self.gl_box = QGroupBox(self.centralwidget)
|
||||||
|
self.gl_box.setObjectName(u"gl_box")
|
||||||
|
sizePolicy1 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||||
|
sizePolicy1.setHorizontalStretch(0)
|
||||||
|
sizePolicy1.setVerticalStretch(4)
|
||||||
|
sizePolicy1.setHeightForWidth(self.gl_box.sizePolicy().hasHeightForWidth())
|
||||||
|
self.gl_box.setSizePolicy(sizePolicy1)
|
||||||
|
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, 2, 9, 1)
|
||||||
|
|
||||||
|
self.groupBox = QGroupBox(self.centralwidget)
|
||||||
|
self.groupBox.setObjectName(u"groupBox")
|
||||||
|
self.gridLayout_3 = QGridLayout(self.groupBox)
|
||||||
|
self.gridLayout_3.setObjectName(u"gridLayout_3")
|
||||||
|
self.pb_revop = QPushButton(self.groupBox)
|
||||||
|
self.pb_revop.setObjectName(u"pb_revop")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_revop, 2, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_extrdop = QPushButton(self.groupBox)
|
||||||
|
self.pb_extrdop.setObjectName(u"pb_extrdop")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_extrdop, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_arrayop = QPushButton(self.groupBox)
|
||||||
|
self.pb_arrayop.setObjectName(u"pb_arrayop")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_arrayop, 2, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_cutop = QPushButton(self.groupBox)
|
||||||
|
self.pb_cutop.setObjectName(u"pb_cutop")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_cutop, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_combop = QPushButton(self.groupBox)
|
||||||
|
self.pb_combop.setObjectName(u"pb_combop")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_combop, 1, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_moveop = QPushButton(self.groupBox)
|
||||||
|
self.pb_moveop.setObjectName(u"pb_moveop")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_moveop, 1, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.groupBox, 0, 3, 1, 1, Qt.AlignTop)
|
||||||
|
|
||||||
|
self.compo_box = QGroupBox(self.centralwidget)
|
||||||
|
self.compo_box.setObjectName(u"compo_box")
|
||||||
|
self.compo_box.setMinimumSize(QSize(0, 50))
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.compo_box, 9, 1, 1, 2)
|
||||||
|
|
||||||
|
self.groupBox_10 = QGroupBox(self.centralwidget)
|
||||||
|
self.groupBox_10.setObjectName(u"groupBox_10")
|
||||||
|
sizePolicy2 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
|
||||||
|
sizePolicy2.setHorizontalStretch(0)
|
||||||
|
sizePolicy2.setVerticalStretch(0)
|
||||||
|
sizePolicy2.setHeightForWidth(self.groupBox_10.sizePolicy().hasHeightForWidth())
|
||||||
|
self.groupBox_10.setSizePolicy(sizePolicy2)
|
||||||
|
self.groupBox_10.setMaximumSize(QSize(200, 16777215))
|
||||||
|
self.verticalLayout_6 = QVBoxLayout(self.groupBox_10)
|
||||||
|
self.verticalLayout_6.setObjectName(u"verticalLayout_6")
|
||||||
|
self.verticalLayout_6.setContentsMargins(5, 5, 5, 5)
|
||||||
|
self.body_list = QListWidget(self.groupBox_10)
|
||||||
|
self.body_list.setObjectName(u"body_list")
|
||||||
|
self.body_list.setSelectionRectVisible(True)
|
||||||
|
|
||||||
|
self.verticalLayout_6.addWidget(self.body_list)
|
||||||
|
|
||||||
|
self.groupBox_8 = QGroupBox(self.groupBox_10)
|
||||||
|
self.groupBox_8.setObjectName(u"groupBox_8")
|
||||||
|
sizePolicy3 = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
||||||
|
sizePolicy3.setHorizontalStretch(0)
|
||||||
|
sizePolicy3.setVerticalStretch(0)
|
||||||
|
sizePolicy3.setHeightForWidth(self.groupBox_8.sizePolicy().hasHeightForWidth())
|
||||||
|
self.groupBox_8.setSizePolicy(sizePolicy3)
|
||||||
|
self.groupBox_8.setMaximumSize(QSize(200, 16777215))
|
||||||
|
self.gridLayout_8 = QGridLayout(self.groupBox_8)
|
||||||
|
self.gridLayout_8.setObjectName(u"gridLayout_8")
|
||||||
|
self.gridLayout_8.setContentsMargins(2, 2, 2, 2)
|
||||||
|
self.pb_del_body = QPushButton(self.groupBox_8)
|
||||||
|
self.pb_del_body.setObjectName(u"pb_del_body")
|
||||||
|
|
||||||
|
self.gridLayout_8.addWidget(self.pb_del_body, 0, 2, 1, 1)
|
||||||
|
|
||||||
|
self.pb_update_body = QPushButton(self.groupBox_8)
|
||||||
|
self.pb_update_body.setObjectName(u"pb_update_body")
|
||||||
|
|
||||||
|
self.gridLayout_8.addWidget(self.pb_update_body, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_edt_sktch_3 = QPushButton(self.groupBox_8)
|
||||||
|
self.pb_edt_sktch_3.setObjectName(u"pb_edt_sktch_3")
|
||||||
|
|
||||||
|
self.gridLayout_8.addWidget(self.pb_edt_sktch_3, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.verticalLayout_6.addWidget(self.groupBox_8)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.groupBox_10, 7, 3, 2, 1)
|
||||||
|
|
||||||
|
self.groupBox_11 = QGroupBox(self.centralwidget)
|
||||||
|
self.groupBox_11.setObjectName(u"groupBox_11")
|
||||||
|
sizePolicy2.setHeightForWidth(self.groupBox_11.sizePolicy().hasHeightForWidth())
|
||||||
|
self.groupBox_11.setSizePolicy(sizePolicy2)
|
||||||
|
self.groupBox_11.setMaximumSize(QSize(200, 16777215))
|
||||||
|
self.verticalLayout_7 = QVBoxLayout(self.groupBox_11)
|
||||||
|
self.verticalLayout_7.setObjectName(u"verticalLayout_7")
|
||||||
|
self.verticalLayout_7.setContentsMargins(5, 5, 5, 5)
|
||||||
|
self.sketch_list = QListWidget(self.groupBox_11)
|
||||||
|
self.sketch_list.setObjectName(u"sketch_list")
|
||||||
|
sizePolicy4 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||||
|
sizePolicy4.setHorizontalStretch(0)
|
||||||
|
sizePolicy4.setVerticalStretch(0)
|
||||||
|
sizePolicy4.setHeightForWidth(self.sketch_list.sizePolicy().hasHeightForWidth())
|
||||||
|
self.sketch_list.setSizePolicy(sizePolicy4)
|
||||||
|
self.sketch_list.setSelectionRectVisible(True)
|
||||||
|
|
||||||
|
self.verticalLayout_7.addWidget(self.sketch_list)
|
||||||
|
|
||||||
|
self.groupBox_6 = QGroupBox(self.groupBox_11)
|
||||||
|
self.groupBox_6.setObjectName(u"groupBox_6")
|
||||||
|
sizePolicy3.setHeightForWidth(self.groupBox_6.sizePolicy().hasHeightForWidth())
|
||||||
|
self.groupBox_6.setSizePolicy(sizePolicy3)
|
||||||
|
self.gridLayout_6 = QGridLayout(self.groupBox_6)
|
||||||
|
self.gridLayout_6.setObjectName(u"gridLayout_6")
|
||||||
|
self.gridLayout_6.setContentsMargins(2, 2, 2, 2)
|
||||||
|
self.pb_edt_sktch = QPushButton(self.groupBox_6)
|
||||||
|
self.pb_edt_sktch.setObjectName(u"pb_edt_sktch")
|
||||||
|
|
||||||
|
self.gridLayout_6.addWidget(self.pb_edt_sktch, 1, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_nw_sktch = QPushButton(self.groupBox_6)
|
||||||
|
self.pb_nw_sktch.setObjectName(u"pb_nw_sktch")
|
||||||
|
|
||||||
|
self.gridLayout_6.addWidget(self.pb_nw_sktch, 1, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_del_sketch = QPushButton(self.groupBox_6)
|
||||||
|
self.pb_del_sketch.setObjectName(u"pb_del_sketch")
|
||||||
|
|
||||||
|
self.gridLayout_6.addWidget(self.pb_del_sketch, 1, 2, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.verticalLayout_7.addWidget(self.groupBox_6)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.groupBox_11, 6, 0, 3, 1)
|
||||||
|
|
||||||
|
self.assmbly_box = QGroupBox(self.centralwidget)
|
||||||
|
self.assmbly_box.setObjectName(u"assmbly_box")
|
||||||
|
self.assmbly_box.setMinimumSize(QSize(0, 50))
|
||||||
|
self.gridLayout_10 = QGridLayout(self.assmbly_box)
|
||||||
|
self.gridLayout_10.setObjectName(u"gridLayout_10")
|
||||||
|
self.pushButton_3 = QPushButton(self.assmbly_box)
|
||||||
|
self.pushButton_3.setObjectName(u"pushButton_3")
|
||||||
|
self.pushButton_3.setMinimumSize(QSize(50, 50))
|
||||||
|
self.pushButton_3.setMaximumSize(QSize(50, 50))
|
||||||
|
|
||||||
|
self.gridLayout_10.addWidget(self.pushButton_3, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pushButton_6 = QPushButton(self.assmbly_box)
|
||||||
|
self.pushButton_6.setObjectName(u"pushButton_6")
|
||||||
|
self.pushButton_6.setMinimumSize(QSize(50, 50))
|
||||||
|
self.pushButton_6.setMaximumSize(QSize(50, 50))
|
||||||
|
|
||||||
|
self.gridLayout_10.addWidget(self.pushButton_6, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.assmbly_box, 9, 3, 1, 1)
|
||||||
|
|
||||||
self.groupBox_4 = QGroupBox(self.centralwidget)
|
self.groupBox_4 = QGroupBox(self.centralwidget)
|
||||||
self.groupBox_4.setObjectName(u"groupBox_4")
|
self.groupBox_4.setObjectName(u"groupBox_4")
|
||||||
@ -298,20 +279,76 @@ class Ui_fluencyCAD(object):
|
|||||||
self.verticalLayout_2.addWidget(self.pushButton_2)
|
self.verticalLayout_2.addWidget(self.pushButton_2)
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox_4, 11, 5, 1, 1)
|
self.gridLayout.addWidget(self.groupBox_4, 6, 3, 1, 1)
|
||||||
|
|
||||||
|
self.compo_tool_box = QGroupBox(self.centralwidget)
|
||||||
|
self.compo_tool_box.setObjectName(u"compo_tool_box")
|
||||||
|
self.compo_tool_box.setMinimumSize(QSize(0, 50))
|
||||||
|
self.gridLayout_9 = QGridLayout(self.compo_tool_box)
|
||||||
|
self.gridLayout_9.setObjectName(u"gridLayout_9")
|
||||||
|
self.new_compo = QPushButton(self.compo_tool_box)
|
||||||
|
self.new_compo.setObjectName(u"new_compo")
|
||||||
|
self.new_compo.setMinimumSize(QSize(50, 50))
|
||||||
|
self.new_compo.setMaximumSize(QSize(50, 50))
|
||||||
|
|
||||||
|
self.gridLayout_9.addWidget(self.new_compo, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
self.del_compo = QPushButton(self.compo_tool_box)
|
||||||
|
self.del_compo.setObjectName(u"del_compo")
|
||||||
|
self.del_compo.setEnabled(True)
|
||||||
|
sizePolicy3.setHeightForWidth(self.del_compo.sizePolicy().hasHeightForWidth())
|
||||||
|
self.del_compo.setSizePolicy(sizePolicy3)
|
||||||
|
self.del_compo.setMinimumSize(QSize(50, 50))
|
||||||
|
self.del_compo.setMaximumSize(QSize(50, 50))
|
||||||
|
self.del_compo.setLayoutDirection(Qt.LeftToRight)
|
||||||
|
|
||||||
|
self.gridLayout_9.addWidget(self.del_compo, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.compo_tool_box, 9, 0, 1, 1)
|
||||||
|
|
||||||
|
self.groupBox_9 = QGroupBox(self.centralwidget)
|
||||||
|
self.groupBox_9.setObjectName(u"groupBox_9")
|
||||||
|
self.groupBox_9.setMaximumSize(QSize(200, 16777215))
|
||||||
|
self.gridLayout_7 = QGridLayout(self.groupBox_9)
|
||||||
|
self.gridLayout_7.setObjectName(u"gridLayout_7")
|
||||||
|
self.pb_origin_wp = QPushButton(self.groupBox_9)
|
||||||
|
self.pb_origin_wp.setObjectName(u"pb_origin_wp")
|
||||||
|
|
||||||
|
self.gridLayout_7.addWidget(self.pb_origin_wp, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_origin_face = QPushButton(self.groupBox_9)
|
||||||
|
self.pb_origin_face.setObjectName(u"pb_origin_face")
|
||||||
|
|
||||||
|
self.gridLayout_7.addWidget(self.pb_origin_face, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_flip_face = QPushButton(self.groupBox_9)
|
||||||
|
self.pb_flip_face.setObjectName(u"pb_flip_face")
|
||||||
|
|
||||||
|
self.gridLayout_7.addWidget(self.pb_flip_face, 1, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_move_wp = QPushButton(self.groupBox_9)
|
||||||
|
self.pb_move_wp.setObjectName(u"pb_move_wp")
|
||||||
|
|
||||||
|
self.gridLayout_7.addWidget(self.pb_move_wp, 1, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.groupBox_9, 0, 0, 1, 1)
|
||||||
|
|
||||||
self.groupBox_2 = QGroupBox(self.centralwidget)
|
self.groupBox_2 = QGroupBox(self.centralwidget)
|
||||||
self.groupBox_2.setObjectName(u"groupBox_2")
|
self.groupBox_2.setObjectName(u"groupBox_2")
|
||||||
sizePolicy1.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth())
|
sizePolicy3.setHeightForWidth(self.groupBox_2.sizePolicy().hasHeightForWidth())
|
||||||
self.groupBox_2.setSizePolicy(sizePolicy1)
|
self.groupBox_2.setSizePolicy(sizePolicy3)
|
||||||
|
self.groupBox_2.setMaximumSize(QSize(200, 16777215))
|
||||||
self.gridLayout_2 = QGridLayout(self.groupBox_2)
|
self.gridLayout_2 = QGridLayout(self.groupBox_2)
|
||||||
self.gridLayout_2.setObjectName(u"gridLayout_2")
|
self.gridLayout_2.setObjectName(u"gridLayout_2")
|
||||||
self.pb_rectool = QPushButton(self.groupBox_2)
|
self.gridLayout_2.setContentsMargins(10, -1, -1, -1)
|
||||||
self.pb_rectool.setObjectName(u"pb_rectool")
|
self.line = QFrame(self.groupBox_2)
|
||||||
self.pb_rectool.setCheckable(True)
|
self.line.setObjectName(u"line")
|
||||||
self.pb_rectool.setAutoExclusive(False)
|
self.line.setFrameShape(QFrame.HLine)
|
||||||
|
self.line.setFrameShadow(QFrame.Sunken)
|
||||||
|
|
||||||
self.gridLayout_2.addWidget(self.pb_rectool, 1, 1, 1, 1, Qt.AlignTop)
|
self.gridLayout_2.addWidget(self.line, 4, 0, 1, 2)
|
||||||
|
|
||||||
self.pb_circtool = QPushButton(self.groupBox_2)
|
self.pb_circtool = QPushButton(self.groupBox_2)
|
||||||
self.pb_circtool.setObjectName(u"pb_circtool")
|
self.pb_circtool.setObjectName(u"pb_circtool")
|
||||||
@ -324,6 +361,7 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_slotool.setObjectName(u"pb_slotool")
|
self.pb_slotool.setObjectName(u"pb_slotool")
|
||||||
self.pb_slotool.setCheckable(True)
|
self.pb_slotool.setCheckable(True)
|
||||||
self.pb_slotool.setAutoExclusive(False)
|
self.pb_slotool.setAutoExclusive(False)
|
||||||
|
self.pb_slotool.setAutoRepeatInterval(98)
|
||||||
|
|
||||||
self.gridLayout_2.addWidget(self.pb_slotool, 2, 1, 1, 1, Qt.AlignTop)
|
self.gridLayout_2.addWidget(self.pb_slotool, 2, 1, 1, 1, Qt.AlignTop)
|
||||||
|
|
||||||
@ -334,40 +372,217 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
self.gridLayout_2.addWidget(self.pb_linetool, 1, 0, 1, 1)
|
self.gridLayout_2.addWidget(self.pb_linetool, 1, 0, 1, 1)
|
||||||
|
|
||||||
|
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_enable_construct = QPushButton(self.groupBox_2)
|
||||||
|
self.pb_enable_construct.setObjectName(u"pb_enable_construct")
|
||||||
|
self.pb_enable_construct.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_2.addWidget(self.pb_enable_construct, 5, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_enable_snap = QPushButton(self.groupBox_2)
|
||||||
|
self.pb_enable_snap.setObjectName(u"pb_enable_snap")
|
||||||
|
self.pb_enable_snap.setCheckable(True)
|
||||||
|
self.pb_enable_snap.setChecked(True)
|
||||||
|
|
||||||
|
self.gridLayout_2.addWidget(self.pb_enable_snap, 5, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox_2, 1, 0, 1, 1)
|
self.gridLayout.addWidget(self.groupBox_2, 1, 0, 1, 1)
|
||||||
|
|
||||||
self.gl_box = QGroupBox(self.centralwidget)
|
self.groupBox_3 = QGroupBox(self.centralwidget)
|
||||||
self.gl_box.setObjectName(u"gl_box")
|
self.groupBox_3.setObjectName(u"groupBox_3")
|
||||||
sizePolicy3 = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
sizePolicy3.setHeightForWidth(self.groupBox_3.sizePolicy().hasHeightForWidth())
|
||||||
sizePolicy3.setHorizontalStretch(0)
|
self.groupBox_3.setSizePolicy(sizePolicy3)
|
||||||
sizePolicy3.setVerticalStretch(4)
|
self.groupBox_3.setMaximumSize(QSize(200, 16777213))
|
||||||
sizePolicy3.setHeightForWidth(self.gl_box.sizePolicy().hasHeightForWidth())
|
self.gridLayout_4 = QGridLayout(self.groupBox_3)
|
||||||
self.gl_box.setSizePolicy(sizePolicy3)
|
self.gridLayout_4.setObjectName(u"gridLayout_4")
|
||||||
font = QFont()
|
self.pb_con_sym = QPushButton(self.groupBox_3)
|
||||||
font.setPointSize(12)
|
self.pb_con_sym.setObjectName(u"pb_con_sym")
|
||||||
self.gl_box.setFont(font)
|
self.pb_con_sym.setCheckable(True)
|
||||||
self.horizontalLayout_4 = QHBoxLayout(self.gl_box)
|
self.pb_con_sym.setAutoExclusive(False)
|
||||||
#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, 12, 1)
|
self.gridLayout_4.addWidget(self.pb_con_sym, 3, 1, 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, 2, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_con_perp = QPushButton(self.groupBox_3)
|
||||||
|
self.pb_con_perp.setObjectName(u"pb_con_perp")
|
||||||
|
self.pb_con_perp.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_4.addWidget(self.pb_con_perp, 1, 1, 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, 2, 0, 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_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_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, 3, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_con_mid = QPushButton(self.groupBox_3)
|
||||||
|
self.pb_con_mid.setObjectName(u"pb_con_mid")
|
||||||
|
self.pb_con_mid.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_4.addWidget(self.pb_con_mid, 1, 0, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.groupBox_3, 2, 0, 1, 1)
|
||||||
|
|
||||||
|
self.tabWidget = QTabWidget(self.centralwidget)
|
||||||
|
self.tabWidget.setObjectName(u"tabWidget")
|
||||||
|
sizePolicy5 = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding)
|
||||||
|
sizePolicy5.setHorizontalStretch(0)
|
||||||
|
sizePolicy5.setVerticalStretch(0)
|
||||||
|
sizePolicy5.setHeightForWidth(self.tabWidget.sizePolicy().hasHeightForWidth())
|
||||||
|
self.tabWidget.setSizePolicy(sizePolicy5)
|
||||||
|
self.tabWidget.setMaximumSize(QSize(200, 16777215))
|
||||||
|
self.tabWidget.setTabPosition(QTabWidget.South)
|
||||||
|
self.widget = QWidget()
|
||||||
|
self.widget.setObjectName(u"widget")
|
||||||
|
self.verticalLayout_3 = QVBoxLayout(self.widget)
|
||||||
|
self.verticalLayout_3.setObjectName(u"verticalLayout_3")
|
||||||
|
self.groupBox_5 = QGroupBox(self.widget)
|
||||||
|
self.groupBox_5.setObjectName(u"groupBox_5")
|
||||||
|
sizePolicy6 = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)
|
||||||
|
sizePolicy6.setHorizontalStretch(0)
|
||||||
|
sizePolicy6.setVerticalStretch(0)
|
||||||
|
sizePolicy6.setHeightForWidth(self.groupBox_5.sizePolicy().hasHeightForWidth())
|
||||||
|
self.groupBox_5.setSizePolicy(sizePolicy6)
|
||||||
|
self.gridLayout_11 = QGridLayout(self.groupBox_5)
|
||||||
|
self.gridLayout_11.setObjectName(u"gridLayout_11")
|
||||||
|
self.gridLayout_11.setContentsMargins(2, 2, 2, 2)
|
||||||
|
self.label = QLabel(self.groupBox_5)
|
||||||
|
self.label.setObjectName(u"label")
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.label, 5, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_snap_vert = QPushButton(self.groupBox_5)
|
||||||
|
self.pb_snap_vert.setObjectName(u"pb_snap_vert")
|
||||||
|
self.pb_snap_vert.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.pb_snap_vert, 2, 1, 1, 1)
|
||||||
|
|
||||||
|
self.line_2 = QFrame(self.groupBox_5)
|
||||||
|
self.line_2.setObjectName(u"line_2")
|
||||||
|
self.line_2.setFrameShape(QFrame.HLine)
|
||||||
|
self.line_2.setFrameShadow(QFrame.Sunken)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.line_2, 4, 0, 1, 2)
|
||||||
|
|
||||||
|
self.label_2 = QLabel(self.groupBox_5)
|
||||||
|
self.label_2.setObjectName(u"label_2")
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.label_2, 5, 1, 1, 1)
|
||||||
|
|
||||||
|
self.spinbox_snap_distance = QSpinBox(self.groupBox_5)
|
||||||
|
self.spinbox_snap_distance.setObjectName(u"spinbox_snap_distance")
|
||||||
|
self.spinbox_snap_distance.setMaximum(30)
|
||||||
|
self.spinbox_snap_distance.setValue(10)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.spinbox_snap_distance, 6, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pushButton_7 = QPushButton(self.groupBox_5)
|
||||||
|
self.pushButton_7.setObjectName(u"pushButton_7")
|
||||||
|
self.pushButton_7.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.pushButton_7, 3, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_snap_horiz = QPushButton(self.groupBox_5)
|
||||||
|
self.pb_snap_horiz.setObjectName(u"pb_snap_horiz")
|
||||||
|
self.pb_snap_horiz.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.pb_snap_horiz, 2, 0, 1, 1)
|
||||||
|
|
||||||
|
self.spinbox_angle_steps = QSpinBox(self.groupBox_5)
|
||||||
|
self.spinbox_angle_steps.setObjectName(u"spinbox_angle_steps")
|
||||||
|
self.spinbox_angle_steps.setMaximum(180)
|
||||||
|
self.spinbox_angle_steps.setValue(15)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.spinbox_angle_steps, 6, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pushButton_8 = QPushButton(self.groupBox_5)
|
||||||
|
self.pushButton_8.setObjectName(u"pushButton_8")
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.pushButton_8, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
self.pb_snap_midp = QPushButton(self.groupBox_5)
|
||||||
|
self.pb_snap_midp.setObjectName(u"pb_snap_midp")
|
||||||
|
self.pb_snap_midp.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.pb_snap_midp, 0, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_snap_angle = QPushButton(self.groupBox_5)
|
||||||
|
self.pb_snap_angle.setObjectName(u"pb_snap_angle")
|
||||||
|
self.pb_snap_angle.setCheckable(True)
|
||||||
|
|
||||||
|
self.gridLayout_11.addWidget(self.pb_snap_angle, 3, 1, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
self.verticalLayout_3.addWidget(self.groupBox_5)
|
||||||
|
|
||||||
|
self.tabWidget.addTab(self.widget, "")
|
||||||
|
self.widget1 = QWidget()
|
||||||
|
self.widget1.setObjectName(u"widget1")
|
||||||
|
self.tabWidget.addTab(self.widget1, "")
|
||||||
|
|
||||||
|
self.gridLayout.addWidget(self.tabWidget, 3, 0, 1, 1)
|
||||||
|
|
||||||
fluencyCAD.setCentralWidget(self.centralwidget)
|
fluencyCAD.setCentralWidget(self.centralwidget)
|
||||||
self.menubar = QMenuBar(fluencyCAD)
|
self.menubar = QMenuBar(fluencyCAD)
|
||||||
self.menubar.setObjectName(u"menubar")
|
self.menubar.setObjectName(u"menubar")
|
||||||
self.menubar.setGeometry(QRect(0, 0, 2214, 24))
|
self.menubar.setGeometry(QRect(0, 0, 2192, 24))
|
||||||
|
self.menuFile = QMenu(self.menubar)
|
||||||
|
self.menuFile.setObjectName(u"menuFile")
|
||||||
|
self.menuSettings = QMenu(self.menubar)
|
||||||
|
self.menuSettings.setObjectName(u"menuSettings")
|
||||||
fluencyCAD.setMenuBar(self.menubar)
|
fluencyCAD.setMenuBar(self.menubar)
|
||||||
self.statusbar = QStatusBar(fluencyCAD)
|
self.statusbar = QStatusBar(fluencyCAD)
|
||||||
self.statusbar.setObjectName(u"statusbar")
|
self.statusbar.setObjectName(u"statusbar")
|
||||||
fluencyCAD.setStatusBar(self.statusbar)
|
fluencyCAD.setStatusBar(self.statusbar)
|
||||||
|
|
||||||
|
self.menubar.addAction(self.menuFile.menuAction())
|
||||||
|
self.menubar.addAction(self.menuSettings.menuAction())
|
||||||
|
self.menuFile.addAction(self.actionNew_Project)
|
||||||
|
self.menuFile.addAction(self.actionLoad_Project)
|
||||||
|
self.menuFile.addAction(self.actionRecent)
|
||||||
|
self.menuFile.addSeparator()
|
||||||
|
|
||||||
self.retranslateUi(fluencyCAD)
|
self.retranslateUi(fluencyCAD)
|
||||||
|
|
||||||
self.InputTab.setCurrentIndex(0)
|
self.InputTab.setCurrentIndex(0)
|
||||||
|
self.tabWidget.setCurrentIndex(1)
|
||||||
|
|
||||||
|
|
||||||
QMetaObject.connectSlotsByName(fluencyCAD)
|
QMetaObject.connectSlotsByName(fluencyCAD)
|
||||||
@ -375,6 +590,17 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
def retranslateUi(self, fluencyCAD):
|
def retranslateUi(self, fluencyCAD):
|
||||||
fluencyCAD.setWindowTitle(QCoreApplication.translate("fluencyCAD", u"fluencyCAD", None))
|
fluencyCAD.setWindowTitle(QCoreApplication.translate("fluencyCAD", u"fluencyCAD", None))
|
||||||
|
self.actionNew_Project.setText(QCoreApplication.translate("fluencyCAD", u"New", None))
|
||||||
|
self.actionLoad_Project.setText(QCoreApplication.translate("fluencyCAD", u"Load", None))
|
||||||
|
self.actionRecent.setText(QCoreApplication.translate("fluencyCAD", u"Recent", None))
|
||||||
|
self.InputTab.setTabText(self.InputTab.indexOf(self.sketch_tab), QCoreApplication.translate("fluencyCAD", u"Sketch", None))
|
||||||
|
self.groupBox_7.setTitle(QCoreApplication.translate("fluencyCAD", u"Executive", None))
|
||||||
|
self.pushButton_5.setText(QCoreApplication.translate("fluencyCAD", u"Load Code", None))
|
||||||
|
self.pushButton_4.setText(QCoreApplication.translate("fluencyCAD", u"Save 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.InputTab.setTabText(self.InputTab.indexOf(self.code_tab), QCoreApplication.translate("fluencyCAD", u"Code", None))
|
||||||
|
self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
|
||||||
self.groupBox.setTitle(QCoreApplication.translate("fluencyCAD", u"Modify", None))
|
self.groupBox.setTitle(QCoreApplication.translate("fluencyCAD", u"Modify", None))
|
||||||
self.pb_revop.setText(QCoreApplication.translate("fluencyCAD", u"Rev", None))
|
self.pb_revop.setText(QCoreApplication.translate("fluencyCAD", u"Rev", None))
|
||||||
self.pb_extrdop.setText(QCoreApplication.translate("fluencyCAD", u"Extrd", None))
|
self.pb_extrdop.setText(QCoreApplication.translate("fluencyCAD", u"Extrd", None))
|
||||||
@ -382,15 +608,25 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_cutop.setText(QCoreApplication.translate("fluencyCAD", u"Cut", None))
|
self.pb_cutop.setText(QCoreApplication.translate("fluencyCAD", u"Cut", None))
|
||||||
self.pb_combop.setText(QCoreApplication.translate("fluencyCAD", u"Comb", None))
|
self.pb_combop.setText(QCoreApplication.translate("fluencyCAD", u"Comb", None))
|
||||||
self.pb_moveop.setText(QCoreApplication.translate("fluencyCAD", u"Mve", None))
|
self.pb_moveop.setText(QCoreApplication.translate("fluencyCAD", u"Mve", None))
|
||||||
self.groupBox_5.setTitle(QCoreApplication.translate("fluencyCAD", u"Sketch", None))
|
self.compo_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Components", None))
|
||||||
self.groupBox_6.setTitle(QCoreApplication.translate("fluencyCAD", u"Tools", None))
|
self.groupBox_10.setTitle(QCoreApplication.translate("fluencyCAD", u"Bodys / Operations", None))
|
||||||
self.pb_del_sketch.setText(QCoreApplication.translate("fluencyCAD", u"Del sketch", None))
|
|
||||||
self.pb_nw_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Add Sktch", None))
|
|
||||||
self.pb_edt_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Edt Sktch", None))
|
|
||||||
self.groupBox_8.setTitle(QCoreApplication.translate("fluencyCAD", u"Tools", None))
|
self.groupBox_8.setTitle(QCoreApplication.translate("fluencyCAD", u"Tools", None))
|
||||||
self.pb_del_body.setText(QCoreApplication.translate("fluencyCAD", u"Del Bdy", None))
|
self.pb_del_body.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
||||||
self.pb_update_body.setText(QCoreApplication.translate("fluencyCAD", u"Bdy Upd", None))
|
self.pb_update_body.setText(QCoreApplication.translate("fluencyCAD", u"Upd", None))
|
||||||
self.pb_edt_sktch_3.setText(QCoreApplication.translate("fluencyCAD", u"Nothing", None))
|
self.pb_edt_sktch_3.setText(QCoreApplication.translate("fluencyCAD", u"Nothing", None))
|
||||||
|
self.groupBox_11.setTitle(QCoreApplication.translate("fluencyCAD", u"Sketch", None))
|
||||||
|
self.groupBox_6.setTitle(QCoreApplication.translate("fluencyCAD", u"Tools", None))
|
||||||
|
self.pb_edt_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Edt", None))
|
||||||
|
self.pb_nw_sktch.setText(QCoreApplication.translate("fluencyCAD", u"Add", None))
|
||||||
|
self.pb_del_sketch.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
||||||
|
self.assmbly_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Assembly Tools", None))
|
||||||
|
self.pushButton_3.setText(QCoreApplication.translate("fluencyCAD", u"+ Cnct", None))
|
||||||
|
self.pushButton_6.setText(QCoreApplication.translate("fluencyCAD", u"- Cnct", None))
|
||||||
|
self.groupBox_4.setTitle(QCoreApplication.translate("fluencyCAD", u"Export", None))
|
||||||
|
self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"STL", None))
|
||||||
|
self.compo_tool_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Component Tools", None))
|
||||||
|
self.new_compo.setText(QCoreApplication.translate("fluencyCAD", u"New", None))
|
||||||
|
self.del_compo.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
||||||
self.groupBox_9.setTitle(QCoreApplication.translate("fluencyCAD", u"Workplanes", None))
|
self.groupBox_9.setTitle(QCoreApplication.translate("fluencyCAD", u"Workplanes", None))
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.pb_origin_wp.setToolTip(QCoreApplication.translate("fluencyCAD", u"<W>orking Plane at 0, 0, 0", None))
|
self.pb_origin_wp.setToolTip(QCoreApplication.translate("fluencyCAD", u"<W>orking Plane at 0, 0, 0", None))
|
||||||
@ -420,47 +656,7 @@ class Ui_fluencyCAD(object):
|
|||||||
#if QT_CONFIG(shortcut)
|
#if QT_CONFIG(shortcut)
|
||||||
self.pb_move_wp.setShortcut(QCoreApplication.translate("fluencyCAD", u"M", None))
|
self.pb_move_wp.setShortcut(QCoreApplication.translate("fluencyCAD", u"M", None))
|
||||||
#endif // QT_CONFIG(shortcut)
|
#endif // QT_CONFIG(shortcut)
|
||||||
self.groupBox_3.setTitle(QCoreApplication.translate("fluencyCAD", u"Constrain", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_line.setToolTip(QCoreApplication.translate("fluencyCAD", u"Point to Line Constrain", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_line.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Lne", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_ptpt.setToolTip(QCoreApplication.translate("fluencyCAD", u"Poin to Point Constrain", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_ptpt.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Pt", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_horiz.setToolTip(QCoreApplication.translate("fluencyCAD", u"Horizontal Constrain ", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_horiz.setText(QCoreApplication.translate("fluencyCAD", u"Horiz", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_vert.setToolTip(QCoreApplication.translate("fluencyCAD", u"Vertical Constrain", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_vert.setText(QCoreApplication.translate("fluencyCAD", u"Vert", None))
|
|
||||||
self.pb_con_sym.setText(QCoreApplication.translate("fluencyCAD", u"Symetrc", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_dist.setToolTip(QCoreApplication.translate("fluencyCAD", u"Dimension of Line of Distance from Point to Line", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_dist.setText(QCoreApplication.translate("fluencyCAD", u"Distnce", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_mid.setToolTip(QCoreApplication.translate("fluencyCAD", u"Point to Middle Point Constrain", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_mid.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Mid_L", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_perp.setToolTip(QCoreApplication.translate("fluencyCAD", u"Constrain Line perpendicular to another line.", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.pb_con_perp.setText(QCoreApplication.translate("fluencyCAD", u"Perp_Lne", None))
|
|
||||||
self.InputTab.setTabText(self.InputTab.indexOf(self.sketch_tab), QCoreApplication.translate("fluencyCAD", u"Sketch", None))
|
|
||||||
self.groupBox_7.setTitle(QCoreApplication.translate("fluencyCAD", u"Executive", None))
|
|
||||||
self.pushButton_5.setText(QCoreApplication.translate("fluencyCAD", u"Load Code", None))
|
|
||||||
self.pushButton_4.setText(QCoreApplication.translate("fluencyCAD", u"Save 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.InputTab.setTabText(self.InputTab.indexOf(self.code_tab), QCoreApplication.translate("fluencyCAD", u"Code", None))
|
|
||||||
self.groupBox_4.setTitle(QCoreApplication.translate("fluencyCAD", u"Export", None))
|
|
||||||
self.pushButton_2.setText(QCoreApplication.translate("fluencyCAD", u"STL", None))
|
|
||||||
self.groupBox_2.setTitle(QCoreApplication.translate("fluencyCAD", u"Drawing", None))
|
self.groupBox_2.setTitle(QCoreApplication.translate("fluencyCAD", u"Drawing", None))
|
||||||
self.pb_rectool.setText(QCoreApplication.translate("fluencyCAD", u"Rctgl", None))
|
|
||||||
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))
|
||||||
#if QT_CONFIG(statustip)
|
#if QT_CONFIG(statustip)
|
||||||
@ -470,6 +666,53 @@ class Ui_fluencyCAD(object):
|
|||||||
#if QT_CONFIG(shortcut)
|
#if QT_CONFIG(shortcut)
|
||||||
self.pb_linetool.setShortcut(QCoreApplication.translate("fluencyCAD", u"S", None))
|
self.pb_linetool.setShortcut(QCoreApplication.translate("fluencyCAD", u"S", None))
|
||||||
#endif // QT_CONFIG(shortcut)
|
#endif // QT_CONFIG(shortcut)
|
||||||
self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
|
self.pb_rectool.setText(QCoreApplication.translate("fluencyCAD", u"Rctgl", None))
|
||||||
|
self.pb_enable_construct.setText(QCoreApplication.translate("fluencyCAD", u"Cstrct", None))
|
||||||
|
self.pb_enable_snap.setText(QCoreApplication.translate("fluencyCAD", u"Snap", None))
|
||||||
|
self.groupBox_3.setTitle(QCoreApplication.translate("fluencyCAD", u"Constrain", None))
|
||||||
|
self.pb_con_sym.setText(QCoreApplication.translate("fluencyCAD", u"Symetrc", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_vert.setToolTip(QCoreApplication.translate("fluencyCAD", u"Vertical Constrain", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_vert.setText(QCoreApplication.translate("fluencyCAD", u"Vert", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_perp.setToolTip(QCoreApplication.translate("fluencyCAD", u"Constrain Line perpendicular to another line.", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_perp.setText(QCoreApplication.translate("fluencyCAD", u"Perp_Lne", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_horiz.setToolTip(QCoreApplication.translate("fluencyCAD", u"Horizontal Constrain ", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_horiz.setText(QCoreApplication.translate("fluencyCAD", u"Horiz", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_ptpt.setToolTip(QCoreApplication.translate("fluencyCAD", u"Poin to Point Constrain", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_ptpt.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Pt", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_line.setToolTip(QCoreApplication.translate("fluencyCAD", u"Point to Line Constrain", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_line.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Lne", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_dist.setToolTip(QCoreApplication.translate("fluencyCAD", u"Dimension of Line of Distance from Point to Line", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_dist.setText(QCoreApplication.translate("fluencyCAD", u"Distnce", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_mid.setToolTip(QCoreApplication.translate("fluencyCAD", u"Point to Middle Point Constrain", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_con_mid.setText(QCoreApplication.translate("fluencyCAD", u"Pt_Mid_L", None))
|
||||||
|
self.groupBox_5.setTitle(QCoreApplication.translate("fluencyCAD", u"Snapping Points", None))
|
||||||
|
self.label.setText(QCoreApplication.translate("fluencyCAD", u"Snp Dst", None))
|
||||||
|
self.pb_snap_vert.setText(QCoreApplication.translate("fluencyCAD", u"Vert", None))
|
||||||
|
self.label_2.setText(QCoreApplication.translate("fluencyCAD", u"Angl Stps", None))
|
||||||
|
self.spinbox_snap_distance.setSuffix(QCoreApplication.translate("fluencyCAD", u"mm", None))
|
||||||
|
self.pushButton_7.setText(QCoreApplication.translate("fluencyCAD", u"Grid", None))
|
||||||
|
self.pb_snap_horiz.setText(QCoreApplication.translate("fluencyCAD", u"Horiz", None))
|
||||||
|
self.spinbox_angle_steps.setSuffix(QCoreApplication.translate("fluencyCAD", u"\u00b0", None))
|
||||||
|
self.pushButton_8.setText(QCoreApplication.translate("fluencyCAD", u"Pnt", None))
|
||||||
|
self.pb_snap_midp.setText(QCoreApplication.translate("fluencyCAD", u"MidP", None))
|
||||||
|
self.pb_snap_angle.setText(QCoreApplication.translate("fluencyCAD", u"Angles", None))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.widget), QCoreApplication.translate("fluencyCAD", u"Setg 1", None))
|
||||||
|
self.tabWidget.setTabText(self.tabWidget.indexOf(self.widget1), QCoreApplication.translate("fluencyCAD", u"Setg 2", None))
|
||||||
|
self.menuFile.setTitle(QCoreApplication.translate("fluencyCAD", u"File", None))
|
||||||
|
self.menuSettings.setTitle(QCoreApplication.translate("fluencyCAD", u"Settings", None))
|
||||||
# retranslateUi
|
# retranslateUi
|
||||||
|
|
||||||
|
1
doc/commands.md
Normal file
1
doc/commands.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
pyside6-uic gui.ui > Gui.py -g python
|
14
doc/flow.md
14
doc/flow.md
@ -19,3 +19,17 @@
|
|||||||
- Transform to 2D xy
|
- Transform to 2D xy
|
||||||
- Transform to linear space for 2D widget to draw.
|
- Transform to linear space for 2D widget to draw.
|
||||||
- Result into 2D cartesian for body interaction extrude etc
|
- Result into 2D cartesian for body interaction extrude etc
|
||||||
|
|
||||||
|
### Elements
|
||||||
|
|
||||||
|
So far these are the elements:
|
||||||
|
|
||||||
|
- Project: Main File
|
||||||
|
- Timeline : Used to track the steps
|
||||||
|
- Assembly: Uses Components and Connectors to from Assemblies
|
||||||
|
- Component: Container for multiple smaller elements "part"
|
||||||
|
- Connector: Preserves connections between parts even if the part in between is deleted
|
||||||
|
- Code: A special type that directly builds bodys from sdfCAD code.
|
||||||
|
- Body: The 3D meshed result from sdfCAD
|
||||||
|
- Sketch: The base to draw new entities.
|
||||||
|
- Interactor: A special component mesh that is used to manipulate the bodys in 3d view.
|
@ -1,6 +1,7 @@
|
|||||||
import math
|
import math
|
||||||
import re
|
import re
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QInputDialog
|
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QInputDialog
|
||||||
@ -19,9 +20,6 @@ class SketchWidget(QWidget):
|
|||||||
self.drag_buffer = [None, None]
|
self.drag_buffer = [None, None]
|
||||||
self.main_buffer = [None, None]
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
self.proj_snap_points = []
|
|
||||||
self.proj_snap_lines = []
|
|
||||||
|
|
||||||
self.hovered_point = None
|
self.hovered_point = None
|
||||||
self.selected_line = None
|
self.selected_line = None
|
||||||
|
|
||||||
@ -30,11 +28,17 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
self.setMouseTracking(True)
|
self.setMouseTracking(True)
|
||||||
self.mouse_mode = False
|
self.mouse_mode = False
|
||||||
self.wp = None
|
|
||||||
self.solv = SolverSystem()
|
self.solv = SolverSystem()
|
||||||
|
|
||||||
self.slv_points_main = []
|
self.sketch = None
|
||||||
self.slv_lines_main = []
|
|
||||||
|
def set_sketch(self, sketch) -> None:
|
||||||
|
print(sketch)
|
||||||
|
self.sketch = sketch
|
||||||
|
self.create_workplane()
|
||||||
|
|
||||||
|
def get_sketch(self):
|
||||||
|
return self.sketch
|
||||||
|
|
||||||
def reset_buffers(self):
|
def reset_buffers(self):
|
||||||
self.line_draw_buffer = [None, None]
|
self.line_draw_buffer = [None, None]
|
||||||
@ -46,44 +50,28 @@ class SketchWidget(QWidget):
|
|||||||
#self.update()
|
#self.update()
|
||||||
|
|
||||||
def create_workplane(self):
|
def create_workplane(self):
|
||||||
self.wp = self.solv.create_2d_base()
|
self.sketch.working_plane = self.solv.create_2d_base()
|
||||||
|
|
||||||
def create_workplane_projected(self):
|
def create_workplane_projected(self):
|
||||||
self.wp = self.solv.create_2d_base()
|
self.sketch.working_plane = self.solv.create_2d_base()
|
||||||
|
|
||||||
def create_proj_points(self, proj_points):
|
def convert_proj_points(self):
|
||||||
"""Lines as orientation projected from the sketch"""
|
out_points = []
|
||||||
|
for point in self.sketch.proj_points:
|
||||||
for point in proj_points:
|
|
||||||
x, y = point
|
x, y = point
|
||||||
coord = QPoint(x, y)
|
coord = QPoint(x, y)
|
||||||
self.proj_snap_points.append(coord)
|
out_points.append(coord)
|
||||||
|
|
||||||
"""relation_point = {} # Reinitialize the dictionary
|
self.sketch.proj_points = out_points
|
||||||
#handle_nr = self.get_handle_nr(str(point))
|
|
||||||
#relation_point['handle_nr'] = handle_nr
|
|
||||||
#relation_point['solv_handle'] = point
|
|
||||||
relation_point['ui_point'] = QPoint(x, y)
|
|
||||||
|
|
||||||
self.slv_points_main.append(relation_point)"""
|
|
||||||
|
|
||||||
def create_proj_lines(self, sel_edges):
|
|
||||||
"""Lines as orientation projected from the sketch"""
|
|
||||||
print("Incoming corrd lines", sel_edges)
|
|
||||||
for line in sel_edges:
|
|
||||||
|
|
||||||
|
def convert_proj_lines(self):
|
||||||
|
out_lines = []
|
||||||
|
for line in self.sketch.proj_lines:
|
||||||
start = QPoint(line[0][0], line[0][1])
|
start = QPoint(line[0][0], line[0][1])
|
||||||
end = QPoint(line[1][0], line[1][1])
|
end = QPoint(line[1][0], line[1][1])
|
||||||
coord = QLine(start, end)
|
coord = QLine(start, end)
|
||||||
self.proj_snap_lines.append(coord)
|
out_lines.append(coord)
|
||||||
|
self.sketch.proj_lines = out_lines
|
||||||
"""relation_point = {} # Reinitialize the dictionary
|
|
||||||
#handle_nr = self.get_handle_nr(str(point))
|
|
||||||
#relation_point['handle_nr'] = handle_nr
|
|
||||||
#relation_point['solv_handle'] = point
|
|
||||||
relation_point['ui_point'] = QPoint(x, y)
|
|
||||||
|
|
||||||
self.slv_points_main.append(relation_point)"""
|
|
||||||
|
|
||||||
def find_duplicate_points_2d(self, edges):
|
def find_duplicate_points_2d(self, edges):
|
||||||
points = []
|
points = []
|
||||||
@ -132,8 +120,8 @@ class SketchWidget(QWidget):
|
|||||||
qw, qx, qy, qz = self.normal_to_quaternion(normal)
|
qw, qx, qy, qz = self.normal_to_quaternion(normal)
|
||||||
|
|
||||||
slv_normal = self.solv.add_normal_3d(qw, qx, qy, qz)
|
slv_normal = self.solv.add_normal_3d(qw, qx, qy, qz)
|
||||||
self.wp = self.solv.add_work_plane(origin_handle, slv_normal)
|
self.sketch.working_plane = self.solv.add_work_plane(origin_handle, slv_normal)
|
||||||
print(self.wp)
|
print(self.sketch.working_plane)
|
||||||
|
|
||||||
def get_handle_nr(self, input_str: str) -> int:
|
def get_handle_nr(self, input_str: str) -> int:
|
||||||
# Define the regex pattern to extract the handle number
|
# Define the regex pattern to extract the handle number
|
||||||
@ -168,7 +156,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
def get_handle_from_ui_point(self, ui_point: QPoint):
|
def get_handle_from_ui_point(self, ui_point: QPoint):
|
||||||
"""Input QPoint and you shall reveive a slvs entity handle!"""
|
"""Input QPoint and you shall reveive a slvs entity handle!"""
|
||||||
for point in self.slv_points_main:
|
for point in self.sketch.slv_points:
|
||||||
if ui_point == point['ui_point']:
|
if ui_point == point['ui_point']:
|
||||||
slv_handle = point['solv_handle']
|
slv_handle = point['solv_handle']
|
||||||
|
|
||||||
@ -176,7 +164,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
def get_line_handle_from_ui_point(self, ui_point: QPoint):
|
def get_line_handle_from_ui_point(self, ui_point: QPoint):
|
||||||
"""Input Qpoint that is on a line and you shall receive the handle of the line!"""
|
"""Input Qpoint that is on a line and you shall receive the handle of the line!"""
|
||||||
for target_line_con in self.slv_lines_main:
|
for target_line_con in self.sketch.slv_lines:
|
||||||
if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]):
|
if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]):
|
||||||
slv_handle = target_line_con['solv_handle']
|
slv_handle = target_line_con['solv_handle']
|
||||||
|
|
||||||
@ -184,7 +172,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
def get_point_line_handles_from_ui_point(self, ui_point: QPoint) -> tuple:
|
def get_point_line_handles_from_ui_point(self, ui_point: QPoint) -> tuple:
|
||||||
"""Input Qpoint that is on a line and you shall receive the handles of the points of the line!"""
|
"""Input Qpoint that is on a line and you shall receive the handles of the points of the line!"""
|
||||||
for target_line_con in self.slv_lines_main:
|
for target_line_con in self.sketch.slv_lines:
|
||||||
if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]):
|
if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]):
|
||||||
lines_to_cons = target_line_con['solv_entity_points']
|
lines_to_cons = target_line_con['solv_entity_points']
|
||||||
|
|
||||||
@ -231,7 +219,7 @@ class SketchWidget(QWidget):
|
|||||||
old_points_ui = []
|
old_points_ui = []
|
||||||
new_points_ui = []
|
new_points_ui = []
|
||||||
|
|
||||||
for old_point_ui in self.slv_points_main:
|
for old_point_ui in self.sketch.slv_points:
|
||||||
old_points_ui.append(old_point_ui['ui_point'])
|
old_points_ui.append(old_point_ui['ui_point'])
|
||||||
|
|
||||||
for i in range(self.solv.entity_len()):
|
for i in range(self.solv.entity_len()):
|
||||||
@ -265,14 +253,14 @@ class SketchWidget(QWidget):
|
|||||||
index, old_point, new_point = tbu_points_idx
|
index, old_point, new_point = tbu_points_idx
|
||||||
|
|
||||||
# Update the point in slv_points_main
|
# Update the point in slv_points_main
|
||||||
self.slv_points_main[index]['ui_point'] = new_point
|
self.sketch.slv_points[index]['ui_point'] = new_point
|
||||||
# Print updated state
|
# Print updated state
|
||||||
# print("Updated slv_points_main:", self.slv_points_main)
|
# print("Updated slv_points_main:", self.slv_points_main)
|
||||||
|
|
||||||
def check_all_lines_and_update(self,changed_points: list):
|
def check_all_lines_and_update(self,changed_points: list):
|
||||||
for tbu_points_idx in changed_points:
|
for tbu_points_idx in changed_points:
|
||||||
index, old_point, new_point = tbu_points_idx
|
index, old_point, new_point = tbu_points_idx
|
||||||
for line_needs_update in self.slv_lines_main:
|
for line_needs_update in self.sketch.slv_lines:
|
||||||
if old_point == line_needs_update['ui_points'][0]:
|
if old_point == line_needs_update['ui_points'][0]:
|
||||||
line_needs_update['ui_points'][0] = new_point
|
line_needs_update['ui_points'][0] = new_point
|
||||||
elif old_point == line_needs_update['ui_points'][1]:
|
elif old_point == line_needs_update['ui_points'][1]:
|
||||||
@ -334,7 +322,7 @@ class SketchWidget(QWidget):
|
|||||||
u = clicked_pos.x()
|
u = clicked_pos.x()
|
||||||
v = clicked_pos.y()
|
v = clicked_pos.y()
|
||||||
|
|
||||||
point = self.solv.add_point_2d(u, v, self.wp)
|
point = self.solv.add_point_2d(u, v, self.sketch.working_plane)
|
||||||
|
|
||||||
relation_point = {} # Reinitialize the dictionary
|
relation_point = {} # Reinitialize the dictionary
|
||||||
handle_nr = self.get_handle_nr(str(point))
|
handle_nr = self.get_handle_nr(str(point))
|
||||||
@ -342,17 +330,17 @@ class SketchWidget(QWidget):
|
|||||||
relation_point['solv_handle'] = point
|
relation_point['solv_handle'] = point
|
||||||
relation_point['ui_point'] = clicked_pos
|
relation_point['ui_point'] = clicked_pos
|
||||||
|
|
||||||
self.slv_points_main.append(relation_point)
|
self.sketch.slv_points.append(relation_point)
|
||||||
|
|
||||||
print("points", self.slv_points_main)
|
print("points", self.sketch.slv_points)
|
||||||
print("lines", self.slv_lines_main)
|
print("lines", self.sketch.slv_lines)
|
||||||
|
|
||||||
elif self.line_draw_buffer[0]:
|
elif self.line_draw_buffer[0]:
|
||||||
self.line_draw_buffer[1] = clicked_pos
|
self.line_draw_buffer[1] = clicked_pos
|
||||||
u = clicked_pos.x()
|
u = clicked_pos.x()
|
||||||
v = clicked_pos.y()
|
v = clicked_pos.y()
|
||||||
|
|
||||||
point2 = self.solv.add_point_2d(u, v, self.wp)
|
point2 = self.solv.add_point_2d(u, v, self.sketch.working_plane)
|
||||||
|
|
||||||
relation_point = {} # Reinitialize the dictionary
|
relation_point = {} # Reinitialize the dictionary
|
||||||
handle_nr = self.get_handle_nr(str(point2))
|
handle_nr = self.get_handle_nr(str(point2))
|
||||||
@ -360,19 +348,21 @@ class SketchWidget(QWidget):
|
|||||||
relation_point['solv_handle'] = point2
|
relation_point['solv_handle'] = point2
|
||||||
relation_point['ui_point'] = clicked_pos
|
relation_point['ui_point'] = clicked_pos
|
||||||
|
|
||||||
self.slv_points_main.append(relation_point)
|
self.sketch.slv_points.append(relation_point)
|
||||||
|
|
||||||
print("points", self.slv_points_main)
|
print("points", self.sketch.slv_points)
|
||||||
print("lines", self.slv_lines_main)
|
print("lines", self.sketch.slv_lines)
|
||||||
|
|
||||||
print("Buffer state", self.line_draw_buffer)
|
print("Buffer state", self.line_draw_buffer)
|
||||||
|
|
||||||
if self.line_draw_buffer[0] and self.line_draw_buffer[1]:
|
if self.line_draw_buffer[0] and self.line_draw_buffer[1]:
|
||||||
|
|
||||||
point_slv1 = self.get_handle_from_ui_point(self.line_draw_buffer[0])
|
point_slv1 = self.get_handle_from_ui_point(self.line_draw_buffer[0])
|
||||||
point_slv2 = self.get_handle_from_ui_point(self.line_draw_buffer[1])
|
point_slv2 = self.get_handle_from_ui_point(self.line_draw_buffer[1])
|
||||||
print(point_slv1)
|
print(point_slv1)
|
||||||
print(point_slv2)
|
print(point_slv2)
|
||||||
|
|
||||||
line = self.solv.add_line_2d(point_slv1, point_slv2, self.wp)
|
line = self.solv.add_line_2d(point_slv1, point_slv2, self.sketch.working_plane)
|
||||||
|
|
||||||
relation_line = {} # Reinitialize the dictionary
|
relation_line = {} # Reinitialize the dictionary
|
||||||
handle_nr_line = self.get_handle_nr(str(line))
|
handle_nr_line = self.get_handle_nr(str(line))
|
||||||
@ -384,7 +374,7 @@ class SketchWidget(QWidget):
|
|||||||
# Track relationship of point in line
|
# Track relationship of point in line
|
||||||
relation_point['part_of_entity'] = handle_nr_line
|
relation_point['part_of_entity'] = handle_nr_line
|
||||||
|
|
||||||
self.slv_lines_main.append(relation_line)
|
self.sketch.slv_lines.append(relation_line)
|
||||||
|
|
||||||
# Reset the buffer for the next line segment
|
# Reset the buffer for the next line segment
|
||||||
self.line_draw_buffer[0] = self.line_draw_buffer[1]
|
self.line_draw_buffer[0] = self.line_draw_buffer[1]
|
||||||
@ -403,7 +393,7 @@ class SketchWidget(QWidget):
|
|||||||
if self.main_buffer[0] and self.main_buffer[1]:
|
if self.main_buffer[0] and self.main_buffer[1]:
|
||||||
print("buf", self.main_buffer)
|
print("buf", self.main_buffer)
|
||||||
|
|
||||||
self.solv.coincident(self.main_buffer[0], self.main_buffer[1], self.wp)
|
self.solv.coincident(self.main_buffer[0], self.main_buffer[1], self.sketch.working_plane)
|
||||||
|
|
||||||
if self.solv.solve() == ResultFlag.OKAY:
|
if self.solv.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
@ -431,7 +421,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
# Contrain point to line
|
# Contrain point to line
|
||||||
if self.main_buffer[1]:
|
if self.main_buffer[1]:
|
||||||
self.solv.coincident(self.main_buffer[0], self.main_buffer[1], self.wp)
|
self.solv.coincident(self.main_buffer[0], self.main_buffer[1], self.sketch.working_plane)
|
||||||
|
|
||||||
if self.solv.solve() == ResultFlag.OKAY:
|
if self.solv.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
@ -462,7 +452,7 @@ class SketchWidget(QWidget):
|
|||||||
|
|
||||||
# Contrain point to line
|
# Contrain point to line
|
||||||
if self.main_buffer[1]:
|
if self.main_buffer[1]:
|
||||||
self.solv.midpoint(self.main_buffer[0], self.main_buffer[1], self.wp)
|
self.solv.midpoint(self.main_buffer[0], self.main_buffer[1], self.sketch.working_plane)
|
||||||
|
|
||||||
if self.solv.solve() == ResultFlag.OKAY:
|
if self.solv.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
@ -484,7 +474,7 @@ class SketchWidget(QWidget):
|
|||||||
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
if line_selected:
|
if line_selected:
|
||||||
self.solv.horizontal(line_selected, self.wp)
|
self.solv.horizontal(line_selected, self.sketch.working_plane)
|
||||||
|
|
||||||
if self.solv.solve() == ResultFlag.OKAY:
|
if self.solv.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
@ -502,7 +492,7 @@ class SketchWidget(QWidget):
|
|||||||
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
if line_selected:
|
if line_selected:
|
||||||
self.solv.vertical(line_selected, self.wp)
|
self.solv.vertical(line_selected, self.sketch.working_plane)
|
||||||
|
|
||||||
if self.solv.solve() == ResultFlag.OKAY:
|
if self.solv.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
@ -543,7 +533,7 @@ class SketchWidget(QWidget):
|
|||||||
if e1 and e2:
|
if e1 and e2:
|
||||||
# Ask fo the dimension and solve if both elements are present
|
# Ask fo the dimension and solve if both elements are present
|
||||||
length, ok = QInputDialog.getDouble(self, 'Distance', 'Enter a mm value:', value=100, decimals=2)
|
length, ok = QInputDialog.getDouble(self, 'Distance', 'Enter a mm value:', value=100, decimals=2)
|
||||||
self.solv.distance(e1, e2, length, self.wp)
|
self.solv.distance(e1, e2, length, self.sketch.working_plane)
|
||||||
|
|
||||||
if self.solv.solve() == ResultFlag.OKAY:
|
if self.solv.solve() == ResultFlag.OKAY:
|
||||||
print("Fuck yeah")
|
print("Fuck yeah")
|
||||||
@ -574,13 +564,15 @@ class SketchWidget(QWidget):
|
|||||||
min_distance = float('inf')
|
min_distance = float('inf')
|
||||||
threshold = 10 # Distance threshold for highlighting
|
threshold = 10 # Distance threshold for highlighting
|
||||||
|
|
||||||
for point in self.slv_points_main:
|
if self.sketch:
|
||||||
|
|
||||||
|
for point in self.sketch.slv_points:
|
||||||
distance = (local_event_pos - point['ui_point']).manhattanLength()
|
distance = (local_event_pos - point['ui_point']).manhattanLength()
|
||||||
if distance < threshold and distance < min_distance:
|
if distance < threshold and distance < min_distance:
|
||||||
closest_point = point['ui_point']
|
closest_point = point['ui_point']
|
||||||
min_distance = distance
|
min_distance = distance
|
||||||
|
|
||||||
for point in self.proj_snap_points:
|
for point in self.sketch.proj_points:
|
||||||
distance = (local_event_pos - point).manhattanLength()
|
distance = (local_event_pos - point).manhattanLength()
|
||||||
if distance < threshold and distance < min_distance:
|
if distance < threshold and distance < min_distance:
|
||||||
closest_point = point
|
closest_point = point
|
||||||
@ -590,7 +582,7 @@ class SketchWidget(QWidget):
|
|||||||
self.hovered_point = closest_point
|
self.hovered_point = closest_point
|
||||||
print(self.hovered_point)
|
print(self.hovered_point)
|
||||||
|
|
||||||
for dic in self.slv_lines_main:
|
for dic in self.sketch.slv_lines:
|
||||||
p1 = dic['ui_points'][0]
|
p1 = dic['ui_points'][0]
|
||||||
p2 = dic['ui_points'][1]
|
p2 = dic['ui_points'][1]
|
||||||
|
|
||||||
@ -722,10 +714,11 @@ class SketchWidget(QWidget):
|
|||||||
painter.setPen(pen)
|
painter.setPen(pen)
|
||||||
|
|
||||||
# Draw points
|
# Draw points
|
||||||
for point in self.slv_points_main:
|
if self.sketch:
|
||||||
|
for point in self.sketch.slv_points:
|
||||||
painter.drawEllipse(point['ui_point'], 3 / self.zoom, 3 / self.zoom)
|
painter.drawEllipse(point['ui_point'], 3 / self.zoom, 3 / self.zoom)
|
||||||
|
|
||||||
for dic in self.slv_lines_main:
|
for dic in self.sketch.slv_lines:
|
||||||
p1 = dic['ui_points'][0]
|
p1 = dic['ui_points'][0]
|
||||||
p2 = dic['ui_points'][1]
|
p2 = dic['ui_points'][1]
|
||||||
painter.drawLine(p1, p2)
|
painter.drawLine(p1, p2)
|
||||||
@ -759,10 +752,10 @@ class SketchWidget(QWidget):
|
|||||||
painter.setPen(QPen(Qt.red, 2 / self.zoom))
|
painter.setPen(QPen(Qt.red, 2 / self.zoom))
|
||||||
painter.drawLine(p1, p2)
|
painter.drawLine(p1, p2)
|
||||||
|
|
||||||
for cross in self.proj_snap_points:
|
for cross in self.sketch.proj_points:
|
||||||
self.draw_cross(painter, cross, 10 / self.zoom)
|
self.draw_cross(painter, cross, 10 / self.zoom)
|
||||||
|
|
||||||
for selected in self.proj_snap_lines:
|
for selected in self.sketch.proj_lines:
|
||||||
pen = QPen(Qt.white, 1, Qt.DashLine)
|
pen = QPen(Qt.white, 1, Qt.DashLine)
|
||||||
painter.setPen(pen)
|
painter.setPen(pen)
|
||||||
painter.drawLine(selected)
|
painter.drawLine(selected)
|
||||||
@ -777,15 +770,141 @@ class SketchWidget(QWidget):
|
|||||||
def aspect_ratio(self):
|
def aspect_ratio(self):
|
||||||
return self.width() / self.height() * (1.0 / abs(self.zoom))
|
return self.width() / self.height() * (1.0 / abs(self.zoom))
|
||||||
|
|
||||||
def clear_sketch(self):
|
|
||||||
self.slv_points_main = []
|
|
||||||
self.slv_lines_main = []
|
|
||||||
self.proj_snap_lines.clear()
|
|
||||||
self.proj_snap_points.clear()
|
|
||||||
self.reset_buffers()
|
|
||||||
self.solv = SolverSystem()
|
|
||||||
|
|
||||||
# Example usage
|
class Point2D:
|
||||||
|
"""Improved oop aaproach?"""
|
||||||
|
def __init__(self):
|
||||||
|
self.ui_point = None
|
||||||
|
self.solve_handle_nr = None
|
||||||
|
self.solve_handle = None
|
||||||
|
self.part_of_entity = None
|
||||||
|
|
||||||
|
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 = center_y - point.y() # Note the change here
|
||||||
|
|
||||||
|
return QPoint(quadrant_x, quadrant_y) / self.zoom
|
||||||
|
|
||||||
|
def from_quadrant_coords(self, point: QPoint):
|
||||||
|
"""Translate quadrant coordinates to linear coordinates."""
|
||||||
|
center_x = self.width() // 2
|
||||||
|
center_y = self.height() // 2
|
||||||
|
widget_x = center_x + point.x() * self.zoom
|
||||||
|
widget_y = center_y - point.y() * self.zoom # Note the subtraction here
|
||||||
|
|
||||||
|
return QPoint(int(widget_x), int(widget_y))
|
||||||
|
|
||||||
|
def from_quadrant_coords_no_center(self, point):
|
||||||
|
"""Invert Y Coordinate for mesh"""
|
||||||
|
center_x = 0
|
||||||
|
center_y = 0
|
||||||
|
widget_x = point.x()
|
||||||
|
widget_y = -point.y()
|
||||||
|
|
||||||
|
return QPoint(int(widget_x), int(widget_y))
|
||||||
|
|
||||||
|
def get_handle_nr(self, input_str: str) -> int:
|
||||||
|
# Define the regex pattern to extract the handle number
|
||||||
|
pattern = r"handle=(\d+)"
|
||||||
|
|
||||||
|
# Use re.search to find the handle number in the string
|
||||||
|
match = re.search(pattern, input_str)
|
||||||
|
|
||||||
|
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:
|
||||||
|
result = []
|
||||||
|
path = []
|
||||||
|
print(d)
|
||||||
|
print(target)
|
||||||
|
for k, v in d.items():
|
||||||
|
path.append(k)
|
||||||
|
if isinstance(v, dict):
|
||||||
|
self.get_keys(v, target)
|
||||||
|
if v == target:
|
||||||
|
result.append(copy(path))
|
||||||
|
path.pop()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_handle_from_ui_point(self, ui_point: QPoint):
|
||||||
|
"""Input QPoint and you shall reveive a slvs entity handle!"""
|
||||||
|
for point in self.sketch.slv_points:
|
||||||
|
if ui_point == point['ui_point']:
|
||||||
|
slv_handle = point['solv_handle']
|
||||||
|
|
||||||
|
return slv_handle
|
||||||
|
|
||||||
|
def get_line_handle_from_ui_point(self, ui_point: QPoint):
|
||||||
|
"""Input Qpoint that is on a line and you shall receive the handle of the line!"""
|
||||||
|
for target_line_con in self.sketch.slv_lines:
|
||||||
|
if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]):
|
||||||
|
slv_handle = target_line_con['solv_handle']
|
||||||
|
|
||||||
|
return slv_handle
|
||||||
|
|
||||||
|
def get_point_line_handles_from_ui_point(self, ui_point: QPoint) -> tuple:
|
||||||
|
"""Input Qpoint that is on a line and you shall receive the handles of the points of the line!"""
|
||||||
|
for target_line_con in self.sketch.slv_lines:
|
||||||
|
if self.is_point_on_line(ui_point, target_line_con['ui_points'][0], target_line_con['ui_points'][1]):
|
||||||
|
lines_to_cons = target_line_con['solv_entity_points']
|
||||||
|
|
||||||
|
return lines_to_cons
|
||||||
|
|
||||||
|
def distance(self, p1, p2):
|
||||||
|
return math.sqrt((p1.x() - p2.x())**2 + (p1.y() - p2.y())**2)
|
||||||
|
|
||||||
|
def calculate_midpoint(self, point1, point2):
|
||||||
|
mx = (point1.x() + point2.x()) // 2
|
||||||
|
my = (point1.y() + point2.y()) // 2
|
||||||
|
return QPoint(mx, my)
|
||||||
|
|
||||||
|
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:
|
||||||
|
return QPoint(self.to_quadrant_coords(qt_pos))
|
||||||
|
|
||||||
|
|
||||||
|
class Line2D:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Sketch2d(SolverSystem):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
897
drawing_modules/draw_widget_solve.py
Normal file
897
drawing_modules/draw_widget_solve.py
Normal file
@ -0,0 +1,897 @@
|
|||||||
|
import math
|
||||||
|
import re
|
||||||
|
from copy import copy
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
from PySide6.QtWidgets import QApplication, QWidget, QMessageBox, QInputDialog
|
||||||
|
from PySide6.QtGui import QPainter, QPen, QColor, QTransform
|
||||||
|
from PySide6.QtCore import Qt, QPoint, QPointF, Signal, QLine
|
||||||
|
from python_solvespace import SolverSystem, ResultFlag
|
||||||
|
|
||||||
|
|
||||||
|
class SketchWidget(QWidget):
|
||||||
|
constrain_done = Signal()
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
self.line_draw_buffer = [None, None]
|
||||||
|
self.drag_buffer = [None, None]
|
||||||
|
self.main_buffer = [None, None]
|
||||||
|
self.dynamic_line_end = None # Cursor position for dynamic drawing
|
||||||
|
|
||||||
|
self.hovered_point = None
|
||||||
|
self.selected_line = None
|
||||||
|
|
||||||
|
self.snapping_range = 20 # Range in pixels for snapping
|
||||||
|
self.zoom = 1
|
||||||
|
|
||||||
|
self.setMouseTracking(True)
|
||||||
|
self.mouse_mode = False
|
||||||
|
self.solv = SolverSystem()
|
||||||
|
|
||||||
|
self.sketch = Sketch2d()
|
||||||
|
|
||||||
|
def create_sketch(self, sketch_in ):
|
||||||
|
self.sketch = Sketch2d()
|
||||||
|
self.sketch.id = sketch_in.id
|
||||||
|
self.sketch.origin = sketch_in.origin
|
||||||
|
|
||||||
|
def set_sketch(self, sketch_in):
|
||||||
|
"""Needs to be an already defined Sketch object coming from the widget itself"""
|
||||||
|
self.sketch = sketch_in
|
||||||
|
|
||||||
|
def get_sketch(self):
|
||||||
|
return self.sketch
|
||||||
|
|
||||||
|
def reset_buffers(self):
|
||||||
|
self.line_draw_buffer = [None, None]
|
||||||
|
self.drag_buffer = [None, None]
|
||||||
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
|
def set_points(self, points: list):
|
||||||
|
self.points = points
|
||||||
|
#self.update()
|
||||||
|
|
||||||
|
def create_workplane(self):
|
||||||
|
self.sketch.wp = self.sketch.create_2d_base()
|
||||||
|
|
||||||
|
def create_workplane_projected(self):
|
||||||
|
self.sketch.wp = self.sketch.create_2d_base()
|
||||||
|
|
||||||
|
def convert_proj_points(self, proj_points: list):
|
||||||
|
### This needs to create a proper Point2D class with bool construction enbaled
|
||||||
|
out_points = []
|
||||||
|
for point in proj_points:
|
||||||
|
pnt = Point2D(point[0], point[1])
|
||||||
|
# Construction
|
||||||
|
pnt.is_helper = True
|
||||||
|
print(point)
|
||||||
|
self.sketch.add_point(pnt)
|
||||||
|
|
||||||
|
def convert_proj_lines(self, proj_lines: list):
|
||||||
|
### same as for point
|
||||||
|
out_lines = []
|
||||||
|
for line in proj_lines:
|
||||||
|
start = Point2D(line[0][0], line[0][1])
|
||||||
|
end = Point2D(line[1][0], line[1][1])
|
||||||
|
start.is_helper = True
|
||||||
|
end.is_helper = True
|
||||||
|
|
||||||
|
self.sketch.add_point(start)
|
||||||
|
self.sketch.add_point(end)
|
||||||
|
|
||||||
|
lne = Line2D(start, end)
|
||||||
|
|
||||||
|
#Construction
|
||||||
|
lne.is_helper = True
|
||||||
|
self.sketch.add_line(lne)
|
||||||
|
|
||||||
|
def find_duplicate_points_2d(self, edges):
|
||||||
|
points = []
|
||||||
|
seen = set()
|
||||||
|
duplicates = []
|
||||||
|
|
||||||
|
for edge in edges:
|
||||||
|
for point in edge:
|
||||||
|
# Extract only x and y coordinates
|
||||||
|
point_2d = (point[0], point[1])
|
||||||
|
if point_2d in seen:
|
||||||
|
if point_2d not in duplicates:
|
||||||
|
duplicates.append(point_2d)
|
||||||
|
else:
|
||||||
|
seen.add(point_2d)
|
||||||
|
points.append(point_2d)
|
||||||
|
|
||||||
|
return duplicates
|
||||||
|
|
||||||
|
def normal_to_quaternion(self, normal):
|
||||||
|
normal = np.array(normal)
|
||||||
|
#normal = normal / np.linalg.norm(normal)
|
||||||
|
|
||||||
|
axis = np.cross([0, 0, 1], normal)
|
||||||
|
if np.allclose(axis, 0):
|
||||||
|
axis = np.array([1, 0, 0])
|
||||||
|
else:
|
||||||
|
axis = axis / np.linalg.norm(axis) # Normalize the axis
|
||||||
|
|
||||||
|
angle = np.arccos(np.dot([0, 0, 1], normal))
|
||||||
|
|
||||||
|
qw = np.cos(angle / 2)
|
||||||
|
sin_half_angle = np.sin(angle / 2)
|
||||||
|
qx, qy, qz = axis * sin_half_angle # This will now work correctly
|
||||||
|
|
||||||
|
return qw, qx, qy, qz
|
||||||
|
|
||||||
|
def create_workplane_space(self, points, normal):
|
||||||
|
print("edges", points)
|
||||||
|
origin = self.find_duplicate_points_2d(points)
|
||||||
|
print(origin)
|
||||||
|
x, y = origin[0]
|
||||||
|
origin = QPoint(x, y)
|
||||||
|
|
||||||
|
origin_handle = self.get_handle_from_ui_point(origin)
|
||||||
|
qw, qx, qy, qz = self.normal_to_quaternion(normal)
|
||||||
|
|
||||||
|
slv_normal = self.sketch.add_normal_3d(qw, qx, qy, qz)
|
||||||
|
self.sketch.wp = self.sketch.add_work_plane(origin_handle, slv_normal)
|
||||||
|
print(self.sketch.wp)
|
||||||
|
|
||||||
|
def get_handle_nr(self, input_str: str) -> int:
|
||||||
|
# Define the regex pattern to extract the handle number
|
||||||
|
pattern = r"handle=(\d+)"
|
||||||
|
|
||||||
|
# Use re.search to find the handle number in the string
|
||||||
|
match = re.search(pattern, input_str)
|
||||||
|
|
||||||
|
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:
|
||||||
|
result = []
|
||||||
|
path = []
|
||||||
|
print(d)
|
||||||
|
print(target)
|
||||||
|
for k, v in d.items():
|
||||||
|
path.append(k)
|
||||||
|
if isinstance(v, dict):
|
||||||
|
self.get_keys(v, target)
|
||||||
|
if v == target:
|
||||||
|
result.append(copy(path))
|
||||||
|
path.pop()
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def get_handle_from_ui_point(self, ui_point: QPoint):
|
||||||
|
"""Input QPoint and you shall reveive a slvs entity handle!"""
|
||||||
|
for point in self.sketch.points:
|
||||||
|
if ui_point == point.ui_point:
|
||||||
|
slv_handle = point.handle
|
||||||
|
|
||||||
|
return slv_handle
|
||||||
|
|
||||||
|
def get_line_handle_from_ui_point(self, ui_point: QPoint):
|
||||||
|
"""Input Qpoint that is on a line and you shall receive the handle of the line!"""
|
||||||
|
for target_line_con in self.sketch.lines:
|
||||||
|
if self.is_point_on_line(ui_point, target_line_con.crd1.ui_point, target_line_con.crd2.ui_point):
|
||||||
|
slv_handle = target_line_con.handle
|
||||||
|
|
||||||
|
return slv_handle
|
||||||
|
|
||||||
|
def get_point_line_handles_from_ui_point(self, ui_point: QPoint) -> tuple:
|
||||||
|
"""Input Qpoint that is on a line and you shall receive the handles of the points of the line!"""
|
||||||
|
for target_line_con in self.sketch.lines:
|
||||||
|
if self.is_point_on_line(ui_point, target_line_con.crd1.ui_point, target_line_con.crd2.ui_point):
|
||||||
|
lines_to_cons = target_line_con.crd1.handle, target_line_con.crd2.handle
|
||||||
|
|
||||||
|
return lines_to_cons
|
||||||
|
|
||||||
|
def distance(self, p1, p2):
|
||||||
|
return math.sqrt((p1.x() - p2.x())**2 + (p1.y() - p2.y())**2)
|
||||||
|
|
||||||
|
def calculate_midpoint(self, point1, point2):
|
||||||
|
mx = (point1.x() + point2.x()) // 2
|
||||||
|
my = (point1.y() + point2.y()) // 2
|
||||||
|
return QPoint(mx, my)
|
||||||
|
|
||||||
|
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:
|
||||||
|
return QPoint(self.to_quadrant_coords(qt_pos))
|
||||||
|
|
||||||
|
def check_all_points(self) -> list:
|
||||||
|
"""
|
||||||
|
Go through solversystem and check points2d for changes in position after solving
|
||||||
|
:return: List with points that now have a different position
|
||||||
|
"""
|
||||||
|
old_points_ui = []
|
||||||
|
new_points_ui = []
|
||||||
|
|
||||||
|
for old_point_ui in self.sketch.points:
|
||||||
|
old_points_ui.append(old_point_ui.ui_point)
|
||||||
|
|
||||||
|
for i in range(self.sketch.entity_len()):
|
||||||
|
# Iterate though full length because mixed list from SS
|
||||||
|
entity = self.sketch.entity(i)
|
||||||
|
if entity.is_point_2d() and self.sketch.params(entity.params):
|
||||||
|
x_tbu, y_tbu = self.sketch.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):
|
||||||
|
print(f"Length mismatch {len(old_points_ui)} - {len(new_points_ui)}")
|
||||||
|
|
||||||
|
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(self, point_list: list):
|
||||||
|
# Print initial state of slv_points_main
|
||||||
|
# print("Initial slv_points_main:", self.slv_points_main)
|
||||||
|
print("Change list:", point_list)
|
||||||
|
|
||||||
|
if len(point_list) > 0:
|
||||||
|
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
|
||||||
|
|
||||||
|
# Update the point in slv_points_main
|
||||||
|
self.sketch.points[index].ui_point = new_point
|
||||||
|
# Print updated state
|
||||||
|
# print("Updated slv_points_main:", self.slv_points_main)
|
||||||
|
|
||||||
|
def check_all_lines_and_update(self,changed_points: list):
|
||||||
|
for tbu_points_idx in changed_points:
|
||||||
|
index, old_point, new_point = tbu_points_idx
|
||||||
|
for line_needs_update in self.sketch.lines:
|
||||||
|
if old_point == line_needs_update.crd1.ui_point:
|
||||||
|
line_needs_update.crd1.ui_point = new_point
|
||||||
|
elif old_point == line_needs_update.crd2.ui_point:
|
||||||
|
line_needs_update.crd2.ui_point = new_point
|
||||||
|
|
||||||
|
def mouseReleaseEvent(self, event):
|
||||||
|
local_event_pos = self.viewport_to_local_coord(event.pos())
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and not self.mouse_mode:
|
||||||
|
self.drag_buffer[1] = local_event_pos
|
||||||
|
|
||||||
|
print("Le main buffer", self.drag_buffer)
|
||||||
|
|
||||||
|
if not None in self.main_buffer and len(self.main_buffer) == 2:
|
||||||
|
entry = self.drag_buffer[0]
|
||||||
|
new_params = self.drag_buffer[1].x(), self.drag_buffer[1].y()
|
||||||
|
self.sketch.set_params(entry.params, new_params)
|
||||||
|
|
||||||
|
self.sketch.solve()
|
||||||
|
|
||||||
|
points_need_update = self.check_all_points()
|
||||||
|
self.update_ui_points(points_need_update)
|
||||||
|
self.check_all_lines_and_update(points_need_update)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
self.drag_buffer = [None, None]
|
||||||
|
|
||||||
|
def mousePressEvent(self, event):
|
||||||
|
local_event_pos = self.viewport_to_local_coord(event.pos())
|
||||||
|
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and not self.mouse_mode:
|
||||||
|
self.drag_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
|
if event.button() == Qt.RightButton and self.mouse_mode:
|
||||||
|
self.reset_buffers()
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "line":
|
||||||
|
if self.hovered_point:
|
||||||
|
clicked_pos = self.hovered_point
|
||||||
|
else:
|
||||||
|
clicked_pos = local_event_pos
|
||||||
|
|
||||||
|
if not self.line_draw_buffer[0]:
|
||||||
|
|
||||||
|
u = clicked_pos.x()
|
||||||
|
v = clicked_pos.y()
|
||||||
|
|
||||||
|
point = Point2D(u,v)
|
||||||
|
self.sketch.add_point(point)
|
||||||
|
|
||||||
|
self.line_draw_buffer[0] = point
|
||||||
|
|
||||||
|
elif self.line_draw_buffer[0]:
|
||||||
|
|
||||||
|
u = clicked_pos.x()
|
||||||
|
v = clicked_pos.y()
|
||||||
|
|
||||||
|
point = Point2D(u, v)
|
||||||
|
self.sketch.add_point(point)
|
||||||
|
|
||||||
|
self.line_draw_buffer[1] = point
|
||||||
|
|
||||||
|
print("Buffer state", self.line_draw_buffer)
|
||||||
|
|
||||||
|
if self.line_draw_buffer[0] and self.line_draw_buffer[1]:
|
||||||
|
|
||||||
|
line = Line2D(self.line_draw_buffer[0], self.line_draw_buffer[1])
|
||||||
|
self.sketch.add_line(line)
|
||||||
|
|
||||||
|
# Reset the buffer for the next line segment
|
||||||
|
self.line_draw_buffer[0] = self.line_draw_buffer[1]
|
||||||
|
self.line_draw_buffer[1] = None
|
||||||
|
|
||||||
|
# Track Relationship
|
||||||
|
# Points
|
||||||
|
|
||||||
|
# CONSTRAINTS
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "pt_pt":
|
||||||
|
if self.hovered_point and not self.main_buffer[0]:
|
||||||
|
self.main_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
|
elif self.main_buffer[0]:
|
||||||
|
self.main_buffer[1] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
|
if self.main_buffer[0] and self.main_buffer[1]:
|
||||||
|
print("buf", self.main_buffer)
|
||||||
|
|
||||||
|
self.sketch.coincident(self.main_buffer[0], self.main_buffer[1], self.sketch.wp)
|
||||||
|
|
||||||
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
|
print("Fuck yeah")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
|
||||||
|
print("Solve_failed - Unknowns")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.INCONSISTENT:
|
||||||
|
print("Solve_failed - Incons")
|
||||||
|
|
||||||
|
self.constrain_done.emit()
|
||||||
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "pt_line":
|
||||||
|
print("ptline")
|
||||||
|
line_selected = None
|
||||||
|
|
||||||
|
if self.hovered_point and not self.main_buffer[1]:
|
||||||
|
self.main_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
|
elif self.main_buffer[0]:
|
||||||
|
self.main_buffer[1] = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
|
# Contrain point to line
|
||||||
|
if self.main_buffer[1]:
|
||||||
|
self.sketch.coincident(self.main_buffer[0], self.main_buffer[1], self.sketch.wp)
|
||||||
|
|
||||||
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
|
print("Fuck yeah")
|
||||||
|
self.constrain_done.emit()
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
|
||||||
|
print("Solve_failed - Unknowns")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.INCONSISTENT:
|
||||||
|
print("Solve_failed - Incons")
|
||||||
|
|
||||||
|
self.constrain_done.emit()
|
||||||
|
# Clear saved_points after solve attempt
|
||||||
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "pb_con_mid":
|
||||||
|
print("ptline")
|
||||||
|
line_selected = None
|
||||||
|
|
||||||
|
if self.hovered_point and not self.main_buffer[1]:
|
||||||
|
self.main_buffer[0] = self.get_handle_from_ui_point(self.hovered_point)
|
||||||
|
|
||||||
|
elif self.main_buffer[0]:
|
||||||
|
self.main_buffer[1] = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
|
# Contrain point to line
|
||||||
|
if self.main_buffer[1]:
|
||||||
|
self.sketch.midpoint(self.main_buffer[0], self.main_buffer[1], self.sketch.wp)
|
||||||
|
|
||||||
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
|
print("Fuck yeah")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
|
||||||
|
print("Solve_failed - Unknowns")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.INCONSISTENT:
|
||||||
|
print("Solve_failed - Incons")
|
||||||
|
self.constrain_done.emit()
|
||||||
|
|
||||||
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "horiz":
|
||||||
|
|
||||||
|
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
|
if line_selected:
|
||||||
|
self.sketch.horizontal(line_selected, self.sketch.wp)
|
||||||
|
|
||||||
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
|
print("Fuck yeah")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
|
||||||
|
print("Solve_failed - Unknowns")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.INCONSISTENT:
|
||||||
|
print("Solve_failed - Incons")
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "vert":
|
||||||
|
line_selected = self.get_line_handle_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
|
if line_selected:
|
||||||
|
self.sketch.vertical(line_selected, self.sketch.wp)
|
||||||
|
|
||||||
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
|
print("Fuck yeah")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
|
||||||
|
print("Solve_failed - Unknowns")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.INCONSISTENT:
|
||||||
|
print("Solve_failed - Incons")
|
||||||
|
|
||||||
|
if event.button() == Qt.LeftButton and self.mouse_mode == "distance":
|
||||||
|
# Depending on selected elemnts either point line or line distance
|
||||||
|
#print("distance")
|
||||||
|
e1 = None
|
||||||
|
e2 = None
|
||||||
|
|
||||||
|
if self.hovered_point:
|
||||||
|
print("buf point")
|
||||||
|
# Get the point as UI point as buffer
|
||||||
|
self.main_buffer[0] = self.hovered_point
|
||||||
|
|
||||||
|
elif self.selected_line:
|
||||||
|
# Get the point as UI point as buffer
|
||||||
|
self.main_buffer[1] = local_event_pos
|
||||||
|
|
||||||
|
if self.main_buffer[0] and self.main_buffer[1]:
|
||||||
|
# Define point line combination
|
||||||
|
e1 = self.get_handle_from_ui_point(self.main_buffer[0])
|
||||||
|
e2 = self.get_line_handle_from_ui_point(self.main_buffer[1])
|
||||||
|
|
||||||
|
elif not self.main_buffer[0]:
|
||||||
|
# Define only line selection
|
||||||
|
e1, e2 = self.get_point_line_handles_from_ui_point(local_event_pos)
|
||||||
|
|
||||||
|
if e1 and e2:
|
||||||
|
# Ask fo the dimension and solve if both elements are present
|
||||||
|
length, ok = QInputDialog.getDouble(self, 'Distance', 'Enter a mm value:', value=100, decimals=2)
|
||||||
|
self.sketch.distance(e1, e2, length, self.sketch.wp)
|
||||||
|
|
||||||
|
if self.sketch.solve() == ResultFlag.OKAY:
|
||||||
|
print("Fuck yeah")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.DIDNT_CONVERGE:
|
||||||
|
print("Solve_failed - Converge")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.TOO_MANY_UNKNOWNS:
|
||||||
|
print("Solve_failed - Unknowns")
|
||||||
|
|
||||||
|
elif self.sketch.solve() == ResultFlag.INCONSISTENT:
|
||||||
|
print("Solve_failed - Incons")
|
||||||
|
|
||||||
|
self.constrain_done.emit()
|
||||||
|
self.main_buffer = [None, None]
|
||||||
|
|
||||||
|
# Update the main point list with the new elements and draw them
|
||||||
|
points_need_update = self.check_all_points()
|
||||||
|
self.update_ui_points(points_need_update)
|
||||||
|
self.check_all_lines_and_update(points_need_update)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def mouseMoveEvent(self, event):
|
||||||
|
local_event_pos = self.viewport_to_local_coord(event.pos())
|
||||||
|
#print(local_event_pos)
|
||||||
|
|
||||||
|
closest_point = None
|
||||||
|
min_distance = float('inf')
|
||||||
|
threshold = 10 # Distance threshold for highlighting
|
||||||
|
|
||||||
|
if self.mouse_mode == "line" and self.line_draw_buffer[0]:
|
||||||
|
# Update the current cursor position as the second point
|
||||||
|
self.dynamic_line_end = self.viewport_to_local_coord(event.pos())
|
||||||
|
self.update() # Trigger a repaint
|
||||||
|
|
||||||
|
if self.sketch.points is not None and len(self.sketch.points) > 0:
|
||||||
|
for point in self.sketch.points:
|
||||||
|
distance = (local_event_pos - point.ui_point).manhattanLength()
|
||||||
|
if distance < threshold and distance < min_distance:
|
||||||
|
closest_point = point.ui_point
|
||||||
|
min_distance = distance
|
||||||
|
|
||||||
|
"""for point in self.sketch.proj_points:
|
||||||
|
distance = (local_event_pos - point).manhattanLength()
|
||||||
|
if distance < threshold and distance < min_distance:
|
||||||
|
closest_point = point
|
||||||
|
min_distance = distance"""
|
||||||
|
|
||||||
|
if closest_point != self.hovered_point:
|
||||||
|
self.hovered_point = closest_point
|
||||||
|
print(self.hovered_point)
|
||||||
|
|
||||||
|
for line in self.sketch.lines:
|
||||||
|
p1 = line.crd1.ui_point
|
||||||
|
p2 = line.crd2.ui_point
|
||||||
|
|
||||||
|
if self.is_point_on_line(local_event_pos, p1, p2):
|
||||||
|
self.selected_line = p1, p2
|
||||||
|
|
||||||
|
# Midpointsnap only in drawer not solver
|
||||||
|
mid = self.calculate_midpoint(p1, p2)
|
||||||
|
distance = (local_event_pos - mid).manhattanLength()
|
||||||
|
if distance < threshold and distance < min_distance:
|
||||||
|
self.hovered_point = mid
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self.selected_line = None
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def mouseDoubleClickEvent(self, event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def drawBackgroundGrid(self, painter):
|
||||||
|
"""Draw a background grid."""
|
||||||
|
grid_spacing = 50
|
||||||
|
pen = QPen(QColor(200, 200, 200), 1, Qt.SolidLine)
|
||||||
|
painter.setPen(pen)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
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 = int(10 * self.zoom)
|
||||||
|
tick_spacing = int(50 * self.zoom)
|
||||||
|
|
||||||
|
pen = QPen(Qt.gray, 1, Qt.SolidLine)
|
||||||
|
painter.setPen(pen)
|
||||||
|
|
||||||
|
# Draw tick marks on the X axis to the right and left from the middle point
|
||||||
|
for x in range(0, self.width() // 2, tick_spacing):
|
||||||
|
painter.drawLine(middle_x + x, middle_y - tick_length // 2, middle_x + x, middle_y + tick_length // 2)
|
||||||
|
painter.drawLine(middle_x - x, middle_y - tick_length // 2, middle_x - x, middle_y + tick_length // 2)
|
||||||
|
|
||||||
|
# Draw tick marks on the Y axis upwards and downwards from the middle point
|
||||||
|
for y in range(0, self.height() // 2, tick_spacing):
|
||||||
|
painter.drawLine(middle_x - tick_length // 2, middle_y + y, middle_x + tick_length // 2, middle_y + y)
|
||||||
|
painter.drawLine(middle_x - tick_length // 2, middle_y - y, middle_x + tick_length // 2, middle_y - y)
|
||||||
|
|
||||||
|
# Draw the origin point in red
|
||||||
|
painter.setPen(QPen(Qt.red, 4))
|
||||||
|
painter.drawPoint(middle_x, middle_y)
|
||||||
|
|
||||||
|
def draw_cross(self, painter, pos: QPoint, size=10):
|
||||||
|
# Set up the pen
|
||||||
|
pen = QPen(QColor('green')) # You can change the color as needed
|
||||||
|
pen.setWidth(int(2 / self.zoom)) # Set the line widt)h
|
||||||
|
painter.setPen(pen)
|
||||||
|
x = pos.x()
|
||||||
|
y = pos.y()
|
||||||
|
|
||||||
|
# Calculate the endpoints of the cross
|
||||||
|
half_size = size // 2
|
||||||
|
|
||||||
|
# Draw the horizontal line
|
||||||
|
painter.drawLine(x - half_size, y, x + half_size, y)
|
||||||
|
|
||||||
|
# Draw the vertical line
|
||||||
|
painter.drawLine(x, y - half_size, x, y + half_size)
|
||||||
|
|
||||||
|
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 = center_y - point.y() # Note the change here
|
||||||
|
return QPoint(quadrant_x, quadrant_y) / self.zoom
|
||||||
|
|
||||||
|
def from_quadrant_coords(self, point: QPoint):
|
||||||
|
"""Translate quadrant coordinates to linear coordinates."""
|
||||||
|
center_x = self.width() // 2
|
||||||
|
center_y = self.height() // 2
|
||||||
|
widget_x = center_x + point.x() * self.zoom
|
||||||
|
widget_y = center_y - point.y() * self.zoom # Note the subtraction here
|
||||||
|
|
||||||
|
return QPoint(int(widget_x), int(widget_y))
|
||||||
|
|
||||||
|
def from_quadrant_coords_no_center(self, point):
|
||||||
|
"""Invert Y Coordinate for mesh"""
|
||||||
|
center_x = 0
|
||||||
|
center_y = 0
|
||||||
|
widget_x = point.x()
|
||||||
|
widget_y = -point.y()
|
||||||
|
return QPoint(int(widget_x), int(widget_y))
|
||||||
|
|
||||||
|
def paintEvent(self, event):
|
||||||
|
painter = QPainter(self)
|
||||||
|
painter.setRenderHint(QPainter.Antialiasing)
|
||||||
|
|
||||||
|
self.drawAxes(painter)
|
||||||
|
|
||||||
|
# Create a QTransform object
|
||||||
|
transform = QTransform()
|
||||||
|
|
||||||
|
# Translate the origin to the center of the widget
|
||||||
|
center = QPointF(self.width() / 2, self.height() / 2)
|
||||||
|
transform.translate(center.x(), center.y())
|
||||||
|
|
||||||
|
# Apply the zoom factor
|
||||||
|
transform.scale(self.zoom, -self.zoom) # Negative y-scale to invert y-axis
|
||||||
|
|
||||||
|
# Set the transform to the painter
|
||||||
|
painter.setTransform(transform)
|
||||||
|
|
||||||
|
pen_normal = QPen(Qt.gray)
|
||||||
|
pen_normal.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
|
pen_construct = QPen(Qt.cyan)
|
||||||
|
pen_construct.setStyle(Qt.PenStyle.DotLine)
|
||||||
|
pen_construct.setWidthF(1 / self.zoom)
|
||||||
|
|
||||||
|
pen_solver = QPen(Qt.green)
|
||||||
|
pen_solver.setWidthF(2 / self.zoom)
|
||||||
|
|
||||||
|
pen_text = QPen(Qt.white)
|
||||||
|
pen_text.setWidthF(1 / self.zoom)
|
||||||
|
|
||||||
|
# Draw points and lines
|
||||||
|
if self.sketch:
|
||||||
|
painter.setPen(pen_normal)
|
||||||
|
for point in self.sketch.points:
|
||||||
|
if point.is_helper:
|
||||||
|
painter.setPen(pen_construct)
|
||||||
|
painter.drawEllipse(point.ui_point, 10 / self.zoom, 10 / self.zoom)
|
||||||
|
else:
|
||||||
|
# Normal point
|
||||||
|
painter.setPen(pen_normal)
|
||||||
|
painter.drawEllipse(point.ui_point, 3 / self.zoom, 3 / self.zoom)
|
||||||
|
|
||||||
|
# Draw the dynamic line
|
||||||
|
if self.mouse_mode == "line" and self.line_draw_buffer[0] and self.dynamic_line_end is not None:
|
||||||
|
start_point = self.line_draw_buffer[0].ui_point
|
||||||
|
end_point = self.dynamic_line_end
|
||||||
|
painter.setPen(Qt.red) # Use a different color for the dynamic line
|
||||||
|
painter.drawLine(start_point, end_point)
|
||||||
|
|
||||||
|
# Save painter state
|
||||||
|
painter.save()
|
||||||
|
painter.setPen(pen_text)
|
||||||
|
|
||||||
|
# Calculate the distance and midpoint
|
||||||
|
dis = self.distance(start_point, end_point)
|
||||||
|
mid = self.calculate_midpoint(start_point, end_point)
|
||||||
|
|
||||||
|
# Transform for text
|
||||||
|
painter.translate(mid.x(), mid.y()) # Move to the midpoint
|
||||||
|
painter.scale(1, -1) # Flip y-axis back to make text readable
|
||||||
|
|
||||||
|
# Draw the text
|
||||||
|
painter.drawText(0, 0, str(round(dis, 2))) # Draw text at transformed position
|
||||||
|
|
||||||
|
# Restore painter state
|
||||||
|
painter.restore()
|
||||||
|
|
||||||
|
for line in self.sketch.lines:
|
||||||
|
if line.is_helper:
|
||||||
|
painter.setPen(pen_construct)
|
||||||
|
p1 = line.crd1.ui_point
|
||||||
|
p2 = line.crd2.ui_point
|
||||||
|
painter.drawLine(p1, p2)
|
||||||
|
else:
|
||||||
|
painter.setPen(pen_normal)
|
||||||
|
p1 = line.crd1.ui_point
|
||||||
|
p2 = line.crd2.ui_point
|
||||||
|
painter.drawLine(p1, p2)
|
||||||
|
|
||||||
|
# Draw all solver points
|
||||||
|
if self.sketch.entity_len():
|
||||||
|
painter.setPen(pen_solver)
|
||||||
|
for i in range(self.sketch.entity_len()):
|
||||||
|
entity = self.sketch.entity(i)
|
||||||
|
if entity.is_point_2d() and self.sketch.params(entity.params):
|
||||||
|
x, y = self.sketch.params(entity.params)
|
||||||
|
point = QPointF(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.setWidthF(2 / self.zoom)
|
||||||
|
painter.setPen(highlight_pen)
|
||||||
|
painter.drawEllipse(self.hovered_point, 5 / self.zoom, 5 / self.zoom)
|
||||||
|
|
||||||
|
# Highlight line hovered
|
||||||
|
if self.selected_line and not self.hovered_point:
|
||||||
|
p1, p2 = self.selected_line
|
||||||
|
painter.setPen(QPen(Qt.red, 2 / self.zoom))
|
||||||
|
painter.drawLine(p1, p2)
|
||||||
|
|
||||||
|
"""for cross in self.sketch.proj_points:
|
||||||
|
self.draw_cross(painter, cross, 10 / self.zoom)
|
||||||
|
|
||||||
|
for selected in self.sketch.proj_lines:
|
||||||
|
pen = QPen(Qt.white, 1, Qt.DashLine)
|
||||||
|
painter.setPen(pen)
|
||||||
|
painter.drawLine(selected)"""
|
||||||
|
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
||||||
|
### GEOMETRY CLASSES
|
||||||
|
class Point2D:
|
||||||
|
def __init__(self, x, y):
|
||||||
|
self.id = None
|
||||||
|
self.ui_x: int = x
|
||||||
|
self.ui_y: int = y
|
||||||
|
self.ui_point = QPoint(self.ui_x, self.ui_y)
|
||||||
|
self.handle = None
|
||||||
|
self.handle_nr: int = None
|
||||||
|
|
||||||
|
# Construction Geometry
|
||||||
|
self.is_helper: bool = False
|
||||||
|
|
||||||
|
class Line2D:
|
||||||
|
def __init__(self, point_s: Point2D, point_e: Point2D):
|
||||||
|
self.id = None
|
||||||
|
|
||||||
|
self.crd1: Point2D = point_s
|
||||||
|
self.crd2: Point2D = point_e
|
||||||
|
self.handle = None
|
||||||
|
self.handle_nr: int = None
|
||||||
|
|
||||||
|
# Construction Geometry
|
||||||
|
self.is_helper: bool = False
|
||||||
|
|
||||||
|
class Sketch2d(SolverSystem):
|
||||||
|
"""
|
||||||
|
Primary class for internal drawing based on the SolveSpace libray
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.id = uuid.uuid1()
|
||||||
|
|
||||||
|
self.wp = self.create_2d_base()
|
||||||
|
self.points = []
|
||||||
|
self.lines = []
|
||||||
|
self.origin = [0,0,0]
|
||||||
|
|
||||||
|
def add_point(self, point: Point2D):
|
||||||
|
"""
|
||||||
|
Adds a point into the solversystem and returns the handle.
|
||||||
|
Appends the added point to the points list.
|
||||||
|
:param point: 2D point in Point2D class format
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
point.handle = self.add_point_2d(point.ui_x, point.ui_y, self.wp)
|
||||||
|
point.handle_nr = self.get_handle_nr(str(point.handle))
|
||||||
|
point.id = uuid.uuid1()
|
||||||
|
|
||||||
|
self.points.append(point)
|
||||||
|
|
||||||
|
def add_line(self, line: Line2D):
|
||||||
|
"""
|
||||||
|
Adds a line into the solversystem and returns the handle.
|
||||||
|
Appends the added line to the line list.
|
||||||
|
:param line:
|
||||||
|
:param point: 2D point in Point2D class format
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
|
||||||
|
line.id = uuid.uuid1()
|
||||||
|
|
||||||
|
line.handle = self.add_line_2d(line.crd1.handle, line.crd2.handle, self.wp)
|
||||||
|
line.handle_nr = self.get_handle_nr(str(line.handle))
|
||||||
|
|
||||||
|
self.lines.append(line)
|
||||||
|
|
||||||
|
### HELPER AND TOOLS
|
||||||
|
def get_handle_nr(self, input_str: str) -> int:
|
||||||
|
# Define the regex pattern to extract the handle number
|
||||||
|
pattern = r"handle=(\d+)"
|
||||||
|
|
||||||
|
# Use re.search to find the handle number in the string
|
||||||
|
match = re.search(pattern, input_str)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
|
||||||
|
app = QApplication(sys.argv)
|
||||||
|
window = SketchWidget()
|
||||||
|
window.setWindowTitle("Snap Line Widget")
|
||||||
|
window.resize(800, 600)
|
||||||
|
window.show()
|
||||||
|
sys.exit(app.exec())
|
@ -1,25 +1,35 @@
|
|||||||
from python_solvespace import SolverSystem, ResultFlag
|
from python_solvespace import SolverSystem, ResultFlag
|
||||||
|
|
||||||
def solve_constraint(self):
|
def solve_constraint():
|
||||||
solv = SolverSystem()
|
solv = SolverSystem()
|
||||||
wp = solv.create_2d_base() # Workplane (Entity)
|
wp = solv.create_2d_base() # Workplane (Entity)
|
||||||
p0 = solv.add_point_2d(0, 0, wp) # Entity
|
p0 = solv.add_point_2d(0, 0, wp) # Entity
|
||||||
|
p1 = solv.add_point_2d(10, 10, wp) # Entity
|
||||||
|
p2 = solv.add_point_2d(0, 10, wp) # Entity
|
||||||
solv.dragged(p0, wp) # Make a constraint with the entity
|
solv.dragged(p0, wp) # Make a constraint with the entity
|
||||||
...
|
|
||||||
line0 = solv.add_line_2d(p0, p1, wp) # Create entity with others
|
line0 = solv.add_line_2d(p0, p1, wp) # Create entity with others
|
||||||
...
|
line1 = solv.add_line_2d(p0, p2, wp)
|
||||||
line1 = solv.add_line_2d(p0, p3, wp)
|
#solv.angle(line0, line1, 45, wp) # Constrain two entities
|
||||||
solv.angle(line0, line1, 45, wp) # Constrain two entities
|
solv.coincident(p0, p1, wp)
|
||||||
|
solv.add_constraint(100006, wp, 0, p1,p2, line0, line1)
|
||||||
|
|
||||||
line1 = solv.entity(-1) # Entity handle can be re-generated and negatively indexed
|
line1 = solv.entity(-1) # Entity handle can be re-generated and negatively indexed
|
||||||
...
|
solv.
|
||||||
if solv.solve() == ResultFlag.OKAY:
|
if solv.solve() == ResultFlag.OKAY:
|
||||||
# Get the result (unpack from the entity or parameters)
|
# Get the result (unpack from the entity or parameters)
|
||||||
# x and y are actually float type
|
# x and y are actually float type
|
||||||
dof = solv.dof()
|
dof = solv.dof()
|
||||||
x, y = solv.params(p2.params)
|
x, y = solv.params(p1.params)
|
||||||
...
|
print(dof)
|
||||||
|
print(x)
|
||||||
|
print(y)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Error!
|
# Error!
|
||||||
# Get the list of all constraints
|
# Get the list of all constraints
|
||||||
failures = solv.failures()
|
failures = solv.failures()
|
||||||
|
print(failures)
|
||||||
...
|
...
|
||||||
|
|
||||||
|
solve_constraint()
|
@ -31,6 +31,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
self.displayed_normal_actors = []
|
self.displayed_normal_actors = []
|
||||||
self.body_actors_orig = []
|
self.body_actors_orig = []
|
||||||
self.projected_mesh_actors = []
|
self.projected_mesh_actors = []
|
||||||
|
self.interactor_actors = []
|
||||||
|
|
||||||
self.flip_toggle = False
|
self.flip_toggle = False
|
||||||
|
|
||||||
@ -52,6 +53,12 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
self.renderer_projections.SetLayer(1)
|
self.renderer_projections.SetLayer(1)
|
||||||
self.renderer_indicators.SetLayer(2) # This will be on top
|
self.renderer_indicators.SetLayer(2) # This will be on top
|
||||||
|
|
||||||
|
# Preserve color and depth buffers for non-zero layers
|
||||||
|
self.renderer_projections.SetPreserveColorBuffer(True)
|
||||||
|
self.renderer_projections.SetPreserveDepthBuffer(True)
|
||||||
|
self.renderer_indicators.SetPreserveColorBuffer(True)
|
||||||
|
self.renderer_indicators.SetPreserveDepthBuffer(True)
|
||||||
|
|
||||||
# Add renderers to the render window
|
# Add renderers to the render window
|
||||||
render_window = self.vtk_widget.GetRenderWindow()
|
render_window = self.vtk_widget.GetRenderWindow()
|
||||||
render_window.SetNumberOfLayers(3)
|
render_window.SetNumberOfLayers(3)
|
||||||
@ -59,11 +66,11 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
render_window.AddRenderer(self.renderer_projections)
|
render_window.AddRenderer(self.renderer_projections)
|
||||||
render_window.AddRenderer(self.renderer_indicators)
|
render_window.AddRenderer(self.renderer_indicators)
|
||||||
|
|
||||||
# Set up shared camera
|
|
||||||
self.camera = vtk.vtkCamera()
|
self.camera = vtk.vtkCamera()
|
||||||
self.camera.SetPosition(5, 5, 1000)
|
self.camera.SetPosition(5, 5, 1000)
|
||||||
self.camera.SetFocalPoint(0, 0, 0)
|
self.camera.SetFocalPoint(0, 0, 0)
|
||||||
self.camera.SetClippingRange(0.1, 100000)
|
self.camera.SetClippingRange(1, 10000) # Adjusted clipping range
|
||||||
|
|
||||||
self.renderer.SetActiveCamera(self.camera)
|
self.renderer.SetActiveCamera(self.camera)
|
||||||
self.renderer_projections.SetActiveCamera(self.camera)
|
self.renderer_projections.SetActiveCamera(self.camera)
|
||||||
self.renderer_indicators.SetActiveCamera(self.camera)
|
self.renderer_indicators.SetActiveCamera(self.camera)
|
||||||
@ -140,13 +147,18 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
self.renderer.AddActor(actor)
|
self.renderer.AddActor(actor)
|
||||||
|
|
||||||
|
def reset_camera(self):
|
||||||
|
self.renderer.ResetCamera()
|
||||||
|
self.camera.SetClippingRange(1, 100000) # Set your desired range
|
||||||
|
self.vtk_widget.GetRenderWindow().Render()
|
||||||
|
|
||||||
def update_render(self):
|
def update_render(self):
|
||||||
self.renderer.ResetCameraClippingRange()
|
self.renderer.ResetCameraClippingRange()
|
||||||
self.renderer_projections.ResetCameraClippingRange()
|
self.renderer_projections.ResetCameraClippingRange()
|
||||||
self.renderer_indicators.ResetCameraClippingRange()
|
self.renderer_indicators.ResetCameraClippingRange()
|
||||||
|
self.camera.SetClippingRange(1, 100000)
|
||||||
self.vtk_widget.GetRenderWindow().Render()
|
self.vtk_widget.GetRenderWindow().Render()
|
||||||
|
|
||||||
|
|
||||||
def create_grid(self, size=100, spacing=10):
|
def create_grid(self, size=100, spacing=10):
|
||||||
# Create a vtkPoints object and store the points in it
|
# Create a vtkPoints object and store the points in it
|
||||||
points = vtk.vtkPoints()
|
points = vtk.vtkPoints()
|
||||||
@ -262,6 +274,7 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
# Add the actor to the scene
|
# Add the actor to the scene
|
||||||
self.renderer.AddActor(actor)
|
self.renderer.AddActor(actor)
|
||||||
|
self.interactor_actors.append(actor)
|
||||||
|
|
||||||
mapper.Update()
|
mapper.Update()
|
||||||
self.vtk_widget.GetRenderWindow().Render()
|
self.vtk_widget.GetRenderWindow().Render()
|
||||||
@ -425,8 +438,60 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
|
|
||||||
return xy_coordinates
|
return xy_coordinates
|
||||||
|
|
||||||
def compute_2d_coordinates_line(self, line_source, normal):
|
def compute_2d_coordinates_line(self, projected_mesh, normal):
|
||||||
|
# Normalize the normal vector
|
||||||
|
normal = np.array(normal)
|
||||||
|
normal = normal / np.linalg.norm(normal)
|
||||||
|
|
||||||
|
# Create a vtkTransform
|
||||||
|
transform = vtk.vtkTransform()
|
||||||
|
transform.PostMultiply() # This ensures transforms are applied in the order we specify
|
||||||
|
|
||||||
|
# Rotate so that the normal aligns with the Z-axis
|
||||||
|
rotation_axis = np.cross(normal, [0, 0, 1])
|
||||||
|
angle = np.arccos(np.dot(normal, [0, 0, 1])) * 180 / np.pi # Convert to degrees
|
||||||
|
|
||||||
|
if np.linalg.norm(rotation_axis) > 1e-6: # Check if rotation is needed
|
||||||
|
transform.RotateWXYZ(angle, rotation_axis[0], rotation_axis[1], rotation_axis[2])
|
||||||
|
|
||||||
|
# Get the transformation matrix
|
||||||
|
matrix = transform.GetMatrix()
|
||||||
|
self.local_matrix = [matrix.GetElement(i, j) for i in range(4) for j in range(4)]
|
||||||
|
|
||||||
|
# Apply the transform to the polydata
|
||||||
|
transformFilter = vtk.vtkTransformPolyDataFilter()
|
||||||
|
transformFilter.SetInputData(projected_mesh)
|
||||||
|
transformFilter.SetTransform(transform)
|
||||||
|
transformFilter.Update()
|
||||||
|
|
||||||
|
# Get the transformed points
|
||||||
|
transformed_polydata = transformFilter.GetOutput()
|
||||||
|
points = transformed_polydata.GetPoints()
|
||||||
|
lines = transformed_polydata.GetLines()
|
||||||
|
|
||||||
|
# Extract 2D coordinates
|
||||||
|
xy_coordinates = []
|
||||||
|
|
||||||
|
if points and lines:
|
||||||
|
points_data = points.GetData()
|
||||||
|
line_ids = vtk.vtkIdList()
|
||||||
|
|
||||||
|
# Loop through all the lines in the vtkCellArray
|
||||||
|
lines.InitTraversal()
|
||||||
|
while lines.GetNextCell(line_ids):
|
||||||
|
line_coordinates = []
|
||||||
|
for j in range(line_ids.GetNumberOfIds()):
|
||||||
|
point_id = line_ids.GetId(j)
|
||||||
|
point = points.GetPoint(point_id)
|
||||||
|
line_coordinates.append((point[0], point[1])) # Only take x, y
|
||||||
|
xy_coordinates.append(line_coordinates)
|
||||||
|
|
||||||
|
return xy_coordinates
|
||||||
|
|
||||||
|
|
||||||
|
def compute_2d_coordinates_line_bak(self, line_source, normal):
|
||||||
# Ensure the input is a vtkLineSource
|
# Ensure the input is a vtkLineSource
|
||||||
|
print("line", line_source)
|
||||||
if not isinstance(line_source, vtk.vtkLineSource):
|
if not isinstance(line_source, vtk.vtkLineSource):
|
||||||
raise ValueError("Input must be a vtkLineSource")
|
raise ValueError("Input must be a vtkLineSource")
|
||||||
|
|
||||||
@ -661,6 +726,11 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
for edge_line in self.picked_edge_actors:
|
for edge_line in self.picked_edge_actors:
|
||||||
self.renderer_indicators.RemoveActor(edge_line)
|
self.renderer_indicators.RemoveActor(edge_line)
|
||||||
|
|
||||||
|
def clear_actors_interactor(self):
|
||||||
|
### Clear the outline of the mesh
|
||||||
|
for interactor in self.interactor_actors:
|
||||||
|
self.renderer.RemoveActor(interactor)
|
||||||
|
|
||||||
def compute_projection(self, direction_invert: bool = False):
|
def compute_projection(self, direction_invert: bool = False):
|
||||||
|
|
||||||
# Compute the normal from the two selected edges )
|
# Compute the normal from the two selected edges )
|
||||||
@ -691,12 +761,16 @@ class VTKWidget(QtWidgets.QWidget):
|
|||||||
# Extract 2D coordinates
|
# Extract 2D coordinates
|
||||||
self.project_tosketch_points = self.compute_2d_coordinates(projected_polydata, self.selected_normal)
|
self.project_tosketch_points = self.compute_2d_coordinates(projected_polydata, self.selected_normal)
|
||||||
|
|
||||||
# Seperately rotate selected edges for drawing
|
# Green indicator mesh needs to be translated to xy point paris start end.
|
||||||
|
self.project_tosketch_lines = self.compute_2d_coordinates_line(projected_polydata, self.selected_normal)
|
||||||
|
|
||||||
|
print("result", self.project_tosketch_lines)
|
||||||
|
"""# Seperately rotate selected edges for drawing
|
||||||
self.project_tosketch_lines.clear()
|
self.project_tosketch_lines.clear()
|
||||||
for vtk_line in self.selected_vtk_line:
|
for vtk_line in self.selected_vtk_line:
|
||||||
proj_vtk_line = self.compute_2d_coordinates_line(vtk_line, self.selected_normal)
|
proj_vtk_line = self.compute_2d_coordinates_line(vtk_line, self.selected_normal)
|
||||||
self.project_tosketch_lines.append(proj_vtk_line)
|
self.project_tosketch_lines.append(proj_vtk_line)
|
||||||
print("outgoing lines", self.project_tosketch_lines)
|
print("outgoing lines", self.project_tosketch_lines)"""
|
||||||
|
|
||||||
# Create a mapper and actor for the projected data
|
# Create a mapper and actor for the projected data
|
||||||
mapper = vtk.vtkPolyDataMapper()
|
mapper = vtk.vtkPolyDataMapper()
|
||||||
|
717
main.py
717
main.py
@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
import names
|
import names
|
||||||
from PySide6.QtCore import Qt, QPoint, Signal
|
from PySide6.QtCore import Qt, QPoint, Signal, QSize
|
||||||
from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy, QInputDialog, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox, QCheckBox, QPushButton
|
from PySide6.QtWidgets import QApplication, QMainWindow, QSizePolicy, QInputDialog, QDialog, QVBoxLayout, QHBoxLayout, QLabel, QDoubleSpinBox, QCheckBox, QPushButton, QButtonGroup
|
||||||
from Gui import Ui_fluencyCAD # Import the generated GUI module
|
from Gui import Ui_fluencyCAD # Import the generated GUI module
|
||||||
from drawing_modules.vtk_widget import VTKWidget
|
from drawing_modules.vtk_widget import VTKWidget
|
||||||
from drawing_modules.vysta_widget import PyVistaWidget
|
from drawing_modules.vysta_widget import PyVistaWidget
|
||||||
from drawing_modules.draw_widget2d import SketchWidget
|
from drawing_modules.draw_widget_solve import SketchWidget
|
||||||
from sdf import *
|
from sdf import *
|
||||||
from python_solvespace import SolverSystem, ResultFlag
|
from python_solvespace import SolverSystem, ResultFlag
|
||||||
from mesh_modules import simple_mesh, vesta_mesh, interactor_mesh
|
from mesh_modules import simple_mesh, vesta_mesh, interactor_mesh
|
||||||
@ -18,11 +18,11 @@ from dataclasses import dataclass, field
|
|||||||
|
|
||||||
# main, draw_widget, gl_widget
|
# main, draw_widget, gl_widget
|
||||||
|
|
||||||
|
|
||||||
class ExtrudeDialog(QDialog):
|
class ExtrudeDialog(QDialog):
|
||||||
def __init__(self, parent=None):
|
def __init__(self, parent=None):
|
||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.setWindowTitle('Extrude Options')
|
self.setWindowTitle('Extrude Options')
|
||||||
|
|
||||||
def create_hline():
|
def create_hline():
|
||||||
line = QLabel()
|
line = QLabel()
|
||||||
line.setStyleSheet("border-top: 1px solid #cccccc;") # Light grey line
|
line.setStyleSheet("border-top: 1px solid #cccccc;") # Light grey line
|
||||||
@ -48,7 +48,6 @@ class ExtrudeDialog(QDialog):
|
|||||||
self.rounded_checkbox = QCheckBox('Round Edges')
|
self.rounded_checkbox = QCheckBox('Round Edges')
|
||||||
self.seperator = create_hline()
|
self.seperator = create_hline()
|
||||||
|
|
||||||
|
|
||||||
# OK and Cancel buttons
|
# OK and Cancel buttons
|
||||||
button_layout = QHBoxLayout()
|
button_layout = QHBoxLayout()
|
||||||
ok_button = QPushButton('OK')
|
ok_button = QPushButton('OK')
|
||||||
@ -76,6 +75,7 @@ class ExtrudeDialog(QDialog):
|
|||||||
def get_values(self):
|
def get_values(self):
|
||||||
return self.length_input.value(), self.symmetric_checkbox.isChecked() ,self.invert_checkbox.isChecked(), self.cut_checkbox.isChecked(), self.union_checkbox.isChecked(), self.rounded_checkbox.isChecked()
|
return self.length_input.value(), self.symmetric_checkbox.isChecked() ,self.invert_checkbox.isChecked(), self.cut_checkbox.isChecked(), self.union_checkbox.isChecked(), self.rounded_checkbox.isChecked()
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
send_command = Signal(str)
|
send_command = Signal(str)
|
||||||
|
|
||||||
@ -98,11 +98,11 @@ class MainWindow(QMainWindow):
|
|||||||
size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
|
size_policy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)
|
||||||
self.sketchWidget.setSizePolicy(size_policy)
|
self.sketchWidget.setSizePolicy(size_policy)
|
||||||
|
|
||||||
### Main Model
|
### Main Model -OLD ?
|
||||||
self.model = {
|
"""self.model = {
|
||||||
'sketch': {},
|
'sketches': {},
|
||||||
'operation': {},
|
'operation': {},
|
||||||
}
|
}"""
|
||||||
self.list_selected = []
|
self.list_selected = []
|
||||||
|
|
||||||
#self.ui.pb_apply_code.pressed.connect(self.check_current_tab)
|
#self.ui.pb_apply_code.pressed.connect(self.check_current_tab)
|
||||||
@ -113,7 +113,7 @@ class MainWindow(QMainWindow):
|
|||||||
self.ui.pb_origin_wp.pressed.connect(self.add_new_sketch_origin)
|
self.ui.pb_origin_wp.pressed.connect(self.add_new_sketch_origin)
|
||||||
self.ui.pb_origin_face.pressed.connect(self.add_new_sketch_wp)
|
self.ui.pb_origin_face.pressed.connect(self.add_new_sketch_wp)
|
||||||
|
|
||||||
self.ui.pb_nw_sktch.pressed.connect(self.add_sketch)
|
self.ui.pb_nw_sktch.pressed.connect(self.add_sketch_to_compo)
|
||||||
self.ui.pb_del_sketch.pressed.connect(self.del_sketch)
|
self.ui.pb_del_sketch.pressed.connect(self.del_sketch)
|
||||||
self.ui.pb_edt_sktch.pressed.connect(self.edit_sketch)
|
self.ui.pb_edt_sktch.pressed.connect(self.edit_sketch)
|
||||||
|
|
||||||
@ -138,33 +138,220 @@ class MainWindow(QMainWindow):
|
|||||||
|
|
||||||
self.send_command.connect(self.custom_3D_Widget.on_receive_command)
|
self.send_command.connect(self.custom_3D_Widget.on_receive_command)
|
||||||
|
|
||||||
def on_flip_face(self):
|
self.ui.actionNew_Project.triggered.connect(self.new_project)
|
||||||
self.send_command.emit("flip")
|
|
||||||
|
self.project = Project()
|
||||||
|
self.new_project()
|
||||||
|
|
||||||
|
### COMPOS
|
||||||
|
### COMPOS
|
||||||
|
|
||||||
|
self.ui.new_compo.pressed.connect(self.new_component)
|
||||||
|
|
||||||
|
"""Project -> (Timeline) -> Component -> Sketch -> Body / Interactor -> Connector -> Assembly -> PB Render"""
|
||||||
|
|
||||||
|
def new_project(self):
|
||||||
|
print("New project")
|
||||||
|
timeline = []
|
||||||
|
self.project.timeline = timeline
|
||||||
|
self.new_component()
|
||||||
|
|
||||||
|
|
||||||
|
def new_component(self):
|
||||||
|
print("Creating a new component...")
|
||||||
|
|
||||||
|
# Lazily initialize self.compo_layout if it doesn't exist
|
||||||
|
if not hasattr(self, 'compo_layout'):
|
||||||
|
print("Initializing compo_layout...")
|
||||||
|
self.compo_layout = QHBoxLayout()
|
||||||
|
|
||||||
|
# Create a button group
|
||||||
|
self.compo_group = QButtonGroup(self)
|
||||||
|
self.compo_group.setExclusive(True) # Ensure exclusivity
|
||||||
|
|
||||||
|
# Ensure the QGroupBox has a layout
|
||||||
|
if not self.ui.compo_box.layout():
|
||||||
|
self.ui.compo_box.setLayout(QVBoxLayout()) # Set a default layout for QGroupBox
|
||||||
|
|
||||||
|
# Add the horizontal layout to the QGroupBox's layout
|
||||||
|
self.ui.compo_box.layout().addLayout(self.compo_layout)
|
||||||
|
|
||||||
|
# Align the layout to the left
|
||||||
|
self.compo_layout.setAlignment(Qt.AlignLeft)
|
||||||
|
|
||||||
|
# Create and initialize a new Component
|
||||||
|
compo = Component()
|
||||||
|
compo.id = f"Component {len(self.project.timeline)}"
|
||||||
|
compo.descript = "Initial Component"
|
||||||
|
compo.sketches = {}
|
||||||
|
compo.bodies = {}
|
||||||
|
self.project.timeline.append(compo)
|
||||||
|
|
||||||
|
# Create a button for the new component
|
||||||
|
button = QPushButton()
|
||||||
|
button.setToolTip(compo.id)
|
||||||
|
button.setText(str(len(self.project.timeline)))
|
||||||
|
button.setFixedSize(QSize(40, 40)) # Set button size
|
||||||
|
button.setCheckable(True)
|
||||||
|
#button.setAutoExclusive(True)
|
||||||
|
button.released.connect(self.on_compo_change)
|
||||||
|
button.setChecked(True)
|
||||||
|
|
||||||
|
# Add button to the group
|
||||||
|
self.compo_group.addButton(button)
|
||||||
|
|
||||||
|
# Add the button to the layout
|
||||||
|
self.compo_layout.addWidget(button)
|
||||||
|
|
||||||
|
# We automatically switch to the new compo hence, refresh
|
||||||
|
self.on_compo_change()
|
||||||
|
|
||||||
|
print(f"Added component {compo.id} to the layout.")
|
||||||
|
|
||||||
|
def get_activated_compo(self):
|
||||||
|
# Iterate through all items in the layout
|
||||||
|
total_elements = self.compo_layout.count()
|
||||||
|
#print(total_elements)
|
||||||
|
for i in range(total_elements):
|
||||||
|
widget = self.compo_layout.itemAt(i).widget() # Get the widget at the index
|
||||||
|
if widget: # Check if the widget is not None
|
||||||
|
if isinstance(widget, QPushButton) and widget.isCheckable():
|
||||||
|
state = widget.isChecked() # Get the checked state
|
||||||
|
print(f"{widget.text()} is {'checked' if state else 'unchecked'}.")
|
||||||
|
if state:
|
||||||
|
return i
|
||||||
|
|
||||||
def add_new_sketch_origin(self):
|
def add_new_sketch_origin(self):
|
||||||
self.sketchWidget.clear_sketch()
|
name = f"sketches-{str(names.get_first_name())}"
|
||||||
self.sketchWidget.create_workplane()
|
sketch = Sketch()
|
||||||
|
sketch.id = name
|
||||||
|
sketch.origin = [0,0,0]
|
||||||
|
|
||||||
|
self.sketchWidget.reset_buffers()
|
||||||
|
self.sketchWidget.create_sketch(sketch)
|
||||||
|
|
||||||
def add_new_sketch_wp(self):
|
def add_new_sketch_wp(self):
|
||||||
self.sketchWidget.clear_sketch()
|
## Sketch projected from 3d view into 2d
|
||||||
#edges = [((-158.0, -20.0, -25.0), (286.0, -195.0, -25.0)), ((-158.0, -20.0, 25.0), (-158.0, -20.0, -25.0))]
|
name = f"sketches-{str(names.get_first_name())}"
|
||||||
points = self.custom_3D_Widget.project_tosketch_points
|
sketch = Sketch()
|
||||||
normal = self.custom_3D_Widget.selected_normal
|
sketch.id = name
|
||||||
selected_lines = self.custom_3D_Widget.project_tosketch_lines
|
sketch.origin = self.custom_3D_Widget.centroid
|
||||||
print("Selected lines", selected_lines)
|
sketch.normal = self.custom_3D_Widget.selected_normal
|
||||||
|
sketch.slv_points = []
|
||||||
|
sketch.slv_lines = []
|
||||||
|
sketch.proj_points = self.custom_3D_Widget.project_tosketch_points
|
||||||
|
sketch.proj_lines = self.custom_3D_Widget.project_tosketch_lines
|
||||||
|
|
||||||
|
self.sketchWidget.reset_buffers()
|
||||||
|
self.sketchWidget.create_sketch(sketch)
|
||||||
self.sketchWidget.create_workplane_projected()
|
self.sketchWidget.create_workplane_projected()
|
||||||
self.sketchWidget.create_proj_points(points)
|
|
||||||
self.sketchWidget.create_proj_lines(selected_lines)
|
if not sketch.proj_lines:
|
||||||
|
self.sketchWidget.convert_proj_points(sketch.proj_points)
|
||||||
|
|
||||||
|
self.sketchWidget.convert_proj_lines(sketch.proj_lines)
|
||||||
|
self.sketchWidget.update()
|
||||||
|
|
||||||
# CLear all selections after it has been projected
|
# CLear all selections after it has been projected
|
||||||
self.custom_3D_Widget.project_tosketch_points.clear()
|
self.custom_3D_Widget.project_tosketch_points.clear()
|
||||||
self.custom_3D_Widget.project_tosketch_lines.clear()
|
self.custom_3D_Widget.project_tosketch_lines.clear()
|
||||||
self.custom_3D_Widget.clear_actors_projection()
|
self.custom_3D_Widget.clear_actors_projection()
|
||||||
self.custom_3D_Widget.clear_actors_normals()
|
self.custom_3D_Widget.clear_actors_normals()
|
||||||
#self.custom_3D_Widget.clear_actors_projection()
|
|
||||||
|
|
||||||
#self.sketchWidget.create_workplane_space(edges, normal)
|
def add_sketch_to_compo(self):
|
||||||
|
"""
|
||||||
|
Add sketch to component
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
sketch = Sketch()
|
||||||
|
sketch_from_widget = self.sketchWidget.get_sketch()
|
||||||
|
|
||||||
|
#Save original for editing later
|
||||||
|
sketch.original_sketch = sketch_from_widget
|
||||||
|
|
||||||
|
#Get parameters
|
||||||
|
points = sketch_from_widget.points
|
||||||
|
|
||||||
|
sketch.convert_points_for_sdf(points)
|
||||||
|
sketch.id = sketch_from_widget.id
|
||||||
|
|
||||||
|
sketch.filter_lines_for_interactor(sketch_from_widget.lines)
|
||||||
|
|
||||||
|
# Register sketch to timeline
|
||||||
|
### Add selection compo here
|
||||||
|
compo_id = self.get_activated_compo()
|
||||||
|
print("newsketch_name", sketch.id)
|
||||||
|
self.project.timeline[compo_id].sketches[sketch.id] = sketch
|
||||||
|
|
||||||
|
# Add Item to slection menu
|
||||||
|
self.ui.sketch_list.addItem(sketch.id)
|
||||||
|
|
||||||
|
# Deactivate drawing
|
||||||
|
self.ui.pb_linetool.setChecked(False)
|
||||||
|
self.sketchWidget.line_mode = False
|
||||||
|
|
||||||
|
items = self.ui.sketch_list.findItems(sketch.id, Qt.MatchExactly)[0]
|
||||||
|
self.ui.sketch_list.setCurrentItem(items)
|
||||||
|
|
||||||
|
def on_compo_change(self):
|
||||||
|
self.custom_3D_Widget.clear_body_actors()
|
||||||
|
self.custom_3D_Widget.clear_actors_interactor()
|
||||||
|
self.custom_3D_Widget.clear_actors_projection()
|
||||||
|
|
||||||
|
compo_id = self.get_activated_compo()
|
||||||
|
if compo_id is not None:
|
||||||
|
self.ui.sketch_list.clear()
|
||||||
|
self.ui.body_list.clear()
|
||||||
|
|
||||||
|
print("id", compo_id)
|
||||||
|
print("sketch_registry", self.project.timeline[compo_id].sketches)
|
||||||
|
|
||||||
|
for sketch in self.project.timeline[compo_id].sketches:
|
||||||
|
print(sketch)
|
||||||
|
self.ui.sketch_list.addItem(sketch)
|
||||||
|
|
||||||
|
for body in self.project.timeline[compo_id].bodies:
|
||||||
|
self.ui.body_list.addItem(body)
|
||||||
|
|
||||||
|
if self.project.timeline[compo_id].bodies:
|
||||||
|
item = self.ui.body_list.findItems(body , Qt.MatchExactly)[0]
|
||||||
|
self.ui.body_list.setCurrentItem(item)
|
||||||
|
self.draw_mesh()
|
||||||
|
|
||||||
|
selected = self.ui.body_list.currentItem()
|
||||||
|
name = selected.text()
|
||||||
|
|
||||||
|
edges = self.project.timeline[compo_id].bodies[name].interactor.edges
|
||||||
|
offset_vec = self.project.timeline[compo_id].bodies[name].interactor.offset_vector
|
||||||
|
self.custom_3D_Widget.load_interactor_mesh(edges, offset_vec)
|
||||||
|
|
||||||
|
def edit_sketch(self):
|
||||||
|
selected = self.ui.sketch_list.currentItem()
|
||||||
|
name = selected.text()
|
||||||
|
sel_compo = self.project.timeline[self.get_activated_compo()]
|
||||||
|
sketch = sel_compo.sketches[name].original_sketch
|
||||||
|
|
||||||
|
self.sketchWidget.set_sketch(sketch)
|
||||||
|
|
||||||
|
self.sketchWidget.update()
|
||||||
|
|
||||||
|
def del_sketch(self):
|
||||||
|
selected = self.ui.sketch_list.currentItem()
|
||||||
|
name = selected.text()
|
||||||
|
sel_compo = self.project.timeline[self.get_activated_compo()]
|
||||||
|
sketch = sel_compo.sketches[name]
|
||||||
|
|
||||||
|
if sketch is not None:
|
||||||
|
sel_compo.sketches.pop(name)
|
||||||
|
row = self.ui.sketch_list.row(selected) # Get the row of the current item
|
||||||
|
self.ui.sketch_list.takeItem(row) # Remove the item from the list widget
|
||||||
|
self.sketchWidget.sketch = None
|
||||||
|
print(sketch)
|
||||||
|
else:
|
||||||
|
print("No item selected.")
|
||||||
|
|
||||||
|
def on_flip_face(self):
|
||||||
|
self.send_command.emit("flip")
|
||||||
|
|
||||||
def act_line_mode(self):
|
def act_line_mode(self):
|
||||||
if not self.ui.pb_linetool.isChecked():
|
if not self.ui.pb_linetool.isChecked():
|
||||||
@ -222,9 +409,12 @@ class MainWindow(QMainWindow):
|
|||||||
self.sketchWidget.reset_buffers()
|
self.sketchWidget.reset_buffers()
|
||||||
|
|
||||||
def draw_mesh(self):
|
def draw_mesh(self):
|
||||||
|
|
||||||
name = self.ui.body_list.currentItem().text()
|
name = self.ui.body_list.currentItem().text()
|
||||||
print("selected_for disp", name)
|
print("selected_for disp", name)
|
||||||
model = self.model['operation'][name]['sdf_object']
|
|
||||||
|
compo_id = self.get_activated_compo()
|
||||||
|
model = self.project.timeline[compo_id].bodies[name].sdf_body
|
||||||
|
|
||||||
vesta = vesta_mesh
|
vesta = vesta_mesh
|
||||||
model_data = vesta.generate_mesh_from_sdf(model, resolution=64, threshold=0)
|
model_data = vesta.generate_mesh_from_sdf(model, resolution=64, threshold=0)
|
||||||
@ -239,96 +429,6 @@ class MainWindow(QMainWindow):
|
|||||||
#self.view_update()
|
#self.view_update()
|
||||||
print(f"Selected item: {name}")
|
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 convert_lines_for_interactor(self):
|
|
||||||
points_for_interact = []
|
|
||||||
for point_to_poly in self.sketchWidget.slv_lines_main:
|
|
||||||
start, end = point_to_poly['ui_points']
|
|
||||||
from_coord_start = self.sketchWidget.from_quadrant_coords_no_center(start)
|
|
||||||
from_coord_end = self.sketchWidget.from_quadrant_coords_no_center(end)
|
|
||||||
start_draw = self.translate_points_tup(from_coord_start)
|
|
||||||
end_draw = self.translate_points_tup(from_coord_end)
|
|
||||||
line = start_draw, end_draw
|
|
||||||
points_for_interact.append(line)
|
|
||||||
|
|
||||||
print("packed_lines", points_for_interact)
|
|
||||||
|
|
||||||
return points_for_interact
|
|
||||||
|
|
||||||
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):
|
def update_body(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -349,55 +449,20 @@ class MainWindow(QMainWindow):
|
|||||||
print(f"Removed operation: {item_name}")
|
print(f"Removed operation: {item_name}")
|
||||||
self.custom_3D_Widget.clear_mesh()
|
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 rotate_point_to_normal(self, centroid, normal):
|
|
||||||
# Ensure the normal is a unit vector
|
|
||||||
normal = normal / np.linalg.norm(normal)
|
|
||||||
|
|
||||||
# Initial direction (assuming positive Z-axis)
|
|
||||||
initial_direction = np.array([0, 0, 1])
|
|
||||||
|
|
||||||
# Compute rotation axis
|
|
||||||
rotation_axis = np.cross(initial_direction, normal)
|
|
||||||
|
|
||||||
# If rotation axis is zero (vectors are parallel), no rotation is needed
|
|
||||||
if np.allclose(rotation_axis, 0):
|
|
||||||
return centroid
|
|
||||||
|
|
||||||
# Compute rotation angle
|
|
||||||
rotation_angle = np.arccos(np.dot(initial_direction, normal))
|
|
||||||
|
|
||||||
# Create rotation matrix using Rodrigues' formula
|
|
||||||
K = np.array([
|
|
||||||
[0, -rotation_axis[2], rotation_axis[1]],
|
|
||||||
[rotation_axis[2], 0, -rotation_axis[0]],
|
|
||||||
[-rotation_axis[1], rotation_axis[0], 0]
|
|
||||||
])
|
|
||||||
rotation_matrix = (
|
|
||||||
np.eye(3) +
|
|
||||||
np.sin(rotation_angle) * K +
|
|
||||||
(1 - np.cos(rotation_angle)) * np.dot(K, K)
|
|
||||||
)
|
|
||||||
|
|
||||||
# Apply rotation to centroid
|
|
||||||
rotated_centroid = np.dot(rotation_matrix, centroid)
|
|
||||||
|
|
||||||
return rotated_centroid
|
|
||||||
|
|
||||||
def send_extrude(self):
|
def send_extrude(self):
|
||||||
|
# Dialog input
|
||||||
is_symmetric = None
|
is_symmetric = None
|
||||||
length = None
|
length = None
|
||||||
invert = None
|
invert = None
|
||||||
|
|
||||||
selected = self.ui.sketch_list.currentItem()
|
selected = self.ui.sketch_list.currentItem()
|
||||||
name = selected.text()
|
name = selected.text()
|
||||||
points = self.model['sketch'][name]['sketch_points']
|
|
||||||
|
sel_compo = self.project.timeline[self.get_activated_compo()]
|
||||||
|
#print(sel_compo)
|
||||||
|
sketch = sel_compo.sketches[name]
|
||||||
|
#print(sketch)
|
||||||
|
points = sketch.sdf_points
|
||||||
|
|
||||||
if points[-1] == points[0]:
|
if points[-1] == points[0]:
|
||||||
#detect loop that causes problems in mesh generation
|
#detect loop that causes problems in mesh generation
|
||||||
@ -406,12 +471,10 @@ class MainWindow(QMainWindow):
|
|||||||
dialog = ExtrudeDialog(self)
|
dialog = ExtrudeDialog(self)
|
||||||
if dialog.exec():
|
if dialog.exec():
|
||||||
length, is_symmetric, invert, cut, union_with, rounded = dialog.get_values()
|
length, is_symmetric, invert, cut, union_with, rounded = dialog.get_values()
|
||||||
print(f"Extrude length: {length}, Symmetric: {is_symmetric} Invert: {invert}")
|
#print(f"Extrude length: {length}, Symmetric: {is_symmetric} Invert: {invert}")
|
||||||
else:
|
else:
|
||||||
length = 0
|
length = 0
|
||||||
print("Extrude cancelled")
|
#print("Extrude cancelled")
|
||||||
|
|
||||||
geo = Geometry()
|
|
||||||
|
|
||||||
normal = self.custom_3D_Widget.selected_normal
|
normal = self.custom_3D_Widget.selected_normal
|
||||||
#print("Normie enter", normal)
|
#print("Normie enter", normal)
|
||||||
@ -425,31 +488,42 @@ class MainWindow(QMainWindow):
|
|||||||
centroid = list(centroid)
|
centroid = list(centroid)
|
||||||
#print("This centroid ", centroid)
|
#print("This centroid ", centroid)
|
||||||
|
|
||||||
f = geo.extrude_shape(points, length, normal, centroid, is_symmetric, invert, 0)
|
sketch.origin = centroid
|
||||||
|
sketch.normal = normal
|
||||||
|
|
||||||
|
f = sketch.extrude(length, is_symmetric, invert, 0)
|
||||||
|
|
||||||
|
# Create body element and assign known stuff
|
||||||
name_op = f"extrd-{name}"
|
name_op = f"extrd-{name}"
|
||||||
element = {
|
|
||||||
'id': name_op,
|
body = Body()
|
||||||
'type': 'extrude',
|
body.sketch = sketch #we add the sketches for reference here
|
||||||
'sdf_object': f,
|
body.id = name_op
|
||||||
}
|
body.sdf_body = f
|
||||||
|
|
||||||
### Interactor
|
### Interactor
|
||||||
lines = self.convert_lines_for_interactor()
|
interactor = Interactor()
|
||||||
|
interactor.add_lines_for_interactor(sketch.interactor_lines)
|
||||||
|
interactor.invert = invert
|
||||||
|
|
||||||
if not invert:
|
if not invert:
|
||||||
edges = interactor_mesh.generate_mesh(lines, 0, length)
|
edges = interactor_mesh.generate_mesh(interactor.lines, 0, length)
|
||||||
else:
|
else:
|
||||||
edges = interactor_mesh.generate_mesh(lines, 0, -length)
|
edges = interactor_mesh.generate_mesh(interactor.lines, 0, -length)
|
||||||
|
|
||||||
offset_vector = geo.vector_to_centroid(None, centroid, normal)
|
sel_compo.bodies[name_op] = body
|
||||||
|
|
||||||
|
offset_vector = interactor.vector_to_centroid(None, centroid, normal)
|
||||||
#print("off_ved", offset_vector)
|
#print("off_ved", offset_vector)
|
||||||
if len(offset_vector) == 0 :
|
if len(offset_vector) == 0 :
|
||||||
offset_vector = [0, 0, 0]
|
offset_vector = [0, 0, 0]
|
||||||
|
|
||||||
|
interactor.edges = edges
|
||||||
|
interactor.offset_vector = offset_vector
|
||||||
|
body.interactor = interactor
|
||||||
|
|
||||||
self.custom_3D_Widget.load_interactor_mesh(edges, offset_vector)
|
self.custom_3D_Widget.load_interactor_mesh(edges, offset_vector)
|
||||||
|
|
||||||
self.model['operation'][name_op] = element
|
|
||||||
self.ui.body_list.addItem(name_op)
|
self.ui.body_list.addItem(name_op)
|
||||||
items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)[0]
|
items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)[0]
|
||||||
self.ui.body_list.setCurrentItem(items)
|
self.ui.body_list.setCurrentItem(items)
|
||||||
@ -457,13 +531,23 @@ class MainWindow(QMainWindow):
|
|||||||
self.draw_mesh()
|
self.draw_mesh()
|
||||||
|
|
||||||
def send_cut(self):
|
def send_cut(self):
|
||||||
name = self.ui.body_list.currentItem().text()
|
"""name = self.ui.body_list.currentItem().text()
|
||||||
points = self.model['operation'][name]['sdf_object']
|
points = self.model['operation'][name]['sdf_object']
|
||||||
self.list_selected.append(points)
|
sel_compo = self.project.timeline[self.get_activated_compo()]
|
||||||
|
points = sel_compo.bodies[].
|
||||||
|
self.list_selected.append(points)"""
|
||||||
|
|
||||||
|
selected = self.ui.body_list.currentItem()
|
||||||
|
name = selected.text()
|
||||||
|
|
||||||
|
sel_compo = self.project.timeline[self.get_activated_compo()]
|
||||||
|
# print(sel_compo)
|
||||||
|
body = sel_compo.bodies[name]
|
||||||
|
# print(sketch)
|
||||||
|
self.list_selected.append(body.sdf_body)
|
||||||
|
|
||||||
if len(self.list_selected) == 2:
|
if len(self.list_selected) == 2:
|
||||||
geo = Geometry()
|
f = difference(self.list_selected[0], self.list_selected[1]) # equivalent
|
||||||
f = geo.cut_shapes(self.list_selected[0], self.list_selected[1] )
|
|
||||||
|
|
||||||
element = {
|
element = {
|
||||||
'id': name,
|
'id': name,
|
||||||
@ -471,13 +555,22 @@ class MainWindow(QMainWindow):
|
|||||||
'sdf_object': f,
|
'sdf_object': f,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Create body element and assign known stuff
|
||||||
name_op = f"cut-{name}"
|
name_op = f"cut-{name}"
|
||||||
self.model['operation'][name_op] = element
|
|
||||||
|
body = Body()
|
||||||
|
body.id = name_op
|
||||||
|
body.sdf_body = f
|
||||||
|
|
||||||
|
## Add to component
|
||||||
|
sel_compo.bodies[name_op] = body
|
||||||
|
|
||||||
self.ui.body_list.addItem(name_op)
|
self.ui.body_list.addItem(name_op)
|
||||||
items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)
|
items = self.ui.body_list.findItems(name_op, Qt.MatchExactly)
|
||||||
self.ui.body_list.setCurrentItem(items[-1])
|
self.ui.body_list.setCurrentItem(items[-1])
|
||||||
self.custom_3D_Widget.clear_body_actors()
|
self.custom_3D_Widget.clear_body_actors()
|
||||||
self.draw_mesh()
|
self.draw_mesh()
|
||||||
|
|
||||||
elif len(self.list_selected) > 2:
|
elif len(self.list_selected) > 2:
|
||||||
self.list_selected.clear()
|
self.list_selected.clear()
|
||||||
else:
|
else:
|
||||||
@ -487,8 +580,122 @@ class MainWindow(QMainWindow):
|
|||||||
self.custom_3D_Widget.load_stl(file)
|
self.custom_3D_Widget.load_stl(file)
|
||||||
self.custom_3D_Widget.update()
|
self.custom_3D_Widget.update()
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Timeline:
|
||||||
|
"""Timeline """
|
||||||
|
### Collection of the Components
|
||||||
|
timeline: list = None
|
||||||
|
|
||||||
|
"""add to time,
|
||||||
|
remove from time, """
|
||||||
|
|
||||||
|
class Assembly:
|
||||||
|
"""Connecting Components in 3D space based on slvs solver"""
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Component:
|
||||||
|
"""The base container combining all related elements
|
||||||
|
id : The unique ID
|
||||||
|
sketches : the base sketches, bodys can contain additonal sketches for features
|
||||||
|
interactor : A smiplified model used as interactor
|
||||||
|
body : The body class that contains the actual 3d information
|
||||||
|
connector : Vector and Nomral information for assembly
|
||||||
|
descript : a basic description
|
||||||
|
materil : Speicfy a material for pbr rendering
|
||||||
|
"""
|
||||||
|
id = None
|
||||||
|
sketches: dict = None
|
||||||
|
bodies: dict = None
|
||||||
|
connector = None
|
||||||
|
|
||||||
|
# Description
|
||||||
|
descript = None
|
||||||
|
|
||||||
|
# PBR
|
||||||
|
material = None
|
||||||
|
|
||||||
|
|
||||||
|
class Connector:
|
||||||
|
"""An Element that contains vectors and or normals as connection points.
|
||||||
|
These connection points can exist independently of bodies and other elements"""
|
||||||
|
id = None
|
||||||
|
vector = None
|
||||||
|
normal = None
|
||||||
|
|
||||||
|
|
||||||
|
class Code:
|
||||||
|
"""A class that holds all information from the code based approach"""
|
||||||
|
command_list = None
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Sketch:
|
||||||
|
"""All of the 2D Information of a sketches"""
|
||||||
|
|
||||||
|
# Save the incomng sketch from the 2D widget for late redit
|
||||||
|
original_sketch = None
|
||||||
|
|
||||||
|
id = None
|
||||||
|
|
||||||
|
# Space Information
|
||||||
|
origin = None
|
||||||
|
slv_plane = None
|
||||||
|
normal = None
|
||||||
|
|
||||||
|
# Points in UI form the sketches widget
|
||||||
|
ui_points: list = None
|
||||||
|
ui_lines: list = None
|
||||||
|
|
||||||
|
# Points cartesian coming as result of the solver
|
||||||
|
slv_points: list = None
|
||||||
|
slv_lines: list = None
|
||||||
|
|
||||||
|
sdf_points: list = None
|
||||||
|
|
||||||
|
interactor_lines: list = None
|
||||||
|
|
||||||
|
# Points coming back from the 3D-Widget as projection to draw on
|
||||||
|
proj_points: list = None
|
||||||
|
proj_lines: list = None
|
||||||
|
|
||||||
|
# Workingplane
|
||||||
|
working_plane = None
|
||||||
|
|
||||||
|
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 vector_to_centroid(self, shape_center, centroid, normal):
|
||||||
|
|
||||||
|
if not shape_center:
|
||||||
|
# Calculate the current center of the shape
|
||||||
|
shape_center = [0, 0, 0]
|
||||||
|
|
||||||
|
# Calculate the vector from the shape's center to the centroid
|
||||||
|
center_to_centroid = np.array(centroid) - np.array(shape_center)
|
||||||
|
|
||||||
|
# Project this vector onto the normal to get the required translation along the normal
|
||||||
|
translation_along_normal = np.dot(center_to_centroid, normal) * normal
|
||||||
|
|
||||||
|
return translation_along_normal
|
||||||
|
|
||||||
class Geometry:
|
|
||||||
def angle_between_normals(self, normal1, normal2):
|
def angle_between_normals(self, normal1, normal2):
|
||||||
# Ensure the vectors are normalized
|
# Ensure the vectors are normalized
|
||||||
n1 = normal1 / np.linalg.norm(normal1)
|
n1 = normal1 / np.linalg.norm(normal1)
|
||||||
@ -519,44 +726,48 @@ 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 vector_to_centroid(self, shape_center, centroid, normal):
|
def convert_points_for_sdf(self, points):
|
||||||
|
points_for_sdf = []
|
||||||
|
for point in points:
|
||||||
|
if point.is_helper is False:
|
||||||
|
print("point", point)
|
||||||
|
points_for_sdf.append(self.translate_points_tup(point.ui_point))
|
||||||
|
|
||||||
if not shape_center:
|
self.sdf_points = points_for_sdf
|
||||||
# Calculate the current center of the shape
|
|
||||||
shape_center = [0, 0, 0]
|
|
||||||
|
|
||||||
# Calculate the vector from the shape's center to the centroid
|
def filter_lines_for_interactor(self, lines):
|
||||||
center_to_centroid = np.array(centroid) - np.array(shape_center)
|
### Filter lines that are not meant to be drawn for the interactor like contruction lines
|
||||||
|
filtered_lines = []
|
||||||
|
for line in lines:
|
||||||
|
if not line.is_helper:
|
||||||
|
filtered_lines.append(line)
|
||||||
|
|
||||||
# Project this vector onto the normal to get the required translation along the normal
|
self.interactor_lines = filtered_lines
|
||||||
translation_along_normal = np.dot(center_to_centroid, normal) * normal
|
|
||||||
|
|
||||||
return translation_along_normal
|
def extrude(self, height: float, symet: bool = True, invert: bool = False, offset_length: float = None):
|
||||||
|
|
||||||
def extrude_shape(self, points, length: float, normal, centroid, symet: bool = True, invert: bool = False,
|
|
||||||
offset_length: float = None):
|
|
||||||
"""
|
"""
|
||||||
Extrude a 2D shape into 3D, orient it along the normal, and position it relative to the centroid.
|
Extrude a 2D shape into 3D, orient it along the normal, and position it relative to the centroid.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Normalize the normal vector
|
# Normalize the normal vector
|
||||||
normal = np.array(normal)
|
normal = np.array(self.normal)
|
||||||
normal = normal / np.linalg.norm(normal)
|
normal = normal / np.linalg.norm(self.normal)
|
||||||
|
|
||||||
# Create the 2D shape
|
# Create the 2D shape
|
||||||
f = polygon(points)
|
f = polygon(self.sdf_points)
|
||||||
|
|
||||||
# Extrude the shape along the Z-axis
|
# Extrude the shape along the Z-axis
|
||||||
f = f.extrude(length)
|
f = f.extrude(height)
|
||||||
|
|
||||||
# Center the shape along its extrusion axis
|
# Center the shape along its extrusion axis
|
||||||
f = f.translate((0, 0, length / 2))
|
f = f.translate((0, 0, height / 2))
|
||||||
|
|
||||||
# Orient the shape along the normal vector
|
# Orient the shape along the normal vector
|
||||||
f = f.orient(normal)
|
f = f.orient(normal)
|
||||||
|
|
||||||
offset_vector = self.vector_to_centroid(None, centroid, normal)
|
offset_vector = self.vector_to_centroid(None, self.origin, normal)
|
||||||
# Adjust the offset vector by subtracting the inset distance along the normal direction
|
# Adjust the offset vector by subtracting the inset distance along the normal direction
|
||||||
adjusted_offset = offset_vector - (normal * length)
|
adjusted_offset = offset_vector - (normal * height)
|
||||||
if invert:
|
if invert:
|
||||||
# Translate the shape along the adjusted offset vector
|
# Translate the shape along the adjusted offset vector
|
||||||
f = f.translate(adjusted_offset)
|
f = f.translate(adjusted_offset)
|
||||||
@ -580,15 +791,69 @@ class Geometry:
|
|||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Interactor:
|
||||||
|
"""Helper mesh consisting of edges for selection"""
|
||||||
|
lines = None
|
||||||
|
faces = None
|
||||||
|
body = None
|
||||||
|
offset_vector = None
|
||||||
|
edges = None
|
||||||
|
|
||||||
|
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 vector_to_centroid(self, shape_center, centroid, normal):
|
||||||
|
|
||||||
|
if not shape_center:
|
||||||
|
# Calculate the current center of the shape
|
||||||
|
shape_center = [0, 0, 0]
|
||||||
|
|
||||||
|
# Calculate the vector from the shape's center to the centroid
|
||||||
|
center_to_centroid = np.array(centroid) - np.array(shape_center)
|
||||||
|
|
||||||
|
# Project this vector onto the normal to get the required translation along the normal
|
||||||
|
translation_along_normal = np.dot(center_to_centroid, normal) * normal
|
||||||
|
|
||||||
|
return translation_along_normal
|
||||||
|
|
||||||
|
def add_lines_for_interactor(self, input_lines: list):
|
||||||
|
"""Takes Line2D objects from the sketch widget and preparesit for interactor mesh.
|
||||||
|
Translates coordinates."""
|
||||||
|
|
||||||
|
points_for_interact = []
|
||||||
|
for point_to_poly in input_lines:
|
||||||
|
from_coord_start = window.sketchWidget.from_quadrant_coords_no_center(point_to_poly.crd1.ui_point)
|
||||||
|
from_coord_end = window.sketchWidget.from_quadrant_coords_no_center(point_to_poly.crd2.ui_point)
|
||||||
|
start_draw = self.translate_points_tup(from_coord_start)
|
||||||
|
end_draw = self.translate_points_tup(from_coord_end)
|
||||||
|
line = start_draw, end_draw
|
||||||
|
points_for_interact.append(line)
|
||||||
|
|
||||||
|
print("packed_lines", points_for_interact)
|
||||||
|
|
||||||
|
self.lines = points_for_interact
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Body:
|
||||||
|
"""The actual body as sdf3 object"""
|
||||||
|
id = None
|
||||||
|
sketch = None
|
||||||
|
height = None
|
||||||
|
interactor = None
|
||||||
|
sdf_body = None
|
||||||
|
|
||||||
def mirror_body(self, sdf_object3d):
|
def mirror_body(self, sdf_object3d):
|
||||||
f = sdf_object3d.rotate(pi)
|
f = sdf_object3d.rotate(pi)
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
||||||
def cut_shapes(self, sdf_object1, sdf_object2):
|
class Output:
|
||||||
f = difference(sdf_object1, sdf_object2) # equivalent
|
|
||||||
return f
|
|
||||||
|
|
||||||
def export_mesh(self, sdf_object):
|
def export_mesh(self, sdf_object):
|
||||||
"""FINAL EXPORT"""
|
"""FINAL EXPORT"""
|
||||||
result_points = sdf_object.generate()
|
result_points = sdf_object.generate()
|
||||||
@ -607,51 +872,13 @@ class Geometry:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Error executing code:", e)
|
print("Error executing code:", e)
|
||||||
|
|
||||||
|
class Project:
|
||||||
@dataclass
|
"""Project -> Timeline -> Component -> Sketch -> Body / Interactor -> Connector -> Assembly -> PB Render"""
|
||||||
class Component:
|
timeline: Timeline = None
|
||||||
"""The base container combinging all related elements"""
|
assembly: Assembly = None
|
||||||
id = None
|
|
||||||
sketch = None
|
|
||||||
interactor = None
|
|
||||||
body = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Sketch:
|
|
||||||
"""All of the 2D Information of a sketch"""
|
|
||||||
origin = None
|
|
||||||
plane = None
|
|
||||||
normal = None
|
|
||||||
ui_points = None
|
|
||||||
ui_lines = None
|
|
||||||
slv_points = None
|
|
||||||
proj_points = None
|
|
||||||
proj_lines = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Interactor:
|
|
||||||
"""Helper mesh consisting of edges for selection"""
|
|
||||||
edges = None
|
|
||||||
faces = None
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Body:
|
|
||||||
"""The actual body as sdf3 object"""
|
|
||||||
sketch = None
|
|
||||||
height = None
|
|
||||||
sdf_body = None
|
|
||||||
|
|
||||||
class Boolean:
|
|
||||||
"""Toolkit that contains the boolean operations for sdf3 objects"""
|
|
||||||
def extrude(self, sketch: Sketch):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class Helper:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication([])
|
app = QApplication()
|
||||||
window = MainWindow()
|
window = MainWindow()
|
||||||
window.show()
|
window.show()
|
||||||
app.exec()
|
app.exec()
|
||||||
|
BIN
modules/out.stl
BIN
modules/out.stl
Binary file not shown.
@ -1,10 +1,66 @@
|
|||||||
|
certifi==2024.7.4
|
||||||
|
cffi==1.16.0
|
||||||
|
charset-normalizer==3.3.2
|
||||||
|
contourpy==1.2.0
|
||||||
|
cycler==0.12.1
|
||||||
|
fonttools==4.47.0
|
||||||
|
freetype-py==2.4.0
|
||||||
|
hsluv==5.0.4
|
||||||
|
idna==3.7
|
||||||
|
imageio==2.33.1
|
||||||
|
kiwisolver==1.4.5
|
||||||
|
lazy_loader==0.3
|
||||||
|
markdown-it-py==3.0.0
|
||||||
matplotlib==3.8.2
|
matplotlib==3.8.2
|
||||||
|
mdurl==0.1.2
|
||||||
|
meshio==5.3.4
|
||||||
|
names==0.3.0
|
||||||
|
networkx==3.2.1
|
||||||
|
Nuitka==2.2.1
|
||||||
numpy==1.26.2
|
numpy==1.26.2
|
||||||
|
numpy-stl==3.1.1
|
||||||
|
ordered-set==4.1.0
|
||||||
|
packaging==23.2
|
||||||
|
panda3d-gltf==1.2.0
|
||||||
|
panda3d-simplepbr==0.12.0
|
||||||
Pillow==10.1.0
|
Pillow==10.1.0
|
||||||
Pint==0.22
|
Pint==0.22
|
||||||
|
platformdirs==4.2.2
|
||||||
|
pooch==1.8.2
|
||||||
|
pycparser==2.21
|
||||||
pygame==2.5.2
|
pygame==2.5.2
|
||||||
|
Pygments==2.17.2
|
||||||
|
PyOpenGL==3.1.7
|
||||||
|
pyparsing==3.1.1
|
||||||
|
PyQt6==6.7.0
|
||||||
|
PyQt6-3D==6.7.0
|
||||||
|
PyQt6-3D-Qt6==6.7.0
|
||||||
|
PyQt6-Qt6==6.7.0
|
||||||
|
PyQt6-sip==13.6.0
|
||||||
PySide6==6.6.1
|
PySide6==6.6.1
|
||||||
|
PySide6-Addons==6.6.1
|
||||||
|
PySide6-Essentials==6.6.1
|
||||||
|
python-dateutil==2.8.2
|
||||||
|
python-solvespace==3.0.8
|
||||||
|
python-utils==3.8.2
|
||||||
|
pyvista==0.43.10
|
||||||
|
pyvistaqt==0.11.1
|
||||||
|
QtPy==2.4.1
|
||||||
|
requests==2.32.3
|
||||||
rich==13.7.0
|
rich==13.7.0
|
||||||
scikit-image==0.22.0
|
scikit-image==0.22.0
|
||||||
scipy==1.11.4
|
scipy==1.11.4
|
||||||
|
scooby==0.10.0
|
||||||
|
sdfcad @ git+https://gitlab.com/nobodyinperson/sdfCAD@9bd4e9021c6ee7e685ee28e8a3a5d2d2c028190c
|
||||||
|
shapely==2.0.4
|
||||||
|
shiboken6==6.6.1
|
||||||
|
six==1.16.0
|
||||||
|
tifffile==2023.12.9
|
||||||
|
trimesh==4.3.2
|
||||||
|
tripy==1.0.0
|
||||||
|
typing_extensions==4.9.0
|
||||||
|
urllib3==2.2.2
|
||||||
|
vispy==0.14.2
|
||||||
vtk==9.3.0
|
vtk==9.3.0
|
||||||
|
vulkan==1.3.275.0
|
||||||
|
zstandard==0.22.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user