1 // Copyright (C) 2007-2021 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 #include <boost/container/flat_set.hpp>
36 #include <boost/make_shared.hpp>
38 //================================================================================
40 * \brief Constructor; mesh must be set by a descendant class
42 //================================================================================
44 SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0), _subContainer(0)
47 //================================================================================
51 //================================================================================
53 SMESH_ProxyMesh::SMESH_ProxyMesh(const SMESH_Mesh& mesh)
55 _subContainer( new SubMesh( GetMeshDS() ) )
59 //================================================================================
61 * \brief Make a proxy mesh from components. Components become empty
63 //================================================================================
65 SMESH_ProxyMesh::SMESH_ProxyMesh(std::vector<SMESH_ProxyMesh::Ptr>& components):
68 if ( components.empty() ) return;
70 for ( unsigned i = 0; i < components.size(); ++i )
72 SMESH_ProxyMesh* m = components[i].get();
75 takeTmpElemsInMesh( m );
77 if ( !_mesh && m->_mesh ) setMesh( *( m->_mesh ));
78 if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
80 if ( _subMeshes.size() < m->_subMeshes.size() )
81 _subMeshes.resize( m->_subMeshes.size(), 0 );
82 for ( unsigned j = 0; j < m->_subMeshes.size(); ++j )
84 if ( !m->_subMeshes[j] ) continue;
88 std::set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
89 _subMeshes[j]->_elements.end());
90 elems.insert( m->_subMeshes[j]->_elements.begin(),
91 m->_subMeshes[j]->_elements.end());
92 _subMeshes[j]->_elements.assign( elems.begin(), elems.end() );
93 m->_subMeshes[j]->_elements.clear();
95 if ( !_subMeshes[j]->_n2n )
96 _subMeshes[j]->_n2n = m->_subMeshes[j]->_n2n, m->_subMeshes[j]->_n2n = 0;
98 else if ( _subMeshes[j]->_n2n && m->_subMeshes[j]->_n2n )
99 _subMeshes[j]->_n2n->insert( m->_subMeshes[j]->_n2n->begin(),
100 m->_subMeshes[j]->_n2n->end());
104 _subMeshes[j] = m->_subMeshes[j];
105 m->_subMeshes[j] = 0;
111 //================================================================================
113 * \brief Destructor deletes proxy submeshes and tmp elements
115 //================================================================================
117 SMESH_ProxyMesh::~SMESH_ProxyMesh()
119 delete _subContainer;
121 for ( size_t i = 0; i < _subMeshes.size(); ++i )
122 delete _subMeshes[i];
125 std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
126 for ( ; i != _elemsInMesh.end(); ++i )
127 GetMeshDS()->RemoveFreeElement( *i, 0 );
128 _elemsInMesh.clear();
131 //================================================================================
135 //================================================================================
137 void SMESH_ProxyMesh::setMesh(const SMESH_Mesh& mesh)
141 _subContainer = new SubMesh( GetMeshDS() );
144 //================================================================================
146 * \brief Returns index of a shape
148 //================================================================================
150 int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
152 return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
155 //================================================================================
157 * \brief Create a SubMesh
158 * \param [ino] index - shape index
159 * \return SubMesh* - new SubMesh
161 //================================================================================
163 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::newSubmesh(int index) const
165 return new SubMesh( GetMeshDS(),index );
168 //================================================================================
170 * \brief Returns the submesh of a shape; it can be a proxy sub-mesh
172 //================================================================================
174 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
176 return GetSubMesh( shapeIndex( shape ));
179 //================================================================================
181 * \brief Return a sub-mesh by a shape ID; it can be a proxy sub-mesh
183 //================================================================================
185 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const int shapeID) const
187 const SMESHDS_SubMesh* sm = 0;
189 if ( 0 < shapeID && shapeID < (int)_subMeshes.size() )
190 sm = _subMeshes[ shapeID ];
192 sm = GetMeshDS()->MeshElements( shapeID );
197 //================================================================================
199 * \brief Returns the proxy sub-mesh of a shape; it can be NULL
201 //================================================================================
203 const SMESH_ProxyMesh::SubMesh*
204 SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const
206 size_t i = shapeIndex(shape);
207 return i < _subMeshes.size() ? _subMeshes[i] : 0;
210 //================================================================================
212 * \brief Returns the proxy node of a node; the input node is returned if no proxy exists
214 //================================================================================
216 const SMDS_MeshNode* SMESH_ProxyMesh::GetProxyNode( const SMDS_MeshNode* node ) const
218 const SMDS_MeshNode* proxy = node;
219 if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
221 if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() ))
222 proxy = proxySM->GetProxyNode( node );
226 TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS());
227 TopTools_ListIteratorOfListOfShape ancIt;
228 if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape ));
229 for ( ; ancIt.More() && proxy == node; ancIt.Next() )
230 if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value())))
231 proxy = proxySM->GetProxyNode( node );
236 //================================================================================
238 * \brief Returns number of proxy sub-meshes
240 //================================================================================
242 int SMESH_ProxyMesh::NbProxySubMeshes() const
245 for ( size_t i = 0; i < _subMeshes.size(); ++i )
246 nb += bool( _subMeshes[i] );
253 //================================================================================
255 * \brief Iterator filtering elements by type
257 //================================================================================
259 class TFilteringIterator : public SMDS_ElemIterator
261 SMDS_ElemIteratorPtr _iter;
262 const SMDS_MeshElement * _curElem;
263 std::vector< SMDSAbs_EntityType> _okTypes;
265 TFilteringIterator( const std::vector< SMDSAbs_EntityType>& okTypes,
266 const SMDS_ElemIteratorPtr& elemIterator)
267 :_iter(elemIterator), _curElem(0), _okTypes(okTypes)
275 virtual const SMDS_MeshElement* next()
277 const SMDS_MeshElement* res = _curElem;
279 while ( _iter->more() && !_curElem )
281 _curElem = _iter->next();
282 if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end())
289 //================================================================================
291 * \brief Iterator returning unique elements from a vector and another iterator
293 //================================================================================
295 class TUniqueIterator : public SMDS_ElemIterator
297 typedef boost::container::flat_set< const SMDS_MeshElement* > TElemSet;
298 typedef SMDS_SetIterator< const SMDS_MeshElement*, TElemSet::const_iterator > TSetIterator;
300 TElemSet _uniqueElems;
301 TSetIterator* _iterator;
304 TUniqueIterator( const std::vector< const SMDS_MeshElement* >& elems,
305 const SMDS_ElemIteratorPtr& elemIterator )
306 : _uniqueElems( elems.begin(), elems.end() )
309 while ( elemIterator->more() )
310 _uniqueElems.insert( elemIterator->next() );
312 _iterator = new TSetIterator( _uniqueElems.begin(), _uniqueElems.end() );
320 return _iterator->more();
322 virtual const SMDS_MeshElement* next()
324 return _iterator->next();
328 //================================================================================
330 * \brief Return iterator on 2 element iterators
332 //================================================================================
334 SMDS_ElemIteratorPtr iteratorOn2Iterators( SMDS_ElemIteratorPtr it1, SMDS_ElemIteratorPtr it2 )
336 std::vector< SMDS_ElemIteratorPtr > iters; iters.reserve(2);
337 if ( it1 ) iters.push_back( it1 );
338 if ( it2 ) iters.push_back( it2 );
340 typedef std::vector< SMDS_ElemIteratorPtr > TElemIterVector;
341 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
342 return SMDS_ElemIteratorPtr( new TItersIter( iters ));
346 //================================================================================
348 * \brief Returns iterator on all faces on the shape taking into account substitutions
350 //================================================================================
352 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
354 if ( !_mesh->HasShapeToMesh() )
355 return SMDS_ElemIteratorPtr();
357 _subContainer->RemoveAllSubmeshes();
359 TopTools_IndexedMapOfShape FF;
360 TopExp::MapShapes( shape, TopAbs_FACE, FF );
361 for ( int i = 1; i <= FF.Extent(); ++i )
362 if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
363 _subContainer->AddSubMesh( sm );
365 return _subContainer->SMESHDS_SubMesh::GetElements();
368 //================================================================================
370 * \brief Returns iterator on all faces of the mesh taking into account substitutions
371 * To be used in case of mesh without shape
373 //================================================================================
375 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
377 if ( _mesh->HasShapeToMesh() )
378 return SMDS_ElemIteratorPtr();
380 _subContainer->RemoveAllSubmeshes();
381 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
383 _subContainer->AddSubMesh( _subMeshes[i] );
385 if ( _subContainer->NbSubMeshes() == 0 ) // no elements substituted
386 return GetMeshDS()->elementsIterator(SMDSAbs_Face);
388 // if _allowedTypes is empty, only elements from _subMeshes are returned,...
389 SMDS_ElemIteratorPtr proxyIter = _subContainer->SMESHDS_SubMesh::GetElements();
390 if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
393 // ... else elements filtered using allowedTypes are additionally returned
394 SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
395 SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
396 return iteratorOn2Iterators( proxyIter, filterIter );
399 //================================================================================
401 * \brief Return total nb of faces taking into account substitutions
403 //================================================================================
405 smIdType SMESH_ProxyMesh::NbFaces() const
408 if ( _mesh->HasShapeToMesh() )
410 TopTools_IndexedMapOfShape FF;
411 TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
412 for ( int i = 1; i <= FF.Extent(); ++i )
413 if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
414 nb += sm->NbElements();
418 if ( _subMeshes.empty() )
419 return GetMeshDS()->NbFaces();
421 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
423 nb += _subMeshes[i]->NbElements();
425 // if _allowedTypes is empty, only elements from _subMeshes are returned,
426 // else elements filtered using allowedTypes are additionally returned
427 if ( !_allowedTypes.empty() )
429 for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
432 ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
434 nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
441 //================================================================================
443 * \brief Returns a proxy sub-mesh; it is created if not yet exists
445 //================================================================================
447 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(int index)
449 if ( int(_subMeshes.size()) <= index )
450 _subMeshes.resize( index+1, 0 );
451 if ( !_subMeshes[index] )
452 _subMeshes[index] = newSubmesh( index );
453 return _subMeshes[index];
456 //================================================================================
458 * \brief Returns a proxy sub-mesh; it is created if not yet exists
460 //================================================================================
462 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape)
464 return getProxySubMesh( shapeIndex( shape ));
467 //================================================================================
469 * \brief Returns a proxy sub-mesh
471 //================================================================================
473 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const
475 return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
478 //================================================================================
480 * \brief Returns mesh DS
482 //================================================================================
484 SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const
486 return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
489 //================================================================================
491 * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found
493 //================================================================================
495 bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape& shape,
496 SMESH_ProxyMesh* proxyMesh )
498 if ( proxyMesh && proxyMesh->_mesh == _mesh )
500 int iS = shapeIndex( shape );
501 if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
503 if ( iS >= int(_subMeshes.size()) )
504 _subMeshes.resize( iS + 1, 0 );
506 proxyMesh->_subMeshes[iS] = 0;
513 //================================================================================
515 * \brief Move tmp elements residing the _mesh from other proxy mesh to this
517 //================================================================================
519 void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh )
523 _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
524 proxyMesh->_elemsInMesh.end());
525 proxyMesh->_elemsInMesh.clear();
529 //================================================================================
531 * \brief Removes tmp elements from the _mesh
533 //================================================================================
535 void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* elem )
537 if ( elem && elem->GetID() > 0 )
539 std::set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( elem );
540 if ( i != _elemsInMesh.end() )
542 std::vector< const SMDS_MeshNode* > nodes( elem->begin_nodes(), elem->end_nodes() );
544 GetMeshDS()->RemoveFreeElement( elem, 0 );
545 _elemsInMesh.erase( i );
547 for ( size_t i = 0; i < nodes.size(); ++i )
548 if ( nodes[i]->GetID() > 0 && nodes[i]->NbInverseElements() == 0 )
549 GetMeshDS()->RemoveFreeNode( nodes[i], 0, false );
558 //================================================================================
560 * \brief Stores tmp element residing the _mesh
562 //================================================================================
564 void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* elem )
566 _elemsInMesh.insert( elem );
569 //================================================================================
571 * \brief Set node-node correspondence
573 //================================================================================
575 void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode,
576 const SMDS_MeshNode* proxyNode,
577 const SubMesh* subMesh)
579 SubMesh* sm = const_cast<SubMesh*>( subMesh );
580 if ( !subMesh->_n2n )
581 sm->_n2n = new TN2NMap;
582 sm->_n2n->insert( std::make_pair( srcNode, proxyNode ));
585 //================================================================================
587 * \brief Return true if the element is a temporary one
589 //================================================================================
591 bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
593 return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
596 //================================================================================
598 * \brief Return iterator on inverse elements of a node that may be a proxy one
600 //================================================================================
602 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetInverseElementIterator(const SMDS_MeshNode* node,
603 SMDSAbs_ElementType type) const
605 typedef std::vector< const SMDS_MeshElement* > TElemVec;
606 TElemVec *elemVecPtr;
608 TNodeElemVecMap& inverseElements = const_cast< TNodeElemVecMap& >( _inverseElements );
609 if ( inverseElements.IsEmpty() && NbProxySubMeshes() > 0 )
612 for ( size_t i = 0; i < _subMeshes.size(); ++i )
614 for ( size_t j = 0; j < _subMeshes[i]->_elements.size(); ++j )
616 const SMDS_MeshElement* e = _subMeshes[i]->_elements[j];
617 for ( SMDS_NodeIteratorPtr nIt = e->nodeIterator(); nIt->more(); )
619 const SMDS_MeshNode* n = nIt->next();
620 elemVecPtr = inverseElements.ChangeSeek( n );
622 elemVecPtr = inverseElements.Bound( n, elemVec );
623 elemVecPtr->push_back( e );
628 SMDS_ElemIteratorPtr iter = node->GetInverseElementIterator( type );
630 if (( elemVecPtr = inverseElements.ChangeSeek( node )))
633 iter = boost::make_shared< TUniqueIterator >( *elemVecPtr, iter );
635 iter = boost::make_shared< SMDS_ElementVectorIterator> ( elemVecPtr->begin(),
642 //================================================================================
644 * \brief Check if a FACE has prisms on its both sides
645 * \param [in] smFace - sub-mesh of the FACE. NOT a proxy sub-mesh!
646 * \return bool - true if there are prisms on the two sides
648 //================================================================================
650 bool SMESH_ProxyMesh::HasPrismsOnTwoSides( SMESHDS_SubMesh* smFace )
652 if ( !smFace || smFace->NbElements() == 0 )
655 SMDS_ElemIteratorPtr faces = smFace->GetElements();
656 while ( faces->more() )
658 const SMDS_MeshElement* f = faces->next();
659 std::vector<const SMDS_MeshNode*> fNodes( f->begin_nodes(), f->end_nodes() );
660 std::vector<const SMDS_MeshElement*> vols;
661 if ( SMDS_Mesh::GetElementsByNodes( fNodes, vols, SMDSAbs_Volume ) < 2 )
663 return ( vols[0]->NbCornerNodes() == 2 * f->NbCornerNodes() &&
664 vols[1]->NbCornerNodes() == 2 * f->NbCornerNodes() );
669 //================================================================================
671 * \brief SubMesh Constructor
673 //================================================================================
675 SMESH_ProxyMesh::SubMesh::SubMesh( const SMDS_Mesh* mesh, int index )
676 : SMESHDS_SubMesh( static_cast<const SMESHDS_Mesh*>( mesh ), index ),
681 //================================================================================
683 * \brief Return a proxy node or an input node
685 //================================================================================
687 const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const
689 TN2NMap::iterator n2n;
690 if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end())
695 //================================================================================
697 * \brief Deletes temporary elements
699 //================================================================================
701 void SMESH_ProxyMesh::SubMesh::Clear()
703 for ( unsigned i = 0; i < _elements.size(); ++i )
704 if ( _elements[i]->GetID() < 0 )
708 delete _n2n, _n2n = 0;
711 //================================================================================
713 * \brief Return number of elements in a proxy sub-mesh. The method is meaningful
714 * for a sub-mesh containing tmp faces.
716 //================================================================================
718 smIdType SMESH_ProxyMesh::SubMesh::NbElements() const
720 return _uvPtStructVec.empty() ? _elements.size() : _uvPtStructVec.size() - 1;
723 //================================================================================
725 * \brief Return elements of a proxy sub-mesh. The method is meaningful
726 * for a sub-mesh containing tmp faces.
728 //================================================================================
730 SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const
732 return SMDS_ElemIteratorPtr
733 ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() ));
736 //================================================================================
738 * \brief Return number of nodes in a proxy sub-mesh. The method is meaningful
739 * for a sub-mesh containing nodes of 2D viscous layer.
741 //================================================================================
743 smIdType SMESH_ProxyMesh::SubMesh::NbNodes() const
745 return _uvPtStructVec.size();
748 //================================================================================
750 * \brief Return nodes of a proxy sub-mesh. The method is meaningful
751 * for a sub-mesh containing nodes of 2D viscous layer.
753 //================================================================================
755 SMDS_NodeIteratorPtr SMESH_ProxyMesh::SubMesh::GetNodes() const
757 if ( !_uvPtStructVec.empty() )
758 return SMDS_NodeIteratorPtr ( new SMDS_SetIterator
760 UVPtStructVec::const_iterator,
761 UVPtStruct::NodeAccessor >
762 ( _uvPtStructVec.begin(), _uvPtStructVec.end() ));
764 return SMDS_NodeIteratorPtr
765 ( new SMDS_SetIterator< SMDS_pNode, std::vector< SMDS_pElement >::const_iterator>
766 ( _elements.begin(), _elements.end() ));
769 //================================================================================
771 * \brief Store an element
773 //================================================================================
775 void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e)
777 _elements.push_back( e );
780 //================================================================================
782 * \brief Check presence of element inside it-self
784 //================================================================================
786 bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const
788 if ( ME->GetType() != SMDSAbs_Node )
789 return find( _elements.begin(), _elements.end(), ME ) != _elements.end();