--- /dev/null
+# 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()
transforming_meshes_ex06.py
viewing_meshes_ex01.py
radial_prism_3d_algo.py
+ create_dual_mesh.py
)
IF(NOT WIN32)
LIST(APPEND BAD_TESTS
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
-.. _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`_.
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).
.. 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.
importing_exporting_meshes.rst
building_compounds.rst
copy_mesh.rst
+ create_dual_mesh.rst
connectivity.rst
--- /dev/null
+.. _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`.
: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?
========================================
: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
=============================
: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>`
+
Update the study
*/
void UpdateStudy();
-
+
/*!
Set enable publishing in the study
*/
void SetEnablePublish( in boolean theIsEnablePublish );
-
+
/*!
Get enable publishing in the study
*/
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
* \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
*/
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
*/
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
*/
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
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 );
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
#ifndef WIN32
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
-#else
+#else
#include <pthread.h>
#endif
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
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;
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
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();
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
void SMESH_Mesh::ClearLog()
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() )
{
//=======================================================================
//function : IsMainShape
-//purpose :
+//purpose :
//=======================================================================
bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
std::map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin();
for ( ; it != _mapGroup.end(); it++ )
anIds.push_back( it->first );
-
+
return anIds;
}
//=============================================================================
/*!
- *
+ *
*/
//=============================================================================
}
}
return true; // no order imposed to given sub-meshes
-}
+}
//=============================================================================
/*!
SMESHGUI_AddNodeOnSegmentDlg.h
SMESHGUI_AddNodeOnFaceDlg.h
SMESHGUI_InteractiveOp.h
+ SMESHGUI_CreateDualMeshDlg.h
+ SMESHGUI_CreateDualMeshOp.h
)
# header files / no moc processing
SMESHGUI_AddNodeOnSegmentDlg.cxx
SMESHGUI_AddNodeOnFaceDlg.cxx
SMESHGUI_InteractiveOp.cxx
+ SMESHGUI_CreateDualMeshDlg.cxx
+ SMESHGUI_CreateDualMeshOp.cxx
)
# sources / to compile
#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"
{
CORBA::Boolean anIsEmbeddedMode;
myComponentSMESH = SMESH_Client::GetSMESHGen(getApp()->orb(),anIsEmbeddedMode);
-
+
//MESSAGE("-------------------------------> anIsEmbeddedMode=" << anIsEmbeddedMode);
// 0019923: EDF 765 SMESH : default values of hypothesis
// 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:
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" );
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 );
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;
--- /dev/null
+// 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();
+}
\ No newline at end of file
--- /dev/null
+// 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
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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
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
<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>
<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>
<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>
<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>
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();
}
}
}
if ( method == "CreateMeshesFromUNV" ||
method == "CreateMeshesFromSTL" ||
+ method == "CreateDualMesh" ||
method == "CopyMesh" ) // command result is a mesh
{
Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() );
const _pyID& meshID = theCreationCmd->GetObject();
addFatherMesh( meshID );
}
-
+
// convert my creation command
Handle(_pyCommand) creationCmd = GetCreationCmd();
creationCmd->SetObject( SMESH_2smeshpy::SmeshpyName() );
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();
// 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);
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;
}
newName += "_Distribution";
prevNewName = newName;
-
+
hyp1d->GetCreationCmd()->SetResultValue( newName );
}
list< Handle(_pyCommand) >& cmds = theGen->GetCommands();
//================================================================================
/*!
- * \brief Check if "[ group1, group2 ] = mesh.GetGroups()" creation command
+ * \brief Check if "[ group1, group2 ] = mesh.GetGroups()" creation command
* can be cleared
*/
//================================================================================
if ( !myNewID.IsEmpty() )
theCommand->SetObject( myNewID );
-
+
// Convert the following set of commands into smesh.GetFilterFromCriteria(criteria)
// aFilter0x2aaab0487080 = aFilterManager.CreateFilter()
// aFilter0x2aaab0487080.SetCriteria(aCriteria)
void _pyFilter::Flush()
{
if ( myNewID.IsEmpty() ) return;
-
+
list< Handle(_pyCommand) >::iterator cmd = myArgCmds.begin();
for ( ; cmd != myArgCmds.end(); ++cmd )
if ( !(*cmd)->IsEmpty() )
// ...
// dim="2">
// <python-wrap>
- // <accumulative-methods>
+ // <accumulative-methods>
// SetEnforcedVertex,
// SetEnforcedVertexNamed
// </accumulative-methods>
#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>
#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;
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
{
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;
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,
smeshBuilder.py
smesh_algorithm.py
smesh_selection.py
+ smesh_tools.py
)
SET(StdMeshers_SCRIPTS
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})
def GetName(obj):
"""
Return a name of an object
-
+
Returns:
object name
"""
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.
if sc:
sb.LoadWith(sc, self)
pass
-
+
def SetEnablePublish( self, theIsEnablePublish ):
"""
Set enable publishing in the study. Calling SetEnablePublish( False ) allows to
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` )
"""
Returns:
an instance of class :class:`Mesh`
- See also:
+ See also:
:meth:`Mesh.Append`
"""
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*
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 )
Returns:
minimum distance value
- See also:
+ See also:
:meth:`GetMinDistance`
"""
Returns:
:class:`SMESH.Measure` structure or None if input data is invalid
- See also:
+ See also:
:meth:`MinDistance`
"""
Returns:
tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
- See also:
+ See also:
:meth:`GetBoundingBox`
"""
Returns:
:class:`SMESH.Measure` structure
- See also:
+ See also:
:meth:`BoundingBox`
"""
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
"""
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)
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
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:
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.
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).
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;
- '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.
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
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
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:
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
"""
Returns:
a list of three double values
- See also:
+ See also:
:meth:`smeshBuilder.GetGravityCenter`
"""
Returns:
tuple of six values (minX, minY, minZ, maxX, maxY, maxZ)
- See Also:
+ See Also:
:meth:`GetBoundingBox()`
"""
Returns:
:class:`SMESH.Measure` structure
- See Also:
+ See Also:
:meth:`BoundingBox()`
"""
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>`
"""
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.
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:
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
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:
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
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
"""
- 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
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
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`
"""
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,
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
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).
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).
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`
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).
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`
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).
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`
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
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.
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* == "".
"""
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.
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()
"""
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 )
--- /dev/null
+#!/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)
--- /dev/null
+#!/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()
SMESH_test1.py
SMESH_test2.py
SMESH_test4.py
+ SMESH_create_dual_mesh_adapt.py
)
IF(NOT WIN32)
LIST(APPEND BAD_TESTS