Merge branch 'yan/dual_mesh_mc'

This commit is contained in:
Yoann Audouin 2022-10-13 16:22:23 +02:00
commit 33d5b0fd2b
28 changed files with 1202 additions and 126 deletions

View File

@ -0,0 +1,59 @@
# Creating dual Mesh
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
# Creating a sphere
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' )
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)
assert(dual_Mesh_1.NbPolyhedrons() > 0)
assert(dual_Mesh_1.NbTetras() == 0)
if salome.sg.hasDesktop():
salome.sg.updateObjBrowser()

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -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 <constructing_meshes_page>` 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 <constructing_meshes_page>` 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 <basic_meshing_algos_page>` and characteristics (e.g. element size) of a required mesh encapsulated in :ref:`hypothesis <about_hypo_page>` 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 <modifying_meshes_page>` operations, especially :ref:`extrusion <extrusion_page>` and :ref:`revolution <revolution_page>`. To create an empty mesh not based on geometry, use the same dialog as to :ref:`construct the mesh on geometry <constructing_meshes_page>` but specify neither the geometry nor meshing algorithms.
* The mesh can be :ref:`imported <importing_exporting_meshes_page>` 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 <importing_exporting_meshes_page>` or created in other way. To setup the meshing parameters of a mesh not based on geometry, just invoke :ref:`Edit mesh / sub-mesh <editing_meshes_page>` command on your 2D mesh.
* Several meshes can be :ref:`combined <building_compounds_page>` into a new mesh.
* The whole mesh or its part (sub-mesh or group) can be :ref:`copied <copy_mesh_page>` into a new mesh.
* A new mesh can be created from a transformed, e.g. :ref:`translated <translation_page>`, part of the mesh.
* A new mesh can be created from the gernation of the :ref:`dual <create_dual_mesh_page>` of a Tetrahedron Mesh.
Meshes can be edited using the MESH functions destined for :ref:`modification <modifying_meshes_page>` 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

View File

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

View File

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

View File

@ -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,16 @@ module SMESH
in boolean theMakeRequiredGroups,
out SMESH::ComputeError theError)
raises ( SALOME::SALOME_Exception );
/*!
* 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 boolean adaptToShape)
raises ( SALOME::SALOME_Exception );
/*!
* Create a mesh by copying a part of another mesh
@ -305,7 +315,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 +536,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 +554,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 +575,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 +593,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 );

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

@ -76,7 +76,7 @@
#ifndef WIN32
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#else
#else
#include <pthread.h>
#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<SMESH_subMesh*>::const_iterator smIt = ancestors.begin();
std::vector<SMESH_subMesh*>::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<SMESHDS_Command*> & 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<int> SMESH_Mesh::GetGroupIds() const
std::map<int, SMESH_Group*>::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
}
}
//=============================================================================
/*!

View File

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

View File

@ -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" );
@ -4411,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 );
@ -6025,6 +6030,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;

View File

@ -0,0 +1,96 @@
// 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 <QGroupBox>
#include <QCheckBox>
#include <QRadioButton>
#include <QButtonGroup>
#include <QGroupBox>
#include <QFrame>
#include <QHBoxLayout>
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#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 );
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
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 );
aLay->addWidget( myMeshNameLabel, 1, 0 );
aLay->addWidget( myMeshName, 1, 2 );
aLay->addWidget( myProjShape, 2, 0 );
}
SMESHGUI_CreateDualMeshDlg::~SMESHGUI_CreateDualMeshDlg()
{
}
void SMESHGUI_CreateDualMeshDlg::ShowWarning(bool toShow)
{
if ( toShow )
myWarning->show();
else
myWarning->hide();
}
bool SMESHGUI_CreateDualMeshDlg::isWarningShown()
{
return myWarning->isVisible();
}

View File

@ -0,0 +1,65 @@
// 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 QLineEdit;
class SMESHGUI_EXPORT SMESHGUI_CreateDualMeshDlg : public SMESHGUI_Dialog
{
Q_OBJECT
public:
SMESHGUI_CreateDualMeshDlg();
virtual ~SMESHGUI_CreateDualMeshDlg();
void ShowWarning(bool);
bool isWarningShown();
QLineEdit* myMeshName;
QCheckBox* myProjShape;
signals:
void onClicked( int );
private:
QLabel* myWarning;
QLabel* myMeshNameLabel;
};
#endif // SMESHGUI_CREATEDUALMESHDLG_H

View File

@ -0,0 +1,293 @@
// 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 <LightApp_UpdateFlags.h>
#include <SUIT_MessageBox.h>
#include <SUIT_OverrideCursor.h>
#include <SalomeApp_Tools.h>
#include <SalomeApp_Application.h>
#include <SALOME_Actor.h>
// Qt includes
#include <QLineEdit>
#include <QCheckBox>
// IDL includes
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
// VTK includes
#include <vtkProperty.h>
//================================================================================
/*!
* \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<SMESH::SMESH_IDSource>( 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<SMESH::SMESH_subMesh>( pObj );
// 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();
myDlg->myMeshName->setText(QString(mesh_name.c_str()));
}
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<SMESH::SMESH_IDSource>( 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=myDlg->myMeshName->text().toUtf8();
bool adapt_to_shape=myDlg->myProjShape->isChecked();
try
{
newMesh = gen->CreateDualMesh(mesh, newMeshName.constData(), adapt_to_shape);
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();
selectionDone();
update( UF_ObjBrowser | UF_Model | UF_Viewer );
}
SMESHGUI::GetSMESHGUI()->getApp()->updateObjectBrowser();
// updateObjBrowser(true);
// SMESHGUI::Modified();
// if( LightApp_Application* anApp =
// dynamic_cast<LightApp_Application*>( 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;
}

View File

@ -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 <SALOMEconfig.h>
#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

View File

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

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

@ -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">
// <python-wrap>
// <accumulative-methods>
// <accumulative-methods>
// SetEnforcedVertex,
// SetEnforcedVertexNamed
// </accumulative-methods>

View File

@ -49,6 +49,10 @@
#include <TopoDS_Wire.hxx>
#include <gp_Pnt.hxx>
// Have to be included before std headers
#include <Python.h>
#include <structmember.h>
#ifdef WIN32
#include <windows.h>
#include <process.h>
@ -147,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;
@ -2802,6 +2809,133 @@ 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,
CORBA::Boolean adapt_to_shape)
{
Unexpect aCatch(SALOME_SalomeException);
TPythonDump* pyDump = new TPythonDump(this); // prevent dump from CreateMesh()
std::unique_ptr<TPythonDump> pyDumpDeleter( pyDump );
// 1. Get source mesh
if ( CORBA::is_nil( mesh ))
THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM );
SMESH::SMESH_Mesh_var srcMesh = mesh->GetMesh();
SMESH_Mesh_i* srcMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( srcMesh );
if ( !srcMesh_i )
THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM );
CORBA::String_var mesh_var=GetORB()->object_to_string(mesh);
std::string mesh_ior = mesh_var.in();
//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(meshName);
MESSAGE("Working in folder" + tmp_folder.string());
// Running Python script
assert(Py_IsInitialized());
PyGILState_STATE gstate;
gstate = PyGILState_Ensure();
std::string ats;
if(adapt_to_shape)
ats = "True";
else
ats = "False";
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);
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("Mesh created in " + dual_mesh_file.string());
// Import created MED
SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil());
SMESH_Mesh_i* newMesh_i = SMESH::DownCast<SMESH_Mesh_i*>( 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, 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 " << meshName);
int ret = newMesh2.MEDToMesh(dual_mesh_file.c_str(), meshName);
*/
newMesh_i->GetImpl().GetMeshDS()->Modified();
*pyDump << newMesh << " = " << this
<< ".CreateDualMesh("
<< mesh << ", "
<< "'" << 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();
}
//================================================================================
/*!
* \brief Create a mesh by copying a part of another mesh
@ -6182,7 +6316,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;

View File

@ -253,6 +253,11 @@ 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,
CORBA::Boolean adapt_to_shape);
// Copy a part of mesh
SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart,
const char* meshName,

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

@ -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 <SMESH.SMESH_Mesh>` given as *obj* parameter.
Parameters:
obj: either
obj: either
1. a :class:`CORBA mesh <SMESH.SMESH_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,33 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
aMesh = Mesh( self, self.geompyD, aSmeshMesh, name=name )
return aMesh
def CreateDualMesh( self, mesh, meshName, adaptToShape):
"""
Create a dual of a mesh.
Parameters:
mesh: Tetrahedron mesh
:class:`mesh, <SMESH.SMESH_IDSource>`.
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()
print("calling createdualmesh from Python")
dualMesh = SMESH._objref_SMESH_Gen.CreateDualMesh(self, mesh, meshName, adaptToShape)
return Mesh(self, self.geompyD, dualMesh)
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 <SMESH.SMESH_IDSource>`.
To copy nodes or elements not forming any mesh object,
pass result of :meth:`Mesh.GetIDSource` as *meshPart*
@ -810,7 +831,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 +1306,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
Returns:
minimum distance value
See also:
See also:
:meth:`GetMinDistance`
"""
@ -1313,7 +1334,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 +1381,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 +1402,7 @@ class smeshBuilder( SMESH._objref_SMESH_Gen, object ):
Returns:
:class:`SMESH.Measure` structure
See also:
See also:
:meth:`BoundingBox`
"""
@ -1460,14 +1481,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 <SMESH.SMESH_IDSource>`
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 +1502,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 +1572,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 +2102,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 +2321,23 @@ class Mesh(metaclass = MeshMeta):
meshPart: a part of mesh (:class:`sub-mesh, group or filter <SMESH.SMESH_IDSource>`)
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 +2392,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 +2408,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 +2417,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 +2585,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 +2662,7 @@ class Mesh(metaclass = MeshMeta):
Create an empty standalone mesh group
Parameters:
elementType: the :class:`type <SMESH.ElementType>` of elements in the group;
elementType: the :class:`type <SMESH.ElementType>` of elements in the group;
either of (SMESH.NODE, SMESH.EDGE, SMESH.FACE, SMESH.VOLUME)
name: the name of the mesh group
@ -2881,7 +2902,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 +3613,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 +3907,7 @@ class Mesh(metaclass = MeshMeta):
Returns:
a list of three double values
See also:
See also:
:meth:`smeshBuilder.GetGravityCenter`
"""
@ -4004,7 +4025,7 @@ class Mesh(metaclass = MeshMeta):
Returns:
tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
See Also:
See Also:
:meth:`GetBoundingBox()`
"""
@ -4027,7 +4048,7 @@ class Mesh(metaclass = MeshMeta):
Returns:
:class:`SMESH.Measure` structure
See Also:
See Also:
:meth:`BoundingBox()`
"""
@ -4163,7 +4184,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() <SMESH.SMESH_IDSource.GetIDs>`
"""
@ -4537,7 +4558,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 +4625,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 +4895,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 <SMESH.SMESH_IDSource>`
or a list of face IDs. By default all quadrangles are split
@ -4943,8 +4964,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 +5117,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 <SMESH.SMESH_IDSource>`
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 +5609,7 @@ class Mesh(metaclass = MeshMeta):
of all steps, else - size of each step
Returns:
the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
the list of created :class:`groups <SMESH.SMESH_GroupBase>` if *MakeGroups* == True,
empty list otherwise
"""
@ -5644,7 +5665,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 +5883,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 +5897,7 @@ class Mesh(metaclass = MeshMeta):
else *scaleFactors* [i] is applied to nodes at the i-th extrusion step
Returns:
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
:class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>`
Example: :ref:`tui_extrusion_along_path`
"""
@ -5896,7 +5917,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 +5938,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 +5981,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 +6022,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 +6033,7 @@ class Mesh(metaclass = MeshMeta):
variation of the given Angles along path steps
Returns:
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
:class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
Example: :ref:`tui_extrusion_along_path`
@ -6039,7 +6060,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 +6071,7 @@ class Mesh(metaclass = MeshMeta):
variation of the given Angles along path steps
Returns:
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
:class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
Example: :ref:`tui_extrusion_along_path`
@ -6077,7 +6098,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 +6109,7 @@ class Mesh(metaclass = MeshMeta):
variation of the given Angles along path steps
Returns:
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
list of created :class:`groups <SMESH.SMESH_GroupBase>` and
:class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` if *MakeGroups* == True,
only :class:`error code <SMESH.SMESH_MeshEditor.Extrusion_Error>` otherwise
Example: :ref:`tui_extrusion_along_path`
@ -6498,7 +6519,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 +6900,7 @@ class Mesh(metaclass = MeshMeta):
Parameters:
theElements: container of elements to duplicate. It can be a
:class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
:class:`mesh, sub-mesh, group, filter <SMESH.SMESH_IDSource>`
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 +6910,7 @@ class Mesh(metaclass = MeshMeta):
in any group.
Returns:
a :class:`group <SMESH.SMESH_Group>` where the new elements are added.
a :class:`group <SMESH.SMESH_Group>` where the new elements are added.
None if *theGroupName* == "".
"""
@ -7158,7 +7179,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 +7197,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 +7352,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 )

View File

@ -0,0 +1,127 @@
#!/usr/bin/env python3
import sys
import salome
import medcoupling as mc
from math import pi
import numpy as np
#salome.salome_init()
import GEOM
from salome.geom import geomBuilder
geompy = geomBuilder.New()
import SMESH, SALOMEDS
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
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(mesh_ior)
if not mesh:
raise Exception("Could not find mesh using id: ", mesh_ior)
shape = mesh.GetShapeToMesh()
# Creating output file
logger.debug("Creating file with mesh: "+mesh_name)
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)
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()
## 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):
# 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()
# 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()
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:
logger.debug("Adapting to shape")
ptsAddedCoo = ptsAddedMesh.getCoords()
ptsAddedCooModified = ptsAddedCoo[:]
# Matching faces with their ids
faces = geompy.ExtractShapes(shape, geompy.ShapeType["FACE"], True)
id2face = {}
for face in faces:
id2face[face.GetSubShapeIndices()[0]] = face
## 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
polyh.setName(mesh_name)
myfile.setMeshAtLevel(0, polyh)
logger.debug("Writting dual mesh in :"+output_file)
myfile.write(output_file, 2)

View File

@ -0,0 +1,94 @@
#!/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_raw_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_raw_1', False)
dual_Mesh_1 = smesh.CreateDualMesh(Mesh_1, 'dual_Mesh_1', True)
[ 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()
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()

View File

@ -62,6 +62,7 @@ SET(BAD_TESTS
SMESH_test1.py
SMESH_test2.py
SMESH_test4.py
SMESH_create_dual_mesh_adapt.py
)
IF(NOT WIN32)
LIST(APPEND BAD_TESTS