1 // Copyright (C) 2007-2011 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.
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 "SMESH_MesherHelper.hxx"
29 #include <TopTools_ListIteratorOfListOfShape.hxx>
31 #include <TopTools_IndexedMapOfShape.hxx>
33 //================================================================================
35 * \brief Constructor; mesh must be set by a descendant class
37 //================================================================================
39 SMESH_ProxyMesh::SMESH_ProxyMesh():_mesh(0)
42 //================================================================================
44 * \brief Make a proxy mesh from components. Components become empty
46 //================================================================================
48 SMESH_ProxyMesh::SMESH_ProxyMesh(vector<SMESH_ProxyMesh::Ptr>& components):
51 if ( components.empty() ) return;
53 for ( unsigned i = 0; i < components.size(); ++i )
55 SMESH_ProxyMesh* m = components[i].get();
58 takeTmpElemsInMesh( m );
60 if ( !_mesh ) _mesh = m->_mesh;
61 if ( _allowedTypes.empty() ) _allowedTypes = m->_allowedTypes;
63 if ( _subMeshes.size() < m->_subMeshes.size() )
64 _subMeshes.resize( m->_subMeshes.size(), 0 );
65 for ( unsigned j = 0; j < m->_subMeshes.size(); ++j )
67 if ( !m->_subMeshes[j] ) continue;
71 set< const SMDS_MeshElement * > elems( _subMeshes[j]->_elements.begin(),
72 _subMeshes[j]->_elements.end());
73 elems.insert( m->_subMeshes[j]->_elements.begin(),
74 m->_subMeshes[j]->_elements.end());
75 _subMeshes[j]->_elements.assign( elems.begin(), elems.end() );
76 m->_subMeshes[j]->_elements.clear();
78 if ( !_subMeshes[j]->_n2n )
79 _subMeshes[j]->_n2n = m->_subMeshes[j]->_n2n, m->_subMeshes[j]->_n2n = 0;
81 else if ( _subMeshes[j]->_n2n && m->_subMeshes[j]->_n2n )
82 _subMeshes[j]->_n2n->insert( m->_subMeshes[j]->_n2n->begin(),
83 m->_subMeshes[j]->_n2n->end());
87 _subMeshes[j] = m->_subMeshes[j];
94 //================================================================================
96 * \brief Destructor deletes proxy submeshes and tmp elemens
98 //================================================================================
100 SMESH_ProxyMesh::~SMESH_ProxyMesh()
102 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
103 delete _subMeshes[i];
106 set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.begin();
107 for ( ; i != _elemsInMesh.end(); ++i )
108 GetMeshDS()->RemoveFreeElement( *i, 0 );
109 _elemsInMesh.clear();
112 //================================================================================
114 * \brief Returns index of a shape
116 //================================================================================
118 int SMESH_ProxyMesh::shapeIndex(const TopoDS_Shape& shape) const
120 return ( shape.IsNull() || !_mesh->HasShapeToMesh() ? 0 : GetMeshDS()->ShapeToIndex(shape));
123 //================================================================================
125 * \brief Returns the submesh of a shape; it can be a proxy sub-mesh
127 //================================================================================
129 const SMESHDS_SubMesh* SMESH_ProxyMesh::GetSubMesh(const TopoDS_Shape& shape) const
131 const SMESHDS_SubMesh* sm = 0;
133 int i = shapeIndex(shape);
134 if ( i < _subMeshes.size() )
137 sm = GetMeshDS()->MeshElements( i );
142 //================================================================================
144 * \brief Returns the proxy sub-mesh of a shape; it can be NULL
146 //================================================================================
148 const SMESH_ProxyMesh::SubMesh*
149 SMESH_ProxyMesh::GetProxySubMesh(const TopoDS_Shape& shape) const
151 int i = shapeIndex(shape);
152 return i < _subMeshes.size() ? _subMeshes[i] : 0;
155 //================================================================================
157 * \brief Returns the proxy node of a node; the input node is returned if no proxy exists
159 //================================================================================
161 const SMDS_MeshNode* SMESH_ProxyMesh::GetProxyNode( const SMDS_MeshNode* node ) const
163 const SMDS_MeshNode* proxy = node;
164 if ( node->GetPosition()->GetTypeOfPosition() == SMDS_TOP_FACE )
166 if ( const SubMesh* proxySM = findProxySubMesh( node->getshapeId() ))
167 proxy = proxySM->GetProxyNode( node );
171 TopoDS_Shape shape = SMESH_MesherHelper::GetSubShapeByNode( node, GetMeshDS());
172 TopTools_ListIteratorOfListOfShape ancIt;
173 if ( !shape.IsNull() ) ancIt.Initialize( _mesh->GetAncestors( shape ));
174 for ( ; ancIt.More() && proxy == node; ancIt.Next() )
175 if ( const SubMesh* proxySM = findProxySubMesh( shapeIndex(ancIt.Value())))
176 proxy = proxySM->GetProxyNode( node );
183 //================================================================================
185 * \brief Iterator filtering elements by type
187 //================================================================================
189 class TFilteringIterator : public SMDS_ElemIterator
191 SMDS_ElemIteratorPtr _iter;
192 const SMDS_MeshElement * _curElem;
193 vector< SMDSAbs_EntityType> _okTypes;
195 TFilteringIterator( const vector< SMDSAbs_EntityType>& okTypes,
196 const SMDS_ElemIteratorPtr& elemIterator)
197 :_iter(elemIterator), _curElem(0), _okTypes(okTypes)
205 virtual const SMDS_MeshElement* next()
207 const SMDS_MeshElement* res = _curElem;
209 while ( _iter->more() && !_curElem )
211 _curElem = _iter->next();
212 if ( find( _okTypes.begin(), _okTypes.end(), _curElem->GetEntityType()) == _okTypes.end())
220 //================================================================================
222 * \brief Returns iterator on all faces on the shape taking into account substitutions
224 //================================================================================
226 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces(const TopoDS_Shape& shape) const
228 if ( !_mesh->HasShapeToMesh() )
229 return SMDS_ElemIteratorPtr();
231 _subContainer.RemoveAllSubmeshes();
233 TopTools_IndexedMapOfShape FF;
234 TopExp::MapShapes( shape, TopAbs_FACE, FF );
235 for ( int i = 1; i <= FF.Extent(); ++i )
236 if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
237 _subContainer.AddSubMesh( sm );
239 return _subContainer.SMESHDS_SubMesh::GetElements();
242 //================================================================================
244 * \brief Returns iterator on all faces of the mesh taking into account substitutions
245 * To be used in case of mesh without shape
247 //================================================================================
249 SMDS_ElemIteratorPtr SMESH_ProxyMesh::GetFaces() const
251 if ( _mesh->HasShapeToMesh() )
252 return SMDS_ElemIteratorPtr();
254 _subContainer.RemoveAllSubmeshes();
255 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
257 _subContainer.AddSubMesh( _subMeshes[i] );
259 if ( _subContainer.NbSubMeshes() == 0 ) // no elements substituted
260 return GetMeshDS()->elementsIterator(SMDSAbs_Face);
262 // if _allowedTypes is empty, only elements from _subMeshes are returned,...
263 SMDS_ElemIteratorPtr proxyIter = _subContainer.SMESHDS_SubMesh::GetElements();
264 if ( _allowedTypes.empty() || NbFaces() == _mesh->NbFaces() )
267 // ... else elements filtered using allowedTypes are additionally returned
268 SMDS_ElemIteratorPtr facesIter = GetMeshDS()->elementsIterator(SMDSAbs_Face);
269 SMDS_ElemIteratorPtr filterIter( new TFilteringIterator( _allowedTypes, facesIter ));
270 vector< SMDS_ElemIteratorPtr > iters(2);
271 iters[0] = proxyIter;
272 iters[1] = filterIter;
274 typedef vector< SMDS_ElemIteratorPtr > TElemIterVector;
275 typedef SMDS_IteratorOnIterators<const SMDS_MeshElement *, TElemIterVector> TItersIter;
276 return SMDS_ElemIteratorPtr( new TItersIter( iters ));
279 //================================================================================
281 * \brief Return total nb of faces taking into account substitutions
283 //================================================================================
285 int SMESH_ProxyMesh::NbFaces() const
288 if ( _mesh->HasShapeToMesh() )
290 TopTools_IndexedMapOfShape FF;
291 TopExp::MapShapes( _mesh->GetShapeToMesh(), TopAbs_FACE, FF );
292 for ( int i = 1; i <= FF.Extent(); ++i )
293 if ( const SMESHDS_SubMesh* sm = GetSubMesh( FF(i)))
294 nb += sm->NbElements();
298 if ( _subMeshes.empty() )
299 return GetMeshDS()->NbFaces();
301 for ( unsigned i = 0; i < _subMeshes.size(); ++i )
303 nb += _subMeshes[i]->NbElements();
305 // if _allowedTypes is empty, only elements from _subMeshes are returned,
306 // else elements filtered using allowedTypes are additionally returned
307 if ( !_allowedTypes.empty() )
309 for ( int t = SMDSEntity_Triangle; t <= SMDSEntity_Quad_Quadrangle; ++t )
312 ( find( _allowedTypes.begin(), _allowedTypes.end(), t ) != _allowedTypes.end() );
314 nb += GetMeshDS()->GetMeshInfo().NbEntities( SMDSAbs_EntityType( t ));
321 //================================================================================
323 * \brief Returns a proxy sub-mesh; it is created if not yet exists
325 //================================================================================
327 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(int index)
329 if ( int(_subMeshes.size()) <= index )
330 _subMeshes.resize( index+1, 0 );
331 if ( !_subMeshes[index] )
332 _subMeshes[index] = new SubMesh( index );
333 return _subMeshes[index];
336 //================================================================================
338 * \brief Returns a proxy sub-mesh; it is created if not yet exists
340 //================================================================================
342 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::getProxySubMesh(const TopoDS_Shape& shape)
344 return getProxySubMesh( shapeIndex( shape ));
347 //================================================================================
349 * \brief Returns a proxy sub-mesh
351 //================================================================================
353 SMESH_ProxyMesh::SubMesh* SMESH_ProxyMesh::findProxySubMesh(int shapeIndex) const
355 return shapeIndex < int(_subMeshes.size()) ? _subMeshes[shapeIndex] : 0;
358 //================================================================================
360 * \brief Returns mesh DS
362 //================================================================================
364 SMESHDS_Mesh* SMESH_ProxyMesh::GetMeshDS() const
366 return (SMESHDS_Mesh*)( _mesh ? _mesh->GetMeshDS() : 0 );
369 //================================================================================
371 * \brief Move proxy sub-mesh from other proxy mesh to this, returns true if sub-mesh found
373 //================================================================================
375 bool SMESH_ProxyMesh::takeProxySubMesh( const TopoDS_Shape& shape,
376 SMESH_ProxyMesh* proxyMesh )
378 if ( proxyMesh && proxyMesh->_mesh == _mesh )
380 int iS = shapeIndex( shape );
381 if ( SubMesh* sm = proxyMesh->findProxySubMesh( iS ))
383 if ( iS >= int(_subMeshes.size()) )
384 _subMeshes.resize( iS + 1, 0 );
386 proxyMesh->_subMeshes[iS] = 0;
393 //================================================================================
395 * \brief Move tmp elements residing the _mesh from other proxy mesh to this
397 //================================================================================
399 void SMESH_ProxyMesh::takeTmpElemsInMesh( SMESH_ProxyMesh* proxyMesh )
403 _elemsInMesh.insert( proxyMesh->_elemsInMesh.begin(),
404 proxyMesh->_elemsInMesh.end());
405 proxyMesh->_elemsInMesh.clear();
409 //================================================================================
411 * \brief Removes tmp faces from the _mesh
413 //================================================================================
415 void SMESH_ProxyMesh::removeTmpElement( const SMDS_MeshElement* face )
417 if ( face && face->GetID() > 0 )
419 set< const SMDS_MeshElement* >::iterator i = _elemsInMesh.find( face );
420 if ( i != _elemsInMesh.end() )
422 GetMeshDS()->RemoveFreeElement( face, 0 );
423 _elemsInMesh.erase( i );
432 //================================================================================
434 * \brief Stores tmp element residing the _mesh
436 //================================================================================
438 void SMESH_ProxyMesh::storeTmpElement( const SMDS_MeshElement* face )
440 _elemsInMesh.insert( face );
443 //================================================================================
445 * \brief Set node-node correspondence
447 //================================================================================
449 void SMESH_ProxyMesh::setNode2Node(const SMDS_MeshNode* srcNode,
450 const SMDS_MeshNode* proxyNode,
451 const SubMesh* subMesh)
453 SubMesh* sm = const_cast<SubMesh*>( subMesh );
454 if ( !subMesh->_n2n )
455 sm->_n2n = new TN2NMap;
456 sm->_n2n->insert( make_pair( srcNode, proxyNode ));
459 //================================================================================
461 * \brief Return true if the element is a temporary one
463 //================================================================================
465 bool SMESH_ProxyMesh::IsTemporary(const SMDS_MeshElement* elem ) const
467 return ( elem->GetID() < 1 ) || _elemsInMesh.count( elem );
470 //================================================================================
472 * \brief Return a proxy node or an input node
474 //================================================================================
476 const SMDS_MeshNode* SMESH_ProxyMesh::SubMesh::GetProxyNode( const SMDS_MeshNode* n ) const
478 TN2NMap::iterator n2n;
479 if ( _n2n && ( n2n = _n2n->find( n )) != _n2n->end())
484 //================================================================================
486 * \brief Deletes temporary elements
488 //================================================================================
490 void SMESH_ProxyMesh::SubMesh::Clear()
492 for ( unsigned i = 0; i < _elements.size(); ++i )
493 if ( _elements[i]->GetID() < 0 )
497 delete _n2n, _n2n = 0;
500 //================================================================================
502 * \brief Return number of elements in a proxy submesh
504 //================================================================================
506 int SMESH_ProxyMesh::SubMesh::NbElements() const
508 return _elements.size();
511 //================================================================================
513 * \brief Return elements of a proxy submesh
515 //================================================================================
517 SMDS_ElemIteratorPtr SMESH_ProxyMesh::SubMesh::GetElements() const
519 return SMDS_ElemIteratorPtr
520 ( new SMDS_ElementVectorIterator( _elements.begin(), _elements.end() ));
523 //================================================================================
525 * \brief Store an element
527 //================================================================================
529 void SMESH_ProxyMesh::SubMesh::AddElement(const SMDS_MeshElement * e)
531 _elements.push_back( e );
534 //================================================================================
536 * \brief Check presence of element inside it-self
538 //================================================================================
540 bool SMESH_ProxyMesh::SubMesh::Contains(const SMDS_MeshElement * ME) const
542 if ( ME->GetType() != SMDSAbs_Node )
543 return find( _elements.begin(), _elements.end(), ME ) != _elements.end();