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