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