1 // Copyright (C) 2007-2019 CEA/DEN, EDF R&D, OPEN CASCADE
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // File : SMESH_ProxyMesh.cxx
20 // Created : Thu Dec 2 12:32:53 2010
21 // Author : Edward AGAPOV (eap)
23 #include "SMESH_ProxyMesh.hxx"
25 #include "SMDS_IteratorOnIterators.hxx"
26 #include "SMDS_SetIterator.hxx"
27 #include "SMESHDS_Mesh.hxx"
28 #include "SMESH_Mesh.hxx"
29 #include "SMESH_MesherHelper.hxx"
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
33 #include <TopTools_IndexedMapOfShape.hxx>
35 //================================================================================
37 * \brief Constructor; mesh must be set by a descendant class
39 //================================================================================
41 SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0), _subContainer(0)
44 //================================================================================
48 //================================================================================
50 SMESH_ProxyMesh::SMESH_ProxyMesh(const SMESH_Mesh& mesh)
52 _subContainer( new SubMesh( GetMeshDS() ) )
56 //================================================================================
58 * \brief Make a proxy mesh from components. Components become empty
60 //================================================================================
62 SMESH_ProxyMesh::SMESH_ProxyMesh(std::vector<SMESH_ProxyMesh::Ptr>& components):
65 if ( components.empty() ) return;
67 for ( unsigned i = 0; i < components.size(); ++i )
69 SMESH_ProxyMesh* m = components[i].get();
72 takeTmpElemsInMesh( m );
74 if ( !_mesh && m->_mesh ) setMesh( *( m->_mesh ));
75 if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
77 if ( _subMeshes.size() < m->_subMeshes.size() )
78 _subMeshes.resize( m->_subMeshes.size(), 0 );
79 for ( unsigned j = 0; j < m->_subMeshes.size(); ++j )
81 if ( !m->_subMeshes[j] ) continue;
85 std::set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
86 _subMeshes[j]->_elements.end());
87 elems.insert( m->_subMeshes[j]->_elements.begin(),
88 m->_subMeshes[j]->_elements.end());
89 _subMeshes[j]->_elements.assign( elems.begin(), elems.end() );
90 m->_subMeshes[j]->_elements.clear();
92 if ( !_subMeshes[j]->_n2n )
93 _subMeshes[j]->_n2n = m->_subMeshes[j]->_n2n, m->_subMeshes[j]->_n2n = 0;
95 else if ( _subMeshes[j]->_n2n && m->_subMeshes[j]->_n2n )
96 _subMeshes[j]->_n2n->insert( m->_subMeshes[j]->_n2n->begin(),
97 m->_subMeshes[j]->_n2n->end());
101 _subMeshes[j] = m->_subMeshes[j];
102 m->_subMeshes[j] = 0;
108 //================================================================================
110 * \brief Destructor deletes proxy submeshes and tmp elements
112 //================================================================================
114 SMESH_ProxyMesh::~SMESH_ProxyMesh()
116 delete _subContainer;
118 for ( size_t i = 0; i < _subMeshes.size(); ++i )
119 delete _subMeshes[i];
122 std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
123 for ( ; i != _elemsInMesh.end(); ++i )
124 GetMeshDS()->RemoveFreeElement( *i, 0 );
125 _elemsInMesh.clear();
128 //================================================================================
132 //================================================================================
134 void SMESH_ProxyMesh::setMesh(const SMESH_Mesh& mesh)
138 _subContainer = new SubMesh( GetMeshDS() );
141 //================================================================================
143 * \brief Returns index of a shape
145 //================================================================================
147 int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
149 return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
152 //================================================================================
154 * \brief Create a SubMesh
155 * \param [ino] index - shape index
156 * \return SubMesh* - new SubMesh
158 //================================================================================
160 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::newSubmesh(int index) const
162 return new SubMesh( GetMeshDS(),index );
165 //================================================================================
167 * \brief Returns the submesh of a shape; it can be a proxy sub-mesh
169 //================================================================================
171 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
173 const SMESHDS_SubMesh* sm = 0;
175 size_t i = shapeIndex(shape);
176 if ( i < _subMeshes.size() )
179 sm = GetMeshDS()->MeshElements( i );
184 //================================================================================
186 * \brief Returns the proxy sub-mesh of a shape; it can be NULL
188 //================================================================================
190 const SMESH_ProxyMesh::SubMesh*
191 SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const
193 size_t i = shapeIndex(shape);
194 return i < _subMeshes.size() ? _subMeshes[i] : 0;
197 //================================================================================
199 * \brief Returns the proxy node of a node; the input node is returned if no proxy exists
201 //================================================================================
203 const SMDS_MeshNode* SMESH_ProxyMesh::GetProxyNode( const SMDS_MeshNode* node ) const
205 const SMDS_MeshNode* proxy = node;
206 if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
208 if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() ))
209 proxy = proxySM->GetProxyNode( node );
213 TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS());
214 TopTools_ListIteratorOfListOfShape ancIt;
215 if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape ));
216 for ( ; ancIt.More() && proxy == node; ancIt.Next() )
217 if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value())))
218 proxy = proxySM->GetProxyNode( node );
223 //================================================================================
225 * \brief Returns number of proxy sub-meshes
227 //================================================================================
229 int SMESH_ProxyMesh::NbProxySubMeshes() const
232 for ( size_t i = 0; i < _subMeshes.size(); ++i )
233 nb += bool( _subMeshes[i] );
240 //================================================================================
242 * \brief Iterator filtering elements by type
244 //================================================================================
246 class TFilteringIterator : public SMDS_ElemIterator
248 SMDS_ElemIteratorPtr _iter;
249 const SMDS_MeshElement * _curElem;
250 std::vector< SMDSAbs_EntityType> _okTypes;
252 TFilteringIterator( const std::vector< SMDSAbs_EntityType>& okTypes,
253 const SMDS_ElemIteratorPtr& elemIterator)
254 :_iter(elemIterator), _curElem(0), _okTypes(okTypes)
262 virtual const SMDS_MeshElement* next()
264 const SMDS_MeshElement* res = _curElem;
266 while ( _iter->more() && !_curElem )
268 _curElem = _iter->next();
269 if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end())
277 //================================================================================
279 * \brief Returns iterator on all faces on the shape taking into account substitutions
281 //================================================================================
283 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
285 if ( !_mesh->HasShapeToMesh() )
286 return SMDS_ElemIteratorPtr();
288 _subContainer->RemoveAllSubmeshes();
290 TopTools_IndexedMapOfShape FF;
291 TopExp::MapShapes( shape, TopAbs_FACE, FF );
292 for ( int i = 1; i <= FF.Extent(); ++i )
293 if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
294 _subContainer->AddSubMesh( sm );
296 return _subContainer->SMESHDS_SubMesh::GetElements();
299 //================================================================================
301 * \brief Returns iterator on all faces of the mesh taking into account substitutions
302 * To be used in case of mesh without shape
304 //================================================================================
306 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
308 if ( _mesh->HasShapeToMesh() )
309 return SMDS_ElemIteratorPtr();
311 _subContainer->RemoveAllSubmeshes();
312 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
314 _subContainer->AddSubMesh( _subMeshes[i] );
316 if ( _subContainer->NbSubMeshes() == 0 ) // no elements substituted
317 return GetMeshDS()->elementsIterator(SMDSAbs_Face);
319 // if _allowedTypes is empty, only elements from _subMeshes are returned,...
320 SMDS_ElemIteratorPtr proxyIter = _subContainer->SMESHDS_SubMesh::GetElements();
321 if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
324 // ... else elements filtered using allowedTypes are additionally returned
325 SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
326 SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
327 std::vector< SMDS_ElemIteratorPtr > iters(2);
328 iters[0] = proxyIter;
329 iters[1] = filterIter;
331 typedef std::vector< SMDS_ElemIteratorPtr > TElemIterVector;
332 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
333 return SMDS_ElemIteratorPtr( new TItersIter( iters ));
336 //================================================================================
338 * \brief Return total nb of faces taking into account substitutions
340 //================================================================================
342 int SMESH_ProxyMesh::NbFaces() const
345 if ( _mesh->HasShapeToMesh() )
347 TopTools_IndexedMapOfShape FF;
348 TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
349 for ( int i = 1; i <= FF.Extent(); ++i )
350 if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
351 nb += sm->NbElements();
355 if ( _subMeshes.empty() )
356 return GetMeshDS()->NbFaces();
358 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
360 nb += _subMeshes[i]->NbElements();
362 // if _allowedTypes is empty, only elements from _subMeshes are returned,
363 // else elements filtered using allowedTypes are additionally returned
364 if ( !_allowedTypes.empty() )
366 for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
369 ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
371 nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
378 //================================================================================
380 * \brief Returns a proxy sub-mesh; it is created if not yet exists
382 //================================================================================
384 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(int index)
386 if ( int(_subMeshes.size()) <= index )
387 _subMeshes.resize( index+1, 0 );
388 if ( !_subMeshes[index] )
389 _subMeshes[index] = newSubmesh( index );
390 return _subMeshes[index];
393 //================================================================================
395 * \brief Returns a proxy sub-mesh; it is created if not yet exists
397 //================================================================================
399 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape)
401 return getProxySubMesh( shapeIndex( shape ));
404 //================================================================================
406 * \brief Returns a proxy sub-mesh
408 //================================================================================
410 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const
412 return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
415 //================================================================================
417 * \brief Returns mesh DS
419 //================================================================================
421 SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const
423 return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
426 //================================================================================
428 * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found
430 //================================================================================
432 bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape& shape,
433 SMESH_ProxyMesh* proxyMesh )
435 if ( proxyMesh && proxyMesh->_mesh == _mesh )
437 int iS = shapeIndex( shape );
438 if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
440 if ( iS >= int(_subMeshes.size()) )
441 _subMeshes.resize( iS + 1, 0 );
443 proxyMesh->_subMeshes[iS] = 0;
450 //================================================================================
452 * \brief Move tmp elements residing the _mesh from other proxy mesh to this
454 //================================================================================
456 void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh )
460 _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
461 proxyMesh->_elemsInMesh.end());
462 proxyMesh->_elemsInMesh.clear();
466 //================================================================================
468 * \brief Removes tmp elements from the _mesh
470 //================================================================================
472 void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* elem )
474 if ( elem && elem->GetID() > 0 )
476 std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( elem );
477 if ( i != _elemsInMesh.end() )
479 GetMeshDS()->RemoveFreeElement( elem, 0 );
480 _elemsInMesh.erase( i );
489 //================================================================================
491 * \brief Stores tmp element residing the _mesh
493 //================================================================================
495 void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* elem )
497 _elemsInMesh.insert( elem );
500 //================================================================================
502 * \brief Set node-node correspondence
504 //================================================================================
506 void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode,
507 const SMDS_MeshNode* proxyNode,
508 const SubMesh* subMesh)
510 SubMesh* sm = const_cast<SubMesh*>( subMesh );
511 if ( !subMesh->_n2n )
512 sm->_n2n = new TN2NMap;
513 sm->_n2n->insert( std::make_pair( srcNode, proxyNode ));
516 //================================================================================
518 * \brief Return true if the element is a temporary one
520 //================================================================================
522 bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
524 return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
527 //================================================================================
529 * \brief SubMesh Constructor
531 //================================================================================
533 SMESH_ProxyMesh::SubMesh::SubMesh( const SMDS_Mesh* mesh, int index )
534 : SMESHDS_SubMesh( static_cast<const SMESHDS_Mesh*>( mesh ), index ),
539 //================================================================================
541 * \brief Return a proxy node or an input node
543 //================================================================================
545 const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const
547 TN2NMap::iterator n2n;
548 if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end())
553 //================================================================================
555 * \brief Deletes temporary elements
557 //================================================================================
559 void SMESH_ProxyMesh::SubMesh::Clear()
561 for ( unsigned i = 0; i < _elements.size(); ++i )
562 if ( _elements[i]->GetID() < 0 )
566 delete _n2n, _n2n = 0;
569 //================================================================================
571 * \brief Return number of elements in a proxy sub-mesh. The method is meaningful
572 * for a sub-mesh containing tmp faces.
574 //================================================================================
576 int SMESH_ProxyMesh::SubMesh::NbElements() const
578 return _uvPtStructVec.empty() ? _elements.size() : _uvPtStructVec.size() - 1;
581 //================================================================================
583 * \brief Return elements of a proxy sub-mesh. The method is meaningful
584 * for a sub-mesh containing tmp faces.
586 //================================================================================
588 SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const
590 return SMDS_ElemIteratorPtr
591 ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() ));
594 //================================================================================
596 * \brief Return number of nodes in a proxy sub-mesh. The method is meaningful
597 * for a sub-mesh containing nodes of 2D viscous layer.
599 //================================================================================
601 int SMESH_ProxyMesh::SubMesh::NbNodes() const
603 return _uvPtStructVec.size();
606 //================================================================================
608 * \brief Return nodes of a proxy sub-mesh. The method is meaningful
609 * for a sub-mesh containing nodes of 2D viscous layer.
611 //================================================================================
613 SMDS_NodeIteratorPtr SMESH_ProxyMesh::SubMesh::GetNodes() const
615 if ( !_uvPtStructVec.empty() )
616 return SMDS_NodeIteratorPtr ( new SMDS_SetIterator
618 UVPtStructVec::const_iterator,
619 UVPtStruct::NodeAccessor >
620 ( _uvPtStructVec.begin(), _uvPtStructVec.end() ));
622 return SMDS_NodeIteratorPtr
623 ( new SMDS_SetIterator< SMDS_pNode, std::vector< SMDS_pElement >::const_iterator>
624 ( _elements.begin(), _elements.end() ));
627 //================================================================================
629 * \brief Store an element
631 //================================================================================
633 void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e)
635 _elements.push_back( e );
638 //================================================================================
640 * \brief Check presence of element inside it-self
642 //================================================================================
644 bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const
646 if ( ME->GetType() != SMDSAbs_Node )
647 return find( _elements.begin(), _elements.end(), ME ) != _elements.end();