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