- added contrain context menu
- improved line pickability.
This commit is contained in:
Generated
+32
-10
@@ -4,16 +4,13 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="8f0bafd6-58a0-4b20-aa2b-ddc3ba278873" name="Changes" comment="- Render improvements, camera plane, update">
|
<list default="true" id="8f0bafd6-58a0-4b20-aa2b-ddc3ba278873" name="Changes" comment="- added contrain context menu - improved line pickability.">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/gui.ui" beforeDir="false" afterPath="$PROJECT_DIR$/gui.ui" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/gui.ui" beforeDir="false" afterPath="$PROJECT_DIR$/gui.ui" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/gui_ui.py" beforeDir="false" afterPath="$PROJECT_DIR$/gui_ui.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/gui_ui.py" beforeDir="false" afterPath="$PROJECT_DIR$/gui_ui.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/fluency/geometry_occ/kernel.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/geometry_occ/kernel.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/fluency/geometry_occ/kernel.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/geometry_occ/kernel.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/fluency/models/data_model.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/models/data_model.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/fluency/ui/dialogs.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/ui/dialogs.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/fluency/rendering/mitsuba_backend.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/rendering/mitsuba_backend.py" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/fluency/rendering/occ_renderer.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/rendering/occ_renderer.py" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/fluency/ui/main_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/ui/main_window.py" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/fluency/ui/main_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/ui/main_window.py" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/fluency/ui/render_window.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/fluency/ui/render_window.py" afterDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -72,6 +69,7 @@
|
|||||||
"Python.side_fluency.executor": "Run",
|
"Python.side_fluency.executor": "Run",
|
||||||
"Python.simple_mesh.executor": "Run",
|
"Python.simple_mesh.executor": "Run",
|
||||||
"Python.sketch.executor": "Run",
|
"Python.sketch.executor": "Run",
|
||||||
|
"Python.surface_modifier.executor": "Run",
|
||||||
"Python.vtk_widget.executor": "Run",
|
"Python.vtk_widget.executor": "Run",
|
||||||
"Python.vulkan.executor": "Run",
|
"Python.vulkan.executor": "Run",
|
||||||
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
"RunOnceActivity.OpenProjectViewOnStart": "true",
|
||||||
@@ -80,7 +78,7 @@
|
|||||||
"RunOnceActivity.git.unshallow": "true",
|
"RunOnceActivity.git.unshallow": "true",
|
||||||
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
"RunOnceActivity.typescript.service.memoryLimit.init": "true",
|
||||||
"codeWithMe.voiceChat.enabledByDefault": "false",
|
"codeWithMe.voiceChat.enabledByDefault": "false",
|
||||||
"git-widget-placeholder": "feature/occ-migration",
|
"git-widget-placeholder": "feature/surface-modifier-pyramid-patterns",
|
||||||
"last_opened_file_path": "/Volumes/Data_drive/Programming/fluency",
|
"last_opened_file_path": "/Volumes/Data_drive/Programming/fluency",
|
||||||
"node.js.detected.package.eslint": "true",
|
"node.js.detected.package.eslint": "true",
|
||||||
"node.js.selected.package.eslint": "(autodetect)",
|
"node.js.selected.package.eslint": "(autodetect)",
|
||||||
@@ -442,7 +440,31 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1783976498520</updated>
|
<updated>1783976498520</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="41" />
|
<task id="LOCAL-00041" summary="Improved render previews">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1784408804224</created>
|
||||||
|
<option name="number" value="00041" />
|
||||||
|
<option name="presentableId" value="LOCAL-00041" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1784408804224</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00042" summary="- added contrain context menu - improved line pickability.">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1784452692776</created>
|
||||||
|
<option name="number" value="00042" />
|
||||||
|
<option name="presentableId" value="LOCAL-00042" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1784452692776</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00043" summary="- added contrain context menu - improved line pickability.">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1784470032428</created>
|
||||||
|
<option name="number" value="00043" />
|
||||||
|
<option name="presentableId" value="LOCAL-00043" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1784470032428</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="44" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -463,8 +485,6 @@
|
|||||||
<ignored-roots>
|
<ignored-roots>
|
||||||
<path value="$PROJECT_DIR$/pythonProject" />
|
<path value="$PROJECT_DIR$/pythonProject" />
|
||||||
</ignored-roots>
|
</ignored-roots>
|
||||||
<MESSAGE value="- Sketch projection partly works again :)" />
|
|
||||||
<MESSAGE value="- Added new componnt controls" />
|
|
||||||
<MESSAGE value="- changing compos for sketches works" />
|
<MESSAGE value="- changing compos for sketches works" />
|
||||||
<MESSAGE value="- changing compos including sketches and bodies" />
|
<MESSAGE value="- changing compos including sketches and bodies" />
|
||||||
<MESSAGE value="- Drawing bodys depending on the selected compo - Cut working - Edit sketch working" />
|
<MESSAGE value="- Drawing bodys depending on the selected compo - Cut working - Edit sketch working" />
|
||||||
@@ -488,6 +508,8 @@
|
|||||||
<MESSAGE value="- added renderer" />
|
<MESSAGE value="- added renderer" />
|
||||||
<MESSAGE value="- added renderer - Added undo" />
|
<MESSAGE value="- added renderer - Added undo" />
|
||||||
<MESSAGE value="- Render improvements, camera plane, update" />
|
<MESSAGE value="- Render improvements, camera plane, update" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="- Render improvements, camera plane, update" />
|
<MESSAGE value="Improved render previews" />
|
||||||
|
<MESSAGE value="- added contrain context menu - improved line pickability." />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="- added contrain context menu - improved line pickability." />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -501,6 +501,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QPushButton" name="pb_surface_mod">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Apply surface modifier (pyramid pattern for grips)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>SrfMod</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -1098,32 +1108,6 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="3" rowspan="5">
|
|
||||||
<widget class="QGroupBox" name="gl_box">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>4</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="font">
|
|
||||||
<font>
|
|
||||||
<pointsize>12</pointsize>
|
|
||||||
</font>
|
|
||||||
</property>
|
|
||||||
<property name="title">
|
|
||||||
<string>Model Viewer</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
|
||||||
<property name="spacing">
|
|
||||||
<number>-1</number>
|
|
||||||
</property>
|
|
||||||
<property name="leftMargin">
|
|
||||||
<number>12</number>
|
|
||||||
</property>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="4" column="4">
|
<item row="4" column="4">
|
||||||
<widget class="QGroupBox" name="groupBox_12">
|
<widget class="QGroupBox" name="groupBox_12">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@@ -1312,6 +1296,32 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="2" rowspan="5">
|
||||||
|
<widget class="QGroupBox" name="gl_box">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>4</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>12</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>Model Viewer</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>12</number>
|
||||||
|
</property>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenuBar" name="menubar">
|
<widget class="QMenuBar" name="menubar">
|
||||||
|
|||||||
@@ -289,6 +289,11 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
self.gridLayout_3.addWidget(self.pb_moveop, 1, 1, 1, 1)
|
self.gridLayout_3.addWidget(self.pb_moveop, 1, 1, 1, 1)
|
||||||
|
|
||||||
|
self.pb_surface_mod = QPushButton(self.groupBox)
|
||||||
|
self.pb_surface_mod.setObjectName(u"pb_surface_mod")
|
||||||
|
|
||||||
|
self.gridLayout_3.addWidget(self.pb_surface_mod, 3, 0, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox, 0, 4, 1, 1)
|
self.gridLayout.addWidget(self.groupBox, 0, 4, 1, 1)
|
||||||
|
|
||||||
@@ -601,25 +606,6 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
self.gridLayout.addWidget(self.InputTab, 0, 1, 5, 1)
|
self.gridLayout.addWidget(self.InputTab, 0, 1, 5, 1)
|
||||||
|
|
||||||
self.gl_box = QGroupBox(self.centralwidget)
|
|
||||||
self.gl_box.setObjectName(u"gl_box")
|
|
||||||
sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
|
||||||
sizePolicy5.setHorizontalStretch(0)
|
|
||||||
sizePolicy5.setVerticalStretch(4)
|
|
||||||
sizePolicy5.setHeightForWidth(self.gl_box.sizePolicy().hasHeightForWidth())
|
|
||||||
self.gl_box.setSizePolicy(sizePolicy5)
|
|
||||||
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, 3, 5, 1)
|
|
||||||
|
|
||||||
self.groupBox_12 = QGroupBox(self.centralwidget)
|
self.groupBox_12 = QGroupBox(self.centralwidget)
|
||||||
self.groupBox_12.setObjectName(u"groupBox_12")
|
self.groupBox_12.setObjectName(u"groupBox_12")
|
||||||
sizePolicy2.setHeightForWidth(self.groupBox_12.sizePolicy().hasHeightForWidth())
|
sizePolicy2.setHeightForWidth(self.groupBox_12.sizePolicy().hasHeightForWidth())
|
||||||
@@ -706,6 +692,25 @@ class Ui_fluencyCAD(object):
|
|||||||
|
|
||||||
self.gridLayout.addWidget(self.groupBox_10, 3, 4, 1, 1)
|
self.gridLayout.addWidget(self.groupBox_10, 3, 4, 1, 1)
|
||||||
|
|
||||||
|
self.gl_box = QGroupBox(self.centralwidget)
|
||||||
|
self.gl_box.setObjectName(u"gl_box")
|
||||||
|
sizePolicy5 = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
|
||||||
|
sizePolicy5.setHorizontalStretch(0)
|
||||||
|
sizePolicy5.setVerticalStretch(4)
|
||||||
|
sizePolicy5.setHeightForWidth(self.gl_box.sizePolicy().hasHeightForWidth())
|
||||||
|
self.gl_box.setSizePolicy(sizePolicy5)
|
||||||
|
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, 5, 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")
|
||||||
@@ -863,6 +868,10 @@ 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))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.pb_surface_mod.setToolTip(QCoreApplication.translate("fluencyCAD", u"Apply surface modifier (pyramid pattern for grips)", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.pb_surface_mod.setText(QCoreApplication.translate("fluencyCAD", u"SrfMod", None))
|
||||||
self.compo_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Components", None))
|
self.compo_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Components", None))
|
||||||
self.compo_tool_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Component Tools", None))
|
self.compo_tool_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Component Tools", None))
|
||||||
self.pb_new_compo.setText(QCoreApplication.translate("fluencyCAD", u"New", None))
|
self.pb_new_compo.setText(QCoreApplication.translate("fluencyCAD", u"New", None))
|
||||||
@@ -902,7 +911,6 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_apply_code.setText(QCoreApplication.translate("fluencyCAD", u"Apply Code", None))
|
self.pb_apply_code.setText(QCoreApplication.translate("fluencyCAD", u"Apply Code", None))
|
||||||
self.pushButton.setText(QCoreApplication.translate("fluencyCAD", u"Delete Code", None))
|
self.pushButton.setText(QCoreApplication.translate("fluencyCAD", u"Delete Code", None))
|
||||||
self.InputTab.setTabText(self.InputTab.indexOf(self.code_tab), QCoreApplication.translate("fluencyCAD", u"Code", None))
|
self.InputTab.setTabText(self.InputTab.indexOf(self.code_tab), QCoreApplication.translate("fluencyCAD", u"Code", None))
|
||||||
self.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
|
|
||||||
self.groupBox_12.setTitle(QCoreApplication.translate("fluencyCAD", u"Component Connections", None))
|
self.groupBox_12.setTitle(QCoreApplication.translate("fluencyCAD", u"Component Connections", None))
|
||||||
self.groupBox_13.setTitle(QCoreApplication.translate("fluencyCAD", u"Tools", None))
|
self.groupBox_13.setTitle(QCoreApplication.translate("fluencyCAD", u"Tools", None))
|
||||||
self.pb_del_connection.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
self.pb_del_connection.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
||||||
@@ -913,6 +921,7 @@ class Ui_fluencyCAD(object):
|
|||||||
self.pb_del_body.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
self.pb_del_body.setText(QCoreApplication.translate("fluencyCAD", u"Del", None))
|
||||||
self.pb_update_body.setText(QCoreApplication.translate("fluencyCAD", u"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.gl_box.setTitle(QCoreApplication.translate("fluencyCAD", u"Model Viewer", None))
|
||||||
self.menuFile.setTitle(QCoreApplication.translate("fluencyCAD", u"File", None))
|
self.menuFile.setTitle(QCoreApplication.translate("fluencyCAD", u"File", None))
|
||||||
self.menuSettings.setTitle(QCoreApplication.translate("fluencyCAD", u"Settings", None))
|
self.menuSettings.setTitle(QCoreApplication.translate("fluencyCAD", u"Settings", None))
|
||||||
# retranslateUi
|
# retranslateUi
|
||||||
|
|||||||
@@ -780,3 +780,67 @@ class OCGeometryKernel(GeometryKernel):
|
|||||||
|
|
||||||
cg = props.CentreOfMass()
|
cg = props.CentreOfMass()
|
||||||
return Point3D(cg.X(), cg.Y(), cg.Z())
|
return Point3D(cg.X(), cg.Y(), cg.Z())
|
||||||
|
|
||||||
|
def apply_surface_modifier(
|
||||||
|
self,
|
||||||
|
body_geometry: GeometryObject,
|
||||||
|
modifier_type: str = 'pyramid',
|
||||||
|
height: float = 2.0,
|
||||||
|
radius: float = 3.0,
|
||||||
|
spacing: float = 8.0,
|
||||||
|
num_rings: int = 3,
|
||||||
|
) -> Optional[GeometryObject]:
|
||||||
|
"""Apply a surface modifier to a body geometry.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
body_geometry: The OCCGeometryObject to modify
|
||||||
|
modifier_type: Type of modifier ('pyramid', 'bump')
|
||||||
|
height: Height/depth of the pattern features
|
||||||
|
radius: Base radius of pattern features
|
||||||
|
spacing: Distance between pattern features
|
||||||
|
num_rings: Number of concentric rings
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Modified geometry, or None on failure
|
||||||
|
"""
|
||||||
|
from fluency.geometry_occ.surface_modifier import SurfaceModifier
|
||||||
|
|
||||||
|
shape = self._get_shape(body_geometry)
|
||||||
|
if shape is None:
|
||||||
|
logger.error("No geometry found in body")
|
||||||
|
return None
|
||||||
|
|
||||||
|
modifier = SurfaceModifier()
|
||||||
|
|
||||||
|
try:
|
||||||
|
if modifier_type == 'pyramid':
|
||||||
|
result_shape = modifier.apply_pyramid_pattern(
|
||||||
|
shape,
|
||||||
|
pyramid_height=height,
|
||||||
|
base_radius=radius,
|
||||||
|
spacing=spacing,
|
||||||
|
num_rings=num_rings,
|
||||||
|
direction=(0, 0, 1),
|
||||||
|
)
|
||||||
|
elif modifier_type == 'bump':
|
||||||
|
result_shape = modifier.apply_bump_pattern(
|
||||||
|
shape,
|
||||||
|
bump_height=height,
|
||||||
|
bump_radius=radius,
|
||||||
|
spacing=spacing,
|
||||||
|
num_rings=num_rings,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
logger.error(f"Unknown modifier type: {modifier_type}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
if result_shape is None:
|
||||||
|
logger.error("Surface modifier application failed")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Return the modified shape wrapped in OCCGeometryObject
|
||||||
|
return OCCGeometryObject(result_shape)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Error applying surface modifier: {e}", exc_info=True)
|
||||||
|
return None
|
||||||
|
|||||||
@@ -4,16 +4,12 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Tuple
|
||||||
|
|
||||||
from PySide6.QtCore import Qt, QPoint, QPointF
|
|
||||||
from PySide6.QtGui import QColor, QFont, QKeySequence
|
|
||||||
from PySide6.QtWidgets import (
|
from PySide6.QtWidgets import (
|
||||||
QButtonGroup,
|
QButtonGroup,
|
||||||
QCheckBox,
|
QCheckBox,
|
||||||
QComboBox,
|
|
||||||
QDialog,
|
QDialog,
|
||||||
QDialogButtonBox,
|
|
||||||
QDoubleSpinBox,
|
QDoubleSpinBox,
|
||||||
QFormLayout,
|
QFormLayout,
|
||||||
QFrame,
|
QFrame,
|
||||||
@@ -24,7 +20,6 @@ from PySide6.QtWidgets import (
|
|||||||
QPushButton,
|
QPushButton,
|
||||||
QRadioButton,
|
QRadioButton,
|
||||||
QVBoxLayout,
|
QVBoxLayout,
|
||||||
QWidget,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
@@ -265,6 +260,95 @@ class OffsetDialog(QDialog):
|
|||||||
return (self.distance_input.value(), self.inward_checkbox.isChecked())
|
return (self.distance_input.value(), self.inward_checkbox.isChecked())
|
||||||
|
|
||||||
|
|
||||||
|
class SurfaceModifierDialog(QDialog):
|
||||||
|
"""Dialog for surface modifier settings."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
super().__init__(parent)
|
||||||
|
self.setWindowTitle("Surface Modifier")
|
||||||
|
self.setMinimumWidth(400)
|
||||||
|
|
||||||
|
layout = QVBoxLayout(self)
|
||||||
|
|
||||||
|
# Pattern type selection
|
||||||
|
pattern_layout = QGridLayout()
|
||||||
|
|
||||||
|
self._pattern_group = QButtonGroup(self)
|
||||||
|
patterns = [
|
||||||
|
("Pyramid Pattern", "pyramid"),
|
||||||
|
("Bump Pattern", "bump"),
|
||||||
|
]
|
||||||
|
for idx, (label, pattern_type) in enumerate(patterns):
|
||||||
|
btn = QRadioButton(label)
|
||||||
|
btn.setChecked(idx == 0)
|
||||||
|
self._pattern_group.addButton(btn, idx)
|
||||||
|
btn.pattern_type = pattern_type
|
||||||
|
pattern_layout.addWidget(btn, 0, idx)
|
||||||
|
layout.addLayout(pattern_layout)
|
||||||
|
|
||||||
|
# Parameters for pyramid/bump patterns
|
||||||
|
param_layout = QFormLayout()
|
||||||
|
|
||||||
|
self.height_input = QDoubleSpinBox()
|
||||||
|
self.height_input.setDecimals(2)
|
||||||
|
self.height_input.setRange(0.1, 50.0)
|
||||||
|
self.height_input.setValue(2.0)
|
||||||
|
self.height_input.setSuffix(" mm")
|
||||||
|
param_layout.addRow("Height:", self.height_input)
|
||||||
|
|
||||||
|
self.radius_input = QDoubleSpinBox()
|
||||||
|
self.radius_input.setDecimals(2)
|
||||||
|
self.radius_input.setRange(0.5, 20.0)
|
||||||
|
self.radius_input.setValue(3.0)
|
||||||
|
self.radius_input.setSuffix(" mm")
|
||||||
|
param_layout.addRow("Base Radius:", self.radius_input)
|
||||||
|
|
||||||
|
self.spacing_input = QDoubleSpinBox()
|
||||||
|
self.spacing_input.setDecimals(1)
|
||||||
|
self.spacing_input.setRange(1.0, 50.0)
|
||||||
|
self.spacing_input.setValue(8.0)
|
||||||
|
self.spacing_input.setSuffix(" mm")
|
||||||
|
param_layout.addRow("Spacing:", self.spacing_input)
|
||||||
|
|
||||||
|
layout.addLayout(param_layout)
|
||||||
|
|
||||||
|
# Number of rings
|
||||||
|
self.rings_input = QSpinBox()
|
||||||
|
self.rings_input.setMinimum(1)
|
||||||
|
self.rings_input.setMaximum(20)
|
||||||
|
self.rings_input.setValue(3)
|
||||||
|
param_layout.addRow("Number of Rings:", self.rings_input)
|
||||||
|
|
||||||
|
line = QFrame()
|
||||||
|
line.setFrameShape(QFrame.HLine)
|
||||||
|
layout.addWidget(line)
|
||||||
|
|
||||||
|
button_layout = QHBoxLayout()
|
||||||
|
ok_button = QPushButton("Apply")
|
||||||
|
ok_button.clicked.connect(self.accept)
|
||||||
|
cancel_button = QPushButton("Cancel")
|
||||||
|
cancel_button.clicked.connect(self.reject)
|
||||||
|
button_layout.addWidget(ok_button)
|
||||||
|
button_layout.addWidget(cancel_button)
|
||||||
|
layout.addLayout(button_layout)
|
||||||
|
|
||||||
|
def get_values(self) -> dict:
|
||||||
|
"""Return the modifier settings."""
|
||||||
|
pattern_type = None
|
||||||
|
for btn in self._pattern_group.buttons():
|
||||||
|
if btn.isChecked():
|
||||||
|
pattern_type = getattr(btn, 'pattern_type', None)
|
||||||
|
break
|
||||||
|
|
||||||
|
return {
|
||||||
|
'type': pattern_type or 'pyramid',
|
||||||
|
'height': self.height_input.value(),
|
||||||
|
'radius': self.radius_input.value(),
|
||||||
|
'spacing': self.spacing_input.value(),
|
||||||
|
'num_rings': self.rings_input.value(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class WorkplaneOrientationDialog(QDialog):
|
class WorkplaneOrientationDialog(QDialog):
|
||||||
"""Modal dialog to choose the orientation of a new workplane.
|
"""Modal dialog to choose the orientation of a new workplane.
|
||||||
|
|
||||||
@@ -404,7 +488,6 @@ class WorkplaneOrientationDialog(QDialog):
|
|||||||
def _on_ok(self):
|
def _on_ok(self):
|
||||||
"""Compute the final orientation and accept."""
|
"""Compute the final orientation and accept."""
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
|
||||||
|
|
||||||
if self._custom_radio.isChecked():
|
if self._custom_radio.isChecked():
|
||||||
# Custom: start from XY normal and rotate by the two angles.
|
# Custom: start from XY normal and rotate by the two angles.
|
||||||
@@ -454,7 +537,6 @@ class WorkplaneOrientationDialog(QDialog):
|
|||||||
whether called before or after ``_on_ok``.
|
whether called before or after ``_on_ok``.
|
||||||
"""
|
"""
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
|
||||||
|
|
||||||
if self._custom_radio.isChecked():
|
if self._custom_radio.isChecked():
|
||||||
ax = math.radians(self._angle_x.value())
|
ax = math.radians(self._angle_x.value())
|
||||||
|
|||||||
@@ -717,6 +717,8 @@ class MainWindow(QMainWindow):
|
|||||||
self._btn_move = ui.pb_moveop
|
self._btn_move = ui.pb_moveop
|
||||||
self._btn_revolve = ui.pb_revop
|
self._btn_revolve = ui.pb_revop
|
||||||
self._btn_array = ui.pb_arrayop
|
self._btn_array = ui.pb_arrayop
|
||||||
|
# ── Surface Modifier ──
|
||||||
|
self._btn_surface_mod = ui.pb_surface_mod
|
||||||
# ── Export ──
|
# ── Export ──
|
||||||
self._btn_export_stl = ui.pushButton_2
|
self._btn_export_stl = ui.pushButton_2
|
||||||
self._btn_export_step = ui.pb_export_step
|
self._btn_export_step = ui.pb_export_step
|
||||||
@@ -772,14 +774,14 @@ class MainWindow(QMainWindow):
|
|||||||
if panel == "viewer":
|
if panel == "viewer":
|
||||||
# Viewer 2/3, sketch 1/3 — more room for 3D work, sketch stays visible.
|
# Viewer 2/3, sketch 1/3 — more room for 3D work, sketch stays visible.
|
||||||
self._grid.setColumnStretch(1, 1)
|
self._grid.setColumnStretch(1, 1)
|
||||||
self._grid.setColumnStretch(2, 2)
|
self._grid.setColumnStretch(3, 2)
|
||||||
elif panel == "sketch":
|
elif panel == "sketch":
|
||||||
# Sketch 2/3, viewer 1/3 — comfortable sketching, 3D stays visible.
|
# Sketch 2/3, viewer 1/3 — comfortable sketching, 3D stays visible.
|
||||||
self._grid.setColumnStretch(1, 2)
|
self._grid.setColumnStretch(1, 2)
|
||||||
self._grid.setColumnStretch(2, 1)
|
self._grid.setColumnStretch(3, 1)
|
||||||
else: # equal
|
else: # equal
|
||||||
self._grid.setColumnStretch(1, 1)
|
self._grid.setColumnStretch(1, 1)
|
||||||
self._grid.setColumnStretch(2, 1)
|
self._grid.setColumnStretch(3, 1)
|
||||||
logger.info(f"Panel focus -> {self._panel_focus}")
|
logger.info(f"Panel focus -> {self._panel_focus}")
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
@@ -832,6 +834,7 @@ class MainWindow(QMainWindow):
|
|||||||
self._btn_cut.clicked.connect(self._boolean_cut)
|
self._btn_cut.clicked.connect(self._boolean_cut)
|
||||||
self._btn_combine.clicked.connect(self._boolean_union)
|
self._btn_combine.clicked.connect(self._boolean_union)
|
||||||
self._btn_revolve.clicked.connect(self._revolve_sketch)
|
self._btn_revolve.clicked.connect(self._revolve_sketch)
|
||||||
|
self._btn_surface_mod.clicked.connect(self._open_surface_modifier_dialog)
|
||||||
|
|
||||||
self._btn_add_sketch.clicked.connect(self._add_sketch_to_component)
|
self._btn_add_sketch.clicked.connect(self._add_sketch_to_component)
|
||||||
self._btn_edit_sketch.clicked.connect(self._edit_sketch)
|
self._btn_edit_sketch.clicked.connect(self._edit_sketch)
|
||||||
@@ -3994,6 +3997,56 @@ class MainWindow(QMainWindow):
|
|||||||
logger.exception(f"Boolean union failed: {e}")
|
logger.exception(f"Boolean union failed: {e}")
|
||||||
QMessageBox.critical(self, "Error", f"Boolean union failed: {e}")
|
QMessageBox.critical(self, "Error", f"Boolean union failed: {e}")
|
||||||
|
|
||||||
|
def _open_surface_modifier_dialog(self):
|
||||||
|
"""Open the surface modifier dialog and apply to selected body."""
|
||||||
|
if not self._current_component or not self._selected_body:
|
||||||
|
QMessageBox.warning(self, "No Selection", "Please select a body first")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Create and show the dialog
|
||||||
|
dialog = SurfaceModifierDialog(self)
|
||||||
|
accepted = dialog.exec()
|
||||||
|
|
||||||
|
if not accepted:
|
||||||
|
logger.info("Surface modifier dialog cancelled")
|
||||||
|
return
|
||||||
|
|
||||||
|
# Get the settings from the dialog
|
||||||
|
settings = dialog.get_values()
|
||||||
|
logger.info(f"Surface modifier settings: {settings}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Apply the surface modifier to the selected body
|
||||||
|
result_geom = self._kernel.apply_surface_modifier(
|
||||||
|
self._selected_body.geometry,
|
||||||
|
**settings
|
||||||
|
)
|
||||||
|
|
||||||
|
if result_geom is not None:
|
||||||
|
# Update the body geometry
|
||||||
|
self._selected_body.geometry = result_geom
|
||||||
|
self._mark_dirty()
|
||||||
|
|
||||||
|
logger.debug("Adding shape to OCC viewer")
|
||||||
|
shape = self._kernel._get_shape(result_geom)
|
||||||
|
self._selected_body.render_object = self._viewer_3d.show_shape(
|
||||||
|
shape, self._selected_body.color, self._selected_body.name
|
||||||
|
)
|
||||||
|
logger.info(f"Render object: {self._selected_body.render_object}")
|
||||||
|
|
||||||
|
self._refresh_lists()
|
||||||
|
self._update_component_thumbnail(self._get_active_component_index())
|
||||||
|
self._viewer_3d.fit_camera()
|
||||||
|
logger.info("Surface modifier applied successfully")
|
||||||
|
else:
|
||||||
|
QMessageBox.warning(
|
||||||
|
self, "Error", "Failed to apply surface modifier"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.exception(f"Surface modifier failed: {e}")
|
||||||
|
QMessageBox.critical(self, "Error", f"Surface modifier failed: {e}")
|
||||||
|
|
||||||
def _delete_body(self):
|
def _delete_body(self):
|
||||||
selected = self._body_list.currentItem()
|
selected = self._body_list.currentItem()
|
||||||
if not selected or not self._current_component:
|
if not selected or not self._current_component:
|
||||||
|
|||||||
Reference in New Issue
Block a user