1 // Copyright (C) 2007-2016 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 size_t 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() || ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )) &&
113 ( !theSubMesh->GetAlgo() ))
115 // on father sub-meshes, check presence of an algo which will mesh this sub-mesh
116 // even if no algo is assigned to this sub-mesh
117 bool topAlgoPresent = false;
118 TopTools_ListIteratorOfListOfShape ancestors( aMesh->GetAncestors( aShape ));
119 for ( ; ancestors.More() && !topAlgoPresent; ancestors.Next() )
120 if (( sm = aMesh->GetSubMeshContaining( ancestors.Value() )))
121 topAlgoPresent = ( sm->GetAlgo() && !sm->GetAlgo()->NeedDiscreteBoundary() );
123 if ( !topAlgoPresent )
125 // find max dimension of an assigned algo
126 TopAbs_ShapeEnum algoShape = TopAbs_SHAPE;
127 const std::list <const SMESHDS_Hypothesis * >& hyps = aMesh->GetHypothesisList( aShape );
128 std::list <const SMESHDS_Hypothesis * >::const_iterator hypIt = hyps.begin();
129 for ( ; hypIt != hyps.end(); ++hypIt )
130 if ( const SMESH_Algo* algo = dynamic_cast< const SMESH_Algo* >( *hypIt ))
131 switch ( algo->GetDim() ) {
132 case 1: algoShape = TopAbs_EDGE; break;
133 case 2: algoShape = TopAbs_FACE; break;
134 case 3: algoShape = TopAbs_SOLID; break;
135 case 0: algoShape = TopAbs_VERTEX; break;
137 if ( algoShape != TopAbs_SHAPE )
139 // return all sub-meshes on this dimension
140 SMESH_subMeshIteratorPtr smIt = theSubMesh->getDependsOnIterator(/*includeSelf=*/false);
141 while ( smIt->more() )
144 if ( sm->GetSubShape().ShapeType() == algoShape && sm->GetSubMeshDS() )
145 theSubMeshList.push_back( sm->GetSubMeshDS() );
147 return size < theSubMeshList.size();
152 switch ( aShapeType )
156 // add sub-mesh of solid itself
157 if (( aSubMeshDS = aMeshDS->MeshElements( aShape )))
158 theSubMeshList.push_back( aSubMeshDS );
160 // and of the first shell
161 TopExp_Explorer exp( aShape, TopAbs_SHELL );
163 if (( aSubMeshDS = aMeshDS->MeshElements( exp.Current() )))
164 theSubMeshList.push_back( aSubMeshDS );
168 case TopAbs_COMPOUND:
169 case TopAbs_COMPSOLID:
171 // call getSubMeshes() for sub-shapes
172 list<TopoDS_Shape> shapeList;
173 shapeList.push_back( aShape );
174 list<TopoDS_Shape>::iterator sh = shapeList.begin();
175 for ( ; sh != shapeList.end(); ++sh ) {
176 for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
177 if (( sm = aMesh->GetSubMeshContaining( it.Value() )))
178 getSubMeshes( sm, theSubMeshList ); // add found sub-mesh or explore deeper
180 // no submesh for a compound inside compound
181 shapeList.push_back( it.Value() );
184 // return only unique sub-meshes
185 set<SMESHDS_SubMesh*> smSet( theSubMeshList.begin(), theSubMeshList.end() );
186 theSubMeshList.assign( smSet.begin(), smSet.end() );
191 theSubMeshList.push_back( aSubMeshDS );
193 return size < theSubMeshList.size();
196 //=============================================================================
200 //=============================================================================
202 CORBA::Long SMESH_subMesh_i::GetNumberOfElements()
203 throw (SALOME::SALOME_Exception)
205 Unexpect aCatch(SALOME_SalomeException);
208 return _preMeshInfo->NbElements();
210 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
213 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
214 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
215 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
218 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
220 // volumes are bound to shell
221 TListOfSubMeshes smList;
222 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
224 TListOfSubMeshes::iterator sm = smList.begin();
225 for ( ; sm != smList.end(); ++sm )
226 nbElems += (*sm)->NbElements();
231 //=============================================================================
235 //=============================================================================
237 CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all)
238 throw (SALOME::SALOME_Exception)
240 Unexpect aCatch(SALOME_SalomeException);
242 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
247 if ( all ) return _preMeshInfo->NbNodes();
248 else _preMeshInfo->FullLoadFromFile();
250 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
251 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
252 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
255 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
257 // sub-mesh on a geom group, always return all nodes
258 return aSubMeshDS->NbNodes();
260 if ( aSubMeshDS && !all )
262 // return anything we have
263 return aSubMeshDS->NbNodes();
265 if ( all ) // get nodes from aSubMesh and all child sub-meshes
268 SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator( /*includeSelf=*/true );
269 while ( smIt->more() )
271 aSubMesh = smIt->next();
272 if (( aSubMeshDS = aSubMesh->GetSubMeshDS() ))
273 nbNodes += aSubMeshDS->NbNodes();
278 return aSubMeshDS ? aSubMeshDS->NbNodes() : 0;
281 //=============================================================================
285 //=============================================================================
287 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
288 throw (SALOME::SALOME_Exception)
290 Unexpect aCatch(SALOME_SalomeException);
292 SMESH::long_array_var aResult = new SMESH::long_array();
294 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
295 return aResult._retn();
298 _preMeshInfo->FullLoadFromFile();
300 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
301 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
302 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
305 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
306 TListOfSubMeshes smList;
308 smList.push_back( aSubMeshDS );
310 // volumes are bound to shell
311 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
313 TListOfSubMeshes::iterator sm = smList.begin();
314 for ( ; sm != smList.end(); ++sm )
315 nbElems += (*sm)->NbElements();
318 aResult->length( nbElems );
321 TListOfSubMeshes::iterator sm = smList.begin();
322 for ( int i = 0; sm != smList.end(); sm++ )
324 SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
325 for ( ; i < nbElems && anIt->more(); i++ )
326 aResult[i] = anIt->next()->GetID();
329 return aResult._retn();
333 //=============================================================================
337 //=============================================================================
339 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
340 throw (SALOME::SALOME_Exception)
342 Unexpect aCatch(SALOME_SalomeException);
344 SMESH::long_array_var aResult = new SMESH::long_array();
346 if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
347 return aResult._retn();
350 _preMeshInfo->FullLoadFromFile();
352 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
353 SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
354 if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
357 // PAL5440, return all nodes belonging to elements of submesh
359 int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
361 // volumes may be bound to shell instead of solid
362 TListOfSubMeshes smList;
363 if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
365 TListOfSubMeshes::iterator sm = smList.begin();
366 for ( ; sm != smList.end(); ++sm )
368 if ( theElemType == SMESH::NODE )
370 SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
372 while ( eIt->more() ) {
373 const SMDS_MeshElement* anElem = eIt->next();
374 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
375 while ( nIt->more() )
376 nodeIds.insert( nIt->next()->GetID() );
379 SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
380 while ( nIt->more() )
381 nodeIds.insert( nIt->next()->GetID() );
386 nbElems += (*sm)->NbElements();
394 smList.push_back( aSubMeshDS );
397 if ( theElemType == SMESH::NODE && aSubMeshDS )
399 SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
401 while ( eIt->more() ) {
402 const SMDS_MeshElement* anElem = eIt->next();
403 SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
404 while ( nIt->more() )
405 nodeIds.insert( nIt->next()->GetID() );
408 SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
409 while ( nIt->more() )
410 nodeIds.insert( nIt->next()->GetID() );
414 if ( theElemType == SMESH::NODE )
415 aResult->length( nodeIds.size() );
417 aResult->length( nbElems );
419 int i = 0, n = aResult->length();
421 if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
422 set<int>::iterator idIt = nodeIds.begin();
423 for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
427 if ( theElemType != SMESH::NODE ) {
428 TListOfSubMeshes::iterator sm = smList.begin();
429 for ( i = 0; sm != smList.end(); sm++ )
432 SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
433 while ( i < n && anIt->more() ) {
434 const SMDS_MeshElement* anElem = anIt->next();
435 if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
436 aResult[i++] = anElem->GetID();
441 aResult->length( i );
443 return aResult._retn();
446 //=============================================================================
450 //=============================================================================
452 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
453 throw (SALOME::SALOME_Exception)
455 Unexpect aCatch(SALOME_SalomeException);
457 SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
458 return aResult._retn();
461 //=============================================================================
465 //=============================================================================
467 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
468 throw (SALOME::SALOME_Exception)
470 Unexpect aCatch(SALOME_SalomeException);
471 return _mesh_i->_this();
474 //=============================================================================
478 //=============================================================================
480 CORBA::Long SMESH_subMesh_i::GetId()
485 //=======================================================================
486 //function : GetSubShape
488 //=======================================================================
490 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
491 throw (SALOME::SALOME_Exception)
493 Unexpect aCatch(SALOME_SalomeException);
494 GEOM::GEOM_Object_var aShapeObj;
496 if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
497 TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
499 aShapeObj = _gen_i->ShapeToGeomObject( S );
500 //mzn: N7PAL16232, N7PAL16233
501 //In some cases it's possible that GEOM_Client contains the shape same to S, but
502 //with another orientation.
503 if (aShapeObj->_is_nil())
504 aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() );
508 catch(SALOME_Exception & S_ex) {
509 THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
511 return aShapeObj._retn();
514 //=============================================================================
518 //=============================================================================
519 SMESH::long_array* SMESH_subMesh_i::GetIDs()
521 return GetElementsId();
524 //=============================================================================
528 //=============================================================================
529 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
530 throw (SALOME::SALOME_Exception)
533 _preMeshInfo->FullLoadFromFile();
534 return GetFather()->GetElementType( id, iselem );
537 //=============================================================================
539 * Returns number of mesh elements of each \a EntityType
540 * @return array of number of elements per \a EntityType
542 //=============================================================================
544 SMESH::long_array* SMESH_subMesh_i::GetMeshInfo()
547 return _preMeshInfo->GetMeshInfo();
549 SMESH::long_array_var aRes = new SMESH::long_array();
550 aRes->length(SMESH::Entity_Last);
551 for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
554 // get number of nodes
555 aRes[ SMESH::Entity_Node ] = GetNumberOfNodes(true);
557 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
559 // get statistic from child sub-meshes
560 TListOfSubMeshes smList;
561 if ( getSubMeshes( aSubMesh, smList ) )
562 for ( TListOfSubMeshes::iterator sm = smList.begin(); sm != smList.end(); ++sm )
563 SMESH_Mesh_i::CollectMeshInfo( (*sm)->GetElements(), aRes );
568 //=======================================================================
570 * Returns number of mesh elements of each \a ElementType
572 //=======================================================================
574 SMESH::long_array* SMESH_subMesh_i::GetNbElementsByType()
576 SMESH::long_array_var aRes = new SMESH::long_array();
577 aRes->length(SMESH::NB_ELEMENT_TYPES);
578 for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
580 aRes[ i ] = _preMeshInfo->NbElements( SMDSAbs_ElementType( i ));
586 aRes[ SMESH::NODE ] = GetNumberOfNodes(true);
588 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
589 if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
591 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
593 aRes[ eIt->next()->GetType() ] = smDS->NbElements();
600 //=======================================================================
601 //function : GetTypes
602 //purpose : Returns types of elements it contains
603 //=======================================================================
605 SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
608 return _preMeshInfo->GetTypes();
610 SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
612 ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
613 if ( SMESHDS_SubMesh* smDS = aSubMesh->GetSubMeshDS() )
615 SMDS_ElemIteratorPtr eIt = smDS->GetElements();
619 types[0] = SMESH::ElementType( eIt->next()->GetType());
621 else if ( smDS->GetNodes()->more() )
623 TopoDS_Shape shape = aSubMesh->GetSubShape();
624 while ( !shape.IsNull() && shape.ShapeType() == TopAbs_COMPOUND )
626 TopoDS_Iterator it( shape );
627 shape = it.More() ? it.Value() : TopoDS_Shape();
629 if ( !shape.IsNull() && shape.ShapeType() == TopAbs_VERTEX )
632 types[0] = SMESH::NODE;
636 return types._retn();
639 //=======================================================================
641 //purpose : interface SMESH_IDSource
642 //=======================================================================
644 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetMesh()
649 //=======================================================================
650 //function : IsMeshInfoCorrect
651 //purpose : * Returns false if GetMeshInfo() returns incorrect information that may
652 // * happen if mesh data is not yet fully loaded from the file of study.
653 //=======================================================================
655 bool SMESH_subMesh_i::IsMeshInfoCorrect()
657 return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
660 //=======================================================================
661 //function : GetVtkUgStream
662 //purpose : Return data vtk unstructured grid (not implemented)
663 //=======================================================================
665 SALOMEDS::TMPFile* SMESH_subMesh_i::GetVtkUgStream()
667 SALOMEDS::TMPFile_var SeqFile;
668 return SeqFile._retn();