1 // Copyright (C) 2007-2015 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, or (at your option) any later version.
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 <TopExp_Explorer.hxx>
39 #include <TopTools_ListIteratorOfListOfShape.hxx>
40 #include <TopoDS_Iterator.hxx>
44 //=============================================================================
48 //=============================================================================
50 SMESH_subMesh_i::SMESH_subMesh_i()
51 : SALOME::GenericObj_i( PortableServer::POA::_nil() )
53 MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i default, not for use");
57 //=============================================================================
61 //=============================================================================
63 SMESH_subMesh_i::SMESH_subMesh_i( PortableServer::POA_ptr thePOA,
67 : SALOME::GenericObj_i( thePOA )
74 //=============================================================================
78 //=============================================================================
80 SMESH_subMesh_i::~SMESH_subMesh_i()
82 MESSAGE("SMESH_subMesh_i::~SMESH_subMesh_i");
83 if ( _preMeshInfo ) delete _preMeshInfo;
87 //=======================================================================
88 //function : getSubMeshes
89 //purpose : for a submesh on shape to which elements are not bound directly,
90 // return submeshes containing elements
91 //=======================================================================
93 typedef list<SMESHDS_SubMesh*> TListOfSubMeshes;
95 bool getSubMeshes(::SMESH_subMesh* theSubMesh,
96 TListOfSubMeshes& theSubMeshList)
98 int size = theSubMeshList.size();
100 SMESH_Mesh* aMesh = theSubMesh->GetFather();
101 SMESHDS_Mesh* aMeshDS = aMesh->GetMeshDS();
102 SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS();
105 // nodes can be bound to either vertex, edge, face or solid_or_shell
106 TopoDS_Shape aShape = theSubMesh->GetSubShape();
107 TopAbs_ShapeEnum aShapeType = aShape.ShapeType();
109 // IPAL18558: Wrong information of the created sub-mesh is shown. (Sub-mesh on a FACE
110 // with only 1D algo assigned
111 // Find dimension of sub-meshes to return as highest dimension of the assigned algorithm
112 if ( theSubMesh->IsEmpty() && !theSubMesh->GetAlgo() )
114 // on father sub-meshes, check presence of an algo which will mesh this sub-mesh
115 // even if no algo is assigned to this sub-mesh
116 bool topAlgoPresent = false;
117 TopTools_ListIteratorOfListOfShape ancestors( aMesh->GetAncestors( aShape ));
118 for ( ; ancestors.More() && !topAlgoPresent; ancestors.Next() )
119 if (( sm = aMesh->GetSubMeshContaining( ancestors.Value() )))
120 topAlgoPresent = ( sm->GetAlgo() && !sm->GetAlgo()->NeedDiscreteBoundary() );
122 if ( !topAlgoPresent )
124 // look for a sub-mesh with an algo
125 SMESH_subMeshIteratorPtr smIt =
126 theSubMesh->getDependsOnIterator(/*includeSelf=*/false, /*complexShapeFirst=*/true);
127 TopAbs_ShapeEnum algoShape = TopAbs_SHAPE;
128 while ( smIt->more() && algoShape == TopAbs_SHAPE )
132 algoShape = sm->GetSubShape().ShapeType();
134 if ( algoShape != TopAbs_SHAPE )
136 // return all sub-meshes on this shape type
137 smIt = theSubMesh->getDependsOnIterator(/*includeSelf=*/false, /*complexShapeFirst=*/true);
138 while ( smIt->more() )
141 if ( sm->GetSubShape().ShapeType() == algoShape && sm->GetSubMeshDS() )
142 theSubMeshList.push_back( sm->GetSubMeshDS() );
144 return size < theSubMeshList.size();
149 switch ( aShapeType )
153 // add sub-mesh of solid itself
154 if (( aSubMeshDS = aMeshDS->MeshElements( aShape )))
155 theSubMeshList.push_back( aSubMeshDS );
157 // and of the first shell
158 TopExp_Explorer exp( aShape, TopAbs_SHELL );
160 if (( aSubMeshDS = aMeshDS->MeshElements( exp.Current() )))
161 theSubMeshList.push_back( aSubMeshDS );
165 case TopAbs_COMPOUND:
166 case TopAbs_COMPSOLID:
168 // call getSubMeshes() for sub-shapes
169 list<TopoDS_Shape> shapeList;
170 shapeList.push_back( aShape );
171 list<TopoDS_Shape>::iterator sh = shapeList.begin();
172 for ( ; sh != shapeList.end(); ++sh ) {
173 for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
174 if (( sm = aMesh->GetSubMeshContaining( it.Value() )))
175 getSubMeshes( sm, theSubMeshList ); // add found sub-mesh or explore deeper
177 // no submesh for a compound inside compound
178 shapeList.push_back( it.Value() );
181 // return only unique sub-meshes
182 set<SMESHDS_SubMesh*> smSet( theSubMeshList.begin(), theSubMeshList.end() );
183 theSubMeshList.assign( smSet.begin(), smSet.end() );
188 theSubMeshList.push_back( aSubMeshDS );
190 return size < theSubMeshList.size();
193 //=============================================================================
197 //=============================================================================
199 CORBA::Long SMESH_subMesh_i::GetNumberOfElements()
200 throw (SALOME::SALOME_Exception)
202 Unexpect aCatch(SALOME_SalomeException);
205 return _preMeshInfo->NbElements();
207 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
210 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
211 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
213 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
215 // volumes are bound to shell
216 TListOfSubMeshes smList;
217 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
219 TListOfSubMeshes::iterator sm = smList.begin();
220 for ( ; sm != smList.end(); ++sm )
221 nbElems += (*sm)->NbElements();
226 //=============================================================================
230 //=============================================================================
232 CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all)
233 throw (SALOME::SALOME_Exception)
235 Unexpect aCatch(SALOME_SalomeException);
237 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
242 if ( all ) return _preMeshInfo->NbNodes();
243 else _preMeshInfo->FullLoadFromFile();
245 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
246 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
248 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
250 // sub-mesh on a geom group, always return all nodes
251 return aSubMeshDS->NbNodes();
253 if ( aSubMeshDS && !all )
255 // return anything we have
256 return aSubMeshDS->NbNodes();
258 if ( all ) // get nodes from aSubMesh and all child sub-meshes
261 SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator( /*includeSelf=*/true );
262 while ( smIt->more() )
264 aSubMesh = smIt->next();
265 if (( aSubMeshDS = aSubMesh->GetSubMeshDS() ))
266 nbNodes += aSubMeshDS->NbNodes();
271 return aSubMeshDS ? aSubMeshDS->NbNodes() : 0;
274 //=============================================================================
278 //=============================================================================
280 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
281 throw (SALOME::SALOME_Exception)
283 Unexpect aCatch(SALOME_SalomeException);
285 SMESH::long_array_var aResult = new SMESH::long_array();
287 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
288 return aResult._retn();
291 _preMeshInfo->FullLoadFromFile();
293 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
294 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
296 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
297 TListOfSubMeshes smList;
299 smList.push_back( aSubMeshDS );
301 // volumes are bound to shell
302 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
304 TListOfSubMeshes::iterator sm = smList.begin();
305 for ( ; sm != smList.end(); ++sm )
306 nbElems += (*sm)->NbElements();
309 aResult->length( nbElems );
312 TListOfSubMeshes::iterator sm = smList.begin();
313 for ( int i = 0; sm != smList.end(); sm++ )
315 SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
316 for ( ; i < nbElems && anIt->more(); i++ )
317 aResult[i] = anIt->next()->GetID();
320 return aResult._retn();
324 //=============================================================================
328 //=============================================================================
330 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
331 throw (SALOME::SALOME_Exception)
333 Unexpect aCatch(SALOME_SalomeException);
335 SMESH::long_array_var aResult = new SMESH::long_array();
337 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
338 return aResult._retn();
341 _preMeshInfo->FullLoadFromFile();
343 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
344 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
346 // PAL5440, return all nodes belonging to elements of submesh
348 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
350 // volumes may be bound to shell instead of solid
351 TListOfSubMeshes smList;
352 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
354 TListOfSubMeshes::iterator sm = smList.begin();
355 for ( ; sm != smList.end(); ++sm )
357 if ( theElemType == SMESH::NODE )
359 SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
361 while ( eIt->more() ) {
362 const SMDS_MeshElement* anElem = eIt->next();
363 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
364 while ( nIt->more() )
365 nodeIds.insert( nIt->next()->GetID() );
368 SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
369 while ( nIt->more() )
370 nodeIds.insert( nIt->next()->GetID() );
375 nbElems += (*sm)->NbElements();
383 smList.push_back( aSubMeshDS );
386 if ( theElemType == SMESH::NODE && aSubMeshDS )
388 SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
390 while ( eIt->more() ) {
391 const SMDS_MeshElement* anElem = eIt->next();
392 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
393 while ( nIt->more() )
394 nodeIds.insert( nIt->next()->GetID() );
397 SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
398 while ( nIt->more() )
399 nodeIds.insert( nIt->next()->GetID() );
403 if ( theElemType == SMESH::NODE )
404 aResult->length( nodeIds.size() );
406 aResult->length( nbElems );
408 int i = 0, n = aResult->length();
410 if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
411 set<int>::iterator idIt = nodeIds.begin();
412 for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
416 if ( theElemType != SMESH::NODE ) {
417 TListOfSubMeshes::iterator sm = smList.begin();
418 for ( i = 0; sm != smList.end(); sm++ )
421 SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
422 while ( i < n && anIt->more() ) {
423 const SMDS_MeshElement* anElem = anIt->next();
424 if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
425 aResult[i++] = anElem->GetID();
430 aResult->length( i );
432 return aResult._retn();
435 //=============================================================================
439 //=============================================================================
441 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
442 throw (SALOME::SALOME_Exception)
444 Unexpect aCatch(SALOME_SalomeException);
446 SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
447 return aResult._retn();
450 //=============================================================================
454 //=============================================================================
456 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
457 throw (SALOME::SALOME_Exception)
459 Unexpect aCatch(SALOME_SalomeException);
460 return _mesh_i->_this();
463 //=============================================================================
467 //=============================================================================
469 CORBA::Long SMESH_subMesh_i::GetId()
474 //=======================================================================
475 //function : GetSubShape
477 //=======================================================================
479 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
480 throw (SALOME::SALOME_Exception)
482 Unexpect aCatch(SALOME_SalomeException);
483 GEOM::GEOM_Object_var aShapeObj;
485 if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
486 TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
488 aShapeObj = _gen_i->ShapeToGeomObject( S );
489 //mzn: N7PAL16232, N7PAL16233
490 //In some cases it's possible that GEOM_Client contains the shape same to S, but
491 //with another orientation.
492 if (aShapeObj->_is_nil())
493 aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() );
497 catch(SALOME_Exception & S_ex) {
498 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
500 return aShapeObj._retn();
503 //=============================================================================
507 //=============================================================================
508 SMESH::long_array* SMESH_subMesh_i::GetIDs()
510 return GetElementsId();
513 //=============================================================================
517 //=============================================================================
518 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
519 throw (SALOME::SALOME_Exception)
522 _preMeshInfo->FullLoadFromFile();
523 return GetFather()->GetElementType( id, iselem );
526 //=============================================================================
528 * Returns number of mesh elements of each \a EntityType
529 * @return array of number of elements per \a EntityType
531 //=============================================================================
533 SMESH::long_array* SMESH_subMesh_i::GetMeshInfo()
536 return _preMeshInfo->GetMeshInfo();
538 SMESH::long_array_var aRes = new SMESH::long_array();
539 aRes->length(SMESH::Entity_Last);
540 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
543 // get number of nodes
544 aRes[ SMESH::Entity_Node ] = GetNumberOfNodes(true);
546 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
548 // get statistic from child sub-meshes
549 TListOfSubMeshes smList;
550 if ( getSubMeshes( aSubMesh, smList ) )
551 for ( TListOfSubMeshes::iterator sm = smList.begin(); sm != smList.end(); ++sm )
552 SMESH_Mesh_i::CollectMeshInfo( (*sm)->GetElements(), aRes );
557 //=======================================================================
559 * Returns number of mesh elements of each \a ElementType
561 //=======================================================================
563 SMESH::long_array* SMESH_subMesh_i::GetNbElementsByType()
565 SMESH::long_array_var aRes = new SMESH::long_array();
566 aRes->length(SMESH::NB_ELEMENT_TYPES);
567 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
569 aRes[ i ] = _preMeshInfo->NbElements( SMDSAbs_ElementType( i ));
575 aRes[ SMESH::NODE ] = GetNumberOfNodes(true);
577 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
578 if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
580 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
582 aRes[ eIt->next()->GetType() ] = smDS->NbElements();
589 //=======================================================================
590 //function : GetTypes
591 //purpose : Returns types of elements it contains
592 //=======================================================================
594 SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
597 return _preMeshInfo->GetTypes();
599 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
601 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
602 if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
604 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
608 types[0] = SMESH::ElementType( eIt->next()->GetType());
610 else if ( smDS->GetNodes()->more() )
612 TopoDS_Shape shape = aSubMesh->GetSubShape();
613 while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
615 TopoDS_Iterator it( shape );
616 shape = it.More() ? it.Value() : TopoDS_Shape();
618 if ( !shape.IsNull() && shape.ShapeType() == TopAbs_VERTEX )
621 types[0] = SMESH::NODE;
625 return types._retn();
628 //=======================================================================
630 //purpose : interface SMESH_IDSource
631 //=======================================================================
633 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetMesh()
638 //=======================================================================
639 //function : IsMeshInfoCorrect
640 //purpose : * Returns false if GetMeshInfo() returns incorrect information that may
641 // * happen if mesh data is not yet fully loaded from the file of study.
642 //=======================================================================
644 bool SMESH_subMesh_i::IsMeshInfoCorrect()
646 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
649 //=======================================================================
650 //function : GetVtkUgStream
651 //purpose : Return data vtk unstructured grid (not implemented)
652 //=======================================================================
654 SALOMEDS::TMPFile* SMESH_subMesh_i::GetVtkUgStream()
656 SALOMEDS::TMPFile_var SeqFile;
657 return SeqFile._retn();