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