From 61db0a0614c350a3b3768adc909a163203941d19 Mon Sep 17 00:00:00 2001 From: Paul RASCLE Date: Tue, 1 Dec 2020 23:14:06 +0100 Subject: [PATCH] cut mesh by shape dialog --- src/HYDROTools/CMakeLists.txt | 2 +- src/HYDROTools/hydro_plugins.py | 19 +- src/HYDROTools/plugins/CMakeLists.txt | 2 + src/HYDROTools/plugins/cutMesh.ui | 504 ++++++++++++++++++++++++ src/HYDROTools/plugins/cutMeshDialog.py | 244 ++++++++++++ 5 files changed, 765 insertions(+), 6 deletions(-) create mode 100644 src/HYDROTools/plugins/cutMesh.ui create mode 100644 src/HYDROTools/plugins/cutMeshDialog.py diff --git a/src/HYDROTools/CMakeLists.txt b/src/HYDROTools/CMakeLists.txt index 551b8322..7eda5fa4 100644 --- a/src/HYDROTools/CMakeLists.txt +++ b/src/HYDROTools/CMakeLists.txt @@ -34,7 +34,7 @@ SET(PYFILES # --- plugins dialogs ADD_SUBDIRECTORY(plugins) -ADD_SUBDIRECTORY(testPlugin) +#ADD_SUBDIRECTORY(testPlugin) # --- plugin scripts / static diff --git a/src/HYDROTools/hydro_plugins.py b/src/HYDROTools/hydro_plugins.py index c86b138a..0fe2dbad 100644 --- a/src/HYDROTools/hydro_plugins.py +++ b/src/HYDROTools/hydro_plugins.py @@ -42,11 +42,20 @@ except Exception as e: pass try: - from testPlugin import testDialog - salome_pluginsmanager.AddFunction('test Dialog', - 'test Dialog not implemented', - testDialog.execDialog) + from plugins import cutMeshDialog + salome_pluginsmanager.AddFunction('Cut Mesh', + 'Cut a mesh by a polyline shape', + cutMeshDialog.execDialog) except Exception as e: - salome_pluginsmanager.logger.info('ERROR: test plug-in is unavailable: {}'.format(e)) + salome_pluginsmanager.logger.info('ERROR: cutMesh plug-in is unavailable: {}'.format(e)) pass +# try: +# from testPlugin import testDialog +# salome_pluginsmanager.AddFunction('test Dialog', +# 'test Dialog not implemented', +# testDialog.execDialog) +# except Exception as e: +# salome_pluginsmanager.logger.info('ERROR: test plug-in is unavailable: {}'.format(e)) +# pass + diff --git a/src/HYDROTools/plugins/CMakeLists.txt b/src/HYDROTools/plugins/CMakeLists.txt index e01a3d4b..653e4ed0 100644 --- a/src/HYDROTools/plugins/CMakeLists.txt +++ b/src/HYDROTools/plugins/CMakeLists.txt @@ -21,11 +21,13 @@ SET(PLUGIN_SCRIPTS __init__.py meshEdgesToShapesDialog.py fitShapePointsToMeshEdgesDialog.py + cutMeshDialog.py ) SET(UIFILES meshEdgesToShapes.ui fitShapePointsToMeshEdges.ui + cutMesh.ui ) # --- rules --- diff --git a/src/HYDROTools/plugins/cutMesh.ui b/src/HYDROTools/plugins/cutMesh.ui new file mode 100644 index 00000000..c540c328 --- /dev/null +++ b/src/HYDROTools/plugins/cutMesh.ui @@ -0,0 +1,504 @@ + + + Dialog + + + + 0 + 0 + 817 + 440 + + + + Cut a mesh by a polyline shape + + + Qt::LeftToRight + + + + + + Input + + + + + + + + + 0 + 0 + + + + MED file + + + + + + + Select a mesh in the Object Browser + + + ... + + + + + + + + + + + 0 + 0 + + + + Select a mesh in the file system + + + ... + + + + + + + + + + + + 0 + 0 + + + + Offset X + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Offset Y + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Y coordinate of origin of input mesh + + + 0 + + + -10000000.000000000000000 + + + 10000000.000000000000000 + + + + + + + + 0 + 0 + + + + X coordinate of origin of input mesh + + + Qt::LeftToRight + + + 0 + + + -100000000.000000000000000 + + + 10000000.000000000000000 + + + + + + + + + + + + 0 + 0 + + + + Cutting shapefile + + + + + + + Select a shape in the HYDRO object browser + + + ... + + + + + + + + + + + 0 + 0 + + + + Select a shapefile in the file system + + + ... + + + + + + + + + + + + Output + + + + + + + + + 0 + 0 + + + + Output dir: + + + + + + + directory to store shapefiles and output mesh file if kept + + + + + + + + 0 + 0 + + + + Select a directory in the file system + + + ... + + + + + + + + + + + + 0 + 0 + + + + Offset X + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Offset Y + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Y coordinate of origin of output mesh + + + 0 + + + -10000000.000000000000000 + + + 10000000.000000000000000 + + + + + + + + 0 + 0 + + + + X coordinate of origin of output mesh + + + Qt::LeftToRight + + + 0 + + + -100000000.000000000000000 + + + 10000000.000000000000000 + + + + + + + + + + + + Qt::Vertical + + + + 20 + 66 + + + + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + Help + + + + + + + + + + + pb_ok + rejected() + Dialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + pb_ok + accepted() + Dialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + dsb_offsetX + valueChanged(double) + dsb_outOffsetX + setValue(double) + + + 142 + 87 + + + 142 + 263 + + + + + dsb_offsetY + valueChanged(double) + dsb_outOffsetY + setValue(double) + + + 142 + 119 + + + 142 + 295 + + + + + diff --git a/src/HYDROTools/plugins/cutMeshDialog.py b/src/HYDROTools/plugins/cutMeshDialog.py new file mode 100644 index 00000000..bcb7067a --- /dev/null +++ b/src/HYDROTools/plugins/cutMeshDialog.py @@ -0,0 +1,244 @@ +# Copyright (C) 2012-2013 EDF +# +# This file is part of SALOME HYDRO module. +# +# SALOME HYDRO module is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# SALOME HYDRO module 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with SALOME HYDRO module. If not, see . + +import os +import sys +import salome + +salome.salome_init() + +import SalomePyQt +sgPyQt = SalomePyQt.SalomePyQt() +import libSALOME_Swig +salome_gui = libSALOME_Swig.SALOMEGUI_Swig() + +from PyQt5.QtCore import * +from PyQt5.QtGui import * +from PyQt5.QtWidgets import * +from PyQt5 import uic +from HYDROPy import * +import json + +import tempfile + +from salome.hydrotools.hydroGeoMeshUtils import importPolylines +from salome.hydrotools.changeCoords import changeCoords +from salome.hydrotools.cutMesh import cutMesh + +import SMESH, SALOMEDS +from salome.smesh import smeshBuilder + +hydro_root = os.path.join(os.environ['HYDRO_ROOT_DIR'], 'share', 'salome', 'plugins', 'hydro', 'plugins') +hydro_resources = os.path.join(os.environ['HYDRO_ROOT_DIR'], 'share', 'salome', 'resources', 'hydro') + +class cutMeshDialog(QDialog): + """ + This dialog is used to extract all groups of edges from a mesh, plus all the border (free) edges, + and write the groups as shapefiles. + """ + + def __init__(self, parent = None, modal = 0): + QDialog.__init__(self, parent) + uic.loadUi(os.path.join(hydro_root, 'cutMesh.ui'), self ) + + # Connections + self.pb_medFile.clicked.connect(self.on_med_file_browse) + self.tb_medFile.setIcon(QIcon(QPixmap(os.path.join(hydro_resources, "icon_select.png")))) + self.tb_medFile.clicked.connect(self.on_select_med_file) + self.pb_shapeCut.clicked.connect(self.on_shape_file_browse) + self.tb_shapeCut.setIcon(QIcon(QPixmap(os.path.join(hydro_resources, "icon_select.png")))) + self.tb_shapeCut.clicked.connect(self.on_select_shape_file) + self.pb_outDir.clicked.connect(self.on_outputDir_browse) + self.pb_help.clicked.connect(self.on_help) + self.pb_ok.accepted.connect(self.on_accept) + self.pb_ok.rejected.connect(self.on_reject) + self.medFile = None + self.outDir = None + self.tmpdir = tempfile.mkdtemp() + print("tmpdir=",self.tmpdir) + + def get_selected_mesh(self): + """ + Select a mesh in the object browser and return associated filename + """ + nbsel = salome.sg.SelectedCount() + if nbsel != 1: + return "" + sel=salome.sg.getSelected(0) + so=salome.myStudy.FindObjectID(sel) + if so is None: + return "" + obj=so.GetObject() + smesh = smeshBuilder.New() + smesh.SetEnablePublish( False ) + mesh1 = smesh.Mesh() + smesh.SetEnablePublish( True ) + if not isinstance(obj, type(mesh1.GetMesh())): + return "" + filename = obj.GetMesh().GetMEDFileInfo().fileName + return filename + + def on_select_med_file(self): + """ + set selected mesh filename on dialog + """ + filename = self.get_selected_mesh() + print("selected mesh: %s"%filename) + if filename != "": + self.medFile = filename + self.le_medFile.setText(self.medFile) + + def on_med_file_browse(self): + """ + Select MED file in file system + """ + print("on_med_file_browse") + self.medFile, filt = QFileDialog.getOpenFileName(self, self.tr("Input MED file"), "", self.tr("MED files (*.med)")) + print(self.medFile) + if not self.medFile: + return + self.le_medFile.setText(self.medFile) + + def get_selected_polyline(self): + """ + Select a polyline2D in the HYDRO object browser + """ + ind = SalomePyQt.SalomePyQt.getObjectBrowser().selectionModel().selectedIndexes() + doc = HYDROData_Document.Document() + for i in ind: + if i.column()==0: + name = str(i.data()) + case = doc.FindObjectByName( name ) + if isinstance(case, HYDROData_PolylineXY): + print("selected %s"%name) + return name + return None + + def on_select_shape_file(self): + """ + Get selected Polyline in the HYDRO object browser + """ + name = self.get_selected_polyline() + if name is None: + return + doc = HYDROData_Document.Document() + polyXY = doc.FindObjectByName(name) + if polyXY is None: + return + self.shapeCut = os.path.join(self.tmpdir, name + ".shp") + res = HYDROData_PolylineXY.ExportShapeXY(doc, self.shapeCut, [polyXY]) + self.le_shapeCut.setText(self.shapeCut) + + def on_shape_file_browse(self): + """ + Select shapefile to cut mesh + """ + print("on_shape_file_browse") + self.shapeCut, filt = QFileDialog.getOpenFileName(self, self.tr("shapefile of mesh border edges"), "", self.tr("shapefiles (*.shp)")) + print(self.shapeCut) + if not self.shapeCut: + return + self.le_shapeCut.setText(self.shapeCut) + + + def on_outputDir_browse(self): + """ + Select OutputDirectory + """ + print("on_ouptutDir_browse") + self.outDir = QFileDialog.getExistingDirectory(self, self.tr("Output Directory"), "") + print(self.outDir) + if not self.outDir: + return + self.le_outDir.setText(self.outDir) + + def on_help(self): + """ + display a help message + """ + msg = """ +

Cut a mesh by a polyline shape Dialog

+ + This dialog is used to cut a mesh using a polygonal shape, removing all the nodes and elements inside the shape. +

+ The shape should be in the same system of coordinates of the mesh, without origin offset. +
+ The mesh is saved in a new file. +
+ If the mesh uses a local coordinate system with an origin offset, the coordinates of this origin should be set in the dialog. +

+ Below is the description of the dialog controls. + +

MED file

+ This field allows selection of a med file (via the standard file open dialog). + The filling of this field is mandatory. + +

offsetX, offsetY

+ These fields are used to set the Origin of the local coordinates system of the mesh, if any. + +

Cutting shapefile

+ Select the shape via the standard file open dialog or by selection in the object browser. + +

Output directory

+ This field allows selection of a directory to store the shapes and the outputMesh. + +

offsetX, offsetY

+ These fields are used to set the Origin of the local coordinates system of the output mesh, if any. + """ + QMessageBox.about(self, self.tr("About cut mesh by shape dialog"), msg); + + + def on_accept(self): + print("accept") + medFile = self.le_medFile.text() + offsetX = self.dsb_offsetX.value() + offsetY = self.dsb_offsetY.value() + shapeCut = self.le_shapeCut.text() + outDir = self.le_outDir.text() + outOffsetX = self.dsb_outOffsetX.value() + outOffsetY = self.dsb_outOffsetY.value() + self.accept() + print(medFile) + print(offsetX, offsetY) + print(shapeCut) + print(outDir) + print(outOffsetX, outOffsetY) + a = os.path.splitext(medFile) + + medFileTrans = os.path.join(self.tmpdir, os.path.basename(a[0])+'_trs.med') + changeCoords(medFile, medFileTrans, 2154, 2154, offsetX, offsetY, 0, 0) + + medFileOut = os.path.join(outDir, os.path.basename(a[0]) + '_cut' + a[1]) + print(medFileOut) + meshFileOut = cutMesh(medFileTrans, + shapeCut, + medFileOut, outOffsetX, outOffsetY) + + if salome.sg.hasDesktop(): + salome.sg.updateObjBrowser() + + + def on_reject(self): + print("reject") + self.reject() + + +def execDialog(context): + print("execDialog") + desktop = sgPyQt.getDesktop() + dlg = cutMeshDialog(desktop) + dlg.show() -- 2.39.2