From ba7a525f8c7245b409cbcb7e697408c463751f78 Mon Sep 17 00:00:00 2001 From: Pascal Obry Date: Fri, 9 Sep 2022 15:50:21 +0200 Subject: [PATCH 1/8] Some fixes to compile against ParaView master. --- src/OBJECT/SMESH_DeviceActor.cxx | 4 ++-- src/OBJECT/SMESH_DeviceActor.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/OBJECT/SMESH_DeviceActor.cxx b/src/OBJECT/SMESH_DeviceActor.cxx index 0012cf373..c476156c8 100644 --- a/src/OBJECT/SMESH_DeviceActor.cxx +++ b/src/OBJECT/SMESH_DeviceActor.cxx @@ -60,7 +60,7 @@ #include #include -#include +#include #include @@ -118,7 +118,7 @@ SMESH_DeviceActor myTransformFilter = VTKViewer_TransformFilter::New(); for(int i = 0; i < 6; i++) - myPassFilter.push_back(vtkPassThroughFilter::New()); + myPassFilter.push_back(vtkPassThrough::New()); // Orientation of faces myIsFacesOriented = false; diff --git a/src/OBJECT/SMESH_DeviceActor.h b/src/OBJECT/SMESH_DeviceActor.h index a3724ac6f..258597d4b 100644 --- a/src/OBJECT/SMESH_DeviceActor.h +++ b/src/OBJECT/SMESH_DeviceActor.h @@ -44,7 +44,7 @@ class vtkShrinkFilter; class vtkUnstructuredGrid; class vtkLookupTable; class vtkImplicitBoolean; -class vtkPassThroughFilter; +class vtkPassThrough; class vtkPlaneCollection; class VTKViewer_Transform; @@ -183,7 +183,7 @@ class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{ bool myStoreClippingMapping; VTKViewer_GeometryFilter *myGeomFilter; VTKViewer_TransformFilter *myTransformFilter; - std::vector myPassFilter; + std::vector myPassFilter; vtkShrinkFilter* myShrinkFilter; bool myIsShrinkable; From 1b69b0f98a53cc4ba9bd3d8002aba861d71b4185 Mon Sep 17 00:00:00 2001 From: jfa Date: Wed, 12 Oct 2022 10:06:32 +0300 Subject: [PATCH 2/8] [bos #32505] [CEA] Additional patches for Fedora 36. SPNS-29988-SMESH_V9_9_0.patch --- src/SMESH/SMESH_MeshEditor.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index be874359b..efa01a4c2 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -4636,7 +4636,7 @@ void SMESH_MeshEditor::sweepElement(const SMDS_MeshElement* elem, std::swap( itNN[0], itNN[1] ); std::swap( prevNod[0], prevNod[1] ); std::swap( nextNod[0], nextNod[1] ); - std::swap( isSingleNode[0], isSingleNode[1] ); + std::vector::swap(isSingleNode[0], isSingleNode[1]); if ( nbSame > 0 ) sames[0] = 1 - sames[0]; iNotSameNode = 1 - iNotSameNode; From 246a01ab716909058ec8255c089999a6e2a5d99f Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Fri, 23 Sep 2022 10:40:31 +0200 Subject: [PATCH 3/8] First working version Missing update of object browser + parameters + generic adaptation to shape --- idl/SMESH_Gen.idl | 34 ++- src/SMESHGUI/CMakeLists.txt | 4 + src/SMESHGUI/SMESHGUI.cxx | 12 +- src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx | 86 ++++++ src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h | 59 ++++ src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx | 284 ++++++++++++++++++++ src/SMESHGUI/SMESHGUI_CreateDualMeshOp.h | 64 +++++ src/SMESHGUI/SMESHGUI_Operations.h | 1 + src/SMESH_I/SMESH_2smeshpy.cxx | 21 +- src/SMESH_I/SMESH_Gen_i.cxx | 114 +++++++- src/SMESH_I/SMESH_Gen_i.hxx | 4 + src/SMESH_SWIG/smeshBuilder.py | 164 ++++++----- 12 files changed, 750 insertions(+), 97 deletions(-) create mode 100644 src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx create mode 100644 src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h create mode 100644 src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx create mode 100644 src/SMESHGUI/SMESHGUI_CreateDualMeshOp.h diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 1f25c739f..e9b678031 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -159,12 +159,12 @@ module SMESH Update the study */ void UpdateStudy(); - + /*! Set enable publishing in the study */ void SetEnablePublish( in boolean theIsEnablePublish ); - + /*! Get enable publishing in the study */ @@ -284,6 +284,14 @@ module SMESH in boolean theMakeRequiredGroups, out SMESH::ComputeError theError) raises ( SALOME::SALOME_Exception ); + /*! + * Create a dual mesh of a Tetrahedron mesh + * \param meshPart - TetraHedron mesh to create dual from + * \param meshName - a name of the new mesh + */ + SMESH_Mesh CreateDualMesh(in SMESH_IDSource mesh, + in string meshName) + raises ( SALOME::SALOME_Exception ); /*! * Create a mesh by copying a part of another mesh @@ -305,7 +313,7 @@ module SMESH * \param newGeometry - a new geometry * \param meshName - a name of the new mesh * \param toCopyGroups - to create groups in the new mesh - * \param toReuseHypotheses - if True, existing hypothesis will be used by the new mesh, + * \param toReuseHypotheses - if True, existing hypothesis will be used by the new mesh, * otherwise new hypotheses with the same parameters will be created for the new mesh. * \param toCopyElements - to copy mesh elements of same sub-shapes of the two geometries * \param newMesh - return a new mesh @@ -526,10 +534,10 @@ module SMESH */ long_array GetInsideSphere( in SMESH_IDSource theSource, in ElementType theElemType, - in double theX, - in double theY, + in double theX, + in double theY, in double theZ, - in double theR ); + in double theR ); /*! * Return indices of elements, which are located inside the box @@ -544,12 +552,12 @@ module SMESH */ long_array GetInsideBox( in SMESH_IDSource theSource, in ElementType theElemType, - in double theX1, - in double theY1, + in double theX1, + in double theY1, in double theZ1, in double theX2, in double theY2, - in double theZ2); + in double theZ2); /*! * Return indices of elements, which are located inside the box * \param theSource - mesh, sub-mesh or group @@ -565,14 +573,14 @@ module SMESH */ long_array GetInsideCylinder( in SMESH_IDSource theSource, in ElementType theElemType, - in double theX, - in double theY, + in double theX, + in double theY, in double theZ, in double theDX, in double theDY, in double theDZ, in double theH, - in double theR ); + in double theR ); /*! * Return indices of elements, which are located inside the geometry * \param theSource - mesh, sub-mesh or group @@ -583,7 +591,7 @@ module SMESH long_array GetInside( in SMESH_IDSource theSource, in ElementType theElemType, in GEOM::GEOM_Object theGeom, - in double theTolerance ); + in double theTolerance ); MG_ADAPT CreateMG_ADAPT(); SMESHHOMARD::HOMARD_Gen CreateHOMARD_ADAPT() raises ( SALOME::SALOME_Exception ); diff --git a/src/SMESHGUI/CMakeLists.txt b/src/SMESHGUI/CMakeLists.txt index ff26f0dc0..2ab720fc6 100644 --- a/src/SMESHGUI/CMakeLists.txt +++ b/src/SMESHGUI/CMakeLists.txt @@ -157,6 +157,8 @@ SET(_moc_HEADERS SMESHGUI_AddNodeOnSegmentDlg.h SMESHGUI_AddNodeOnFaceDlg.h SMESHGUI_InteractiveOp.h + SMESHGUI_CreateDualMeshDlg.h + SMESHGUI_CreateDualMeshOp.h ) # header files / no moc processing @@ -283,6 +285,8 @@ SET(_other_SOURCES SMESHGUI_AddNodeOnSegmentDlg.cxx SMESHGUI_AddNodeOnFaceDlg.cxx SMESHGUI_InteractiveOp.cxx + SMESHGUI_CreateDualMeshDlg.cxx + SMESHGUI_CreateDualMeshOp.cxx ) # sources / to compile diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index c326027ed..e57f7ea4d 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -97,6 +97,8 @@ #include "SMESHGUI_SymmetryDlg.h" #include "SMESHGUI_TranslationDlg.h" #include "SMESHGUI_TransparencyDlg.h" +#include "SMESHGUI_CreateDualMeshDlg.h" +#include "SMESHGUI_CreateDualMeshOp.h" #include "SMESHGUI_Utils.h" #include "SMESHGUI_VTKUtils.h" @@ -2142,7 +2144,7 @@ SMESHGUI::SMESHGUI() : SalomeApp_Module( "SMESH" ) { CORBA::Boolean anIsEmbeddedMode; myComponentSMESH = SMESH_Client::GetSMESHGen(getApp()->orb(),anIsEmbeddedMode); - + //MESSAGE("-------------------------------> anIsEmbeddedMode=" << anIsEmbeddedMode); // 0019923: EDF 765 SMESH : default values of hypothesis @@ -3051,6 +3053,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) // Adaptation - end case SMESHOp::OpSplitBiQuadratic: case SMESHOp::OpConvertMeshToQuadratic: + case SMESHOp::OpCreateDualMesh: case SMESHOp::OpCreateBoundaryElements: // create 2D mesh from 3D case SMESHOp::OpReorientFaces: case SMESHOp::OpCreateGeometryGroup: @@ -4275,6 +4278,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( SMESHOp::OpRevolution, "REVOLUTION", "ICON_REVOLUTION" ); createSMESHAction( SMESHOp::OpPatternMapping, "MAP", "ICON_MAP" ); createSMESHAction( SMESHOp::OpConvertMeshToQuadratic, "CONV_TO_QUAD", "ICON_CONV_TO_QUAD" ); + createSMESHAction( SMESHOp::OpCreateDualMesh, "CREATE_DUAL_MESH","ICON_CREATE_DUAL_MESH" ); createSMESHAction( SMESHOp::OpCreateBoundaryElements, "2D_FROM_3D", "ICON_2D_FROM_3D" ); createSMESHAction( SMESHOp::OpReset, "RESET" ); @@ -4524,6 +4528,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( SMESHOp::OpConvertMeshToQuadratic, modifyId, -1 ); createMenu( SMESHOp::OpCreateBoundaryElements, modifyId, -1 ); + createMenu( SMESHOp::OpCreateDualMesh, modifyId, -1 ); createMenu( SMESHOp::OpExtrusion, modifyId, -1 ); createMenu( SMESHOp::OpExtrusionAlongAPath, modifyId, -1 ); createMenu( SMESHOp::OpRevolution, modifyId, -1 ); @@ -4675,6 +4680,7 @@ void SMESHGUI::initialize( CAM_Application* app ) int modifyTb = createTool( tr( "TB_MODIFY" ), QString( "SMESHModificationToolbar" ) ) ; createTool( SMESHOp::OpConvertMeshToQuadratic, modifyTb ); + createTool( SMESHOp::OpCreateDualMesh, modifyTb ); createTool( SMESHOp::OpCreateBoundaryElements, modifyTb ); createTool( SMESHOp::OpExtrusion, modifyTb ); createTool( SMESHOp::OpExtrusionAlongAPath, modifyTb ); @@ -4788,6 +4794,7 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->insert( separator(), -1, 0 ); createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh_submesh, "&& " + hasElems ); createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh_group, "&& selcount=1 && dim>=2"); + createPopupItem( SMESHOp::OpCreateDualMesh, OB, mesh_submesh, "&& selcount=1 && dim>=2"); // Adaptation - begin popupMgr()->insert( separator(), -1, 0 ); @@ -6025,6 +6032,9 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const case SMESHOp::OpCreateBoundaryElements: // create 2D mesh as boundary on 3D op = new SMESHGUI_Make2DFrom3DOp(); break; + case SMESHOp::OpCreateDualMesh: + op = new SMESHGUI_CreateDualMeshOp(); + break; case SMESHOp::OpReorientFaces: op = new SMESHGUI_ReorientFacesOp(); break; diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx new file mode 100644 index 000000000..614220058 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx @@ -0,0 +1,86 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CreateDualMeshDlg.cxx +// Author : Yoann AUDOUIN (EDF) +// SMESH includes +// +#include "SMESHGUI_CreateDualMeshDlg.h" + +#include "SMESHGUI_CreateDualMeshOp.h" + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SPACING 6 +#define MARGIN 11 + +SMESHGUI_CreateDualMeshDlg::SMESHGUI_CreateDualMeshDlg() + : SMESHGUI_Dialog( 0, false, true ) +{ + setWindowTitle( tr( "CAPTION" ) ); + + // Create top controls + + // mesh + setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) ); + createObject( tr( "MESH" ), mainFrame(), 0 ); + + myWarning = new QLabel(QString("%1").arg(tr("NON_TETRA_MESH_WARNING")), mainFrame()); + + // Fill layout + QGridLayout* aLay = new QGridLayout( mainFrame() ); + aLay->setMargin( 5 ); + aLay->setSpacing( 5 ); + + aLay->addWidget( objectWg( 0, Label ), 0, 0 ); + aLay->addWidget( objectWg( 0, Btn ), 0, 1 ); + aLay->addWidget( objectWg( 0, Control ), 0, 2 ); + aLay->addWidget( myWarning, 3, 0, 1, 3 ); + +} + +SMESHGUI_CreateDualMeshDlg::~SMESHGUI_CreateDualMeshDlg() +{ +} + +void SMESHGUI_CreateDualMeshDlg::ShowWarning(bool toShow) +{ + if ( toShow ) + myWarning->show(); + else + myWarning->hide(); +} + +bool SMESHGUI_CreateDualMeshDlg::isWarningShown() +{ + return myWarning->isVisible(); +} \ No newline at end of file diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h new file mode 100644 index 000000000..e5096b237 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h @@ -0,0 +1,59 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CreateDualMeshDlg.h +// Author : Yoann Audouin (EDF) +// +#ifndef SMESHGUI_CREATEDUALMESHDLG_H +#define SMESHGUI_CREATEDUALMESHDLG_H + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" + +#include "SMESHGUI_Dialog.h" + +class QCheckBox; +class QRadioButton; +class QButtonGroup; +class QGroupBox; +class QLabel; + +class SMESHGUI_EXPORT SMESHGUI_CreateDualMeshDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + +public: + SMESHGUI_CreateDualMeshDlg(); + virtual ~SMESHGUI_CreateDualMeshDlg(); + + void ShowWarning(bool); + bool isWarningShown(); + +signals: + void onClicked( int ); + +private: + QLabel* myWarning; +}; + +#endif // SMESHGUI_CREATEDUALMESHDLG_H diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx new file mode 100644 index 000000000..25f811700 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx @@ -0,0 +1,284 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CreateDualMeshOp.cxx +// Author : Yoann AUDOUIN (EDF) +// SMESH includes +// +#include "SMESHGUI_CreateDualMeshOp.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_CreateDualMeshDlg.h" +#include "SMESHGUI_MeshEditPreview.h" +#include "SMESHGUI_Utils.h" +#include "SMESH_ActorUtils.h" +#include "SMESH_TypeFilter.hxx" +#include "SMDSAbs_ElementType.hxx" + +// SALOME GUI includes +#include +#include +#include +#include +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) + +// VTK includes +#include + +//================================================================================ +/*! + * \brief Constructor + * + * Initialize operation +*/ +//================================================================================ +SMESHGUI_CreateDualMeshOp::SMESHGUI_CreateDualMeshOp() + : SMESHGUI_SelectionOp(), + myDlg( 0 ) +{ +} + +//================================================================================ +/*! + * \brief Destructor +*/ +//================================================================================ +SMESHGUI_CreateDualMeshOp::~SMESHGUI_CreateDualMeshOp() +{ + if ( myDlg ) delete myDlg; +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation +*/ +//================================================================================ +LightApp_Dialog* SMESHGUI_CreateDualMeshOp::dlg() const +{ + return myDlg; +} + +//================================================================================ +/*! + * \brief Creates dialog if necessary and shows it + * + * Virtual method redefined from base class called when operation is started creates + * dialog if necessary and shows it, activates selection + */ +//================================================================================ +void SMESHGUI_CreateDualMeshOp::startOperation() +{ + if( !myDlg ) + { + myDlg = new SMESHGUI_CreateDualMeshDlg( ); + } + connect( myDlg, SIGNAL( onClicked( int ) ), SLOT( ConnectRadioButtons( int ) ) ); + + myHelpFileName = "create_dual_mesh.html"; + + SMESHGUI_SelectionOp::startOperation(); + + myDlg->activateObject( 0 ); + myDlg->ShowWarning( false ); + myDlg->show(); + + selectionDone(); +} + +//================================================================================ +/*! + * \brief Updates dialog's look and feel + * + * Virtual method redefined from the base class updates dialog's look and feel + */ +//================================================================================ +void SMESHGUI_CreateDualMeshOp::selectionDone() +{ + if ( !dlg()->isVisible() ) + return; + + SMESHGUI_SelectionOp::selectionDone(); + try + { + QString anObjEntry = myDlg->selectedObject( 0 ); + _PTR(SObject) pObj = SMESH::getStudy()->FindObjectID( anObjEntry.toUtf8().data() ); + if ( !pObj ) return; + + SMESH::SMESH_IDSource_var idSource = + SMESH::SObjectToInterface( pObj ); + + myDlg->setButtonEnabled( true, QtxDialog::OK | QtxDialog::Apply ); + if( idSource->_is_nil() ) + { + myDlg->setButtonEnabled( false, QtxDialog::OK | QtxDialog::Apply ); + return; + } + SMESH::SMESH_Mesh_var mesh = idSource->GetMesh(); + + // show warning on non-conformal result mesh + if ( ! idSource->_is_nil() ) + { + SMESH::SMESH_subMesh_var subMesh = + SMESH::SObjectToInterface( pObj ); + // TODO: Check that mesh is only tetra + if (!checkMesh(idSource)){ + myDlg->ShowWarning( true ); + } + } + } + catch ( const SALOME::SALOME_Exception& S_ex ) + { + SalomeApp_Tools::QtCatchCorbaException( S_ex ); + } + catch ( ... ) + { + } +} + +//================================================================================ +/*! + * \brief Creates selection filter + * \param theId - identifier of current selection widget + * \retval SUIT_SelectionFilter* - pointer to the created filter or null + * + * Creates selection filter in accordance with identifier of current selection widget + */ +//================================================================================ +SUIT_SelectionFilter* SMESHGUI_CreateDualMeshOp::createFilter( const int theId ) const +{ + if ( theId == 0 ) + return new SMESH_TypeFilter( SMESH::MESHorSUBMESH ); + else + return 0; +} + +//================================================================================ +/*! + * \brief Edits mesh + * + * Virtual slot redefined from the base class called when "Apply" button is clicked + */ +//================================================================================ +bool SMESHGUI_CreateDualMeshOp::onApply() +{ + SUIT_OverrideCursor aWaitCursor; + + QString aMess; + QStringList anEntryList; + + QString anObjEntry = myDlg->selectedObject( 0 ); + _PTR(SObject) pObj = SMESH::getStudy()->FindObjectID( anObjEntry.toUtf8().data() ); + if ( !pObj ) + { + dlg()->show(); + SUIT_MessageBox::warning( myDlg, + tr( "SMESH_WRN_WARNING" ), tr("MESH_IS_NOT_SELECTED") ); + return false; + } + + SMESH::SMESH_Mesh_var mesh; + SMESH::SMESH_IDSource_var idSource = + SMESH::SObjectToInterface( pObj ); + if( !CORBA::is_nil(idSource) ) + mesh = idSource->GetMesh(); + + if( CORBA::is_nil(mesh) ) + { + SUIT_MessageBox::warning( myDlg, + tr( "SMESH_WRN_WARNING" ), tr("REF_IS_NULL") ); + return false; + } + + bool aResult = false; + SMESH::SMESH_Gen_var gen = SMESHGUI::GetSMESHGen(); + SMESH::SMESH_Mesh_var newMesh; + QByteArray newMeshName="MESH_DUAL"; + try + { + // TODO: Call the python script using medcoupling + // String to run medcoupling dual + // TODO: change name as previous name + "_dual" + newMesh = gen->CreateDualMesh(mesh, newMeshName.constData()); + + if ( !newMesh->_is_nil() ) + if ( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) ) + { + anEntryList.append( aSObject->GetID().c_str() ); + + SMESH::SetName( aSObject, newMeshName ); + } + aResult = true; + } + catch ( const SALOME::SALOME_Exception& S_ex ) + { + SalomeApp_Tools::QtCatchCorbaException( S_ex ); + aResult = false; + } + catch ( ... ) + { + aResult = false; + } + if( aResult ) + { + SMESHGUI::Modified(); + update( UF_ObjBrowser | UF_Model | UF_Viewer ); + selectionDone(); + } + + + // updateObjBrowser(true); + // SMESHGUI::Modified(); + + // if( LightApp_Application* anApp = + // dynamic_cast( SUIT_Session::session()->activeApplication() ) ) + // anApp->browseObjects( anEntryList, true ); + + return true; + +} + +//================================================================================ +/*! checkMesh + * Verify that mesh as only tetraheadrons as 3D elements + */ +//================================================================================ + +bool +SMESHGUI_CreateDualMeshOp::checkMesh( const SMESH::SMESH_IDSource_var& idSource) +{ + SMESH::smIdType_array_var nbElemOfType = idSource->GetMeshInfo(); + // Checking that the mesh only has Tetrahedron + bool hasOnlyTetra = ( + nbElemOfType[SMDSEntity_Tetra ] && + !nbElemOfType[SMDSEntity_Hexa ] && + !nbElemOfType[SMDSEntity_Pyramid ] && + !nbElemOfType[SMDSEntity_Polygon ] && + !nbElemOfType[SMDSEntity_Penta ] ); + + return hasOnlyTetra; +} diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.h b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.h new file mode 100644 index 000000000..cc928e6a3 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.h @@ -0,0 +1,64 @@ +// Copyright (C) 2007-2021 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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 http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CreateDualMeshOp.h +// Author : Yoann AUDOUIN (EDF) +// +#ifndef SMESHGUI_CREATEDUALMESHOP_H +#define SMESHGUI_CREATEDUALMESHOP_H + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" + +#include "SMESHGUI_SelectionOp.h" + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +class SMESHGUI_CreateDualMeshDlg; + +class SMESHGUI_EXPORT SMESHGUI_CreateDualMeshOp : public SMESHGUI_SelectionOp +{ + Q_OBJECT + +public: + SMESHGUI_CreateDualMeshOp(); + virtual ~SMESHGUI_CreateDualMeshOp(); + + virtual LightApp_Dialog* dlg() const; + + static bool checkMesh( const SMESH::SMESH_IDSource_var& ); +protected: + virtual void startOperation(); + virtual void selectionDone(); + virtual SUIT_SelectionFilter* createFilter( const int ) const; + +protected slots: + virtual bool onApply(); + +private: + SMESHGUI_CreateDualMeshDlg* myDlg; +}; + +#endif // SMESHGUI_CREATEDUALMESHOP_H diff --git a/src/SMESHGUI/SMESHGUI_Operations.h b/src/SMESHGUI/SMESHGUI_Operations.h index bb1596ec8..4fe19ff50 100644 --- a/src/SMESHGUI/SMESHGUI_Operations.h +++ b/src/SMESHGUI/SMESHGUI_Operations.h @@ -186,6 +186,7 @@ namespace SMESHOp { OpMoveNodeInteractive = 4516, // MENU MODIFICATION - MOVE NODE INTERACTIVE OpSplitEdgeInteract = 4517, // MENU MODIFICATION - INTERACTIVE ADD NODE ON EDGE OpSplitFaceInteract = 4518, // MENU MODIFICATION - INTERACTIVE ADD NODE ON FACE + OpCreateDualMesh = 4519, // MENU MODIFICATION - CREATE DUAL MESH // Adaptation ---------------------//-------------------------------- OpMGAdapt = 8020, // MENU ADAPTATION - MG-ADAPT OpHomardAdapt = 8021, // MENU ADAPTATION - HOMARD-ADAPT diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index 22e47dc9c..03a600094 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -458,7 +458,7 @@ namespace { initialized = true; filteredArgs.push_back( "SMESH.MED_V2_1" ); filteredArgs.push_back( "SMESH.MED_V2_2" ); - } + } return std::find( filteredArgs.begin(), filteredArgs.end(), theArg ) != filteredArgs.end(); } } @@ -1022,6 +1022,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) } if ( method == "CreateMeshesFromUNV" || method == "CreateMeshesFromSTL" || + method == "CreateDualMesh" || method == "CopyMesh" ) // command result is a mesh { Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() ); @@ -1827,7 +1828,7 @@ _pyMesh::_pyMesh(const Handle(_pyCommand) theCreationCmd, const _pyID& meshId): const _pyID& meshID = theCreationCmd->GetObject(); addFatherMesh( meshID ); } - + // convert my creation command Handle(_pyCommand) creationCmd = GetCreationCmd(); creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() ); @@ -2419,7 +2420,7 @@ void _pyMesh::ClearCommands() list< Handle(_pySubMesh) >::iterator sm = mySubmeshes.begin(); for ( ; sm != mySubmeshes.end(); ++sm ) (*sm)->ClearCommands(); - + list< Handle(_pyGroup) >::iterator gr = myGroups.begin(); for ( ; gr != myGroups.end(); ++gr ) (*gr)->ClearCommands(); @@ -2579,7 +2580,7 @@ void _pyMeshEditor::Process( const Handle(_pyCommand)& theCommand) // 1. Remove "MakeGroups" from the Command TCollection_AsciiString aMethod = theCommand->GetMethod(); int nbArgsToAdd = diffLastTwoArgsMethods.Contains(aMethod) ? 2 : 1; - + if(is0DmethObj) pos = pos-2; //Remove "0D" from the Command too aMethod.Trunc(pos-1); @@ -3410,7 +3411,7 @@ void _pyLayerDistributionHypo::Flush() list< Handle(_pyCommand) >::iterator cmd = myArgCommands.begin(); _pyID prevNewName; for ( cmd = myArgCommands.begin(); cmd != myArgCommands.end(); ++cmd ) - { + { const _pyID& hyp1dID = (*cmd)->GetArg( 1 ); if ( hyp1dID.IsEmpty() ) continue; @@ -3434,7 +3435,7 @@ void _pyLayerDistributionHypo::Flush() } newName += "_Distribution"; prevNewName = newName; - + hyp1d->GetCreationCmd()->SetResultValue( newName ); } list< Handle(_pyCommand) >& cmds = theGen->GetCommands(); @@ -4631,7 +4632,7 @@ _pyGroup::_pyGroup(const Handle(_pyCommand)& theCreationCmd, const _pyID & id) //================================================================================ /*! - * \brief Check if "[ group1, group2 ] = mesh.GetGroups()" creation command + * \brief Check if "[ group1, group2 ] = mesh.GetGroups()" creation command * can be cleared */ //================================================================================ @@ -4802,7 +4803,7 @@ void _pyFilter::Process( const Handle(_pyCommand)& theCommand) if ( !myNewID.IsEmpty() ) theCommand->SetObject( myNewID ); - + // Convert the following set of commands into smesh.GetFilterFromCriteria(criteria) // aFilter0x2aaab0487080 = aFilterManager.CreateFilter() // aFilter0x2aaab0487080.SetCriteria(aCriteria) @@ -4845,7 +4846,7 @@ void _pyFilter::Process( const Handle(_pyCommand)& theCommand) void _pyFilter::Flush() { if ( myNewID.IsEmpty() ) return; - + list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin(); for ( ; cmd != myArgCmds.end(); ++cmd ) if ( !(*cmd)->IsEmpty() ) @@ -4982,7 +4983,7 @@ _pyHypothesisReader::_pyHypothesisReader() // ... // dim="2"> // - // + // // SetEnforcedVertex, // SetEnforcedVertexNamed // diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index cfc7c95b5..79d031823 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -49,6 +49,10 @@ #include #include +// Have to be included before std headers +#include +#include + #ifdef WIN32 #include #include @@ -2802,6 +2806,114 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray, return newMesh._retn(); } + +//================================================================================ +/*! + * \brief Create a mesh by copying a part of another mesh + * \param mesh - TetraHedron mesh + * \param meshName Name of the created mesh + * \retval SMESH::SMESH_Mesh_ptr - the new mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh, + const char* meshName) +{ + Unexpect aCatch(SALOME_SalomeException); + + TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh() + std::unique_ptr pyDumpDeleter( pyDump ); + + // 1. Get source mesh + + if ( CORBA::is_nil( mesh )) + THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM ); + + std::cout << mesh << std::endl; + SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh(); + SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( srcMesh ); + if ( !srcMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM ); + + SMESH_Mesh& srcMesh2 = srcMesh_i->GetImpl(); + + // TODO: Get it + CORBA::String_var mesh_ior=GetORB()->object_to_string(mesh); + std::string mesh_id = mesh_ior.in(); + std::string dual_mesh_file="/tmp/test_dual.med"; + std::string mesh_name = "MESH"; + + std::string python_code; + python_code += "import sys\n"; + python_code += "import salome\n"; + python_code += "import medcoupling as mc\n"; + python_code += "from math import pi\n"; + python_code += "salome.salome_init()\n"; + python_code += "import GEOM\n"; + python_code += "from salome.geom import geomBuilder\n"; + python_code += "geompy = geomBuilder.New()\n"; + python_code += "import SMESH, SALOMEDS\n"; + python_code += "from salome.smesh import smeshBuilder\n"; + python_code += "smesh = smeshBuilder.New()\n"; + python_code += "def create_dual_mesh(mesh_ior, output_file):\n"; + python_code += " mesh = salome.orb.string_to_object(mesh_ior)\n"; + python_code += " shape = mesh.GetShapeToMesh()\n"; + python_code += " if not mesh:\n"; + python_code += " raise Exception(\"Could not find mesh using id: \", mesh_id)\n"; + python_code += " int_ptr = mesh.ExportMEDCoupling(True, True)\n"; + python_code += " dab = mc.FromPyIntPtrToDataArrayByte(int_ptr)\n"; + python_code += " tetras = mc.MEDFileMesh.New(dab)[0]\n"; + python_code += " tetras = mc.MEDCoupling1SGTUMesh(tetras)\n"; + python_code += " polyh = tetras.computeDualMesh()\n"; + python_code += " skin = tetras.buildUnstructured().computeSkin()\n"; + python_code += " skin_polyh = polyh.buildUnstructured().computeSkin()\n"; + python_code += " allNodesOnSkinPolyh = skin_polyh.computeFetchedNodeIds()\n"; + python_code += " allNodesOnSkin = skin.computeFetchedNodeIds()\n"; + python_code += " ptsAdded = allNodesOnSkinPolyh.buildSubstraction(allNodesOnSkin)\n"; + python_code += " ptsAddedMesh = mc.MEDCouplingUMesh.Build0DMeshFromCoords( skin_polyh.getCoords()[ptsAdded] )\n"; + python_code += " ptsAddedCoo = ptsAddedMesh.getCoords()\n"; + python_code += " ptsAddedCooModified = ptsAddedCoo[:]\n"; + python_code += " polyh.setName(\"MESH\")\n"; + python_code += " polyh.write(output_file)\n"; + + // Running Python script + assert(Py_IsInitialized()); + PyGILState_STATE gstate; + gstate = PyGILState_Ensure(); + PyRun_SimpleString(python_code.c_str()); + std::string cmd=""; + cmd += "create_dual_mesh(\"" + mesh_id + "\", \"" + dual_mesh_file + "\")"; + PyRun_SimpleString(cmd.c_str()); + + PyGILState_Release(gstate); + + // Import created MED + SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil()); + SMESH_Mesh_i* newMesh_i = SMESH::DownCast( newMesh ); + if ( !newMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR ); + SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh ); + if ( !meshSO->_is_nil() ) + { + SetName( meshSO, meshName, "Mesh" ); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); + } + + SMESH_Mesh& newMesh2 = newMesh_i->GetImpl(); + + newMesh2.MEDToMesh(dual_mesh_file.c_str(), "MESH"); + + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); + + newMeshDS->Modified(); + + *pyDump << newMesh << " = " << this + << ".CreateDualMesh( " << mesh << ", " + << "'" << meshName << "') "; + + return newMesh._retn(); +} + //================================================================================ /*! * \brief Create a mesh by copying a part of another mesh @@ -6182,7 +6294,7 @@ CORBA::Long SMESH_Gen_i::GetObjectId(CORBA::Object_ptr theObject) { if ( myStudyContext && !CORBA::is_nil( theObject )) { CORBA::String_var iorString = GetORB()->object_to_string( theObject ); - string iorStringCpp(iorString.in()); + string iorStringCpp(iorString.in()); return myStudyContext->findId( iorStringCpp ); } return 0; diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index ad86102ef..bd8872038 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -253,6 +253,10 @@ public: CORBA::Boolean theMakeRequiredGroups, SMESH::ComputeError_out theError); + // Create dual mesh of a tetrahedron mesh + SMESH::SMESH_Mesh_ptr CreateDualMesh(SMESH::SMESH_IDSource_ptr meshPart, + const char* meshName); + // Copy a part of mesh SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, const char* meshName, diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index d0fa9a291..c46a97751 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -216,7 +216,7 @@ NO_NAME = "NoName" def GetName(obj): """ Return a name of an object - + Returns: object name """ @@ -429,26 +429,26 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): def init_smesh(self,geompyD = None): """ Set Geometry component - """ + """ #print("init_smesh") self.UpdateStudy(geompyD) notebook.myStudy = salome.myStudy def Mesh(self, obj=0, name=0): """ - Create a mesh. This mesh can be either + Create a mesh. This mesh can be either * an empty mesh not bound to geometry, if *obj* == 0 * an empty mesh bound to geometry, if *obj* is GEOM.GEOM_Object * a mesh wrapping a :class:`CORBA mesh ` given as *obj* parameter. Parameters: - obj: either + obj: either 1. a :class:`CORBA mesh ` got by calling e.g. :: - salome.myStudy.FindObjectID("0:1:2:3").GetObject() + salome.myStudy.FindObjectID("0:1:2:3").GetObject() 2. a geometrical object for meshing 3. none. @@ -648,7 +648,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): if sc: sb.LoadWith(sc, self) pass - + def SetEnablePublish( self, theIsEnablePublish ): """ Set enable publishing in the study. Calling SetEnablePublish( False ) allows to @@ -677,7 +677,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Create a Mesh object(s) importing data from the given MED file Returns: - a tuple ( list of class :class:`Mesh` instances, + a tuple ( list of class :class:`Mesh` instances, :class:`SMESH.DriverMED_ReadStatus` ) """ @@ -744,7 +744,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Returns: an instance of class :class:`Mesh` - See also: + See also: :meth:`Mesh.Append` """ @@ -773,12 +773,32 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name ) return aMesh + def CreateDualMesh( self, mesh, meshName): + """ + Create a dual of a mesh. + + Parameters: + mesh: Tetrahedron mesh + :class:`mesh, `. + + meshName: a name of the new mesh + + Returns: + an instance of class :class:`Mesh` + """ + + if isinstance( mesh, Mesh ): + meshPart = mesh.GetMesh() + mesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName) + return Mesh(self, self.geompyD, mesh) + + def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False): """ Create a mesh by copying a part of another mesh. Parameters: - meshPart: a part of mesh to copy, either + meshPart: a part of mesh to copy, either :class:`mesh, sub-mesh, group or filter `. To copy nodes or elements not forming any mesh object, pass result of :meth:`Mesh.GetIDSource` as *meshPart* @@ -810,7 +830,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): meshName: an optional name of the new mesh. If omitted, the mesh name is kept. toCopyGroups: to create groups in the new mesh. toReuseHypotheses: to reuse hypotheses of the *sourceMesh*. - toCopyElements: to copy mesh elements present on non-modified sub-shapes of + toCopyElements: to copy mesh elements present on non-modified sub-shapes of *sourceMesh*. Returns: tuple ( ok, newMesh, newGroups, newSubMeshes, newHypotheses, invalidEntries ) @@ -1285,7 +1305,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Returns: minimum distance value - See also: + See also: :meth:`GetMinDistance` """ @@ -1313,7 +1333,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Returns: :class:`SMESH.Measure` structure or None if input data is invalid - See also: + See also: :meth:`MinDistance` """ @@ -1360,7 +1380,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Returns: tuple of six values (minX, minY, minZ, maxX, maxY, maxZ) - See also: + See also: :meth:`GetBoundingBox` """ @@ -1381,7 +1401,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Returns: :class:`SMESH.Measure` structure - See also: + See also: :meth:`BoundingBox` """ @@ -1460,14 +1480,14 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): def GetGravityCenter(self, obj): """ Get gravity center of all nodes of a mesh object. - - Parameters: + + Parameters: obj: :class:`mesh, sub-mesh, group or filter ` - Returns: + Returns: Three components of the gravity center (x,y,z) - See also: + See also: :meth:`Mesh.BaryCenter` """ if isinstance(obj, Mesh): obj = obj.mesh @@ -1481,11 +1501,11 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): """ Computes a radian measure of an angle defined by 3 points: <(p1,p2,p3) - Parameters: - p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct + Parameters: + p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct or list [x,y,z] - Returns: + Returns: Angle in radians """ if isinstance( p1, list ): p1 = PointStruct(*p1) @@ -1551,7 +1571,7 @@ class Mesh(metaclass = MeshMeta): It also has methods to define groups of mesh elements, to modify a mesh (by addition of new nodes and elements and by changing the existing entities), to get information about a mesh and to export a mesh in different formats. - """ + """ geom = 0 mesh = 0 @@ -2081,12 +2101,12 @@ class Mesh(metaclass = MeshMeta): def SetMeshOrder(self, submeshes): """ Set priority of sub-meshes. It works in two ways: - + * For sub-meshes with assigned algorithms of same dimension generating mesh of *several dimensions*, it sets the order in which the sub-meshes are computed. * For the rest sub-meshes, it sets the order in which the sub-meshes are checked - when looking for meshing parameters to apply to a sub-shape. To impose the - order in which sub-meshes with uni-dimensional algorithms are computed, + when looking for meshing parameters to apply to a sub-shape. To impose the + order in which sub-meshes with uni-dimensional algorithms are computed, call **submesh.Compute()** in a desired order. Parameters: @@ -2300,23 +2320,23 @@ class Mesh(metaclass = MeshMeta): meshPart: a part of mesh (:class:`sub-mesh, group or filter `) to export instead of the mesh autoDimension: if *True* (default), a space dimension of a MED mesh can be either - + - 1D if all mesh nodes lie on OX coordinate axis, or - 2D if all mesh nodes lie on XOY coordinate plane, or - 3D in the rest cases. - + If *autoDimension* is *False*, the space dimension is always 3. fields: list of GEOM fields defined on the shape to mesh. - geomAssocFields: each character of this string means a need to export a - corresponding field; correspondence between fields and characters + geomAssocFields: each character of this string means a need to export a + corresponding field; correspondence between fields and characters is following: - + - 'v' stands for "_vertices_" field; - 'e' stands for "_edges_" field; - 'f' stands for "_faces_" field; - 's' stands for "_solids_" field. - - zTolerance (float): tolerance in Z direction. If Z coordinate of a node is + + zTolerance (float): tolerance in Z direction. If Z coordinate of a node is close to zero within a given tolerance, the coordinate is set to zero. If *ZTolerance* is negative (default), the node coordinates are kept as is. saveNumbers(boolean) : enable saving numbers of nodes and cells. @@ -2371,8 +2391,8 @@ class Mesh(metaclass = MeshMeta): the typical use is auto_groups=False. version (int): define the version (xy, where version is x.y.z) of MED file format. For instance med 3.2.1 is coded 3*10+2 = 32, med 4.0.0 is coded 4*10+0 = 40. - The rules of compatibility to write a mesh in an older version than - the current version depend on the current version. For instance, + The rules of compatibility to write a mesh in an older version than + the current version depend on the current version. For instance, with med 4.0 it is possible to write/append med files in 4.0.0 (default) or 3.2.1 or 3.3.1 formats. If the version is equal to -1, the version is not changed (default). @@ -2387,8 +2407,8 @@ class Mesh(metaclass = MeshMeta): If *autoDimension* is *False*, the space dimension is always 3. fields: list of GEOM fields defined on the shape to mesh. - geomAssocFields: each character of this string means a need to export a - corresponding field; correspondence between fields and characters + geomAssocFields: each character of this string means a need to export a + corresponding field; correspondence between fields and characters is following: - 'v' stands for "_vertices_" field; @@ -2396,7 +2416,7 @@ class Mesh(metaclass = MeshMeta): - 'f' stands for "_faces_" field; - 's' stands for "_solids_" field. - zTolerance (float): tolerance in Z direction. If Z coordinate of a node is + zTolerance (float): tolerance in Z direction. If Z coordinate of a node is close to zero within a given tolerance, the coordinate is set to zero. If *ZTolerance* is negative (default), the node coordinates are kept as is. saveNumbers (boolean) : enable saving numbers of nodes and cells. @@ -2564,7 +2584,7 @@ class Mesh(metaclass = MeshMeta): If **autoDimension** is *False*, the space dimension is always 3. """ - + print("WARNING: ExportToMED() is deprecated, use ExportMED() instead") # process positional arguments #args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility @@ -2641,7 +2661,7 @@ class Mesh(metaclass = MeshMeta): Create an empty standalone mesh group Parameters: - elementType: the :class:`type ` of elements in the group; + elementType: the :class:`type ` of elements in the group; either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME) name: the name of the mesh group @@ -2881,7 +2901,7 @@ class Mesh(metaclass = MeshMeta): def GetGroups(self, elemType = SMESH.ALL): """ - Get the list of groups existing in the mesh in the order of creation + Get the list of groups existing in the mesh in the order of creation (starting from the oldest one) Parameters: @@ -3592,7 +3612,7 @@ class Mesh(metaclass = MeshMeta): Return the type of mesh element or node Returns: - the value from :class:`SMESH.ElementType` enumeration. + the value from :class:`SMESH.ElementType` enumeration. Return SMESH.ALL if element or node with the given ID does not exist """ @@ -3886,7 +3906,7 @@ class Mesh(metaclass = MeshMeta): Returns: a list of three double values - See also: + See also: :meth:`smeshBuilder.GetGravityCenter` """ @@ -4004,7 +4024,7 @@ class Mesh(metaclass = MeshMeta): Returns: tuple of six values (minX, minY, minZ, maxX, maxY, maxZ) - See Also: + See Also: :meth:`GetBoundingBox()` """ @@ -4027,7 +4047,7 @@ class Mesh(metaclass = MeshMeta): Returns: :class:`SMESH.Measure` structure - See Also: + See Also: :meth:`BoundingBox()` """ @@ -4163,7 +4183,7 @@ class Mesh(metaclass = MeshMeta): Returns: an object (a new group or a temporary :class:`SMESH.SMESH_IDSource`) holding IDs of new and/or found 0D elements. IDs of 0D elements - can be retrieved from the returned object by + can be retrieved from the returned object by calling :meth:`GetIDs() ` """ @@ -4537,7 +4557,7 @@ class Mesh(metaclass = MeshMeta): edges = self.GetIDSource( edges, SMESH.EDGE ) unRegister.set( edges ) return self.editor.Get1DBranches( edges, startNode ) - + def FindSharpEdges( self, angle, addExisting=False ): """ Return sharp edges of faces and non-manifold ones. @@ -4604,7 +4624,7 @@ class Mesh(metaclass = MeshMeta): def AddNodeOnSegment(self, Node1, Node2, position = 0.5): """ Replace each triangle bound by Node1-Node2 segment with - two triangles by connecting a node made on the link with a node + two triangles by connecting a node made on the link with a node opposite to the link. Parameters: @@ -4874,7 +4894,7 @@ class Mesh(metaclass = MeshMeta): a quadrangle. Parameters: - theElements: the faces to be splitted. This can be either + theElements: the faces to be splitted. This can be either :class:`mesh, sub-mesh, group, filter ` or a list of face IDs. By default all quadrangles are split @@ -4943,8 +4963,8 @@ class Mesh(metaclass = MeshMeta): to numerical functors. Returns: - * 1 if 1-3 diagonal is better, - * 2 if 2-4 diagonal is better, + * 1 if 1-3 diagonal is better, + * 2 if 2-4 diagonal is better, * 0 if error occurs. Note: @@ -5096,7 +5116,7 @@ class Mesh(metaclass = MeshMeta): This operation uses :doc:`pattern_mapping` functionality for splitting. Parameters: - theObject: the object from which the list of hexahedrons is taken; + theObject: the object from which the list of hexahedrons is taken; this is :class:`mesh, sub-mesh, group or filter ` theNode000,theNode001: within the range [0,7]; gives the orientation of the pattern relatively each hexahedron: the (0,0,0) key-point of the pattern @@ -5588,7 +5608,7 @@ class Mesh(metaclass = MeshMeta): of all steps, else - size of each step Returns: - the list of created :class:`groups ` if *MakeGroups* == True, + the list of created :class:`groups ` if *MakeGroups* == True, empty list otherwise """ @@ -5644,7 +5664,7 @@ class Mesh(metaclass = MeshMeta): - a list of tree components of the point or - a node ID or - a GEOM point - angles: list of angles in radians. Nodes at each extrusion step are rotated + angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. anglesVariation: forces the computation of rotation angles as linear variation of the given *angles* along path steps @@ -5862,13 +5882,13 @@ class Mesh(metaclass = MeshMeta): PathShape: optional shape (edge or wire) which defines the sub-mesh of the mesh defined by *PathObject* if the mesh contains not only path segments, else it can be None NodeStart: the first or the last node on the path. Defines the direction of extrusion HasAngles: not used obsolete - Angles: list of angles in radians. Nodes at each extrusion step are rotated + Angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. LinearVariation: forces the computation of rotation angles as linear variation of the given Angles along path steps HasRefPoint: allows using the reference point RefPoint: optional scaling and rotation center (mass center of the extruded - elements by default). The User can specify any point as the Reference Point. + elements by default). The User can specify any point as the Reference Point. *RefPoint* can be either GEOM Vertex, [x,y,z] or :class:`SMESH.PointStruct` MakeGroups: forces the generation of new groups from existing ones ScaleFactors: optional scale factors to apply during extrusion @@ -5876,7 +5896,7 @@ class Mesh(metaclass = MeshMeta): else *scaleFactors* [i] is applied to nodes at the i-th extrusion step Returns: - list of created :class:`groups ` and + list of created :class:`groups ` and :class:`error code ` Example: :ref:`tui_extrusion_along_path` """ @@ -5896,7 +5916,7 @@ class Mesh(metaclass = MeshMeta): Angles,AnglesParameters,hasVars = ParseAngles(Angles) ScaleFactors,ScalesParameters,hasVars = ParseParameters(ScaleFactors) Parameters = AnglesParameters + var_separator + \ - RefPoint.parameters + var_separator + ScalesParameters + RefPoint.parameters + var_separator + ScalesParameters self.mesh.SetParameters(Parameters) return self.editor.ExtrusionAlongPathObjects(Nodes, Edges, Faces, PathObject, PathShape, NodeStart, @@ -5917,7 +5937,7 @@ class Mesh(metaclass = MeshMeta): Path: 1D mesh or 1D sub-mesh, along which proceeds the extrusion NodeStart: the start node from Path. Defines the direction of extrusion HasAngles: not used obsolete - Angles: list of angles in radians. Nodes at each extrusion step are rotated + Angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. LinearVariation: forces the computation of rotation angles as linear variation of the given Angles along path steps @@ -5960,7 +5980,7 @@ class Mesh(metaclass = MeshMeta): PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion HasAngles: not used obsolete - Angles: list of angles in radians. Nodes at each extrusion step are rotated + Angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). @@ -6001,7 +6021,7 @@ class Mesh(metaclass = MeshMeta): PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion HasAngles: not used obsolete - Angles: list of angles in radians. Nodes at each extrusion step are rotated + Angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). @@ -6012,7 +6032,7 @@ class Mesh(metaclass = MeshMeta): variation of the given Angles along path steps Returns: - list of created :class:`groups ` and + list of created :class:`groups ` and :class:`error code ` if *MakeGroups* == True, only :class:`error code ` otherwise Example: :ref:`tui_extrusion_along_path` @@ -6039,7 +6059,7 @@ class Mesh(metaclass = MeshMeta): PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion HasAngles: not used obsolete - Angles: list of angles in radians. Nodes at each extrusion step are rotated + Angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). @@ -6050,7 +6070,7 @@ class Mesh(metaclass = MeshMeta): variation of the given Angles along path steps Returns: - list of created :class:`groups ` and + list of created :class:`groups ` and :class:`error code ` if *MakeGroups* == True, only :class:`error code ` otherwise Example: :ref:`tui_extrusion_along_path` @@ -6077,7 +6097,7 @@ class Mesh(metaclass = MeshMeta): PathShape: shape (edge) defines the sub-mesh for the path NodeStart: the first or the last node on the edge. Defines the direction of extrusion HasAngles: not used obsolete - Angles: list of angles in radians. Nodes at each extrusion step are rotated + Angles: list of angles in radians. Nodes at each extrusion step are rotated around *basePoint*, additionally to previous steps. HasRefPoint: allows using the reference point RefPoint: the reference point around which the shape is rotated (the mass center of the shape by default). @@ -6088,7 +6108,7 @@ class Mesh(metaclass = MeshMeta): variation of the given Angles along path steps Returns: - list of created :class:`groups ` and + list of created :class:`groups ` and :class:`error code ` if *MakeGroups* == True, only :class:`error code ` otherwise Example: :ref:`tui_extrusion_along_path` @@ -6498,7 +6518,7 @@ class Mesh(metaclass = MeshMeta): theObject (SMESH.SMESH_IDSource): the source object (mesh, sub-mesh, group or filter) theValue (float): signed offset size MakeGroups (boolean): forces the generation of new groups from existing ones - CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements, + CopyElements (boolean): if *NewMeshName* is empty, True means to keep original elements, False means to remove original elements. NewMeshName (string): the name of a mesh to create. If empty, offset elements are added to this mesh @@ -6879,7 +6899,7 @@ class Mesh(metaclass = MeshMeta): Parameters: theElements: container of elements to duplicate. It can be a - :class:`mesh, sub-mesh, group, filter ` + :class:`mesh, sub-mesh, group, filter ` or a list of element IDs. If *theElements* is a :class:`Mesh`, elements of highest dimension are duplicated theGroupName: a name of group to contain the generated elements. @@ -6889,7 +6909,7 @@ class Mesh(metaclass = MeshMeta): in any group. Returns: - a :class:`group ` where the new elements are added. + a :class:`group ` where the new elements are added. None if *theGroupName* == "". """ @@ -7158,7 +7178,7 @@ class Mesh(metaclass = MeshMeta): return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords ) def MakePolyLine(self, segments, groupName='', isPreview=False ): - """ + """ Create a polyline consisting of 1D mesh elements each lying on a 2D element of the initial triangle mesh. Positions of new nodes are found by cutting the mesh by the plane passing through pairs of points specified by each :class:`SMESH.PolySegment` structure. @@ -7176,7 +7196,7 @@ class Mesh(metaclass = MeshMeta): segments: list of :class:`SMESH.PolySegment` defining positions of cutting planes. groupName: optional name of a group where created mesh segments will be added. - """ + """ editor = self.editor if isPreview: editor = self.mesh.GetMeshEditPreviewer() @@ -7331,10 +7351,10 @@ class Mesh(metaclass = MeshMeta): """ Computes a radian measure of an angle defined by 3 nodes: <(node1,node2,node3) - Parameters: + Parameters: node1,node2,node3: IDs of the three nodes - Returns: + Returns: Angle in radians [0,PI]. -1 if failure case. """ p1 = self.GetNodeXYZ( node1 ) From 08485b06fa309a40c3769a9113c2b88dd26e103d Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Fri, 23 Sep 2022 13:47:18 +0200 Subject: [PATCH 4/8] Working version of dual_meshing (using medcoupling) functionality --- idl/SMESH_Gen.idl | 2 +- resources/CMakeLists.txt | 1 + resources/mesh_create_dual_mesh.png | Bin 0 -> 13290 bytes src/SMESHGUI/SMESHGUI.cxx | 4 +- src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx | 10 +++ src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h | 6 ++ src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx | 17 +++-- src/SMESHGUI/SMESH_images.ts | 4 ++ src/SMESHGUI/SMESH_msg_en.ts | 31 ++++++++ src/SMESH_I/SMESH_Gen_i.cxx | 60 +++++----------- src/SMESH_SWIG/CMakeLists.txt | 3 +- src/SMESH_SWIG/smeshBuilder.py | 7 +- src/SMESH_SWIG/smesh_tools.py | 74 ++++++++++++++++++++ test/SMESH_create_dual_mesh.py | 61 ++++++++++++++++ test/tests.set | 1 + 15 files changed, 223 insertions(+), 58 deletions(-) create mode 100644 resources/mesh_create_dual_mesh.png create mode 100644 src/SMESH_SWIG/smesh_tools.py create mode 100644 test/SMESH_create_dual_mesh.py diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index e9b678031..010525eaf 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -286,7 +286,7 @@ module SMESH raises ( SALOME::SALOME_Exception ); /*! * Create a dual mesh of a Tetrahedron mesh - * \param meshPart - TetraHedron mesh to create dual from + * \param mesh - TetraHedron mesh to create dual from * \param meshName - a name of the new mesh */ SMESH_Mesh CreateDualMesh(in SMESH_IDSource mesh, diff --git a/resources/CMakeLists.txt b/resources/CMakeLists.txt index 8f5bdb415..b2be7d8b8 100644 --- a/resources/CMakeLists.txt +++ b/resources/CMakeLists.txt @@ -60,6 +60,7 @@ SET(SMESH_RESOURCES_FILES mesh_conv_to_quad.png mesh_cutGroups.png mesh_cutquad.png + mesh_create_dual_mesh.png mesh_deflection.png mesh_deleteGroups.png mesh_diagonal.png diff --git a/resources/mesh_create_dual_mesh.png b/resources/mesh_create_dual_mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..d7a7be370f98331c7c471dd0b9c54eff04be653e GIT binary patch literal 13290 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 separator(), -1, 0 ); createPopupItem( SMESHOp::OpConvertMeshToQuadratic, OB, mesh_submesh, "&& " + hasElems ); createPopupItem( SMESHOp::OpCreateBoundaryElements, OB, mesh_group, "&& selcount=1 && dim>=2"); - createPopupItem( SMESHOp::OpCreateDualMesh, OB, mesh_submesh, "&& selcount=1 && dim>=2"); // Adaptation - begin popupMgr()->insert( separator(), -1, 0 ); diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx index 614220058..da67de1aa 100644 --- a/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.cxx @@ -39,6 +39,7 @@ #include #include #include +#include #define SPACING 6 #define MARGIN 11 @@ -54,6 +55,12 @@ SMESHGUI_CreateDualMeshDlg::SMESHGUI_CreateDualMeshDlg() setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) ); createObject( tr( "MESH" ), mainFrame(), 0 ); + myMeshNameLabel = new QLabel(QString(tr("DUAL_MESH_NAME")), mainFrame()); + myMeshName = new QLineEdit(mainFrame()); + + myProjShape = new QCheckBox(QString(tr("PROJ_SHAPE")), mainFrame()); + myProjShape->toggle(); + myWarning = new QLabel(QString("%1").arg(tr("NON_TETRA_MESH_WARNING")), mainFrame()); // Fill layout @@ -65,6 +72,9 @@ SMESHGUI_CreateDualMeshDlg::SMESHGUI_CreateDualMeshDlg() aLay->addWidget( objectWg( 0, Btn ), 0, 1 ); aLay->addWidget( objectWg( 0, Control ), 0, 2 ); aLay->addWidget( myWarning, 3, 0, 1, 3 ); + aLay->addWidget( myMeshNameLabel, 1, 0 ); + aLay->addWidget( myMeshName, 1, 2 ); + aLay->addWidget( myProjShape, 2, 0 ); } diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h index e5096b237..83b2a959c 100644 --- a/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshDlg.h @@ -37,6 +37,7 @@ class QRadioButton; class QButtonGroup; class QGroupBox; class QLabel; +class QLineEdit; class SMESHGUI_EXPORT SMESHGUI_CreateDualMeshDlg : public SMESHGUI_Dialog { @@ -49,11 +50,16 @@ public: void ShowWarning(bool); bool isWarningShown(); + QLineEdit* myMeshName; + QCheckBox* myProjShape; + signals: void onClicked( int ); + private: QLabel* myWarning; + QLabel* myMeshNameLabel; }; #endif // SMESHGUI_CREATEDUALMESHDLG_H diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx index 25f811700..449f0a582 100644 --- a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx @@ -40,8 +40,12 @@ #include #include #include +#include #include +// Qt includes +#include + // IDL includes #include #include CORBA_SERVER_HEADER(SMESH_MeshEditor) @@ -150,6 +154,9 @@ void SMESHGUI_CreateDualMeshOp::selectionDone() myDlg->ShowWarning( true ); } } + std::string mesh_name = "dual_" + pObj->GetName(); + myDlg->myMeshName->setText(QString(mesh_name.c_str())); + } catch ( const SALOME::SALOME_Exception& S_ex ) { @@ -158,6 +165,7 @@ void SMESHGUI_CreateDualMeshOp::selectionDone() catch ( ... ) { } + } //================================================================================ @@ -217,11 +225,9 @@ bool SMESHGUI_CreateDualMeshOp::onApply() bool aResult = false; SMESH::SMESH_Gen_var gen = SMESHGUI::GetSMESHGen(); SMESH::SMESH_Mesh_var newMesh; - QByteArray newMeshName="MESH_DUAL"; + QByteArray newMeshName=myDlg->myMeshName->text().toUtf8(); try { - // TODO: Call the python script using medcoupling - // String to run medcoupling dual // TODO: change name as previous name + "_dual" newMesh = gen->CreateDualMesh(mesh, newMeshName.constData()); @@ -246,10 +252,11 @@ bool SMESHGUI_CreateDualMeshOp::onApply() if( aResult ) { SMESHGUI::Modified(); - update( UF_ObjBrowser | UF_Model | UF_Viewer ); selectionDone(); - } + update( UF_ObjBrowser | UF_Model | UF_Viewer ); + } + SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser(); // updateObjBrowser(true); // SMESHGUI::Modified(); diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index 2116ee51b..fc90e47de 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -95,6 +95,10 @@ ICON_CONV_TO_QUAD mesh_conv_to_quad.png + + ICON_CREATE_DUAL_MESH + mesh_create_dual_mesh.png + ICON_CUT mesh_cutGroups.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 7c52712ec..a627143da 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -292,6 +292,10 @@ MEN_COPY_MESH Copy Mesh + + MEN_CREATE_DUAL_MESH + Create Dual Mesh + MEN_CLIP Clipping @@ -3300,6 +3304,10 @@ Use Display Entity menu command to show them. STB_COPY_MESH Copy Mesh + + STB_CREATE_DUAL_MESH + Create Dual Mesh + STB_CLIP Clipping @@ -5679,6 +5687,29 @@ Please specify it and try again Warning: mesh can become non-conformal + + SMESHGUI_CreateDualMeshDlg + + CAPTION + Create Dual Mesh + + + MESH + Mesh or Sub-mesh + + + NON_TETRA_MESH_WARNING + Warning: mesh must have only Tetrahedron 3D elements + + + DUAL_MESH_NAME + Name of the dual mesh + + + PROJ_SHAPE + Project boundary elements on shape + + SMESHGUI_ConvToQuadOp diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 79d031823..7157f413c 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -151,6 +151,9 @@ #include #include #include +#include + +namespace fs = boost::filesystem; using namespace std; using SMESH::TPythonDump; @@ -2835,54 +2838,23 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh if ( !srcMesh_i ) THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM ); - SMESH_Mesh& srcMesh2 = srcMesh_i->GetImpl(); + CORBA::String_var mesh_var=GetORB()->object_to_string(mesh); + std::string mesh_ior = mesh_var.in(); - // TODO: Get it - CORBA::String_var mesh_ior=GetORB()->object_to_string(mesh); - std::string mesh_id = mesh_ior.in(); - std::string dual_mesh_file="/tmp/test_dual.med"; + fs::path tmp_folder = fs::unique_path(fs::path("dual_mesh-%%%%-%%%%")); + fs::create_directories(tmp_folder); + fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med"); std::string mesh_name = "MESH"; - std::string python_code; - python_code += "import sys\n"; - python_code += "import salome\n"; - python_code += "import medcoupling as mc\n"; - python_code += "from math import pi\n"; - python_code += "salome.salome_init()\n"; - python_code += "import GEOM\n"; - python_code += "from salome.geom import geomBuilder\n"; - python_code += "geompy = geomBuilder.New()\n"; - python_code += "import SMESH, SALOMEDS\n"; - python_code += "from salome.smesh import smeshBuilder\n"; - python_code += "smesh = smeshBuilder.New()\n"; - python_code += "def create_dual_mesh(mesh_ior, output_file):\n"; - python_code += " mesh = salome.orb.string_to_object(mesh_ior)\n"; - python_code += " shape = mesh.GetShapeToMesh()\n"; - python_code += " if not mesh:\n"; - python_code += " raise Exception(\"Could not find mesh using id: \", mesh_id)\n"; - python_code += " int_ptr = mesh.ExportMEDCoupling(True, True)\n"; - python_code += " dab = mc.FromPyIntPtrToDataArrayByte(int_ptr)\n"; - python_code += " tetras = mc.MEDFileMesh.New(dab)[0]\n"; - python_code += " tetras = mc.MEDCoupling1SGTUMesh(tetras)\n"; - python_code += " polyh = tetras.computeDualMesh()\n"; - python_code += " skin = tetras.buildUnstructured().computeSkin()\n"; - python_code += " skin_polyh = polyh.buildUnstructured().computeSkin()\n"; - python_code += " allNodesOnSkinPolyh = skin_polyh.computeFetchedNodeIds()\n"; - python_code += " allNodesOnSkin = skin.computeFetchedNodeIds()\n"; - python_code += " ptsAdded = allNodesOnSkinPolyh.buildSubstraction(allNodesOnSkin)\n"; - python_code += " ptsAddedMesh = mc.MEDCouplingUMesh.Build0DMeshFromCoords( skin_polyh.getCoords()[ptsAdded] )\n"; - python_code += " ptsAddedCoo = ptsAddedMesh.getCoords()\n"; - python_code += " ptsAddedCooModified = ptsAddedCoo[:]\n"; - python_code += " polyh.setName(\"MESH\")\n"; - python_code += " polyh.write(output_file)\n"; - // Running Python script assert(Py_IsInitialized()); PyGILState_STATE gstate; gstate = PyGILState_Ensure(); - PyRun_SimpleString(python_code.c_str()); - std::string cmd=""; - cmd += "create_dual_mesh(\"" + mesh_id + "\", \"" + dual_mesh_file + "\")"; + + std::string cmd="import salome.smesh.smesh_tools as smt"; + PyRun_SimpleString(cmd.c_str()); + + cmd = "smt.create_dual_mesh(\"" + mesh_ior + "\", \"" + dual_mesh_file.string() + "\", \"" + mesh_name + "\")"; PyRun_SimpleString(cmd.c_str()); PyGILState_Release(gstate); @@ -2896,19 +2868,19 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh if ( !meshSO->_is_nil() ) { SetName( meshSO, meshName, "Mesh" ); - SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH"); } SMESH_Mesh& newMesh2 = newMesh_i->GetImpl(); - newMesh2.MEDToMesh(dual_mesh_file.c_str(), "MESH"); + newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName); SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); newMeshDS->Modified(); *pyDump << newMesh << " = " << this - << ".CreateDualMesh( " << mesh << ", " + << ".CreateDualMesh(" << "'" << meshName << "') "; return newMesh._retn(); diff --git a/src/SMESH_SWIG/CMakeLists.txt b/src/SMESH_SWIG/CMakeLists.txt index e39db09f9..81cf38a69 100644 --- a/src/SMESH_SWIG/CMakeLists.txt +++ b/src/SMESH_SWIG/CMakeLists.txt @@ -37,6 +37,7 @@ SET(smesh_SCRIPTS smeshBuilder.py smesh_algorithm.py smesh_selection.py + smesh_tools.py ) SET(StdMeshers_SCRIPTS @@ -52,7 +53,7 @@ SET_SOURCE_FILES_PROPERTIES(SMeshHelper.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(SMeshHelper.i PROPERTIES SWIG_FLAGS "-py3") SET_SOURCE_FILES_PROPERTIES(SMeshHelper_wrap.cpp PROPERTIES COMPILE_FLAGS "-DHAVE_CONFIG_H") SET(_swig_SCRIPTS ${CMAKE_CURRENT_BINARY_DIR}/SMeshHelper.py ) -IF(${CMAKE_VERSION} VERSION_LESS "3.8.0") +IF(${CMAKE_VERSION} VERSION_LESS "3.8.0") SWIG_ADD_MODULE(SMeshHelper python ${SMeshHelper_SOURCES}) ELSE() SWIG_ADD_LIBRARY(SMeshHelper LANGUAGE python SOURCES ${SMeshHelper_SOURCES}) diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index c46a97751..42bad03cf 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -786,11 +786,10 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): Returns: an instance of class :class:`Mesh` """ - if isinstance( mesh, Mesh ): - meshPart = mesh.GetMesh() - mesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName) - return Mesh(self, self.geompyD, mesh) + mesh = mesh.GetMesh() + dualMesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName) + return Mesh(self, self.geompyD, dualMesh) def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False): diff --git a/src/SMESH_SWIG/smesh_tools.py b/src/SMESH_SWIG/smesh_tools.py new file mode 100644 index 000000000..38cd978e0 --- /dev/null +++ b/src/SMESH_SWIG/smesh_tools.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python3 + +import sys +import salome +import medcoupling as mc +from math import pi + +#salome.salome_init() + +import GEOM +from salome.geom import geomBuilder + +geompy = geomBuilder.New() + +import SMESH, SALOMEDS +from salome.smesh import smeshBuilder + +smesh = smeshBuilder.New() + +def create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH"): + """ Create a dual of the mesh in input_file into output_file + + Args: + mesh_ior (string): corba Id of the Tetrahedron mesh + output_file (string): dual mesh file + """ + # Import mesh from file + # mesh = salome.orb.string_to_object(salome.salome_study.myStudy.FindObjectID(mesh_id).GetIOR()) + mesh = salome.orb.string_to_object(mesh_ior) + if not mesh: + raise Exception("Could not find mesh using id: ", mesh_ior) + + shape = mesh.GetShapeToMesh() + + # We got a meshProxy so we need to convert pointer to MEDCoupling + int_ptr = mesh.ExportMEDCoupling(True, True) + dab = mc.FromPyIntPtrToDataArrayByte(int_ptr) + tetras = mc.MEDFileMesh.New(dab)[0] + # End of SMESH -> MEDCoupling part for dualmesh + + tetras = mc.MEDCoupling1SGTUMesh(tetras) + polyh = tetras.computeDualMesh() + skin = tetras.buildUnstructured().computeSkin() + skin_polyh = polyh.buildUnstructured().computeSkin() + allNodesOnSkinPolyh = skin_polyh.computeFetchedNodeIds() + allNodesOnSkin = skin.computeFetchedNodeIds() + ptsAdded = allNodesOnSkinPolyh.buildSubstraction(allNodesOnSkin) + ptsAddedMesh = mc.MEDCouplingUMesh.Build0DMeshFromCoords( skin_polyh.getCoords()[ptsAdded] ) + + if adapt_to_shape: + ptsAddedCoo = ptsAddedMesh.getCoords() + ptsAddedCooModified = ptsAddedCoo[:] + + # We need the geometry for that + # TODO : Loop on faces identify points associated to which face + faces = geompy.ExtractShapes(shape, geompy.ShapeType["FACE"], True) + #assert( len(faces) == 1 ) + ## projection des points ajoutés par le dual sur la surface + #for i,tup in enumerate(ptsAddedCooModified): + # vertex = geompy.MakeVertex(*tuple(tup)) + # prj = geompy.MakeProjection(vertex, faces) + # newCoor = geompy.PointCoordinates( prj ) + # ptsAddedCooModified[i] = newCoor + ## assign coordinates with projected ones + #polyh.getCoords()[ptsAdded] = ptsAddedCooModified + + print("Writing dual mesh in ", output_file) + polyh.setName(mesh_name) + polyh.write(output_file) + + + + + diff --git a/test/SMESH_create_dual_mesh.py b/test/SMESH_create_dual_mesh.py new file mode 100644 index 000000000..007dbb8a7 --- /dev/null +++ b/test/SMESH_create_dual_mesh.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python + +### +### This file is generated automatically by SALOME v9.9.0 with dump python functionality +### + +import sys +import salome + +salome.salome_init() +import salome_notebook +notebook = salome_notebook.NoteBook() +sys.path.insert(0, r'/home/B61570/work_in_progress/dual_mesh') + +### +### GEOM component +### + +import GEOM +from salome.geom import geomBuilder +import math +import SALOMEDS + + +geompy = geomBuilder.New() + +O = geompy.MakeVertex(0, 0, 0) +OX = geompy.MakeVectorDXDYDZ(1, 0, 0) +OY = geompy.MakeVectorDXDYDZ(0, 1, 0) +OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) +Sphere_1 = geompy.MakeSphereR(100) +[geomObj_1] = geompy.ExtractShapes(Sphere_1, geompy.ShapeType["FACE"], True) +geompy.addToStudy( O, 'O' ) +geompy.addToStudy( OX, 'OX' ) +geompy.addToStudy( OY, 'OY' ) +geompy.addToStudy( OZ, 'OZ' ) +geompy.addToStudy( Sphere_1, 'Sphere_1' ) + +### +### SMESH component +### + +import SMESH, SALOMEDS +from salome.smesh import smeshBuilder + +smesh = smeshBuilder.New() + +NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters', 'NETGENEngine', 34.641, 0 ) +Mesh_1 = smesh.Mesh(Sphere_1,'Mesh_1') +status = Mesh_1.AddHypothesis( Sphere_1, NETGEN_3D_Parameters_1 ) +NETGEN_1D_2D_3D = Mesh_1.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D) +isDone = Mesh_1.Compute() +dual_Mesh_1 = smesh.CreateDualMesh( Mesh_1, 'dual_Mesh_1') + + +assert(dual_Mesh_1.NbPolyhedrons() > 0) +assert(dual_Mesh_1.NbTetras() == 0) + + +if salome.sg.hasDesktop(): + salome.sg.updateObjBrowser() diff --git a/test/tests.set b/test/tests.set index de38c9f13..f00bde4c6 100644 --- a/test/tests.set +++ b/test/tests.set @@ -62,6 +62,7 @@ SET(BAD_TESTS SMESH_test1.py SMESH_test2.py SMESH_test4.py + SMESH_create_dual_mesh.py ) IF(NOT WIN32) LIST(APPEND BAD_TESTS From 7d1a127bbb12d9e3fd816f164feb07390bc6a725 Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Thu, 6 Oct 2022 08:43:27 +0200 Subject: [PATCH 5/8] Corrections to handle adapation to shape --- idl/SMESH_Gen.idl | 4 +- src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx | 5 +- src/SMESH_I/SMESH_Gen_i.cxx | 30 +++++-- src/SMESH_I/SMESH_Gen_i.hxx | 3 +- src/SMESH_SWIG/smeshBuilder.py | 6 +- src/SMESH_SWIG/smesh_tools.py | 43 +++++----- test/SMESH_create_dual_mesh.py | 2 +- test/SMESH_create_dual_mesh_adapt.py | 92 ++++++++++++++++++++++ test/tests.set | 1 + 9 files changed, 152 insertions(+), 34 deletions(-) create mode 100644 test/SMESH_create_dual_mesh_adapt.py diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 010525eaf..a5b48aaa6 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -288,9 +288,11 @@ module SMESH * Create a dual mesh of a Tetrahedron mesh * \param mesh - TetraHedron mesh to create dual from * \param meshName - a name of the new mesh + * \param adaptToShape - if True project boundary point on shape */ SMESH_Mesh CreateDualMesh(in SMESH_IDSource mesh, - in string meshName) + in string meshName, + in boolean adaptToShape) raises ( SALOME::SALOME_Exception ); /*! diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx index 449f0a582..4ee81382a 100644 --- a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx @@ -45,6 +45,7 @@ // Qt includes #include +#include // IDL includes #include @@ -226,10 +227,10 @@ bool SMESHGUI_CreateDualMeshOp::onApply() SMESH::SMESH_Gen_var gen = SMESHGUI::GetSMESHGen(); SMESH::SMESH_Mesh_var newMesh; QByteArray newMeshName=myDlg->myMeshName->text().toUtf8(); + bool adapt_to_shape=myDlg->myProjShape->isChecked(); try { - // TODO: change name as previous name + "_dual" - newMesh = gen->CreateDualMesh(mesh, newMeshName.constData()); + newMesh = gen->CreateDualMesh(mesh, newMeshName.constData(), adapt_to_shape); if ( !newMesh->_is_nil() ) if ( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) ) diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 7157f413c..0fd53cbc7 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -2820,7 +2820,8 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::ListOfIDSources& theMeshesArray, //================================================================================ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh, - const char* meshName) + const char* meshName, + CORBA::Boolean adapt_to_shape) { Unexpect aCatch(SALOME_SalomeException); @@ -2841,10 +2842,12 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh CORBA::String_var mesh_var=GetORB()->object_to_string(mesh); std::string mesh_ior = mesh_var.in(); - fs::path tmp_folder = fs::unique_path(fs::path("dual_mesh-%%%%-%%%%")); + //temporary folder for the generation of the med file + fs::path tmp_folder = fs::temp_directory_path() / fs::unique_path(fs::path("dual_mesh-%%%%")); fs::create_directories(tmp_folder); fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med"); - std::string mesh_name = "MESH"; + std::string mesh_name = meshName; + MESSAGE("Working in folder" + tmp_folder.string()); // Running Python script assert(Py_IsInitialized()); @@ -2853,11 +2856,20 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh std::string cmd="import salome.smesh.smesh_tools as smt"; PyRun_SimpleString(cmd.c_str()); + std::string ats; + if(adapt_to_shape) + ats = "True"; + else + ats = "False"; - cmd = "smt.create_dual_mesh(\"" + mesh_ior + "\", \"" + dual_mesh_file.string() + "\", \"" + mesh_name + "\")"; + cmd = "smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", \"" + + dual_mesh_file.string() + "\", mesh_name=\"" + mesh_name + "\", adapt_to_shape=" + ats + ")"; + MESSAGE(cmd); PyRun_SimpleString(cmd.c_str()); PyGILState_Release(gstate); + MESSAGE("Executed python script"); + MESSAGE("Mesh created in " + dual_mesh_file.string()); // Import created MED SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil()); @@ -2867,21 +2879,25 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh SALOMEDS::SObject_wrap meshSO = ObjectToSObject( newMesh ); if ( !meshSO->_is_nil() ) { - SetName( meshSO, meshName, "Mesh" ); - SetPixMap( meshSO, "ICON_SMESH_TREE_MESH"); + SetName( meshSO, meshName, meshName ); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); } SMESH_Mesh& newMesh2 = newMesh_i->GetImpl(); newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName); + MESSAGE("Imported created MED") + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); newMeshDS->Modified(); *pyDump << newMesh << " = " << this << ".CreateDualMesh(" - << "'" << meshName << "') "; + << mesh << ", " + << "'" << meshName << "', " + << ats << ") "; return newMesh._retn(); } diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index bd8872038..822e71f2e 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -255,7 +255,8 @@ public: // Create dual mesh of a tetrahedron mesh SMESH::SMESH_Mesh_ptr CreateDualMesh(SMESH::SMESH_IDSource_ptr meshPart, - const char* meshName); + const char* meshName, + CORBA::Boolean adapt_to_shape); // Copy a part of mesh SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, diff --git a/src/SMESH_SWIG/smeshBuilder.py b/src/SMESH_SWIG/smeshBuilder.py index 42bad03cf..62db88951 100644 --- a/src/SMESH_SWIG/smeshBuilder.py +++ b/src/SMESH_SWIG/smeshBuilder.py @@ -773,7 +773,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name ) return aMesh - def CreateDualMesh( self, mesh, meshName): + def CreateDualMesh( self, mesh, meshName, adaptToShape): """ Create a dual of a mesh. @@ -782,13 +782,15 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ): :class:`mesh, `. meshName: a name of the new mesh + adpatToShape: if true project boundary points on shape Returns: an instance of class :class:`Mesh` """ if isinstance( mesh, Mesh ): mesh = mesh.GetMesh() - dualMesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName) + print("calling createdualmesh from Python") + dualMesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName, adaptToShape) return Mesh(self, self.geompyD, dualMesh) diff --git a/src/SMESH_SWIG/smesh_tools.py b/src/SMESH_SWIG/smesh_tools.py index 38cd978e0..1a6995eed 100644 --- a/src/SMESH_SWIG/smesh_tools.py +++ b/src/SMESH_SWIG/smesh_tools.py @@ -17,7 +17,7 @@ from salome.smesh import smeshBuilder smesh = smeshBuilder.New() -def create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH"): +def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH"): """ Create a dual of the mesh in input_file into output_file Args: @@ -25,7 +25,6 @@ def create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH output_file (string): dual mesh file """ # Import mesh from file - # mesh = salome.orb.string_to_object(salome.salome_study.myStudy.FindObjectID(mesh_id).GetIOR()) mesh = salome.orb.string_to_object(mesh_ior) if not mesh: raise Exception("Could not find mesh using id: ", mesh_ior) @@ -35,11 +34,14 @@ def create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH # We got a meshProxy so we need to convert pointer to MEDCoupling int_ptr = mesh.ExportMEDCoupling(True, True) dab = mc.FromPyIntPtrToDataArrayByte(int_ptr) - tetras = mc.MEDFileMesh.New(dab)[0] + tetras = mc.MEDFileMesh.New(dab)[0] # End of SMESH -> MEDCoupling part for dualmesh tetras = mc.MEDCoupling1SGTUMesh(tetras) polyh = tetras.computeDualMesh() + dual_volume_raw = polyh.getMeasureField(True).accumulate()[0] + + # Getting list of new points added on the skin skin = tetras.buildUnstructured().computeSkin() skin_polyh = polyh.buildUnstructured().computeSkin() allNodesOnSkinPolyh = skin_polyh.computeFetchedNodeIds() @@ -51,24 +53,25 @@ def create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH ptsAddedCoo = ptsAddedMesh.getCoords() ptsAddedCooModified = ptsAddedCoo[:] - # We need the geometry for that - # TODO : Loop on faces identify points associated to which face + # Matching faces with their ids faces = geompy.ExtractShapes(shape, geompy.ShapeType["FACE"], True) - #assert( len(faces) == 1 ) - ## projection des points ajoutés par le dual sur la surface - #for i,tup in enumerate(ptsAddedCooModified): - # vertex = geompy.MakeVertex(*tuple(tup)) - # prj = geompy.MakeProjection(vertex, faces) - # newCoor = geompy.PointCoordinates( prj ) - # ptsAddedCooModified[i] = newCoor - ## assign coordinates with projected ones - #polyh.getCoords()[ptsAdded] = ptsAddedCooModified + id2face = {} + for face in faces: + id2face[face.GetSubShapeIndices()[0]] = face + print(id2face) + + ## Projecting each points added by the dual mesh on the surface it is + # associated with + for i, tup in enumerate(ptsAddedCooModified): + vertex = geompy.MakeVertex(*tuple(tup)) + shapes = geompy.GetShapesNearPoint(shape, vertex, + geompy.ShapeType["FACE"]) + prj = geompy.MakeProjection(vertex, + id2face[shapes.GetSubShapeIndices()[0]]) + new_coor = geompy.PointCoordinates(prj) + ptsAddedCooModified[i] = new_coor + + polyh.getCoords()[ptsAdded] = ptsAddedCooModified - print("Writing dual mesh in ", output_file) polyh.setName(mesh_name) polyh.write(output_file) - - - - - diff --git a/test/SMESH_create_dual_mesh.py b/test/SMESH_create_dual_mesh.py index 007dbb8a7..08621f30e 100644 --- a/test/SMESH_create_dual_mesh.py +++ b/test/SMESH_create_dual_mesh.py @@ -50,7 +50,7 @@ Mesh_1 = smesh.Mesh(Sphere_1,'Mesh_1') status = Mesh_1.AddHypothesis( Sphere_1, NETGEN_3D_Parameters_1 ) NETGEN_1D_2D_3D = Mesh_1.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D) isDone = Mesh_1.Compute() -dual_Mesh_1 = smesh.CreateDualMesh( Mesh_1, 'dual_Mesh_1') +dual_Mesh_1 = smesh.CreateDualMesh( Mesh_1, 'dual_Mesh_1', True) assert(dual_Mesh_1.NbPolyhedrons() > 0) diff --git a/test/SMESH_create_dual_mesh_adapt.py b/test/SMESH_create_dual_mesh_adapt.py new file mode 100644 index 000000000..c95e6a62e --- /dev/null +++ b/test/SMESH_create_dual_mesh_adapt.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python + +### +### This file is generated automatically by SALOME v9.9.0 with dump python functionality +### + +import sys +import salome + +salome.salome_init() +import salome_notebook +notebook = salome_notebook.NoteBook() +sys.path.insert(0, r'/home/B61570/work_in_progress/dual_mesh') + +### +### GEOM component +### + +import GEOM +from salome.geom import geomBuilder +import math +import SALOMEDS + + +geompy = geomBuilder.New() + +O = geompy.MakeVertex(0, 0, 0) +OX = geompy.MakeVectorDXDYDZ(1, 0, 0) +OY = geompy.MakeVectorDXDYDZ(0, 1, 0) +OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) +Cylinder_1 = geompy.MakeCylinderRH(100, 400) +Sphere_1 = geompy.MakeSpherePntR(O, 100) +Fuse_1 = geompy.MakeFuseList([Cylinder_1, Sphere_1], True, True) + +[geomObj_1,geomObj_2,geomObj_3] = geompy.ExtractShapes(Fuse_1, geompy.ShapeType["FACE"], True) + +top = geompy.CreateGroup(Fuse_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(top, geomObj_1.GetSubShapeIndices()) + +middle = geompy.CreateGroup(Fuse_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(middle, geomObj_2.GetSubShapeIndices()) + +bottom = geompy.CreateGroup(Fuse_1, geompy.ShapeType["FACE"]) +geompy.UnionIDs(bottom, geomObj_3.GetSubShapeIndices()) + +#[top, middle, bottom] = geompy.GetExistingSubObjects(Fuse_1, False) + +geompy.addToStudy( O, 'O' ) +geompy.addToStudy( OX, 'OX' ) +geompy.addToStudy( OY, 'OY' ) +geompy.addToStudy( OZ, 'OZ' ) +geompy.addToStudy( Cylinder_1, 'Cylinder_1' ) +geompy.addToStudy( Sphere_1, 'Sphere_1' ) +geompy.addToStudy( Fuse_1, 'Fuse_1' ) +geompy.addToStudyInFather( Fuse_1, top, 'top' ) +geompy.addToStudyInFather( Fuse_1, middle, 'middle' ) +geompy.addToStudyInFather( Fuse_1, bottom, 'bottom' ) + +### +### SMESH component +### + +import SMESH, SALOMEDS +from salome.smesh import smeshBuilder + +smesh = smeshBuilder.New() + +NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters', 'NETGENEngine', 50, 0 ) +Mesh_1 = smesh.Mesh(Fuse_1,'Mesh_1') +status = Mesh_1.AddHypothesis( Fuse_1, NETGEN_3D_Parameters_1 ) +NETGEN_1D_2D_3D = Mesh_1.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D) +top_1 = Mesh_1.GroupOnGeom(top,'top',SMESH.FACE) +middle_1 = Mesh_1.GroupOnGeom(middle,'middle',SMESH.FACE) +bottom_1 = Mesh_1.GroupOnGeom(bottom,'bottom',SMESH.FACE) +isDone = Mesh_1.Compute() + +[ top_1, middle_1, bottom_1 ] = Mesh_1.GetGroups() + + +dual_Mesh_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', True) +dual_Mesh_raw_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', False) + +#Comparing volumes +dual_volume = dual_Mesh_1.GetVolume() +dual_raw_volume = dual_Mesh_raw_1.GetVolume() +print("dual_volume: ", dual_volume) +print("dual_raw_volume: ", dual_raw_volume) + +assert (dual_volume >= dual_raw_volume) + +if salome.sg.hasDesktop(): + salome.sg.updateObjBrowser() diff --git a/test/tests.set b/test/tests.set index f00bde4c6..977f4a667 100644 --- a/test/tests.set +++ b/test/tests.set @@ -63,6 +63,7 @@ SET(BAD_TESTS SMESH_test2.py SMESH_test4.py SMESH_create_dual_mesh.py + SMESH_create_dual_mesh_adapt.py ) IF(NOT WIN32) LIST(APPEND BAD_TESTS From b131becc0872f2050b117ce5bfc0fda84e34faa6 Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Mon, 10 Oct 2022 09:34:15 +0200 Subject: [PATCH 6/8] Adding user documentation --- .../examples/create_dual_mesh.py | 14 ++--- doc/examples/tests.set | 1 + doc/gui/CMakeLists.txt | 2 +- doc/gui/images/create_dual_mesh_dlg.png | Bin 0 -> 11000 bytes doc/gui/input/about_meshes.rst | 21 ++++--- doc/gui/input/create_dual_mesh.rst | 42 ++++++++++++++ doc/gui/input/tui_creating_meshes.rst | 16 +++++- src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx | 3 +- src/SMESH_I/SMESH_Gen_i.cxx | 1 + src/SMESH_SWIG/smesh_tools.py | 52 ++++++++++++++++-- test/SMESH_create_dual_mesh_adapt.py | 2 + test/tests.set | 1 - 12 files changed, 128 insertions(+), 27 deletions(-) rename test/SMESH_create_dual_mesh.py => doc/examples/create_dual_mesh.py (90%) create mode 100644 doc/gui/images/create_dual_mesh_dlg.png create mode 100644 doc/gui/input/create_dual_mesh.rst diff --git a/test/SMESH_create_dual_mesh.py b/doc/examples/create_dual_mesh.py similarity index 90% rename from test/SMESH_create_dual_mesh.py rename to doc/examples/create_dual_mesh.py index 08621f30e..08dfea822 100644 --- a/test/SMESH_create_dual_mesh.py +++ b/doc/examples/create_dual_mesh.py @@ -1,8 +1,5 @@ -#!/usr/bin/env python +# Creating dual Mesh -### -### This file is generated automatically by SALOME v9.9.0 with dump python functionality -### import sys import salome @@ -22,6 +19,7 @@ import math import SALOMEDS +# Creating a sphere geompy = geomBuilder.New() O = geompy.MakeVertex(0, 0, 0) @@ -36,20 +34,20 @@ geompy.addToStudy( OY, 'OY' ) geompy.addToStudy( OZ, 'OZ' ) geompy.addToStudy( Sphere_1, 'Sphere_1' ) -### -### SMESH component -### - import SMESH, SALOMEDS from salome.smesh import smeshBuilder smesh = smeshBuilder.New() +# Meshing sphere in Tetrahedron NETGEN_3D_Parameters_1 = smesh.CreateHypothesisByAverageLength( 'NETGEN_Parameters', 'NETGENEngine', 34.641, 0 ) Mesh_1 = smesh.Mesh(Sphere_1,'Mesh_1') status = Mesh_1.AddHypothesis( Sphere_1, NETGEN_3D_Parameters_1 ) NETGEN_1D_2D_3D = Mesh_1.Tetrahedron(algo=smeshBuilder.NETGEN_1D2D3D) isDone = Mesh_1.Compute() + + +# Creating Dual mesh dual_Mesh_1 = smesh.CreateDualMesh( Mesh_1, 'dual_Mesh_1', True) diff --git a/doc/examples/tests.set b/doc/examples/tests.set index cb22edab5..df39d9dd9 100644 --- a/doc/examples/tests.set +++ b/doc/examples/tests.set @@ -128,6 +128,7 @@ SET(BAD_TESTS transforming_meshes_ex06.py viewing_meshes_ex01.py radial_prism_3d_algo.py + create_dual_mesh.py ) IF(NOT WIN32) LIST(APPEND BAD_TESTS diff --git a/doc/gui/CMakeLists.txt b/doc/gui/CMakeLists.txt index c85b76e94..26660b650 100644 --- a/doc/gui/CMakeLists.txt +++ b/doc/gui/CMakeLists.txt @@ -57,7 +57,7 @@ SET(_cmd_smeshBuilder_gen_options ${smesh_merge_file} -o tmp2/smeshBuilder.py sm SALOME_GENERATE_ENVIRONMENT_SCRIPT(_cmd_smeshBuilder_gen env_script "${PYTHON_EXECUTABLE}" "${_cmd_smeshBuilder_gen_options}" CONTEXT "SMESH_DOC" ADDITIONAL_VARIABLES ${ADD_VAR}) ADD_CUSTOM_TARGET(pre_usr_docs - # 1. Make temporary directories for python modules + # 1. Make temporary directories for python modules COMMAND ${CMAKE_COMMAND} -E make_directory tmp1 COMMAND ${CMAKE_COMMAND} -E make_directory tmp2 diff --git a/doc/gui/images/create_dual_mesh_dlg.png b/doc/gui/images/create_dual_mesh_dlg.png new file mode 100644 index 0000000000000000000000000000000000000000..b28beaaf83f28c62ed22b23baccd167ed71579a3 GIT binary patch literal 11000 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 literal 0 HcmV?d00001 diff --git a/doc/gui/input/about_meshes.rst b/doc/gui/input/about_meshes.rst index 270fbe5e1..73af1714e 100644 --- a/doc/gui/input/about_meshes.rst +++ b/doc/gui/input/about_meshes.rst @@ -1,8 +1,8 @@ -.. _about_meshes_page: +.. _about_meshes_page: ************ About meshes -************ +************ **MESH** represents a discrete approximation of a subset of the three-dimensional space by `elementary geometrical elements`_. @@ -10,7 +10,7 @@ A SALOME study can contain multiple meshes, but they do not implicitly compose o Mesh module provides several ways to create the mesh: -* The main way is to :ref:`construct the mesh ` on the basis of the geometrical shape produced in the Geometry module. This way implies selection of +* The main way is to :ref:`construct the mesh ` on the basis of the geometrical shape produced in the Geometry module. This way implies selection of * a geometrical object (*main shape*) and * *meshing parameters* (:ref:`meshing algorithms ` and characteristics (e.g. element size) of a required mesh encapsulated in :ref:`hypothesis ` objects). @@ -20,19 +20,21 @@ Mesh module provides several ways to create the mesh: .. note:: Algorithms and hypotheses used at mesh level are referred to as *global* ones and those used at sub-mesh level are referred to as *local* ones. - + * Bottom-up way, using :ref:`mesh modification ` operations, especially :ref:`extrusion ` and :ref:`revolution `. To create an empty mesh not based on geometry, use the same dialog as to :ref:`construct the mesh on geometry ` but specify neither the geometry nor meshing algorithms. - + * The mesh can be :ref:`imported ` from (and exported to) the file in MED, UNV, STL, CGNS, DAT and GMF formats. - + * The 3D mesh can be generated from the 2D mesh not based on geometry, which was either :ref:`imported ` or created in other way. To setup the meshing parameters of a mesh not based on geometry, just invoke :ref:`Edit mesh / sub-mesh ` command on your 2D mesh. - + * Several meshes can be :ref:`combined ` into a new mesh. - + * The whole mesh or its part (sub-mesh or group) can be :ref:`copied ` into a new mesh. - + * A new mesh can be created from a transformed, e.g. :ref:`translated `, part of the mesh. +* A new mesh can be created from the gernation of the :ref:`dual ` of a Tetrahedron Mesh. + Meshes can be edited using the MESH functions destined for :ref:`modification ` of meshes. @@ -82,4 +84,5 @@ Quadratic mesh can be obtained in three ways: importing_exporting_meshes.rst building_compounds.rst copy_mesh.rst + create_dual_mesh.rst connectivity.rst diff --git a/doc/gui/input/create_dual_mesh.rst b/doc/gui/input/create_dual_mesh.rst new file mode 100644 index 000000000..2a540a1c6 --- /dev/null +++ b/doc/gui/input/create_dual_mesh.rst @@ -0,0 +1,42 @@ +.. _create_dual_mesh_page: + +**************** +Create Dual Mesh +**************** + +We can create the dual of a Tetrahedron Mesh which will be a polyhedron mesh. +The Mesh is created using MEDCoupling computeDualMesh function. + +*To create a dual mesh:* + +.. |img| image:: ../images/create_dual_mesh_icon.png + +From the contextual menu in the Object Browser of from the **Mesh** menu select +**Create Dual Mesh** or click *"Create Dual Mesh"* button |img| in the toolbar. + +The following dialog box will appear: + +.. image:: ../images/create_dual_mesh_dlg.png + :align: center + +In the dialog: + +* specify the mesh for which to create the dual mesh: + * **Select whole mesh** from the study tree. If a mesh was selected before calling function it will be preselected. + * If the mesh is not made of only Tetrahedrons a error message will be displayed and you won't be allowed to go through. +* specify the **New Mesh Name**; +* activate **Project boundary elements on shape** for the boundary points of the + dual mesh to be projected on their associated shape. + +* Click **Apply** or **Apply and Close** button to confirm the operation. + +---------------------------- +Limitations of the dual mesh +---------------------------- + +Only 2d groups will be transferred to the dual mesh. + +If you have convex shape the projection might not improve the mesh. + + +**See Also** a sample script of :ref:`tui_create_dual_mesh`. diff --git a/doc/gui/input/tui_creating_meshes.rst b/doc/gui/input/tui_creating_meshes.rst index 9d3cb5077..253fbf260 100644 --- a/doc/gui/input/tui_creating_meshes.rst +++ b/doc/gui/input/tui_creating_meshes.rst @@ -70,7 +70,7 @@ Export of a Mesh :download:`Download this script <../../examples/creating_meshes_ex05.py>` -.. _how_to_mesh_a_cylinder_with_hexahedrons: +.. _how_to_mesh_a_cylinder_with_hexahedrons: How to mesh a cylinder with hexahedrons? ======================================== @@ -84,10 +84,10 @@ demonstrates the resulting mesh. :download:`Download this script <../../examples/creating_meshes_ex06.py>` .. image:: ../images/mesh_cylinder_hexa.png - :align: center + :align: center -.. _tui_building_compound: +.. _tui_building_compound: Building a compound of meshes ============================= @@ -107,3 +107,13 @@ Mesh Copying :download:`Download this script <../../examples/creating_meshes_ex08.py>` +.. _tui_create_dual_mesh: + +Creating Dual Mesh +================== + +.. literalinclude:: ../../examples/create_dual_mesh.py + :language: python + +:download:`Download this script <../../examples/create_dual_mesh.py>` + diff --git a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx index 4ee81382a..c0fed0340 100644 --- a/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx +++ b/src/SMESHGUI/SMESHGUI_CreateDualMeshOp.cxx @@ -150,9 +150,10 @@ void SMESHGUI_CreateDualMeshOp::selectionDone() { SMESH::SMESH_subMesh_var subMesh = SMESH::SObjectToInterface( pObj ); - // TODO: Check that mesh is only tetra + // Check that mesh is only tetra if (!checkMesh(idSource)){ myDlg->ShowWarning( true ); + myDlg->setButtonEnabled(false, QtxDialog::OK|QtxDialog::Apply); } } std::string mesh_name = "dual_" + pObj->GetName(); diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 0fd53cbc7..f6abcbdce 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -2885,6 +2885,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh SMESH_Mesh& newMesh2 = newMesh_i->GetImpl(); + MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << mesh_name); newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName); MESSAGE("Imported created MED") diff --git a/src/SMESH_SWIG/smesh_tools.py b/src/SMESH_SWIG/smesh_tools.py index 1a6995eed..3d95f730c 100644 --- a/src/SMESH_SWIG/smesh_tools.py +++ b/src/SMESH_SWIG/smesh_tools.py @@ -4,6 +4,7 @@ import sys import salome import medcoupling as mc from math import pi +import numpy as np #salome.salome_init() @@ -17,6 +18,10 @@ from salome.smesh import smeshBuilder smesh = smeshBuilder.New() +from salome.kernel.logger import Logger +logger = Logger("salome.smesh.smesh_tools") +logger.setLevel("DEBUG") + def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name="MESH"): """ Create a dual of the mesh in input_file into output_file @@ -31,15 +36,51 @@ def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name shape = mesh.GetShapeToMesh() + # Creating output file + myfile = mc.MEDFileUMesh() + myfile.setName(mesh_name) + + # We got a meshProxy so we need to convert pointer to MEDCoupling int_ptr = mesh.ExportMEDCoupling(True, True) dab = mc.FromPyIntPtrToDataArrayByte(int_ptr) - tetras = mc.MEDFileMesh.New(dab)[0] + mc_mesh_file = mc.MEDFileMesh.New(dab) + tetras = mc_mesh_file[0] # End of SMESH -> MEDCoupling part for dualmesh tetras = mc.MEDCoupling1SGTUMesh(tetras) polyh = tetras.computeDualMesh() - dual_volume_raw = polyh.getMeasureField(True).accumulate()[0] + + ## Adding skin + transfering groups on faces from tetras mesh + mesh2d = polyh.buildUnstructured().computeSkin() + mesh2d.setName(mesh_name) + myfile.setMeshAtLevel(-1, mesh2d) + + + for grp_name in mc_mesh_file.getGroupsOnSpecifiedLev(-1): + logger.debug("Transferring group: "+ grp_name) + grp_tria = mc_mesh_file.getGroup(-1, grp_name) + # Retrieve the nodes in group + grp_nodes = grp_tria.computeFetchedNodeIds() + # Find all the cells lying on one of the nodes + id_grp_poly = mesh2d.getCellIdsLyingOnNodes(grp_nodes, False) + + grp_poly = mesh2d[id_grp_poly] + + # We use the interpolation to remove the element that are not really in + # the group (the ones that are next to a nodes nut not in the group + # will have the sum of their column in the enterpolation matrix equal + # to zero) + rem = mc.MEDCouplingRemapper() + + rem.prepare(grp_poly, grp_tria, "P0P0") + m = rem.getCrudeCSRMatrix() + _, id_to_keep = np.where(m.sum(dtype=np.int64, axis=0) >= 1e-07) + + id_grp_poly = id_grp_poly[id_to_keep.tolist()] + id_grp_poly.setName(grp_name) + + myfile.addGroup(-1, id_grp_poly) # Getting list of new points added on the skin skin = tetras.buildUnstructured().computeSkin() @@ -50,6 +91,7 @@ def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name ptsAddedMesh = mc.MEDCouplingUMesh.Build0DMeshFromCoords( skin_polyh.getCoords()[ptsAdded] ) if adapt_to_shape: + logger.debug("Adapting to shape") ptsAddedCoo = ptsAddedMesh.getCoords() ptsAddedCooModified = ptsAddedCoo[:] @@ -58,7 +100,6 @@ def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name id2face = {} for face in faces: id2face[face.GetSubShapeIndices()[0]] = face - print(id2face) ## Projecting each points added by the dual mesh on the surface it is # associated with @@ -74,4 +115,7 @@ def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name polyh.getCoords()[ptsAdded] = ptsAddedCooModified polyh.setName(mesh_name) - polyh.write(output_file) + myfile.setMeshAtLevel(0, polyh) + + logger.debug("Writting dual mesh in :"+output_file) + myfile.write(output_file, 2) diff --git a/test/SMESH_create_dual_mesh_adapt.py b/test/SMESH_create_dual_mesh_adapt.py index c95e6a62e..9f79618da 100644 --- a/test/SMESH_create_dual_mesh_adapt.py +++ b/test/SMESH_create_dual_mesh_adapt.py @@ -80,6 +80,8 @@ isDone = Mesh_1.Compute() dual_Mesh_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', True) dual_Mesh_raw_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', False) +[ top_2, middle_2, bottom_2 ] = dual_Mesh_1.GetGroups() + #Comparing volumes dual_volume = dual_Mesh_1.GetVolume() dual_raw_volume = dual_Mesh_raw_1.GetVolume() diff --git a/test/tests.set b/test/tests.set index 977f4a667..fddb00249 100644 --- a/test/tests.set +++ b/test/tests.set @@ -62,7 +62,6 @@ SET(BAD_TESTS SMESH_test1.py SMESH_test2.py SMESH_test4.py - SMESH_create_dual_mesh.py SMESH_create_dual_mesh_adapt.py ) IF(NOT WIN32) From c3ca179bcbb814aae3ab1ee9c2ec5b6b29c84c10 Mon Sep 17 00:00:00 2001 From: Yoann Audouin Date: Thu, 13 Oct 2022 14:03:31 +0200 Subject: [PATCH 7/8] Handling error in PyRun + better import of MED file --- src/SMESH/SMESH_Mesh.cxx | 30 +++++++------- src/SMESH_I/SMESH_Gen_i.cxx | 61 +++++++++++++++++++++------- src/SMESH_SWIG/smesh_tools.py | 6 +++ test/SMESH_create_dual_mesh_adapt.py | 2 +- 4 files changed, 69 insertions(+), 30 deletions(-) diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 8d0d9392b..5ff4c1830 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -76,7 +76,7 @@ #ifndef WIN32 #include #include -#else +#else #include #endif @@ -99,7 +99,7 @@ class SMESH_Mesh::SubMeshHolder : public SMESHDS_TSubMeshHolder< SMESH_subMesh > //============================================================================= /*! - * + * */ //============================================================================= @@ -629,7 +629,7 @@ SMESH_ComputeErrorPtr SMESH_Mesh::GMFToMesh(const char* theFileName, //============================================================================= /*! - * + * */ //============================================================================= @@ -724,7 +724,7 @@ SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape, //============================================================================= /*! - * + * */ //============================================================================= @@ -741,7 +741,7 @@ SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape, SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId]; if(MYDEBUG) { SCRUTE(anHyp->GetType()); } - // shape + // shape bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO ); SMESH_subMesh::algo_event event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP; @@ -794,7 +794,7 @@ SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape, //============================================================================= /*! - * + * */ //============================================================================= @@ -861,7 +861,7 @@ const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const SMESH_subMesh * aSubM const_cast< std::vector< SMESH_subMesh * > & > ( aSubMesh->GetAncestors() ); SortByMeshOrder( ancestors ); - std::vector::const_iterator smIt = ancestors.begin(); + std::vector::const_iterator smIt = ancestors.begin(); for ( ; smIt != ancestors.end(); smIt++ ) { const TopoDS_Shape& curSh = (*smIt)->GetSubShape(); @@ -1004,7 +1004,7 @@ SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const int anHypId) const //============================================================================= /*! - * + * */ //============================================================================= @@ -1015,7 +1015,7 @@ const std::list & SMESH_Mesh::GetLog() //============================================================================= /*! - * + * */ //============================================================================= void SMESH_Mesh::ClearLog() @@ -1727,7 +1727,7 @@ double SMESH_Mesh::GetComputeProgress() const const SMESH_subMesh* curSM = _gen->GetCurrentSubMesh(); // get progress of a current algo - TColStd_MapOfInteger currentSubIds; + TColStd_MapOfInteger currentSubIds; if ( curSM ) if ( SMESH_Algo* algo = curSM->GetAlgo() ) { @@ -2035,7 +2035,7 @@ bool SMESH_Mesh::IsNotConformAllowed() const //======================================================================= //function : IsMainShape -//purpose : +//purpose : //======================================================================= bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const @@ -2055,7 +2055,7 @@ TopoDS_Shape SMESH_Mesh::GetShapeByEntry(const std::string& entry) const //============================================================================= /*! - * + * */ //============================================================================= @@ -2169,7 +2169,7 @@ std::list SMESH_Mesh::GetGroupIds() const std::map::const_iterator it = _mapGroup.begin(); for ( ; it != _mapGroup.end(); it++ ) anIds.push_back( it->first ); - + return anIds; } @@ -2188,7 +2188,7 @@ void SMESH_Mesh::SetCallUp( TCallUp* upCaller ) //============================================================================= /*! - * + * */ //============================================================================= @@ -2546,7 +2546,7 @@ bool SMESH_Mesh::IsOrderOK( const SMESH_subMesh* smBefore, } } return true; // no order imposed to given sub-meshes -} +} //============================================================================= /*! diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index f6abcbdce..6c0face11 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -2833,7 +2833,6 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh if ( CORBA::is_nil( mesh )) THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM ); - std::cout << mesh << std::endl; SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh(); SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( srcMesh ); if ( !srcMesh_i ) @@ -2846,7 +2845,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh fs::path tmp_folder = fs::temp_directory_path() / fs::unique_path(fs::path("dual_mesh-%%%%")); fs::create_directories(tmp_folder); fs::path dual_mesh_file = tmp_folder / fs::path("tmp_dual_mesh.med"); - std::string mesh_name = meshName; + std::string mesh_name(meshName); MESSAGE("Working in folder" + tmp_folder.string()); // Running Python script @@ -2854,21 +2853,47 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh PyGILState_STATE gstate; gstate = PyGILState_Ensure(); - std::string cmd="import salome.smesh.smesh_tools as smt"; - PyRun_SimpleString(cmd.c_str()); + std::string ats; if(adapt_to_shape) ats = "True"; else ats = "False"; - cmd = "smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", \"" + + std::string cmd="import salome.smesh.smesh_tools as smt\n"; + cmd +="smt.smesh_create_dual_mesh(\"" + mesh_ior + "\", \"" + dual_mesh_file.string() + "\", mesh_name=\"" + mesh_name + "\", adapt_to_shape=" + ats + ")"; MESSAGE(cmd); - PyRun_SimpleString(cmd.c_str()); + + PyObject *py_main = PyImport_AddModule("__main__"); + PyObject *py_dict = PyModule_GetDict(py_main); + + PyRun_String(cmd.c_str(), Py_file_input, py_dict, py_dict); + + if (PyErr_Occurred()) { + // Restrieving python error + MESSAGE("Catching error") + PyObject *errtype, *errvalue, *traceback; + PyErr_Fetch(&errtype, &errvalue, &traceback); + if(errvalue != NULL) { + MESSAGE("Error has a value") + PyObject *s = PyObject_Str(errvalue); + Py_ssize_t size; + std::string msg = PyUnicode_AsUTF8AndSize(s, &size); + msg = "Issue with the execution of create_dual_mesh:\n"+msg; + MESSAGE("throwing exception") + // We need to deactivate the GIL before throwing the exception + PyGILState_Release(gstate); + THROW_SALOME_CORBA_EXCEPTION(msg.c_str(), SALOME::INTERNAL_ERROR ); + Py_DECREF(s); + } + Py_XDECREF(errvalue); + Py_XDECREF(errtype); + Py_XDECREF(traceback); + } PyGILState_Release(gstate); - MESSAGE("Executed python script"); + MESSAGE("Mesh created in " + dual_mesh_file.string()); // Import created MED @@ -2882,24 +2907,32 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh SetName( meshSO, meshName, meshName ); SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); } + int ret = newMesh_i->ImportMEDFile(dual_mesh_file.c_str(), meshName); + if(ret) + THROW_SALOME_CORBA_EXCEPTION( "Issue when importing mesh", SALOME::INTERNAL_ERROR ); + /* SMESH_Mesh& newMesh2 = newMesh_i->GetImpl(); - MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << mesh_name); - newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName); - MESSAGE("Imported created MED") + MESSAGE("Loading file: " << dual_mesh_file.string() << " with mesh " << meshName); + int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName); + */ - SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); - - newMeshDS->Modified(); + newMesh_i->GetImpl().GetMeshDS()->Modified(); *pyDump << newMesh << " = " << this << ".CreateDualMesh(" << mesh << ", " - << "'" << meshName << "', " + << "'" << mesh_name << "', " << ats << ") "; + pyDumpDeleter.reset(); // allow dump in GetGroups() + + if ( srcMesh_i->GetImpl().GetGroupIds().size() > 0 ) // dump created groups + MESSAGE("Dump of groups"); + SMESH::ListOfGroups_var groups = newMesh->GetGroups(); + return newMesh._retn(); } diff --git a/src/SMESH_SWIG/smesh_tools.py b/src/SMESH_SWIG/smesh_tools.py index 3d95f730c..e475ab24e 100644 --- a/src/SMESH_SWIG/smesh_tools.py +++ b/src/SMESH_SWIG/smesh_tools.py @@ -37,6 +37,7 @@ def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name shape = mesh.GetShapeToMesh() # Creating output file + logger.debug("Creating file with mesh: "+mesh_name) myfile = mc.MEDFileUMesh() myfile.setName(mesh_name) @@ -58,7 +59,12 @@ def smesh_create_dual_mesh(mesh_ior, output_file, adapt_to_shape=True, mesh_name for grp_name in mc_mesh_file.getGroupsOnSpecifiedLev(-1): + # This group is created by the export + if grp_name == "Group_Of_All_Faces": + logger.debug("Skipping group: "+ grp_name) + continue logger.debug("Transferring group: "+ grp_name) + grp_tria = mc_mesh_file.getGroup(-1, grp_name) # Retrieve the nodes in group grp_nodes = grp_tria.computeFetchedNodeIds() diff --git a/test/SMESH_create_dual_mesh_adapt.py b/test/SMESH_create_dual_mesh_adapt.py index 9f79618da..ccabb5aa5 100644 --- a/test/SMESH_create_dual_mesh_adapt.py +++ b/test/SMESH_create_dual_mesh_adapt.py @@ -77,8 +77,8 @@ isDone = Mesh_1.Compute() [ top_1, middle_1, bottom_1 ] = Mesh_1.GetGroups() +dual_Mesh_raw_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_raw_1', False) dual_Mesh_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', True) -dual_Mesh_raw_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', False) [ top_2, middle_2, bottom_2 ] = dual_Mesh_1.GetGroups() From 4dc895105ab7686df2e2987d35d46a4e379ea707 Mon Sep 17 00:00:00 2001 From: Anthony Geay Date: Mon, 17 Oct 2022 12:44:49 +0200 Subject: [PATCH 8/8] Fix compilation on windows --- src/SMESH_I/SMESH_Gen_i.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index 6c0face11..263454015 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -2907,7 +2907,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateDualMesh(SMESH::SMESH_IDSource_ptr mesh SetName( meshSO, meshName, meshName ); SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); } - int ret = newMesh_i->ImportMEDFile(dual_mesh_file.c_str(), meshName); + int ret = newMesh_i->ImportMEDFile(dual_mesh_file.string().c_str(), meshName); if(ret) THROW_SALOME_CORBA_EXCEPTION( "Issue when importing mesh", SALOME::INTERNAL_ERROR );