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