--- /dev/null
+# -*- 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_())
--- /dev/null
+# -*- 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_())