The MESH module contains a set of meshing algorithms, which are used for meshing entities (1D, 2D, 3D sub-shapes) composing geometrical objects.
-.. note:: Algorithms added to the module as plug-ins are described in documentation of the plug-ins.
+.. note:: Algorithms added to the module as plug-ins are described in documentation of the plug-ins (menu **Help / User's Guide / Mesh module / Plugins**).
An algorithm represents either an implementation of a certain meshing technique or an interface to the whole meshing program generating elements of several dimensions.
.. centered::
A sphere meshed by Body Fitting algorithm
+.. note:: The algorithm creates only 3D elements. To add 2D elements use :ref:`Generate boundary elements <make_2dmesh_from_3d_page>` operation.
+
The meshing algorithm is as follows.
#. Lines of a Cartesian structured grid defined by :ref:`Body Fitting Parameters <cartesian_hyp_anchor>` hypothesis are intersected with the geometry boundary, thus nodes lying on the boundary are found. This step also allows finding out for each node of the Cartesian grid if it is inside or outside the geometry.
* **Python Dump**
* **Historical python dump** - allows switching between *Historical* and *Snapshot* dump mode:
- * In *Historical* mode, Python Dump script includes all commands performed by SMESH engine.
- * In *Snapshot* mode, the commands relating to objects removed from the Study as well as the commands not influencing the current state of meshes are excluded from the script.
+
+ * In *Historical* mode, Python Dump script includes all commands performed by SMESH engine.
+ * In *Snapshot* mode, the commands relating to objects removed from the Study as well as the commands not influencing the current state of meshes are excluded from the script.
.. _mesh_tab_preferences:
* :ref:`Add <adding_nodes_and_elements_page>` mesh elements from nodes to polyhedrons at an arbitrary place in the mesh.
* :ref:`Add quadratic <adding_quadratic_elements_page>` mesh elements from quadratic segments to quadratic hexahedrons at an arbitrary place in the mesh.
-* :ref:`Remove <removing_nodes_and_elements_page>` any existin" mesh elements and nodes.
+* :ref:`Remove <removing_nodes_and_elements_page>` any existing mesh elements and nodes.
+* :ref:`Convert linear mesh to quadratic <convert_to_from_quadratic_mesh_page>`, or vice versa.
+* :ref:`Generate boundary elements <make_2dmesh_from_3d_page>`.
* :ref:`Translate <translation_page>` in the indicated direction the mesh or some of its elements.
* :ref:`Rotate <rotation_page>` by the indicated axis and angle the mesh or some of its elements.
* :ref:`Scale <scale_page>` the mesh or some of its elements.
* :ref:`Mirror <symmetry_page>` the mesh through a point, a vector or a plane of symmetry.
* :ref:`double_nodes_page`. Duplication of nodes can be useful to emulate a crack in the model.
-* Unite meshes by :ref:`sewing <sewing_meshes_page>` free borders, border to side or side elements.
* :ref:`Merge Nodes<merging_nodes_page>` coincident within the indicated tolerance.
* :ref:`Merge Elements <merging_elements_page>` based on the same nodes.
+* Create an :ref:`extrusion <extrusion_page>` along a vector or by normal to a discretized surface.
+* Create an :ref:`extrusion along a path <extrusion_along_path_page>`.
+* Create elements by :ref:`revolution <revolution_page>` of the selected nodes and elements.
* :ref:`Move Nodes <mesh_through_point_page>` to an arbitrary location with consequent transformation of all adjacent elements.
+* :ref:`Change orientation <changing_orientation_of_elements_page>` of the selected elements.
+* :ref:`Orient faces <reorient_faces_page>` by several means.
+* Unite meshes by :ref:`sewing <sewing_meshes_page>` free borders, border to side or side elements.
* :ref:`Invert an edge <diagonal_inversion_of_elements_page>` between neighboring triangles.
* :ref:`Unite two triangles <uniting_two_triangles_page>`.
* :ref:`Unite several adjacent triangles <uniting_set_of_triangles_page>`.
-* :ref:`Change orientation <changing_orientation_of_elements_page>` of the selected elements.
-* :ref:`Orient faces <reorient_faces_page>` by several means.
* :ref:`Cut a quadrangle <cutting_quadrangles_page>` into two triangles.
* :ref:`Split <split_to_tetra_page>` volumic elements into tetrahedra or prisms.
* :ref:`Split bi-quadratic <split_biquad_to_linear_page>` elements into linear ones without creation of additional nodes.
* :ref:`Smooth <smoothing_page>` elements, reducung distortions in them by adjusting the locations of nodes.
-* Create an :ref:`extrusion <extrusion_page>` along a vector or by normal to a discretized surface.
-* Create an :ref:`extrusion along a path <extrusion_along_path_page>`.
-* Create elements by :ref:`revolution <revolution_page>` of the selected nodes and elements.
* Apply :ref:`pattern mapping <pattern_mapping_page>`.
-* :ref:`Convert linear mesh to quadratic <convert_to_from_quadratic_mesh_page>`, or vice versa.
-* :ref:`Generate boundary elements <make_2dmesh_from_3d_page>`.
* :ref:`generate_flat_elements_page`.
* :ref:`cut_mesh_by_plane_page`.
.. note::
- It is possible to :ref:`modify the mesh <edit_anchor>` of a lower dimension before generation of the mesh of a higher dimension.
+ You can use these operations to :ref:`modify the mesh <edit_anchor>` of a lower dimension before generation of the mesh of a higher dimension.
.. note::
It is possible to use the variables defined in the SALOME **NoteBook** to specify the numerical parameters used for modification of any object.
// ============================================================
/*!
- * \brief Base class for elements of not contained in the mesh
+ * \brief Base class for elements not contained in the mesh
*/
// ============================================================
SMDS_ElementChunk::SMDS_ElementChunk( SMDS_ElementFactory* factory, int id0 ):
myFactory( factory ),
- my1stID( id0 ),
- myMinSubID( std::numeric_limits<int>::max() ),
- myMaxSubID( 0 )
+ my1stID( id0 )//,
+ //mySubIDSet( 0 )
+ // myMinSubID( std::numeric_limits<int>::max() ),
+ // myMaxSubID( 0 )
{
if ( !myFactory )
return;
void SMDS_ElementChunk::SetShapeID( const SMDS_MeshElement* e, int shapeID ) const
{
- const size_t nbRanges = mySubIDRanges.Size();
+ //const size_t nbRanges = mySubIDRanges.Size();
SMDS_ElementChunk* me = const_cast<SMDS_ElementChunk*>( this );
int oldShapeID = me->mySubIDRanges.SetValue( Index( e ), shapeID );
uv[1] = 0.;
}
// update min/max
- if (( nbRanges > mySubIDRanges.Size() ) &&
- ( myMinSubID == oldShapeID || myMaxSubID == oldShapeID ))
- {
- me->myMinSubID = ( std::numeric_limits<int>::max() );
- me->myMaxSubID = 0;
- TSubIDRangeSet::set_iterator it;
- for ( it = mySubIDRanges.mySet.begin(); it < mySubIDRanges.mySet.end(); ++it )
- if ( it->myValue > 0 )
- {
- me->myMinSubID = std::min( myMinSubID, it->myValue );
- me->myMaxSubID = std::max( myMaxSubID, it->myValue );
- }
- }
- else if ( shapeID > 0 )
- {
- me->myMinSubID = std::min( myMinSubID, shapeID );
- me->myMaxSubID = std::max( myMaxSubID, shapeID );
- }
+ // if (( nbRanges > mySubIDRanges.Size() ) &&
+ // ( myMinSubID == oldShapeID || myMaxSubID == oldShapeID ))
+ // {
+ // me->myMinSubID = ( std::numeric_limits<int>::max() );
+ // me->myMaxSubID = 0;
+ // TSubIDRangeSet::set_iterator it;
+ // for ( it = mySubIDRanges.mySet.begin(); it < mySubIDRanges.mySet.end(); ++it )
+ // if ( it->myValue > 0 )
+ // {
+ // me->myMinSubID = std::min( myMinSubID, it->myValue );
+ // me->myMaxSubID = std::max( myMaxSubID, it->myValue );
+ // }
+ // }
+ // else if ( shapeID > 0 )
+ // {
+ // me->myMinSubID = std::min( myMinSubID, shapeID );
+ // me->myMaxSubID = std::max( myMaxSubID, shapeID );
+ // }
}
//================================================================================
{
std::cout << "1stID: " << my1stID << std::endl;
- std::cout << "SubID min/max: " << myMinSubID << ", " << myMaxSubID << std::endl;
+ //std::cout << "SubID min/max: " << myMinSubID << ", " << myMaxSubID << std::endl;
std::cout << "SubIDRanges: " << mySubIDRanges.Size() << " ";
{
TSubIDRangeSet::set_iterator i = mySubIDRanges.mySet.begin();
//! Return an iterator on all element assigned to a given shape.
// nbElemsToReturn is used to optimize by stopping the iteration as soon as
// all elements assigned to the shape encountered.
+ // sm1stElem is used to quickly find the first chunk holding elements of the shape;
+ // it must have smallest ID between elements on the shape
template< class ElemIterator >
- boost::shared_ptr< ElemIterator > GetShapeIterator( int shapeID, size_t nbElemsToReturn );
+ boost::shared_ptr< ElemIterator > GetShapeIterator( int shapeID,
+ size_t nbElemsToReturn,
+ const SMDS_MeshElement* sm1stElem );
//! Mark the element as non-used
void Free( const SMDS_MeshElement* );
{
bool isFound = false;
- if ( sizeof( attr_t ) == sizeof( int ) && theMinValue )
- if ( theValue < *theMinValue || theValue > *theMaxValue )
- return isFound;
+ // if ( sizeof( attr_t ) == sizeof( int ) && theMinValue )
+ // if ( theValue < *theMinValue || theValue > *theMaxValue )
+ // return isFound;
for ( set_iterator it = mySet.begin(); it < mySet.end(); ++it )
{
typedef boost::dynamic_bitset<> TBitSet;
//typedef float TParam;
typedef double TParam;
+//typedef std::unordered_set<int> TSubIDSet;
//------------------------------------------------------------------------------------
/*!
TBitSet myMarkedSet; // mark some elements
TUsedRangeSet myUsedRanges; // ranges of used/unused elements
TSubIDRangeSet mySubIDRanges; // ranges of elements on the same sub-shape
- int myMinSubID; // min sub-shape ID
- int myMaxSubID; // max sub-shape ID
+ //TSubIDSet* mySubIDSet; // set of sub-shape IDs
+ // int myMinSubID; // min sub-shape ID
+ // int myMaxSubID; // max sub-shape ID
std::vector<TParam> myPositions; // UV parameters on shape: 2*param_t per an element
public:
//! Return ranges of elements assigned to sub-shapes and min/max of sub-shape IDs
const TSubIDRangeSet& GetSubIDRangesMinMax( int& min, int& max ) const
- { min = myMinSubID; max = myMaxSubID; return mySubIDRanges; }
+ { /*min = myMinSubID; max = myMaxSubID;*/ return mySubIDRanges; }
//! Minimize allocated memory
void Compact();
get_rangeset_fun theGetRangeSetFun,
attr_type theAttrValue,
SMDS_MeshElement::Filter* theFilter,
- size_t theNbElemsToReturn = -1):
+ size_t theNbElemsToReturn = -1,
+ int theChunkIndex = 0):
myElement( 0 ),
myRangeIndex( 0 ),
myChunks( theChunks ),
- myChunkIndex( -1 ),
+ myChunkIndex( theChunkIndex-1 ),
myGetRangeSetFun( theGetRangeSetFun ),
myValue( theAttrValue ),
myFilter( theFilter ),
template< class ElemIterator >
boost::shared_ptr< ElemIterator >
-SMDS_ElementFactory::GetShapeIterator( int shapeID, size_t nbElemsToReturn )
+SMDS_ElementFactory::GetShapeIterator( int shapeID,
+ size_t nbElemsToReturn,
+ const SMDS_MeshElement* sm1stElem )
{
+ int iChunk = sm1stElem ? (( sm1stElem->GetID() - 1 ) / ChunkSize()) : 0;
typedef _ChunkIterator< ElemIterator, TSubIDRangeSet > TChuckIterator;
return boost::make_shared< TChuckIterator >( myChunks,
& SMDS_ElementChunk::GetSubIDRangesMinMax,
/*shapeID=*/shapeID,
new SMDS_MeshElement::NonNullFilter(),
- nbElemsToReturn );
+ nbElemsToReturn,
+ iChunk );
}
#endif
SMDS_ElementHolder::SMDS_ElementHolder( const SMDS_Mesh* mesh )
: myMesh( const_cast< SMDS_Mesh* >( mesh ))
{
- myPtrInMesh = myMesh->myElemHolders.insert( this ).first;
+ if ( myMesh )
+ myPtrInMesh = myMesh->myElemHolders.insert( this ).first;
}
//=======================================================================
SMDS_ElementHolder::~SMDS_ElementHolder()
{
- myMesh->myElemHolders.erase( myPtrInMesh );
+ if ( myMesh )
+ myMesh->myElemHolders.erase( myPtrInMesh );
}
//=======================================================================
myInfo.NbVolumes());
}
-SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID, size_t nbElemsToReturn) const
+SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID,
+ size_t nbElemsToReturn,
+ const SMDS_MeshNode* sm1stNode) const
{
- return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn );
+ return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn, sm1stNode );
}
-SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID, size_t nbElemsToReturn) const
+SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID,
+ size_t nbElemsToReturn,
+ const SMDS_MeshElement* sm1stElem) const
{
- return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn );
+ return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn, sm1stElem );
}
///////////////////////////////////////////////////////////////////////////////
virtual SMDS_ElemIteratorPtr elementGeomIterator(SMDSAbs_GeometryType type) const;
virtual SMDS_ElemIteratorPtr elementEntityIterator(SMDSAbs_EntityType type) const;
- virtual SMDS_NodeIteratorPtr shapeNodesIterator (int shapeID, size_t nbElemsToReturn=-1) const;
- virtual SMDS_ElemIteratorPtr shapeElementsIterator(int shapeID, size_t nbElemsToReturn=-1) const;
+ virtual SMDS_NodeIteratorPtr shapeNodesIterator (int shapeID,
+ size_t nbElemsToReturn=-1,
+ const SMDS_MeshNode* sm1stNode=0) const;
+ virtual SMDS_ElemIteratorPtr shapeElementsIterator(int shapeID,
+ size_t nbElemsToReturn=-1,
+ const SMDS_MeshElement* sm1stElem=0) const;
SMDSAbs_ElementType GetElementType( const int id, const bool iselem ) const;
//
#include "SMESHDS_SubMesh.hxx"
-#include "SMESHDS_Mesh.hxx"
-#include "SMDS_SetIterator.hxx"
#include "SMDS_ElementFactory.hxx"
+#include "SMDS_IteratorOnIterators.hxx"
+#include "SMDS_SetIterator.hxx"
+#include "SMESHDS_Mesh.hxx"
#include <utilities.h>
+namespace
+{
+ typedef const SMDS_MeshElement* PElem;
+ typedef const SMDS_MeshNode* PNode;
+
+ typedef SMDS_SetIterator< PElem, PElem const *,
+ SMDS::SimpleAccessor< PElem, PElem const * >,
+ SMDS::NonNullFilter< PElem > > EArrayIterator;
+
+ typedef SMDS_SetIterator< PNode, PNode const *,
+ SMDS::SimpleAccessor< PNode, PNode const * >,
+ SMDS::NonNullFilter< PNode > > NArrayIterator;
+
+ int ind1st( SMDSAbs_ElementType t )
+ {
+ return t == SMDSAbs_Node;
+ }
+
+ //=======================================================================
+ //class : _MyElemIteratorFromNodeIterator
+ //=======================================================================
+ class _MyElemIteratorFromNodeIterator : public SMDS_ElemIterator
+ {
+ SMDS_NodeIteratorPtr myItr;
+ public:
+ _MyElemIteratorFromNodeIterator(SMDS_NodeIteratorPtr nodeItr): myItr( nodeItr ) {}
+ bool more() { return myItr->more(); }
+ const SMDS_MeshElement* next() { return myItr->next(); }
+ };
+}
+
//================================================================================
/*!
* \brief Constructor
//================================================================================
SMESHDS_SubMesh::SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index)
+ : SMDS_ElementHolder( parent )
{
myParent = parent;
myIndex = index;
myNbElements = 0;
myNbNodes = 0;
+ my1stElemNode[0] = my1stElemNode[1] = 0;
}
//================================================================================
elem->setShapeID( myIndex );
myNbElements++;
+
+ // remember element with smallest ID to optimize iteration on them
+ add( elem );
}
}
{
elem->setShapeID( 0 );
myNbElements--;
+
+ const SMDS_MeshElement* & elem1st = my1stElemNode[ ind1st( elem->GetType() )];
+ if ( elem1st == elem )
+ elem1st = 0;
+
return true;
}
return false;
}
N->setShapeID( myIndex );
myNbNodes++;
+
+ // remember node with smallest ID to optimize iteration on them
+ add( N );
}
}
{
N->setShapeID( 0 );
myNbNodes--;
+
+ const SMDS_MeshElement* & node1st = my1stElemNode[ ind1st( SMDSAbs_Node )];
+ if ( node1st == N )
+ node1st = 0;
+
return true;
}
return false;
return nbElems;
}
-/*!
- * Template class used for iteration on vector of elements which can resize
- * during iteration. The iterator returns only elements present upon its creation.
- */
-template <class ELEM, typename TSET> class MySetIterator : public SMDS_Iterator<ELEM>
-{
-protected:
- int _iCur, _iEnd, _iDelta;
- const TSET& _table;
-public:
- MySetIterator(const TSET& table, bool reverse): _table( table )
- {
- if ( reverse )
- {
- _iCur = _table.size()-1;
- _iEnd = -1;
- _iDelta = -1;
- }
- else
- {
- _iCur = 0;
- _iEnd = _table.size();
- _iDelta = 1;
- }
- if ( more() && !_table[ _iCur ])
- next();
- }
-
- virtual bool more()
- {
- return ( _iEnd - _iCur ) * _iDelta > 0;
- }
-
- virtual ELEM next()
- {
- ELEM e = more() ? _table[ _iCur ] : 0;
- _iCur += _iDelta;
- while ( more() && !_table[ _iCur ])
- _iCur += _iDelta;
- return e;
- }
-};
-
// =====================
// class MyIterator
// =====================
if ( IsComplexSubmesh() )
return SMDS_ElemIteratorPtr( new MyElemIterator( mySubMeshes ));
- return myParent->shapeElementsIterator( myIndex, myNbElements );
+ const SMDS_MeshElement* const * elem1st = & my1stElemNode[ ind1st( SMDSAbs_All )];
+ if ( myNbElements == 1 )
+ {
+ return boost::make_shared< EArrayIterator >( elem1st, elem1st+1 );
+ }
+
+ return myParent->shapeElementsIterator( myIndex, myNbElements, *elem1st );
}
//=======================================================================
if ( IsComplexSubmesh() )
return SMDS_NodeIteratorPtr( new MyNodeIterator( mySubMeshes ));
- return myParent->shapeNodesIterator( myIndex, myNbNodes );
+ PNode const * node1st =
+ reinterpret_cast< PNode const* >( & my1stElemNode[ ind1st( SMDSAbs_Node )] );
+ if ( myNbNodes == 1 )
+ {
+ return boost::make_shared< NArrayIterator >( node1st, node1st+1 );
+ }
+
+ return myParent->shapeNodesIterator( myIndex, myNbNodes, *node1st );
}
//=======================================================================
myNbElements = 0;
myNbNodes = 0;
+ my1stElemNode[0] = my1stElemNode[1] = 0;
if ( NbSubMeshes() > 0 )
{
SMESHDS_SubMeshIteratorPtr sub = GetSubMeshIterator();
}
}
}
+
+//=======================================================================
+//function : getElements
+//purpose : Return iterator on all elements and nodes during compacting
+//=======================================================================
+
+SMDS_ElemIteratorPtr SMESHDS_SubMesh::getElements()
+{
+ if ( IsComplexSubmesh() ) // return nothing
+ boost::make_shared< EArrayIterator >( & my1stElemNode[0], & my1stElemNode[0] );
+
+ typedef std::vector< SMDS_ElemIteratorPtr > TIterVec;
+ TIterVec iterVec(2);
+ iterVec[0] = GetElements();
+ iterVec[1].reset( new _MyElemIteratorFromNodeIterator( GetNodes() ));
+
+ return boost::make_shared< SMDS_IteratorOnIterators< PElem, TIterVec > >( iterVec );
+}
+
+//=======================================================================
+//function : tmpClear
+//purpose : clean up after compacting
+//=======================================================================
+
+void SMESHDS_SubMesh::tmpClear()
+{
+ my1stElemNode[0] = my1stElemNode[1] = 0;
+}
+
+//=======================================================================
+//function : add
+//purpose : update my1stElemNode
+//=======================================================================
+
+void SMESHDS_SubMesh::add( const SMDS_MeshElement* elem )
+{
+ const SMDS_MeshElement* & oldElem = my1stElemNode[ ind1st( elem->GetType() )];
+ if ( !oldElem || oldElem->GetID() > elem->GetID() )
+ oldElem = elem;
+}
#include "SMESH_SMESHDS.hxx"
+#include "SMDS_ElementHolder.hxx"
#include "SMDS_Mesh.hxx"
#include <vector>
class SMESHDS_Mesh;
-class SMESHDS_EXPORT SMESHDS_SubMesh
+class SMESHDS_EXPORT SMESHDS_SubMesh : public SMDS_ElementHolder
{
public:
SMESHDS_SubMesh(SMESHDS_Mesh *parent, int index);
virtual bool RemoveElement(const SMDS_MeshElement * ME); // ret true if ME was in
virtual void AddNode(const SMDS_MeshNode * ME);
virtual bool RemoveNode(const SMDS_MeshNode * ME); // ret true if ME was in
- //virtual const SMDS_MeshElement* GetElement( size_t idInShape ) const;
- //virtual const SMDS_MeshNode* GetNode ( size_t idInShape ) const;
// if IsComplexSubmesh()
void AddSubMesh( const SMESHDS_SubMesh* theSubMesh );
SMESHDS_Mesh* GetParent() const { return const_cast< SMESHDS_Mesh*>( myParent ); }
int GetID() const { return myIndex; }
+ protected: // methods of SMDS_ElementHolder
+
+ virtual SMDS_ElemIteratorPtr getElements();
+ virtual void tmpClear();
+ virtual void add( const SMDS_MeshElement* element );
+ virtual void compact() {}
+
private:
- int myIndex;
- int myNbElements;
- int myNbNodes;
- SMESHDS_Mesh * myParent;
- TSubMeshSet mySubMeshes;
+ int myIndex;
+ int myNbElements;
+ int myNbNodes;
+ const SMDS_MeshElement* my1stElemNode[2]; // elem and node with least ID, to optimize iteration
+ SMESHDS_Mesh * myParent;
+ TSubMeshSet mySubMeshes;
};
#endif
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 is following:
- - 'v' stands for "_vertices _" field;
- - 'e' stands for "_edges _" field;
- - 'f' stands for "_faces _" field;
- - 's' stands for "_solids _" field.
+
+ - 'v' stands for "_vertices_" field;
+ - 'e' stands for "_edges_" field;
+ - 'f' stands for "_faces_" field;
+ - 's' stands for "_solids_" field.
"""
# process positional arguments
#args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility