]> SALOME platform Git repositories - modules/geom.git/commitdiff
Salome HOME
[bos #38044][EDF] (2023-T3) Support for automatic reparation. Updated UI.
authorKonstantin Leontev <Konstantin.LEONTEV@opencascade.com>
Tue, 12 Mar 2024 21:24:39 +0000 (21:24 +0000)
committerKonstantin Leontev <Konstantin.LEONTEV@opencascade.com>
Fri, 14 Jun 2024 17:03:06 +0000 (18:03 +0100)
src/RepairGUIAdv/CMakeLists.txt
src/RepairGUIAdv/basedlg.py
src/RepairGUIAdv/geomrepairadv_common.py
src/RepairGUIAdv/geomrepairadv_execute.py
src/RepairGUIAdv/locate_subshapes.py
src/RepairGUIAdv/merge_faces.py
src/RepairGUIAdv/merge_faces_algo.py
src/RepairGUIAdv/subshapes_basedlg.py [new file with mode: 0644]
src/RepairGUIAdv/union_edges.py

index d2251be453e4cfc3c0b52bd33658ac9a82b55825..c64ea9db23a1246001c2391a22b489db804c93a5 100644 (file)
@@ -45,6 +45,7 @@ IF(SALOME_BUILD_GUI)
   SET(_gui_SCRIPTS
     basedlg.py
     basedlg.ui
+    subshapes_basedlg.py
     ${geom_dlg_ref}/DlgRef_1Sel_QTD.ui
     DlgRef_1Spin_QTD.ui # copied because original was promoted to SalomeApp_DoubleSpinBox
     )
index e69ceefe074cc033cdd18ccf38aa400857bb0db2..b21c75950deb0fa05ebb8a3b6e5a05b7e9f20c3e 100644 (file)
@@ -32,6 +32,7 @@ from libGEOM_Swig import GEOM_Swig
 
 from .basedlg_ui import Ui_BaseDlg
 from .geomrepairadv_execute import execute
+from .geomrepairadv_logger import logger
 from .geomrepairadv_common import DlgRef_1Sel_QTD, \
     GEOM_RESULT_NAME_GRP, NAME_LBL, GEOM_SELECTED_LBL, GEOM_SELECTED_SHAPE
 import GEOM
@@ -236,6 +237,23 @@ class BaseDlg(Ui_BaseDlg, QWidget):
         return self._result_widget.LineEdit1.text()
 
 
+    def set_selection_level(self, selection_level):
+        """
+        Sets selection level.
+
+        Args:
+            selection_level - GEOM selection level.
+
+        Returns:
+            None.
+        """
+
+        self._selection_level = selection_level
+
+        # Update selection for current object
+        self.on_select_object()
+
+
     def set_selection(self, entry = None):
         """
         Sets selection level to self._selection_level or resets it.
@@ -291,6 +309,47 @@ class BaseDlg(Ui_BaseDlg, QWidget):
         self.set_selection(entry)
 
 
+    def get_local_selection(self):
+        """
+        Returns selected sub-shapes ids.
+
+        Args:
+            None.
+
+        Returns:
+            List of ids.
+        """
+
+        geom_swig = GEOM_Swig()
+        selected_ids = geom_swig.getLocalSelection()
+        logger.debug('selected_ids: %s', selected_ids)
+
+        return selected_ids
+
+
+    def is_selection_valid(self, selected_ids, min_selected):
+        """
+        Checks number of sub-shapes ids.
+
+        Args:
+            selected_ids - list of selected.
+
+        Returns:
+            True if we have valid number of ids.
+        """
+
+        if len(selected_ids) < min_selected:
+            QMessageBox.warning(
+                None,
+                'Warning',
+                'The algorithm needs at least {} selected sub-shapes!\n'
+                'Operation was canceled.'.format(min_selected)
+                )
+            return False
+
+        return True
+
+
     def closeEvent(self, event):
         """
         Overrides default close envent to reset selection level.
index 06e91a0392e678b89c546396c5367fd64ce92f27..4d2feafb7d6e8af644bc543bfa0e11dc98f2a04e 100644 (file)
@@ -53,7 +53,12 @@ class DlgRef_1Spin_QTD(Ui_DlgRef_1Spin_QTD, QWidget):
     We need it because a class generated from ui file is derived from an object and
     cannot be added as a widget to a dialog's layout.
     """
-    def __init__(self):
+    def __init__(self, title, default_value, decimals, max_value):
         QWidget.__init__(self)
         # Set up the user interface from Designer.
         self.setupUi(self)
+
+        self.TextLabel1.setText(title)
+        self.SpinBox_DX.setValue(default_value)
+        self.SpinBox_DX.setDecimals(decimals)
+        self.SpinBox_DX.setMaximum(max_value)
index 5be14b852e449b1f6f819f3544ec20ce30fb7a0e..9b76c58d5d6403c30cd6c1d17eeb940f75067505 100644 (file)
@@ -22,8 +22,9 @@
 import os
 import sys
 import importlib.util
+from traceback import format_exc
 
-from qtsalome import QApplication, QFileDialog
+from qtsalome import QApplication, QFileDialog, QMessageBox
 
 from salome.kernel.services import ObjectToID
 from salome.geom.geomtools import GeomStudyTools
@@ -68,7 +69,18 @@ def module_from_filename(filename):
         logger.error('spec.loader is None for %s module!', module_name)
         return None
 
-    spec.loader.exec_module(module)
+    try:
+        spec.loader.exec_module(module)
+
+    except FileNotFoundError:
+        logger.error(format_exc())
+        QMessageBox.warning(
+                None,
+                'Error',
+                'Cannot find module {}!\nOperation was canceled.'.format(module_name)
+                )
+
+        return None
 
     return module
 
index e73e3b3ddf3ee4a38d3b1f4bb53ab6d36c68c3c2..8f4ec67ab6b26e88a914d6774dca49364c6dd948 100644 (file)
 
 import sys
 
-from qtsalome import QGridLayout, QFrame, QApplication
+from qtsalome import QGridLayout, QFrame, QApplication, QComboBox, QLabel, QPushButton, QMessageBox
 
 from salome.geom.geomrepairadv.basedlg import BaseDlg
+
+from .geomrepairadv_common import DlgRef_1Spin_QTD
 import GEOM
 
 class LocateSubShapesDlg(BaseDlg):
@@ -31,14 +33,141 @@ class LocateSubShapesDlg(BaseDlg):
     Dialog for Locate Subshapes plugin that selects the sub-shapes of a compound
     by length, area or volume depending on whether it is an EDGE, a FACE or a SOLID.
     """
-    def __init__(self, selection_level = GEOM.COMPOUND):
+    def __init__(self, selection_level = GEOM.EDGE):
         # Implement widget's content here
         main_widget = QFrame()
         layout = QGridLayout(main_widget)
         layout.setContentsMargins(0, 0, 0, 0)
 
+        # A combobox to choose measurment type
+        type_label = QLabel('Shape Measurement')
+        self._type_widget = QComboBox()
+        type_items = ['Length (EDGE)', 'Area (FACE)', 'Volume (SOLID)']
+        self._type_widget.insertItems(0, type_items)
+        self._type_widget.setToolTip('Select a type of shape measurement')
+        self._type_widget.currentIndexChanged.connect(self.on_measurment_type_changed)
+
+        # Min/max values widgets
+        decimals = 2
+        max_value = sys.float_info.max
+        self._min_widget = DlgRef_1Spin_QTD('Min', 0, decimals, max_value)
+        self._max_widget = DlgRef_1Spin_QTD('Max', 100, decimals, max_value)
+
+        # Add select button
+        self._select_button = QPushButton("Show Selected Sub-shapes")
+        self._select_button.clicked.connect(self.on_select_button_clicked)
+
+        # Add the widgets to layout
+        layout.addWidget(type_label, 0, 0)
+        layout.addWidget(self._type_widget, 1, 0)
+        layout.addWidget(self._min_widget, 2, 0)
+        layout.addWidget(self._max_widget, 3, 0)
+        layout.addWidget(self._select_button, 4, 0)
+
+        # Init base dialog
         BaseDlg.__init__(
-            self, main_widget, 'Locate Subshapes', 'locate_subshapes_algo.py', False, selection_level)
+            self,
+            main_widget,
+            'Locate Subshapes',
+            'locate_subshapes_algo.py',
+            False,
+            selection_level
+            )
+
+
+    def get_limits(self):
+        """
+        Returns current values for min/max limits.
+
+        Args:
+            None.
+
+        Returns:
+            List of limits [min, max].
+        """
+
+        return [self._min_widget.SpinBox_DX.value(),
+                self._max_widget.SpinBox_DX.value()]
+
+
+    def get_measurment_type(self, index):
+        """
+        Returns selection level based on current measurment type.
+
+        Args:
+            index - current combobox index.
+
+        Returns:
+            GEOM selection level value.
+        """
+
+        measurment_types = {
+            0 : GEOM.EDGE,
+            1 : GEOM.FACE,
+            2 : GEOM.SOLID
+        }
+
+        return measurment_types[index]
+
+
+    def on_measurment_type_changed(self, index):
+        """
+        Changes selection level on type changed.
+
+        Args:
+            index - current combobox index.
+
+        Returns:
+            None.
+        """
+
+        selection_level = self.get_measurment_type(index)
+        self.set_selection_level(selection_level)
+
+
+    def on_select_button_clicked(self):
+        """
+        Show selection info on button click.
+
+        Args:
+            None.
+
+        Returns:
+            None.
+        """
+
+        #TODO: what are we going to do on this click?
+        # Should it do a separated script?
+        QMessageBox.warning(None, 'Warning', 'Not implemented yet')
+
+
+    def get_args(self):
+        """
+        Collects arguments for a repair execution algorithm into a dictionary.
+
+        Args:
+            None.
+
+        Returns:
+            Dictionary with arguments for execution.
+        """
+
+        selected_ids = self.get_local_selection()
+        current_index = self._type_widget.currentIndex()
+        selection_level = self.get_measurment_type(current_index)
+        limits = self.get_limits()
+        min_selected = 1
+
+        if self.is_selection_valid(selected_ids, min_selected):
+            return {
+                'selected_ids': selected_ids,
+                'result_name': self.get_result_name(),
+                'selection_level': selection_level,
+                'min_limit': limits[0],
+                'max_limit': limits[1]
+            }
+
+        return None
 
 
 # For testing run as a module from geomrepairadv parent directory in
index cc222b7026167b05f1a4eb6c6269d35ee475e30e..dc85f17c93d1b4cd4e7ffef23b2ca4cc16e9ee37 100644 (file)
 
 import sys
 
-from qtsalome import QGridLayout, QFrame, QMessageBox, QApplication
+from qtsalome import QApplication
 
-from libGEOM_Swig import GEOM_Swig
-from .geomrepairadv_logger import logger
-from .basedlg import BaseDlg
-from .geomrepairadv_common import DlgRef_1Spin_QTD
+from .subshapes_basedlg import SubShapesBaseDlg
 import GEOM
 
-class MergeFacesDlg(BaseDlg):
+class MergeFacesDlg(SubShapesBaseDlg):
     """
     Dialog for Merge Faces plugin that merges selected faces with a given precision.
     """
 
     def __init__(self, selection_level = GEOM.FACE):
-        # Make layout for new widgets
-        main_widget = QFrame()
-        layout = QGridLayout(main_widget)
-        layout.setContentsMargins(0, 0, 0, 0)
-
-        # Precision widget
-        self._precision_widget = DlgRef_1Spin_QTD()
-        self._precision_widget.TextLabel1.setText('Precision')
-        layout.addWidget(self._precision_widget, 0, 0)
-
-        BaseDlg.__init__(
-            self, main_widget, 'Merge Faces', 'merge_faces_algo.py', True, selection_level)
-
-
-    def get_precision(self):
-        """
-        Returns current precision value.
-
-        Args:
-            None.
-
-        Returns:
-            Double.
-        """
-
-        return self._precision_widget.SpinBox_DX.value()
-
-
-    def get_args(self):
-        """
-        Collects arguments for a repair execution algorithm into a dictionary.
-
-        Args:
-            None.
-
-        Returns:
-            Dictionary with arguments for execution.
-        """
-
-        geom_swig = GEOM_Swig()
-        faces_ids = geom_swig.getLocalSelection()
-        logger.debug('faces_ids: %s', faces_ids)
-
-        if len(faces_ids) < 2:
-            QMessageBox.warning(
-                None,
-                'Warning',
-                'The algorithm needs at least two selected faces!\nMerging was canceled.'
-                )
-            return None
-
-        return {
-            'faces_ids': faces_ids,
-            'result_name': self.get_result_name(),
-            'precision': self.get_precision()
-        }
+        SubShapesBaseDlg.__init__(
+            self, 'Merge Faces', 'merge_faces_algo.py', True, selection_level, 2)
 
 
 # For testing run as a module from geomrepairadv parent directory in
index dbe9014f4e8eed94f4eacbc7addc1bc8b54ff179..3808baa49978486b589948dc23be74fed4469892 100755 (executable)
@@ -52,14 +52,15 @@ def run(args_dict, progress_emitter):
 
 
     if ('source_solid' not in args_dict or
-        'faces_ids' not in args_dict or
-        'result_name' not in args_dict):
+        'selected_ids' not in args_dict or
+        'result_name' not in args_dict or
+        'precision' not in args_dict):
 
         logging.info('Cant execute an algo because the arguments are empty!')
         return False
 
     source_solid = args_dict['source_solid']
-    faces_ids = args_dict['faces_ids']
+    faces_ids = args_dict['selected_ids']
     result_name = args_dict['result_name']
 
 
diff --git a/src/RepairGUIAdv/subshapes_basedlg.py b/src/RepairGUIAdv/subshapes_basedlg.py
new file mode 100644 (file)
index 0000000..7608a9c
--- /dev/null
@@ -0,0 +1,99 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2014-2024  EDF
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+#
+# See https://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+#
+# Author : Konstantin Leontev (OpenCascade S.A.S)
+
+import sys
+
+from qtsalome import QGridLayout, QFrame, QApplication
+
+from .basedlg import BaseDlg
+from .geomrepairadv_common import DlgRef_1Spin_QTD
+
+class SubShapesBaseDlg(BaseDlg):
+    """
+    Base dialog for Merge Faces and Union Edges plugins that provides
+    to algorithm selected faces with a given precision.
+    """
+
+    def __init__(self, window_title, algo_name, is_default_location, selection_level, min_selected):
+        # Set min number of selected sub-shapes
+        self._min_selected = min_selected
+
+        # Make layout for new widgets
+        main_widget = QFrame()
+        layout = QGridLayout(main_widget)
+        layout.setContentsMargins(0, 0, 0, 0)
+
+        # Precision widget
+        self._precision_widget = DlgRef_1Spin_QTD('Precision', 0, 2, 100)
+        layout.addWidget(self._precision_widget, 0, 0)
+
+        BaseDlg.__init__(
+            self, main_widget, window_title, algo_name, is_default_location, selection_level)
+
+
+    def get_precision(self):
+        """
+        Returns current precision value.
+
+        Args:
+            None.
+
+        Returns:
+            Double.
+        """
+
+        return self._precision_widget.SpinBox_DX.value()
+
+
+    def get_args(self):
+        """
+        Collects arguments for a repair execution algorithm into a dictionary.
+
+        Args:
+            None.
+
+        Returns:
+            Dictionary with arguments for execution.
+        """
+
+        selected_ids = self.get_local_selection()
+        if self.is_selection_valid(selected_ids, self._min_selected):
+            return {
+                'selected_ids': selected_ids,
+                'result_name': self.get_result_name(),
+                'precision': self.get_precision()
+            }
+
+        return None
+
+
+# For testing run as a module from geomrepairadv parent directory in
+# Salome INSTALL, because the dialog needs a generated Ui_BaseDlg class
+# that we don't have in the SOURCE.
+# Example:
+# $ python -m geomrepairadv.subshapes_basedlg
+if __name__ == '__main__':
+    app = QApplication(sys.argv)
+
+    dlg = SubShapesBaseDlg('Test SubShapesBaseDlg', 'merge_faces_algo.py', True, None, 1)
+    dlg.show()
+
+    sys.exit(app.exec_())
index 0dbd4776a49bc52d033bea7341c5e12653dc1844..f3c07b48e9af588037d85d900d8d7f60f0ecaef7 100644 (file)
 
 import sys
 
-from qtsalome import QGridLayout, QFrame, QApplication
+from qtsalome import QApplication
 
-from salome.geom.geomrepairadv.basedlg import BaseDlg
+from .subshapes_basedlg import SubShapesBaseDlg
 import GEOM
 
-class UnionEdgesDlg(BaseDlg):
+class UnionEdgesDlg(SubShapesBaseDlg):
     """
     Dialog for Union Edges plugin that unifies edges of selected face.
     """
-    def __init__(self, selection_level = GEOM.COMPOUND):
-        # Implement widget's content here
-        main_widget = QFrame()
-        layout = QGridLayout(main_widget)
-        layout.setContentsMargins(0, 0, 0, 0)
-
-        BaseDlg.__init__(
-            self, main_widget, 'Union Edges', 'union_edges_algo.py', False, selection_level)
+    def __init__(self, selection_level = GEOM.FACE):
+        SubShapesBaseDlg.__init__(
+            self, 'Union Edges', 'union_edges_algo.py', False, selection_level, 1)
 
 
 # For testing run as a module from geomrepairadv parent directory in