Working version of dual_meshing (using medcoupling) functionality

This commit is contained in:
Yoann Audouin 2022-09-23 13:47:18 +02:00
parent 246a01ab71
commit 08485b06fa
15 changed files with 223 additions and 58 deletions

View File

@ -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,

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@ -4415,6 +4415,7 @@ void SMESHGUI::initialize( CAM_Application* app )
createMenu( SMESHOp::OpEditMeshOrSubMesh, meshId, -1 );
createMenu( SMESHOp::OpBuildCompoundMesh, meshId, -1 );
createMenu( SMESHOp::OpCopyMesh, meshId, -1 );
createMenu( SMESHOp::OpCreateDualMesh, meshId, -1 );
createMenu( separator(), meshId, -1 );
createMenu( SMESHOp::OpCompute, meshId, -1 );
createMenu( SMESHOp::OpPreCompute, meshId, -1 );
@ -4528,7 +4529,6 @@ 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 );
@ -4680,7 +4680,6 @@ 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 );
@ -4794,7 +4793,6 @@ 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 );

View File

@ -39,6 +39,7 @@
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#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("<b>%1</b>").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 );
}

View File

@ -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

View File

@ -40,8 +40,12 @@
#include <SUIT_MessageBox.h>
#include <SUIT_OverrideCursor.h>
#include <SalomeApp_Tools.h>
#include <SalomeApp_Application.h>
#include <SALOME_Actor.h>
// Qt includes
#include <QLineEdit>
// IDL includes
#include <SALOMEconfig.h>
#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();

View File

@ -95,6 +95,10 @@
<source>ICON_CONV_TO_QUAD</source>
<translation>mesh_conv_to_quad.png</translation>
</message>
<message>
<source>ICON_CREATE_DUAL_MESH</source>
<translation>mesh_create_dual_mesh.png</translation>
</message>
<message>
<source>ICON_CUT</source>
<translation>mesh_cutGroups.png</translation>

View File

@ -292,6 +292,10 @@
<source>MEN_COPY_MESH</source>
<translation>Copy Mesh</translation>
</message>
<message>
<source>MEN_CREATE_DUAL_MESH</source>
<translation>Create Dual Mesh</translation>
</message>
<message>
<source>MEN_CLIP</source>
<translation>Clipping</translation>
@ -3300,6 +3304,10 @@ Use Display Entity menu command to show them.
<source>STB_COPY_MESH</source>
<translation>Copy Mesh</translation>
</message>
<message>
<source>STB_CREATE_DUAL_MESH</source>
<translation>Create Dual Mesh</translation>
</message>
<message>
<source>STB_CLIP</source>
<translation>Clipping</translation>
@ -5679,6 +5687,29 @@ Please specify it and try again</translation>
<translation>Warning: mesh can become non-conformal</translation>
</message>
</context>
<context>
<name>SMESHGUI_CreateDualMeshDlg</name>
<message>
<source>CAPTION</source>
<translation>Create Dual Mesh</translation>
</message>
<message>
<source>MESH</source>
<translation>Mesh or Sub-mesh</translation>
</message>
<message>
<source>NON_TETRA_MESH_WARNING</source>
<translation>Warning: mesh must have only Tetrahedron 3D elements</translation>
</message>
<message>
<source>DUAL_MESH_NAME</source>
<translation>Name of the dual mesh</translation>
</message>
<message>
<source>PROJ_SHAPE</source>
<translation>Project boundary elements on shape</translation>
</message>
</context>
<context>
<name>SMESHGUI_ConvToQuadOp</name>
<message>

View File

@ -151,6 +151,9 @@
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/filesystem.hpp>
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();

View File

@ -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})

View File

@ -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):

View File

@ -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)

View File

@ -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()

View File

@ -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