1 // Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
24 // File : SMESH_subMesh_i.cxx
25 // Author : Paul RASCLE, EDF
28 #include "SMESH_subMesh_i.hxx"
29 #include "SMESH_Gen_i.hxx"
30 #include "SMESH_Mesh_i.hxx"
31 #include "SMESH_PreMeshInfo.hxx"
33 #include "Utils_CorbaException.hxx"
34 #include "utilities.h"
36 #include "Utils_ExceptHandlers.hxx"
38 #include <TopoDS_Iterator.hxx>
39 #include <TopExp_Explorer.hxx>
43 //=============================================================================
47 //=============================================================================
49 SMESH_subMesh_i::SMESH_subMesh_i()
50 : SALOME::GenericObj_i( PortableServer::POA::_nil() )
52 MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i default, not for use");
56 //=============================================================================
60 //=============================================================================
62 SMESH_subMesh_i::SMESH_subMesh_i( PortableServer::POA_ptr thePOA,
66 : SALOME::GenericObj_i( thePOA )
73 //=============================================================================
77 //=============================================================================
79 SMESH_subMesh_i::~SMESH_subMesh_i()
81 MESSAGE("SMESH_subMesh_i::~SMESH_subMesh_i");
82 if ( _preMeshInfo ) delete _preMeshInfo;
86 //=======================================================================
87 //function : getSubMeshes
88 //purpose : for a submesh on shape to which elements are not bound directly,
89 // return submeshes containing elements
90 //=======================================================================
92 typedef list<SMESHDS_SubMesh*> TListOfSubMeshes;
94 bool getSubMeshes(::SMESH_subMesh* theSubMesh,
95 TListOfSubMeshes& theSubMeshList)
97 int size = theSubMeshList.size();
99 SMESH_Mesh* aMesh = theSubMesh->GetFather();
100 SMESHDS_Mesh* aMeshDS = aMesh->GetMeshDS();
101 SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS();
103 // nodes can be bound to either vertex, edge, face or solid_or_shell
104 TopoDS_Shape aShape = theSubMesh->GetSubShape();
105 switch ( aShape.ShapeType() )
108 // add submesh of solid itself
109 aSubMeshDS = aMeshDS->MeshElements( aShape );
111 theSubMeshList.push_back( aSubMeshDS );
112 // and of the first shell
113 TopExp_Explorer exp( aShape, TopAbs_SHELL );
115 aSubMeshDS = aMeshDS->MeshElements( exp.Current() );
117 theSubMeshList.push_back( aSubMeshDS );
122 case TopAbs_COMPOUND:
123 case TopAbs_COMPSOLID: {
124 // call getSubMeshes() for sub-shapes
125 list<TopoDS_Shape> shapeList;
126 shapeList.push_back( aShape );
127 list<TopoDS_Shape>::iterator sh = shapeList.begin();
128 for ( ; sh != shapeList.end(); ++sh ) {
129 for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
130 if ( ::SMESH_subMesh* aSubMesh = aMesh->GetSubMeshContaining( it.Value() ))
131 getSubMeshes( aSubMesh, theSubMeshList ); // add found submesh or explore deeper
133 // no submesh for a compound inside compound
134 shapeList.push_back( it.Value() );
137 // return only unique submeshes
138 set<SMESHDS_SubMesh*> smSet;
139 TListOfSubMeshes::iterator sm = theSubMeshList.begin();
140 while ( sm != theSubMeshList.end() ) {
141 if ( !smSet.insert( *sm ).second )
142 sm = theSubMeshList.erase( sm );
150 theSubMeshList.push_back( aSubMeshDS );
152 return size < theSubMeshList.size();
155 //=============================================================================
159 //=============================================================================
161 CORBA::Long SMESH_subMesh_i::GetNumberOfElements()
162 throw (SALOME::SALOME_Exception)
164 Unexpect aCatch(SALOME_SalomeException);
167 return _preMeshInfo->NbElements();
169 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
172 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
173 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
175 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
177 // volumes are bound to shell
178 TListOfSubMeshes smList;
179 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
181 TListOfSubMeshes::iterator sm = smList.begin();
182 for ( ; sm != smList.end(); ++sm )
183 nbElems += (*sm)->NbElements();
188 //=============================================================================
192 //=============================================================================
194 CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all)
195 throw (SALOME::SALOME_Exception)
197 Unexpect aCatch(SALOME_SalomeException);
199 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
204 if ( all ) return _preMeshInfo->NbNodes();
205 else _preMeshInfo->FullLoadFromFile();
207 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
208 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
210 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
212 // sub-mesh on a geom group, always return all nodes
213 return aSubMeshDS->NbNodes();
215 if ( aSubMeshDS && !all )
217 // return anything we have
218 return aSubMeshDS->NbNodes();
220 if ( all ) // get nodes from aSubMesh and all child sub-meshes
223 SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator( /*includeSelf=*/true );
224 while ( smIt->more() )
226 aSubMesh = smIt->next();
227 if (( aSubMeshDS = aSubMesh->GetSubMeshDS() ))
228 nbNodes += aSubMeshDS->NbNodes();
233 return aSubMeshDS ? aSubMeshDS->NbNodes() : 0;
236 //=============================================================================
240 //=============================================================================
242 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
243 throw (SALOME::SALOME_Exception)
245 Unexpect aCatch(SALOME_SalomeException);
247 SMESH::long_array_var aResult = new SMESH::long_array();
249 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
250 return aResult._retn();
253 _preMeshInfo->FullLoadFromFile();
255 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
256 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
258 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
259 TListOfSubMeshes smList;
261 smList.push_back( aSubMeshDS );
263 // volumes are bound to shell
264 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
266 TListOfSubMeshes::iterator sm = smList.begin();
267 for ( ; sm != smList.end(); ++sm )
268 nbElems += (*sm)->NbElements();
271 aResult->length( nbElems );
274 TListOfSubMeshes::iterator sm = smList.begin();
275 for ( int i = 0; sm != smList.end(); sm++ )
277 SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
278 for ( ; i < nbElems && anIt->more(); i++ )
279 aResult[i] = anIt->next()->GetID();
282 return aResult._retn();
286 //=============================================================================
290 //=============================================================================
292 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
293 throw (SALOME::SALOME_Exception)
295 Unexpect aCatch(SALOME_SalomeException);
297 SMESH::long_array_var aResult = new SMESH::long_array();
299 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
300 return aResult._retn();
303 _preMeshInfo->FullLoadFromFile();
305 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
306 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
308 // PAL5440, return all nodes belonging to elements of submesh
310 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
312 // volumes may be bound to shell instead of solid
313 TListOfSubMeshes smList;
314 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
316 TListOfSubMeshes::iterator sm = smList.begin();
317 for ( ; sm != smList.end(); ++sm )
319 if ( theElemType == SMESH::NODE )
321 SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
323 while ( eIt->more() ) {
324 const SMDS_MeshElement* anElem = eIt->next();
325 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
326 while ( nIt->more() )
327 nodeIds.insert( nIt->next()->GetID() );
330 SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
331 while ( nIt->more() )
332 nodeIds.insert( nIt->next()->GetID() );
337 nbElems += (*sm)->NbElements();
345 smList.push_back( aSubMeshDS );
348 if ( theElemType == SMESH::NODE && aSubMeshDS )
350 SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
352 while ( eIt->more() ) {
353 const SMDS_MeshElement* anElem = eIt->next();
354 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
355 while ( nIt->more() )
356 nodeIds.insert( nIt->next()->GetID() );
359 SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
360 while ( nIt->more() )
361 nodeIds.insert( nIt->next()->GetID() );
365 if ( theElemType == SMESH::NODE )
366 aResult->length( nodeIds.size() );
368 aResult->length( nbElems );
370 int i = 0, n = aResult->length();
372 if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
373 set<int>::iterator idIt = nodeIds.begin();
374 for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
378 if ( theElemType != SMESH::NODE ) {
379 TListOfSubMeshes::iterator sm = smList.begin();
380 for ( i = 0; sm != smList.end(); sm++ )
383 SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
384 while ( i < n && anIt->more() ) {
385 const SMDS_MeshElement* anElem = anIt->next();
386 if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
387 aResult[i++] = anElem->GetID();
392 aResult->length( i );
394 return aResult._retn();
397 //=============================================================================
401 //=============================================================================
403 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
404 throw (SALOME::SALOME_Exception)
406 Unexpect aCatch(SALOME_SalomeException);
408 SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
409 return aResult._retn();
412 //=============================================================================
416 //=============================================================================
418 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
419 throw (SALOME::SALOME_Exception)
421 Unexpect aCatch(SALOME_SalomeException);
422 return _mesh_i->_this();
425 //=============================================================================
429 //=============================================================================
431 CORBA::Long SMESH_subMesh_i::GetId()
436 //=======================================================================
437 //function : GetSubShape
439 //=======================================================================
441 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
442 throw (SALOME::SALOME_Exception)
444 Unexpect aCatch(SALOME_SalomeException);
445 GEOM::GEOM_Object_var aShapeObj;
447 if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
448 TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
450 aShapeObj = _gen_i->ShapeToGeomObject( S );
451 //mzn: N7PAL16232, N7PAL16233
452 //In some cases it's possible that GEOM_Client contains the shape same to S, but
453 //with another orientation.
454 if (aShapeObj->_is_nil())
455 aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() );
459 catch(SALOME_Exception & S_ex) {
460 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
462 return aShapeObj._retn();
465 //=============================================================================
469 //=============================================================================
470 SMESH::long_array* SMESH_subMesh_i::GetIDs()
472 return GetElementsId();
475 //=============================================================================
479 //=============================================================================
480 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
481 throw (SALOME::SALOME_Exception)
484 _preMeshInfo->FullLoadFromFile();
485 return GetFather()->GetElementType( id, iselem );
488 //=============================================================================
490 * Returns number of mesh elements of each \a EntityType
491 * @return array of number of elements per \a EntityType
493 //=============================================================================
495 SMESH::long_array* SMESH_subMesh_i::GetMeshInfo()
498 return _preMeshInfo->GetMeshInfo();
500 SMESH::long_array_var aRes = new SMESH::long_array();
501 aRes->length(SMESH::Entity_Last);
502 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
505 // get number of nodes
506 aRes[ SMESH::Entity_Node ] = GetNumberOfNodes(true);
508 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
510 // get statistic from child sub-meshes
511 TListOfSubMeshes smList;
512 if ( getSubMeshes( aSubMesh, smList ) )
513 for ( TListOfSubMeshes::iterator sm = smList.begin(); sm != smList.end(); ++sm )
514 SMESH_Mesh_i::CollectMeshInfo( (*sm)->GetElements(), aRes );
519 //=======================================================================
521 * Returns number of mesh elements of each \a ElementType
523 //=======================================================================
525 SMESH::long_array* SMESH_subMesh_i::GetNbElementsByType()
527 SMESH::long_array_var aRes = new SMESH::long_array();
528 aRes->length(SMESH::NB_ELEMENT_TYPES);
529 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
531 aRes[ i ] = _preMeshInfo->NbElements( SMDSAbs_ElementType( i ));
537 aRes[ SMESH::NODE ] = GetNumberOfNodes(true);
539 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
540 if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
542 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
544 aRes[ eIt->next()->GetType() ] = smDS->NbElements();
551 //=======================================================================
552 //function : GetTypes
553 //purpose : Returns types of elements it contains
554 //=======================================================================
556 SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
559 return _preMeshInfo->GetTypes();
561 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
563 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
564 if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
566 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
570 types[0] = SMESH::ElementType( eIt->next()->GetType());
572 else if ( smDS->GetNodes()->more() )
574 TopoDS_Shape shape = aSubMesh->GetSubShape();
575 while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
577 TopoDS_Iterator it( shape );
578 shape = it.More() ? it.Value() : TopoDS_Shape();
580 if ( !shape.IsNull() && shape.ShapeType() == TopAbs_VERTEX )
583 types[0] = SMESH::NODE;
587 return types._retn();
590 //=======================================================================
592 //purpose : interface SMESH_IDSource
593 //=======================================================================
595 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetMesh()
600 //=======================================================================
601 //function : IsMeshInfoCorrect
602 //purpose : * Returns false if GetMeshInfo() returns incorrect information that may
603 // * happen if mesh data is not yet fully loaded from the file of study.
604 //=======================================================================
606 bool SMESH_subMesh_i::IsMeshInfoCorrect()
608 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;