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