From cdfe60e59d32dabd6312306d88247ce2754627b3 Mon Sep 17 00:00:00 2001 From: DUC ANH HOANG Date: Thu, 23 May 2024 16:09:49 +0200 Subject: [PATCH] reparation plugin: initialize --- src/RepairGUIAdv/CMakeLists.txt | 2 + src/RepairGUIAdv/geomrepairadv_plugins.py | 14 ++ src/RepairGUIAdv/reparation_plugin.py | 192 +++++++++++++++++++++ src/RepairGUIAdv/reparation_plugin_algo.py | 147 ++++++++++++++++ 4 files changed, 355 insertions(+) create mode 100755 src/RepairGUIAdv/reparation_plugin.py create mode 100644 src/RepairGUIAdv/reparation_plugin_algo.py diff --git a/src/RepairGUIAdv/CMakeLists.txt b/src/RepairGUIAdv/CMakeLists.txt index efd485fa3..fd1f024c4 100644 --- a/src/RepairGUIAdv/CMakeLists.txt +++ b/src/RepairGUIAdv/CMakeLists.txt @@ -42,6 +42,8 @@ IF(SALOME_BUILD_GUI) merge_faces_algo.py union_edges.py union_edges_algo.py + reparation_plugin.py + reparation_plugin_algo.py ) # gui scripts diff --git a/src/RepairGUIAdv/geomrepairadv_plugins.py b/src/RepairGUIAdv/geomrepairadv_plugins.py index 2627b6d29..4edff50d5 100644 --- a/src/RepairGUIAdv/geomrepairadv_plugins.py +++ b/src/RepairGUIAdv/geomrepairadv_plugins.py @@ -28,6 +28,14 @@ from qtsalome import QIcon # For new plugins create a function that shows related dialog, # then add it into plugin manager below. +def reparation_plugin(context): + """ + Opens Reparation plugin's dialog. + """ + from salome.geom.geomrepairadv.reparation_plugin import Reparation_plugin + dialog = Reparation_plugin() + dialog.show() + def locate_subshapes(context): """ Opens Locate Subshapes plugin's dialog. @@ -81,3 +89,9 @@ salome_pluginsmanager.AddFunction( 'Merges edges of selected face', union_edges, get_icon('fuse.png')) + +salome_pluginsmanager.AddFunction( + 'Reparation plugin', + 'Nathalie need it for test', + reparation_plugin, + get_icon('dumb.png')) diff --git a/src/RepairGUIAdv/reparation_plugin.py b/src/RepairGUIAdv/reparation_plugin.py new file mode 100755 index 000000000..1a2437300 --- /dev/null +++ b/src/RepairGUIAdv/reparation_plugin.py @@ -0,0 +1,192 @@ +# -*- 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 : Duc Anh HOANG (OpenCascade S.A.S) + +import sys + +from qtsalome import QGridLayout, QFrame, QApplication, \ + QComboBox, QLabel, QPushButton, QMessageBox, QCheckBox + +from salome.geom.geomrepairadv.basedlg import BaseDlg +from salome.geom import geomBuilder +from libGEOM_Swig import GEOM_Swig + +from .geomrepairadv_common import DlgRef_1Spin_QTD +from .geomrepairadv_execute import execute +from .geomrepairadv_logger import logger +import GEOM + +class Reparation_plugin(BaseDlg): + """ + Dialog for testing. + """ + 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) + + # Min/max values widgets + decimals = 2 + max_value = sys.float_info.max + self._min_widget = DlgRef_1Spin_QTD('Tol Min', 0, decimals, max_value) + self._max_widget = DlgRef_1Spin_QTD('Tol Max', 1000, decimals, max_value) + self._min_widget.SpinBox_DX.valueChanged.connect(self.on_limit_changed) + self._max_widget.SpinBox_DX.valueChanged.connect(self.on_limit_changed) + + # Debug checkbox + #_debug_label = QLabel('Debug') + self._debug = QCheckBox("Debug") + self._debug.setChecked(True) + self._debug.stateChanged.connect(lambda:self.onDebugStatechanged()) + + # Add the widgets to layout + layout.addWidget(self._min_widget, 1, 0) + layout.addWidget(self._max_widget, 2, 0) + layout.addWidget(self._debug, 3, 0) + + + # Init base dialog + BaseDlg.__init__( + self, + main_widget, + 'Reparation plugin', + 'reparation_plugin_algo.py', + True, + selection_level + ) + + # Adjust setup from a base class + self._sel_subshape_widget.hide() + self._is_copy_on = False # disable making a copy of object for algo script + + + def get_args(self): + """ + Collects arguments for execution algorithm into a dictionary. + + Args: + None. + + Returns: + Dictionary with arguments for execution. + """ + + # Update selection with a current values + + # Collect current values for the execution + selected_ids = self.get_local_selection() + selection_level = self.get_selection_level() + min, max = self.get_limits() + min_selected = 0 + + if self.is_selection_valid(selected_ids, min_selected): + return { + 'selected_ids': selected_ids, + 'result_name': self.get_result_name(), + 'selection_level': selection_level, + 'Tol_min' : min, + 'Tol_max' : max, + 'Debug' : self._debug.isChecked() + } + + return None + + def onDebugStatechanged(self,): + if self._debug.isChecked(): + print("Debug is checked") + else: + print("Debug is unchecked") + + 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 set_limits(self, min_value, max_value): + """ + Sets given values for min/max limits. + + Args: + None. + + Returns: + None. + """ + + self._min_widget.SpinBox_DX.setValue(min_value) + self._max_widget.SpinBox_DX.setValue(max_value) + + def on_limit_changed(self): + """ + One of the limits was changed. + + Args: + None. + + Returns: + None. + """ + + # TODO: Do we need an interactive change here? + # self.select_subshapes_in_limits() + print('limit changed') + min, max = self.get_limits() + print("{} - {}".format(min, max)) + + + def on_select_object(self): + """ + Override parent's method to display sub-shapes info. + + Args: + None. + + Returns: + None. + """ + + # Call parent method first + super().on_select_object() + + +# 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.reparation_plugin +if __name__ == '__main__': + app = QApplication(sys.argv) + + dlg = Reparation_plugin(None) + dlg.show() + + sys.exit(app.exec_()) diff --git a/src/RepairGUIAdv/reparation_plugin_algo.py b/src/RepairGUIAdv/reparation_plugin_algo.py new file mode 100644 index 000000000..9a478004b --- /dev/null +++ b/src/RepairGUIAdv/reparation_plugin_algo.py @@ -0,0 +1,147 @@ +# -*- 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 : Duc Anh HOANG (OpenCascade S.A.S) + +"""Example of algorithm script for GEOM Locate Subshapes plugin. +""" + +import sys +import logging +from time import sleep + +import salome + +from salome.geom import geomBuilder +from qtsalome import QFileDialog, QApplication, pyqtSignal +import GEOM + + +salome.salome_init() +geompy = geomBuilder.New() + + +def run(args_dict, progress_emitter): + """ + Helper function to call run() with arguments parsed from dictionary. + + Args: + args_dict - arguments as pairs string : any type value + + Returns: + A result object. + """ + + logging.info('Run Locate Reparation algorithm.') + progress_emitter.emit() + sleep(1) + + if ('source_solid' not in args_dict or + 'selected_ids' not in args_dict or + 'result_name' not in args_dict or + 'selection_level' not in args_dict or + 'Tol_min' not in args_dict or + 'Tol_max' not in args_dict or + 'Debug' not in args_dict): + + logging.info('Cant execute an algo because the arguments are empty!') + return False + + source_solid = args_dict['source_solid'] + selected_ids = args_dict['selected_ids'] + result_name = args_dict['result_name'] + selection_level = args_dict['selection_level'] + Tol_min = args_dict['Tol_min'] + Tol_max = args_dict['Tol_max'] + Debug = args_dict['Debug'] + + # Replace the lines below with an actual algorithm + logging.info('Received arguments:') + logging.info('\tsource_solid: %s', source_solid) + logging.info('\tselected_ids: %s', selected_ids) + logging.info('\tresult_name: %s', result_name) + logging.info('\tselection_level: %s', selection_level) + logging.info('\Tol_min: %s', Tol_min) + logging.info('\Tol_max: %s', Tol_max) + logging.info('\Debug: %s', Debug) + + progress_emitter.emit() + sleep(1) + + # Make a group + # geomBuilder uses their own types - geomBuilder.ShapeType + geom_builder_types = { GEOM.EDGE : 'EDGE', GEOM.FACE : 'FACE', GEOM.SOLID : 'SOLID' } + type_str = geom_builder_types[selection_level] + shape_type = geompy.ShapeType[type_str] + group = geompy.CreateGroup(source_solid, shape_type, theName = result_name) + + logging.info('Step1.') + progress_emitter.emit() + sleep(1) + + # Add sub-shapes into the group + for subshape_id in selected_ids: + geompy.AddObject(group, subshape_id) + + logging.info('Step2.') + progress_emitter.emit() + + return group + + +def test(): + """ + Tests execution of repair algo script. + """ + + logging.basicConfig(level=logging.DEBUG) + + test_file, _ = QFileDialog.getOpenFileName(None, 'Open brep', '/home', 'Brep Files (*.brep)') + if not test_file: + return + + # test_file = "PartitionCube.brep" + source_solid = geompy.ImportBREP(test_file) + geompy.addToStudy(source_solid, "source_solid") + + selection_level = GEOM.EDGE + + # TODO: Implement for actual algorithm + # Here we just use all ids. + all_subshapes = geompy.SubShapeAllIDs(source_solid, selection_level) + + args_dict = { + 'source_solid': source_solid, + 'selected_ids': all_subshapes, + 'result_name': 'LocateSubshapes_result', + 'selection_level': selection_level + } + + # Dummy emitter + # TODO: doesn't work + # progress_emitter = pyqtSignal() + progress_emitter = type('DummyEmitter', (object,), {'emit': lambda self: sleep(0.1)})() + + run(args_dict, progress_emitter) + + +if __name__ == "__main__": + app = QApplication(sys.argv) + test() + sys.exit(app.exec_()) -- 2.39.2