Salome HOME
Merging with branch OCC_development_for_3_2_0b1
[modules/smesh.git] / src / SMESH_I / SMESH_subMesh_i.cxx
1 //  SMESH SMESH_I : idl implementation based on 'SMESH' unit's calsses
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESH_subMesh_i.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESH_subMesh_i.hxx"
30 #include "SMESH_Gen_i.hxx"
31 #include "SMESH_Mesh_i.hxx"
32
33 #include "Utils_CorbaException.hxx"
34 #include "utilities.h"
35 #include "OpUtil.hxx"
36 #include "Utils_ExceptHandlers.hxx"
37
38 #include <BRepTools.hxx>
39 #include <TopoDS.hxx>
40 #include <TopoDS_Iterator.hxx>
41
42 using namespace std;
43
44 //=============================================================================
45 /*!
46  *  
47  */
48 //=============================================================================
49
50 SMESH_subMesh_i::SMESH_subMesh_i()
51      : SALOME::GenericObj_i( PortableServer::POA::_nil() )
52 {
53   MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i default, not for use");
54     ASSERT(0);
55 }
56
57 //=============================================================================
58 /*!
59  *  
60  */
61 //=============================================================================
62
63 SMESH_subMesh_i::SMESH_subMesh_i( PortableServer::POA_ptr thePOA,
64                                   SMESH_Gen_i*            gen_i,
65                                   SMESH_Mesh_i*           mesh_i,
66                                   int                     localId )
67      : SALOME::GenericObj_i( thePOA )
68 {
69   MESSAGE("SMESH_subMesh_i::SMESH_subMesh_i");
70   _gen_i = gen_i;
71   _mesh_i = mesh_i;
72   _localId = localId;
73   thePOA->activate_object( this );
74   // ****
75 }
76 //=============================================================================
77 /*!
78  *  
79  */
80 //=============================================================================
81
82 SMESH_subMesh_i::~SMESH_subMesh_i()
83 {
84   MESSAGE("SMESH_subMesh_i::~SMESH_subMesh_i");
85   // ****
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   int size = theSubMeshList.size();
100
101   SMESH_Mesh*      aMesh      = theSubMesh->GetFather();
102   SMESHDS_Mesh*    aMeshDS    = aMesh->GetMeshDS();
103   SMESHDS_SubMesh* aSubMeshDS = theSubMesh->GetSubMeshDS();
104
105   // nodes can be bound to either vertex, edge, face or solid_or_shell
106   TopoDS_Shape aShape = theSubMesh->GetSubShape();
107   switch ( aShape.ShapeType() )
108   {
109   case TopAbs_SOLID: {
110     // add submesh of solid itself
111     aSubMeshDS = aMeshDS->MeshElements( aShape );
112     if ( aSubMeshDS )
113       theSubMeshList.push_back( aSubMeshDS );
114     // and of the first shell
115     TopExp_Explorer exp( aShape, TopAbs_SHELL );
116     if ( exp.More() ) {
117       aSubMeshDS = aMeshDS->MeshElements( exp.Current() );
118       if ( aSubMeshDS )
119         theSubMeshList.push_back( aSubMeshDS );
120     }
121     break;
122   }
123   case TopAbs_WIRE:
124   case TopAbs_COMPOUND:
125   case TopAbs_COMPSOLID: {
126     // call getSubMeshes() for sub-shapes
127     list<TopoDS_Shape> shapeList;
128     shapeList.push_back( aShape );
129     list<TopoDS_Shape>::iterator sh = shapeList.begin();
130     for ( ; sh != shapeList.end(); ++sh ) {
131       for ( TopoDS_Iterator it( *sh ); it.More(); it.Next() ) {
132         ::SMESH_subMesh* aSubMesh = aMesh->GetSubMeshContaining( it.Value() );
133         if ( aSubMesh )
134           getSubMeshes( aSubMesh, theSubMeshList );
135         else
136           // no submesh for a compound inside compound
137           shapeList.push_back( it.Value() );
138       }
139     }
140     // return only unique submeshes
141     set<SMESHDS_SubMesh*> smSet;
142     TListOfSubMeshes::iterator sm = theSubMeshList.begin();
143     while ( sm != theSubMeshList.end() ) {
144       if ( !smSet.insert( *sm ).second )
145         sm = theSubMeshList.erase( sm );
146       else
147         ++sm;
148     }
149     break;
150   }
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   MESSAGE("SMESH_subMesh_i::GetNumberOfElements");
166   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
167     return 0;
168
169   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
170   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
171
172   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
173
174   // volumes are bound to shell
175   TListOfSubMeshes smList;
176   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
177   {
178     TListOfSubMeshes::iterator sm = smList.begin();
179     for ( ; sm != smList.end(); ++sm )
180       nbElems += (*sm)->NbElements();
181   }
182   return nbElems;
183 }
184
185 //=============================================================================
186 /*!
187  *  
188  */
189 //=============================================================================
190
191 CORBA::Long SMESH_subMesh_i::GetNumberOfNodes(CORBA::Boolean all)
192   throw (SALOME::SALOME_Exception)
193 {
194   Unexpect aCatch(SALOME_SalomeException);
195   MESSAGE("SMESH_subMesh_i::GetNumberOfNodes");
196   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
197     return 0;
198
199   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
200   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
201
202   set<int> nodeIds;
203
204   // nodes are bound to shell instead of solid
205   TListOfSubMeshes smList;
206   if ( all && getSubMeshes( aSubMesh, smList ))
207   {
208     TListOfSubMeshes::iterator sm = smList.begin();
209     for ( ; sm != smList.end(); ++sm )
210     {
211       SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
212       while ( eIt->more() ) {
213         const SMDS_MeshElement* anElem = eIt->next();
214         SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
215         while ( nIt->more() )
216           nodeIds.insert( nIt->next()->GetID() );
217       }
218     }
219     return nodeIds.size();
220   }
221
222   if ( aSubMeshDS == NULL )
223     return 0;
224
225   if ( all ) { // all nodes of submesh elements
226     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
227     while ( eIt->more() ) {
228       const SMDS_MeshElement* anElem = eIt->next();
229       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
230       while ( nIt->more() )
231         nodeIds.insert( nIt->next()->GetID() );
232     }
233     return nodeIds.size();
234   }
235     
236   return aSubMeshDS->NbNodes();
237 }
238
239 //=============================================================================
240 /*!
241  *  
242  */
243 //=============================================================================
244   
245 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
246   throw (SALOME::SALOME_Exception)
247 {
248   Unexpect aCatch(SALOME_SalomeException);
249   MESSAGE("SMESH_subMesh_i::GetElementsId");
250   SMESH::long_array_var aResult = new SMESH::long_array();
251
252   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
253     return aResult._retn();
254
255   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
256   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
257
258   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
259   TListOfSubMeshes smList;
260   if ( nbElems )
261     smList.push_back( aSubMeshDS );
262
263   // volumes are bound to shell
264   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
265   {
266     TListOfSubMeshes::iterator sm = smList.begin();
267     for ( ; sm != smList.end(); ++sm )
268       nbElems += (*sm)->NbElements();
269   }
270
271   aResult->length( nbElems );
272   if ( nbElems )
273   {
274     TListOfSubMeshes::iterator sm = smList.begin();
275     for ( int i = 0; sm != smList.end(); sm++ )
276     {
277       SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
278       for ( int n = aSubMeshDS->NbElements(); i < n && anIt->more(); i++ )
279         aResult[i] = anIt->next()->GetID();
280     }
281   }
282   return aResult._retn();
283 }
284
285
286 //=============================================================================
287 /*!
288  *  
289  */
290 //=============================================================================
291
292 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
293     throw (SALOME::SALOME_Exception)
294 {
295   Unexpect aCatch(SALOME_SalomeException);
296   MESSAGE("SMESH_subMesh_i::GetElementsByType");
297   SMESH::long_array_var aResult = new SMESH::long_array();
298
299   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
300     return aResult._retn();
301
302   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
303   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
304
305   // PAL5440, return all nodes belonging to elements of submesh
306   set<int> nodeIds;
307   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
308
309   // volumes may be bound to shell instead of solid
310   TListOfSubMeshes smList;
311   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
312   {
313     TListOfSubMeshes::iterator sm = smList.begin();
314     for ( ; sm != smList.end(); ++sm )
315     {
316       if ( theElemType == SMESH::NODE )
317       {
318         SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
319         while ( eIt->more() ) {
320           const SMDS_MeshElement* anElem = eIt->next();
321           SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
322           while ( nIt->more() )
323             nodeIds.insert( nIt->next()->GetID() );
324         }
325       }
326       else
327       {
328         nbElems += (*sm)->NbElements();
329       }
330     }
331     aSubMeshDS = 0;
332   }
333   else
334   {
335     if ( nbElems )
336       smList.push_back( aSubMeshDS );
337   }
338
339   if ( theElemType == SMESH::NODE && aSubMeshDS )
340   {
341     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
342     while ( eIt->more() ) {
343       const SMDS_MeshElement* anElem = eIt->next();
344       SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
345       while ( nIt->more() )
346         nodeIds.insert( nIt->next()->GetID() );
347     }
348   }
349
350   if ( theElemType == SMESH::NODE )
351     aResult->length( nodeIds.size() );
352   else
353     aResult->length( nbElems );
354
355   int i = 0, n = aResult->length();
356
357   if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
358     set<int>::iterator idIt = nodeIds.begin();
359     for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
360       aResult[i] = *idIt;
361   }
362
363   if ( theElemType != SMESH::NODE ) {
364     TListOfSubMeshes::iterator sm = smList.begin();
365     for ( i = 0; sm != smList.end(); sm++ )
366     {
367       aSubMeshDS = *sm;
368       SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
369       while ( i < n && anIt->more() ) {
370         const SMDS_MeshElement* anElem = anIt->next();
371         if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
372           aResult[i++] = anElem->GetID();
373       }
374     }
375   }
376
377   aResult->length( i );
378
379   return aResult._retn();
380 }
381
382 //=============================================================================
383 /*!
384  *  
385  */
386 //=============================================================================
387   
388 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
389   throw (SALOME::SALOME_Exception)
390 {
391   Unexpect aCatch(SALOME_SalomeException);
392   MESSAGE("SMESH_subMesh_i::GetNodesId");
393   SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
394   return aResult._retn();
395 }
396
397 //=============================================================================
398 /*!
399  *  
400  */
401 //=============================================================================
402   
403 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
404   throw (SALOME::SALOME_Exception)
405 {
406   Unexpect aCatch(SALOME_SalomeException);
407   MESSAGE("SMESH_subMesh_i::GetFather");
408   return _mesh_i->_this();
409 }
410
411 //=============================================================================
412 /*!
413  *  
414  */
415 //=============================================================================
416   
417 CORBA::Long SMESH_subMesh_i::GetId()
418 {
419   MESSAGE("SMESH_subMesh_i::GetId");
420   return _localId;
421 }
422
423 //=======================================================================
424 //function : GetSubShape
425 //purpose  : 
426 //=======================================================================
427
428 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
429      throw (SALOME::SALOME_Exception)
430 {
431   Unexpect aCatch(SALOME_SalomeException);
432   GEOM::GEOM_Object_var aShapeObj;
433   try {
434     if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
435       TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
436       if ( !S.IsNull() )
437         aShapeObj = _gen_i->ShapeToGeomObject( S );
438     }
439   }
440   catch(SALOME_Exception & S_ex) {
441     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
442   }
443   return aShapeObj._retn();
444 }
445
446 //=============================================================================
447 /*!
448  *  
449  */
450 //=============================================================================
451 SALOME_MED::FAMILY_ptr SMESH_subMesh_i::GetFamily()
452   throw (SALOME::SALOME_Exception)
453 {
454   Unexpect aCatch(SALOME_SalomeException);
455   SALOME_MED::MESH_var MEDMesh = GetFather()->GetMEDMesh();
456
457   SALOME_MED::Family_array_var families = 
458     MEDMesh->getFamilies(SALOME_MED::MED_NODE);
459     
460   for ( int i = 0; i < families->length(); i++ ) {
461     if ( families[i]->getIdentifier() == ( _localId ) )
462       return families[i];
463   }
464   
465   return SALOME_MED::FAMILY::_nil();
466 }
467
468 //=============================================================================
469 /*!
470  *  
471  */
472 //=============================================================================
473 SMESH::long_array* SMESH_subMesh_i::GetIDs()
474 {
475   SMESH::long_array_var aResult = GetElementsId();
476   return aResult._retn();
477 }
478
479 //=============================================================================
480 /*!
481  *
482  */
483 //=============================================================================
484 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
485   throw (SALOME::SALOME_Exception)
486 {
487   return GetFather()->GetElementType( id, iselem );
488 }