Salome HOME
#19765 EDF 21730 - long time to load med file file with huge amount of groups
[modules/smesh.git] / src / SMESH_I / SMESH_subMesh_i.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's classes
24 //  File   : SMESH_subMesh_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //
28 #include "SMESH_subMesh_i.hxx"
29
30 #include "SMESHDS_Mesh.hxx"
31 #include "SMESHDS_SubMesh.hxx"
32 #include "SMESH_Gen_i.hxx"
33 #include "SMESH_Mesh_i.hxx"
34 #include "SMESH_MesherHelper.hxx"
35 #include "SMESH_PreMeshInfo.hxx"
36
37 #include "Utils_CorbaException.hxx"
38 #include "utilities.h"
39 #include "OpUtil.hxx"
40 #include "Utils_ExceptHandlers.hxx"
41
42 #include <TopoDS_Iterator.hxx>
43
44 using namespace std;
45
46 //=============================================================================
47 /*!
48  *  
49  */
50 //=============================================================================
51
52 SMESH_subMesh_i::SMESH_subMesh_i()
53      : SALOME::GenericObj_i( PortableServer::POA::_nil() )
54 {
55   MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i default, not for use");
56   ASSERT(0);
57 }
58
59 //=============================================================================
60 /*!
61  *  
62  */
63 //=============================================================================
64
65 SMESH_subMesh_i::SMESH_subMesh_i( PortableServer::POA_ptr thePOA,
66                                   SMESH_Gen_i*            gen_i,
67                                   SMESH_Mesh_i*           mesh_i,
68                                   int                     localId )
69      : SALOME::GenericObj_i( thePOA )
70 {
71   _gen_i = gen_i;
72   _mesh_i = mesh_i;
73   _localId = localId;
74   _preMeshInfo = NULL;
75 }
76 //=============================================================================
77 /*!
78  *  
79  */
80 //=============================================================================
81
82 SMESH_subMesh_i::~SMESH_subMesh_i()
83 {
84   if ( _preMeshInfo ) delete _preMeshInfo;
85   _preMeshInfo = NULL;
86 }
87
88 //=======================================================================
89 //function : getSubMeshes
90 //purpose  : for a submesh on shape to which elements are not bound directly,
91 //           return submeshes containing elements
92 //=======================================================================
93
94 typedef list<SMESHDS_SubMesh*> TListOfSubMeshes;
95
96 bool getSubMeshes(::SMESH_subMesh*  theSubMesh,
97                   TListOfSubMeshes& theSubMeshList)
98 {
99   if ( !theSubMesh )
100     return false; // "invalid sub-mesh" created by SMESH_Gen_i::CopyMeshWithGeom()
101   size_t size = theSubMeshList.size();
102
103   // check all child sub-meshes of one complexity,
104   // if no elements found and no algo assigned, go to children of lower complexity
105
106   TopoDS_Shape            shape = theSubMesh->GetSubShape();
107   TopAbs_ShapeEnum     mainType = SMESH_MesherHelper::GetGroupType( shape, /*noCompound=*/true );
108   TopAbs_ShapeEnum    shapeType = shape.ShapeType();
109   bool            elementsFound = false;
110   bool                algoFound = false;
111   SMESH_subMeshIteratorPtr smIt = theSubMesh->getDependsOnIterator(/*includeSelf=*/true,
112                                                                    /*complexFirst=*/true);
113   while ( smIt->more() )
114   {
115     ::SMESH_subMesh* sm = smIt->next();
116     if ( sm->GetSubShape().ShapeType() != shapeType )
117     {
118       if ( elementsFound || algoFound )
119         break;
120       if ( sm->GetSubShape().ShapeType() == TopAbs_VERTEX &&
121            mainType != TopAbs_VERTEX )
122         break;
123     }
124     shapeType = sm->GetSubShape().ShapeType();
125     if ( !sm->IsEmpty() )
126     {
127       elementsFound = true;
128       theSubMeshList.push_back( sm->GetSubMeshDS() );
129     }
130     if ( sm->GetAlgo() )
131       algoFound = true;
132   }
133
134   return size < theSubMeshList.size();
135 }
136
137 //=============================================================================
138 /*!
139  *  
140  */
141 //=============================================================================
142
143 CORBA::Long SMESH_subMesh_i::GetNumberOfElements()
144   throw (SALOME::SALOME_Exception)
145 {
146   Unexpect aCatch(SALOME_SalomeException);
147
148   if ( _preMeshInfo )
149     return _preMeshInfo->NbElements();
150
151   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
152     return 0;
153
154   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
155
156   int nbElems = 0;
157
158   TListOfSubMeshes smList;
159   if ( getSubMeshes( aSubMesh, smList ))
160   {
161     TListOfSubMeshes::iterator sm = smList.begin();
162     for ( ; sm != smList.end(); ++sm )
163       nbElems += (*sm)->NbElements();
164   }
165   return nbElems;
166 }
167
168 //=============================================================================
169 /*!
170  *  
171  */
172 //=============================================================================
173
174 CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all)
175   throw (SALOME::SALOME_Exception)
176 {
177   Unexpect aCatch(SALOME_SalomeException);
178
179   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
180     return 0;
181
182   if ( _preMeshInfo )
183   {
184     if ( all ) return _preMeshInfo->NbNodes();
185     else _preMeshInfo->FullLoadFromFile();
186   }
187   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
188   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
189
190   if ( aSubMeshDS && aSubMeshDS->IsComplexSubmesh() )
191   {
192     // sub-mesh on a geom group, always return all nodes
193     return aSubMeshDS->NbNodes();
194   }
195   if ( aSubMeshDS && !all )
196   {
197     // return anything we have
198     return aSubMeshDS->NbNodes();
199   }
200   if ( all ) // get nodes from aSubMesh and all child sub-meshes
201   {
202     int nbNodes = 0;
203     SMESH_subMeshIteratorPtr smIt = aSubMesh->getDependsOnIterator( /*includeSelf=*/true );
204     while ( smIt->more() )
205     {
206       aSubMesh = smIt->next();
207       if (( aSubMeshDS = aSubMesh->GetSubMeshDS() ))
208         nbNodes += aSubMeshDS->NbNodes();
209     }
210     return nbNodes;
211   }
212
213   return aSubMeshDS ? aSubMeshDS->NbNodes() : 0;
214 }
215
216 //=============================================================================
217 /*!
218  *  
219  */
220 //=============================================================================
221
222 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
223   throw (SALOME::SALOME_Exception)
224 {
225   Unexpect aCatch(SALOME_SalomeException);
226
227   SMESH::long_array_var aResult = new SMESH::long_array();
228
229   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
230     return aResult._retn();
231
232   if ( _preMeshInfo )
233     _preMeshInfo->FullLoadFromFile();
234
235   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
236
237   int nbElems = 0;
238   TListOfSubMeshes smList;
239   if ( getSubMeshes( aSubMesh, smList ))
240   {
241     TListOfSubMeshes::iterator sm = smList.begin();
242     for ( ; sm != smList.end(); ++sm )
243       nbElems += (*sm)->NbElements();
244   }
245
246   aResult->length( nbElems );
247   if ( nbElems )
248   {
249     TListOfSubMeshes::iterator sm = smList.begin();
250     for ( int i = 0; sm != smList.end(); sm++ )
251     {
252       SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
253       for ( ; i < nbElems && anIt->more(); i++ )
254         aResult[i] = anIt->next()->GetID();
255     }
256   }
257   return aResult._retn();
258 }
259
260
261 //=============================================================================
262 /*!
263  *  
264  */
265 //=============================================================================
266
267 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
268     throw (SALOME::SALOME_Exception)
269 {
270   Unexpect aCatch(SALOME_SalomeException);
271
272   SMESH::long_array_var aResult = new SMESH::long_array();
273
274   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
275     return aResult._retn();
276
277   if ( _preMeshInfo )
278     _preMeshInfo->FullLoadFromFile();
279
280   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
281
282   // PAL5440, return all nodes belonging to elements of the sub-mesh
283   set<int> nodeIds;
284   int nbElems = 0;
285
286   // volumes may be bound to shell instead of solid
287   TListOfSubMeshes smList;
288   if ( getSubMeshes( aSubMesh, smList ))
289   {
290     TListOfSubMeshes::iterator sm = smList.begin();
291     for ( ; sm != smList.end(); ++sm )
292     {
293       if ( theElemType == SMESH::NODE )
294       {
295         SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
296         if ( eIt->more() ) {
297           while ( eIt->more() ) {
298             const SMDS_MeshElement* anElem = eIt->next();
299             SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
300             while ( nIt->more() )
301               nodeIds.insert( nIt->next()->GetID() );
302           }
303         } else {
304           SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
305           while ( nIt->more() )
306             nodeIds.insert( nIt->next()->GetID() );
307         }
308       }
309       else
310       {
311         nbElems += (*sm)->NbElements();
312       }
313     }
314   }
315
316   if ( theElemType == SMESH::NODE )
317     aResult->length( nodeIds.size() );
318   else
319     aResult->length( nbElems );
320
321   int i = 0, n = aResult->length();
322
323   if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
324     set<int>::iterator idIt = nodeIds.begin();
325     for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
326       aResult[i] = *idIt;
327   }
328
329   if ( theElemType != SMESH::NODE ) {
330     TListOfSubMeshes::iterator sm = smList.begin();
331     for ( i = 0; sm != smList.end(); sm++ )
332     {
333       SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
334       while ( i < n && anIt->more() ) {
335         const SMDS_MeshElement* anElem = anIt->next();
336         if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
337           aResult[i++] = anElem->GetID();
338       }
339     }
340   }
341
342   aResult->length( i );
343
344   return aResult._retn();
345 }
346
347 //=============================================================================
348 /*!
349  *  
350  */
351 //=============================================================================
352   
353 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
354   throw (SALOME::SALOME_Exception)
355 {
356   Unexpect aCatch(SALOME_SalomeException);
357
358   SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
359   return aResult._retn();
360 }
361
362 //=============================================================================
363 /*!
364  *  
365  */
366 //=============================================================================
367   
368 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
369   throw (SALOME::SALOME_Exception)
370 {
371   Unexpect aCatch(SALOME_SalomeException);
372   return _mesh_i->_this();
373 }
374
375 //=============================================================================
376 /*!
377  *  
378  */
379 //=============================================================================
380   
381 CORBA::Long SMESH_subMesh_i::GetId()
382 {
383   return _localId;
384 }
385
386 //=======================================================================
387 //function : GetSubShape
388 //purpose  : 
389 //=======================================================================
390
391 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
392      throw (SALOME::SALOME_Exception)
393 {
394   Unexpect aCatch(SALOME_SalomeException);
395   GEOM::GEOM_Object_var aShapeObj;
396   try {
397     if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
398       TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
399       if ( !S.IsNull() ) {
400         aShapeObj = _gen_i->ShapeToGeomObject( S );
401         //mzn: N7PAL16232, N7PAL16233
402         //In some cases it's possible that GEOM_Client contains the shape same to S, but
403         //with another orientation.
404         if (aShapeObj->_is_nil())
405           aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() );
406       }
407     }
408   }
409   catch(SALOME_Exception & S_ex) {
410     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
411   }
412   return aShapeObj._retn();
413 }
414
415 //=============================================================================
416 /*!
417  *  
418  */
419 //=============================================================================
420 SMESH::long_array* SMESH_subMesh_i::GetIDs()
421 {
422   return GetElementsId();
423 }
424
425 //=============================================================================
426 /*!
427  *
428  */
429 //=============================================================================
430 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
431   throw (SALOME::SALOME_Exception)
432 {
433   if ( _preMeshInfo )
434     _preMeshInfo->FullLoadFromFile();
435   return GetFather()->GetElementType( id, iselem );
436 }
437
438 //=============================================================================
439 /*
440  * Returns number of mesh elements of each \a EntityType
441  * @return array of number of elements per \a EntityType
442  */
443 //=============================================================================
444
445 SMESH::long_array* SMESH_subMesh_i::GetMeshInfo()
446 {
447   if ( _preMeshInfo )
448     return _preMeshInfo->GetMeshInfo();
449
450   SMESH::long_array_var aRes = new SMESH::long_array();
451   aRes->length(SMESH::Entity_Last);
452   for (int i = SMESH::Entity_Node; i < SMESH::Entity_Last; i++)
453     aRes[i] = 0;
454   
455   // get number of nodes
456   aRes[ SMESH::Entity_Node ] = GetNumberOfNodes(true);
457  
458   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
459
460   // get statistic from child sub-meshes
461   TListOfSubMeshes smList;
462   if ( getSubMeshes( aSubMesh, smList ) )
463     for ( TListOfSubMeshes::iterator sm = smList.begin(); sm != smList.end(); ++sm )
464       SMESH_Mesh_i::CollectMeshInfo( (*sm)->GetElements(), aRes );
465
466   return aRes._retn();
467 }
468
469 //=======================================================================
470 /*
471  * Returns number of mesh elements of each \a ElementType
472  */
473 //=======================================================================
474
475 SMESH::long_array* SMESH_subMesh_i::GetNbElementsByType()
476 {
477   SMESH::long_array_var aRes = new SMESH::long_array();
478   aRes->length(SMESH::NB_ELEMENT_TYPES);
479   for (int i = 0; i < SMESH::NB_ELEMENT_TYPES; i++)
480     if ( _preMeshInfo )
481       aRes[ i ] = _preMeshInfo->NbElements( SMDSAbs_ElementType( i ));
482     else
483       aRes[ i ] = 0;
484
485   if ( !_preMeshInfo )
486   {
487     aRes[ SMESH::NODE ] = GetNumberOfNodes(true);
488
489     ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
490     TListOfSubMeshes smList;
491     if ( getSubMeshes( aSubMesh, smList ))
492     {
493       TListOfSubMeshes::iterator smDS = smList.begin();
494       for ( ; smDS != smList.end(); ++smDS )
495       {
496         SMDS_ElemIteratorPtr eIt = (*smDS)->GetElements();
497         if ( eIt->more() )
498           aRes[ eIt->next()->GetType() ] = (*smDS)->NbElements();
499       }
500     }
501   }
502   return aRes._retn();
503 }
504
505
506 //=======================================================================
507 //function : GetTypes
508 //purpose  : Returns types of elements it contains
509 //=======================================================================
510
511 SMESH::array_of_ElementType* SMESH_subMesh_i::GetTypes()
512 {
513   if ( _preMeshInfo )
514     return _preMeshInfo->GetTypes();
515
516   SMESH::array_of_ElementType_var types = new SMESH::array_of_ElementType;
517
518   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
519
520   TListOfSubMeshes smList;
521   if ( getSubMeshes( aSubMesh, smList ))
522   {
523     TListOfSubMeshes::iterator smDS = smList.begin();
524     for ( ; smDS != smList.end(); ++smDS )
525     {
526       SMDS_ElemIteratorPtr eIt = (*smDS)->GetElements();
527       if ( eIt->more() )
528       {
529         types->length( 1 );
530         types[0] = SMESH::ElementType( eIt->next()->GetType());
531         break;
532       }
533     }
534
535     if ( types->length() == 0 )
536     {
537       for ( smDS = smList.begin(); smDS != smList.end(); ++smDS )
538       {
539         if ( (*smDS)->GetNodes()->more() )
540         {
541           int smID = (*smDS)->GetID();
542           TopoDS_Shape shape = (*smDS)->GetParent()->IndexToShape( smID );
543           if ( !shape.IsNull() && shape.ShapeType() == TopAbs_VERTEX )
544           {
545             types->length( 1 );
546             types[0] = SMESH::NODE;
547             break;
548           }
549         }
550       }
551     }
552   }
553   return types._retn();
554 }
555
556 //=======================================================================
557 //function : GetMesh
558 //purpose  : interface SMESH_IDSource
559 //=======================================================================
560
561 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetMesh()
562 {
563   return GetFather();
564 }
565
566 //=======================================================================
567 //function : IsMeshInfoCorrect
568 //purpose  : * Returns false if GetMeshInfo() returns incorrect information that may
569 //           * happen if mesh data is not yet fully loaded from the file of study.
570 //=======================================================================
571
572 bool SMESH_subMesh_i::IsMeshInfoCorrect()
573 {
574   return _preMeshInfo ? _preMeshInfo->IsMeshInfoCorrect() : true;
575 }
576
577 //=======================================================================
578 //function : GetVtkUgStream
579 //purpose  : Return data vtk unstructured grid (not implemented)
580 //=======================================================================
581
582 SALOMEDS::TMPFile* SMESH_subMesh_i::GetVtkUgStream()
583 {
584   SALOMEDS::TMPFile_var SeqFile;
585   return SeqFile._retn();
586 }
587
588 //=======================================================================
589 //function : SMESH_Invalid_subMesh_i
590 //purpose  : constructor of "invalid sub-mesh" created by SMESH_Gen_i::CopyMeshWithGeom()
591 //=======================================================================
592
593 SMESH_Invalid_subMesh_i::SMESH_Invalid_subMesh_i( PortableServer::POA_ptr thePOA,
594                                                   SMESH_Gen_i*            gen_i,
595                                                   SMESH_Mesh_i*           mesh_i,
596                                                   int                     localId,
597                                                   GEOM::GEOM_Object_ptr   shape )
598   : SALOME::GenericObj_i( thePOA ),
599     SMESH_subMesh_i( thePOA, gen_i, mesh_i, localId )
600 {
601   _geom = GEOM::GEOM_Object::_duplicate( shape );
602 }
603
604 //=======================================================================
605 //function : GetSubShape
606 //purpose  : return geometry which is not a sub-shape of the main shape
607 //=======================================================================
608
609 GEOM::GEOM_Object_ptr SMESH_Invalid_subMesh_i::GetSubShape()
610   throw (SALOME::SALOME_Exception)
611 {
612   return GEOM::GEOM_Object::_duplicate( _geom );
613 }