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