Salome HOME
PAL16202,16203 (Propagation 1D on edges group)
[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 #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 <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   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       if ( eIt->more() ) {
214         while ( eIt->more() ) {
215           const SMDS_MeshElement* anElem = eIt->next();
216           SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
217           while ( nIt->more() )
218             nodeIds.insert( nIt->next()->GetID() );
219         }
220       } else {
221         SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
222         while ( nIt->more() )
223           nodeIds.insert( nIt->next()->GetID() );
224       }      
225     }
226     return nodeIds.size();
227   }
228
229   if ( aSubMeshDS == NULL )
230     return 0;
231
232   if ( all ) { // all nodes of submesh elements
233     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
234     if ( eIt->more() ) {
235       while ( eIt->more() ) {
236         const SMDS_MeshElement* anElem = eIt->next();
237         SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
238         while ( nIt->more() )
239           nodeIds.insert( nIt->next()->GetID() );
240       }
241     } else {
242       SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
243       while ( nIt->more() )
244         nodeIds.insert( nIt->next()->GetID() );
245     }
246     return nodeIds.size();
247   }
248
249   return aSubMeshDS->NbNodes();
250 }
251
252 //=============================================================================
253 /*!
254  *  
255  */
256 //=============================================================================
257
258 SMESH::long_array* SMESH_subMesh_i::GetElementsId()
259   throw (SALOME::SALOME_Exception)
260 {
261   Unexpect aCatch(SALOME_SalomeException);
262   MESSAGE("SMESH_subMesh_i::GetElementsId");
263   SMESH::long_array_var aResult = new SMESH::long_array();
264
265   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
266     return aResult._retn();
267
268   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
269   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
270
271   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
272   TListOfSubMeshes smList;
273   if ( nbElems )
274     smList.push_back( aSubMeshDS );
275
276   // volumes are bound to shell
277   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
278   {
279     TListOfSubMeshes::iterator sm = smList.begin();
280     for ( ; sm != smList.end(); ++sm )
281       nbElems += (*sm)->NbElements();
282   }
283
284   aResult->length( nbElems );
285   if ( nbElems )
286   {
287     TListOfSubMeshes::iterator sm = smList.begin();
288     for ( int i = 0; sm != smList.end(); sm++ )
289     {
290       SMDS_ElemIteratorPtr anIt = (*sm)->GetElements();
291       for ( ; i < nbElems && anIt->more(); i++ )
292         aResult[i] = anIt->next()->GetID();
293     }
294   }
295   return aResult._retn();
296 }
297
298
299 //=============================================================================
300 /*!
301  *  
302  */
303 //=============================================================================
304
305 SMESH::long_array* SMESH_subMesh_i::GetElementsByType( SMESH::ElementType theElemType )
306     throw (SALOME::SALOME_Exception)
307 {
308   Unexpect aCatch(SALOME_SalomeException);
309   MESSAGE("SMESH_subMesh_i::GetElementsByType");
310   SMESH::long_array_var aResult = new SMESH::long_array();
311
312   if ( _mesh_i->_mapSubMesh.find( _localId ) == _mesh_i->_mapSubMesh.end() )
313     return aResult._retn();
314
315   ::SMESH_subMesh* aSubMesh = _mesh_i->_mapSubMesh[_localId];
316   SMESHDS_SubMesh* aSubMeshDS = aSubMesh->GetSubMeshDS();
317
318   // PAL5440, return all nodes belonging to elements of submesh
319   set<int> nodeIds;
320   int nbElems = aSubMeshDS ? aSubMeshDS->NbElements() : 0;
321
322   // volumes may be bound to shell instead of solid
323   TListOfSubMeshes smList;
324   if ( nbElems == 0 && getSubMeshes( aSubMesh, smList ))
325   {
326     TListOfSubMeshes::iterator sm = smList.begin();
327     for ( ; sm != smList.end(); ++sm )
328     {
329       if ( theElemType == SMESH::NODE )
330       {
331         SMDS_ElemIteratorPtr eIt = (*sm)->GetElements();
332         if ( eIt->more() ) {
333           while ( eIt->more() ) {
334             const SMDS_MeshElement* anElem = eIt->next();
335             SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
336             while ( nIt->more() )
337               nodeIds.insert( nIt->next()->GetID() );
338           }
339         } else {
340           SMDS_NodeIteratorPtr nIt = (*sm)->GetNodes();
341           while ( nIt->more() )
342             nodeIds.insert( nIt->next()->GetID() );
343         }
344       }
345       else
346       {
347         nbElems += (*sm)->NbElements();
348       }
349     }
350     aSubMeshDS = 0;
351   }
352   else
353   {
354     if ( nbElems )
355       smList.push_back( aSubMeshDS );
356   }
357
358   if ( theElemType == SMESH::NODE && aSubMeshDS )
359   {
360     SMDS_ElemIteratorPtr eIt = aSubMeshDS->GetElements();
361     if ( eIt->more() ) {
362       while ( eIt->more() ) {
363         const SMDS_MeshElement* anElem = eIt->next();
364         SMDS_ElemIteratorPtr nIt = anElem->nodesIterator();
365         while ( nIt->more() )
366           nodeIds.insert( nIt->next()->GetID() );
367       }
368     } else {
369       SMDS_NodeIteratorPtr nIt = aSubMeshDS->GetNodes();
370       while ( nIt->more() )
371         nodeIds.insert( nIt->next()->GetID() );
372     }
373   }
374
375   if ( theElemType == SMESH::NODE )
376     aResult->length( nodeIds.size() );
377   else
378     aResult->length( nbElems );
379
380   int i = 0, n = aResult->length();
381
382   if ( theElemType == SMESH::NODE && !nodeIds.empty() ) {
383     set<int>::iterator idIt = nodeIds.begin();
384     for ( ; i < n && idIt != nodeIds.end() ; i++, idIt++ )
385       aResult[i] = *idIt;
386   }
387
388   if ( theElemType != SMESH::NODE ) {
389     TListOfSubMeshes::iterator sm = smList.begin();
390     for ( i = 0; sm != smList.end(); sm++ )
391     {
392       aSubMeshDS = *sm;
393       SMDS_ElemIteratorPtr anIt = aSubMeshDS->GetElements();
394       while ( i < n && anIt->more() ) {
395         const SMDS_MeshElement* anElem = anIt->next();
396         if ( theElemType == SMESH::ALL || anElem->GetType() == (SMDSAbs_ElementType)theElemType )
397           aResult[i++] = anElem->GetID();
398       }
399     }
400   }
401
402   aResult->length( i );
403
404   return aResult._retn();
405 }
406
407 //=============================================================================
408 /*!
409  *  
410  */
411 //=============================================================================
412   
413 SMESH::long_array* SMESH_subMesh_i::GetNodesId()
414   throw (SALOME::SALOME_Exception)
415 {
416   Unexpect aCatch(SALOME_SalomeException);
417   MESSAGE("SMESH_subMesh_i::GetNodesId");
418   SMESH::long_array_var aResult = GetElementsByType( SMESH::NODE );
419   return aResult._retn();
420 }
421
422 //=============================================================================
423 /*!
424  *  
425  */
426 //=============================================================================
427   
428 SMESH::SMESH_Mesh_ptr SMESH_subMesh_i::GetFather()
429   throw (SALOME::SALOME_Exception)
430 {
431   Unexpect aCatch(SALOME_SalomeException);
432   MESSAGE("SMESH_subMesh_i::GetFather");
433   return _mesh_i->_this();
434 }
435
436 //=============================================================================
437 /*!
438  *  
439  */
440 //=============================================================================
441   
442 CORBA::Long SMESH_subMesh_i::GetId()
443 {
444   MESSAGE("SMESH_subMesh_i::GetId");
445   return _localId;
446 }
447
448 //=======================================================================
449 //function : GetSubShape
450 //purpose  : 
451 //=======================================================================
452
453 GEOM::GEOM_Object_ptr SMESH_subMesh_i::GetSubShape()
454      throw (SALOME::SALOME_Exception)
455 {
456   Unexpect aCatch(SALOME_SalomeException);
457   GEOM::GEOM_Object_var aShapeObj;
458   try {
459     if ( _mesh_i->_mapSubMesh.find( _localId ) != _mesh_i->_mapSubMesh.end()) {
460       TopoDS_Shape S = _mesh_i->_mapSubMesh[ _localId ]->GetSubShape();
461       if ( !S.IsNull() ) {
462         aShapeObj = _gen_i->ShapeToGeomObject( S );
463         //mzn: N7PAL16232, N7PAL16233
464         //In some cases it's possible that GEOM_Client contains the shape same to S, but
465         //with another orientation.
466         if (aShapeObj->_is_nil())
467           aShapeObj = _gen_i->ShapeToGeomObject( S.Reversed() );
468       }
469     }
470   }
471   catch(SALOME_Exception & S_ex) {
472     THROW_SALOME_CORBA_EXCEPTION(S_ex.what(), SALOME::BAD_PARAM);
473   }
474   return aShapeObj._retn();
475 }
476
477 //=============================================================================
478 /*!
479  *  
480  */
481 //=============================================================================
482 SALOME_MED::FAMILY_ptr SMESH_subMesh_i::GetFamily()
483   throw (SALOME::SALOME_Exception)
484 {
485   Unexpect aCatch(SALOME_SalomeException);
486   SALOME_MED::MESH_var MEDMesh = GetFather()->GetMEDMesh();
487
488   SALOME_MED::Family_array_var families = 
489     MEDMesh->getFamilies(SALOME_MED::MED_NODE);
490     
491   for ( int i = 0; i < families->length(); i++ ) {
492     if ( families[i]->getIdentifier() == ( _localId ) )
493       return families[i];
494   }
495   
496   return SALOME_MED::FAMILY::_nil();
497 }
498
499 //=============================================================================
500 /*!
501  *  
502  */
503 //=============================================================================
504 SMESH::long_array* SMESH_subMesh_i::GetIDs()
505 {
506   SMESH::long_array_var aResult = GetElementsId();
507   return aResult._retn();
508 }
509
510 //=============================================================================
511 /*!
512  *
513  */
514 //=============================================================================
515 SMESH::ElementType SMESH_subMesh_i::GetElementType( const CORBA::Long id, const bool iselem )
516   throw (SALOME::SALOME_Exception)
517 {
518   return GetFather()->GetElementType( id, iselem );
519 }