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