]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH/SMESH_Mesh.cxx
Salome HOME
0020511: EDF 1101 SMESH : Add CGNS to Mesh Format Supported
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
1 // Copyright (C) 2007-2011  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.
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 : implementaion of SMESH idl descriptions
24 //  File   : SMESH_Mesh.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //
28 #include "SMESH_Mesh.hxx"
29 #include "SMESH_subMesh.hxx"
30 #include "SMESH_Gen.hxx"
31 #include "SMESH_Hypothesis.hxx"
32 #include "SMESH_Group.hxx"
33 #include "SMESH_HypoFilter.hxx"
34 #include "SMESHDS_Group.hxx"
35 #include "SMESHDS_Script.hxx"
36 #include "SMESHDS_GroupOnGeom.hxx"
37 #include "SMESHDS_Document.hxx"
38 #include "SMDS_MeshVolume.hxx"
39 #include "SMDS_SetIterator.hxx"
40
41 #include "utilities.h"
42
43 #include "DriverMED_W_SMESHDS_Mesh.h"
44 #include "DriverDAT_W_SMDS_Mesh.h"
45 #include "DriverUNV_W_SMDS_Mesh.h"
46 #include "DriverSTL_W_SMDS_Mesh.h"
47
48 #include "DriverMED_R_SMESHDS_Mesh.h"
49 #include "DriverUNV_R_SMDS_Mesh.h"
50 #include "DriverSTL_R_SMDS_Mesh.h"
51 #include "DriverCGNS_Read.hxx"
52 #include "DriverCGNS_Write.hxx"
53
54 #undef _Precision_HeaderFile
55 #include <BRepBndLib.hxx>
56 #include <BRepPrimAPI_MakeBox.hxx>
57 #include <Bnd_Box.hxx>
58 #include <TopExp.hxx>
59 #include <TopExp_Explorer.hxx>
60 #include <TopTools_ListIteratorOfListOfShape.hxx>
61 #include <TopTools_ListOfShape.hxx>
62 #include <TopTools_MapOfShape.hxx>
63 #include <TopoDS_Iterator.hxx>
64
65 #include "Utils_ExceptHandlers.hxx"
66
67 using namespace std;
68
69 // maximum stored group name length in MED file
70 #define MAX_MED_GROUP_NAME_LENGTH 80
71
72 #ifdef _DEBUG_
73 static int MYDEBUG = 0;
74 #else
75 static int MYDEBUG = 0;
76 #endif
77
78 #define cSMESH_Hyp(h) static_cast<const SMESH_Hypothesis*>(h)
79
80 typedef SMESH_HypoFilter THypType;
81
82 //=============================================================================
83 /*!
84  * 
85  */
86 //=============================================================================
87
88 SMESH_Mesh::SMESH_Mesh(int               theLocalId, 
89                        int               theStudyId, 
90                        SMESH_Gen*        theGen,
91                        bool              theIsEmbeddedMode,
92                        SMESHDS_Document* theDocument):
93   _groupId( 0 ), _nbSubShapes( 0 )
94 {
95   MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
96   _id            = theLocalId;
97   _studyId       = theStudyId;
98   _gen           = theGen;
99   _myDocument    = theDocument;
100   _idDoc         = theDocument->NewMesh(theIsEmbeddedMode);
101   _myMeshDS      = theDocument->GetMesh(_idDoc);
102   _isShapeToMesh = false;
103   _isAutoColor   = false;
104   _isModified    = false;
105   _shapeDiagonal = 0.0;
106   _rmGroupCallUp = 0;
107   _myMeshDS->ShapeToMesh( PseudoShape() );
108 }
109
110 //================================================================================
111 /*!
112  * \brief Constructor of SMESH_Mesh being a base of some descendant class
113  */
114 //================================================================================
115
116 SMESH_Mesh::SMESH_Mesh():
117   _groupId( 0 ), _nbSubShapes( 0 )
118 {
119   _myMeshDS      = 0;
120   _isShapeToMesh = false;
121   _isAutoColor   = false;
122   _isModified    = false;
123   _shapeDiagonal = 0.0;
124   _rmGroupCallUp = 0;
125 }
126
127 //=============================================================================
128 /*!
129  * 
130  */
131 //=============================================================================
132
133 SMESH_Mesh::~SMESH_Mesh()
134 {
135   MESSAGE("SMESH_Mesh::~SMESH_Mesh");
136
137   // issue 0020340: EDF 1022 SMESH : Crash with FindNodeClosestTo in a second new study
138   //   Notify event listeners at least that something happens
139   if ( SMESH_subMesh * sm = GetSubMeshContaining(1))
140     sm->ComputeStateEngine( SMESH_subMesh::MESH_ENTITY_REMOVED );
141
142   // delete groups
143   map < int, SMESH_Group * >::iterator itg;
144   for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
145     SMESH_Group *aGroup = (*itg).second;
146     delete aGroup;
147   }
148   _mapGroup.clear();
149
150   if ( _rmGroupCallUp) delete _rmGroupCallUp;
151   _rmGroupCallUp = 0;
152 }
153
154 //=============================================================================
155 /*!
156  * \brief Set geometry to be meshed
157  */
158 //=============================================================================
159
160 void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
161 {
162   if(MYDEBUG) MESSAGE("SMESH_Mesh::ShapeToMesh");
163
164   if ( !aShape.IsNull() && _isShapeToMesh ) {
165     if ( aShape.ShapeType() != TopAbs_COMPOUND && // group contents is allowed to change
166          _myMeshDS->ShapeToMesh().ShapeType() != TopAbs_COMPOUND )
167       throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined"));
168   }
169   // clear current data
170   if ( !_myMeshDS->ShapeToMesh().IsNull() )
171   {
172     // removal of a shape to mesh, delete objects referring to sub-shapes:
173     // - sub-meshes
174     map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.begin();
175     for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
176       delete i_sm->second;
177     _mapSubMesh.clear();
178     //  - groups on geometry
179     map <int, SMESH_Group *>::iterator i_gr = _mapGroup.begin();
180     while ( i_gr != _mapGroup.end() ) {
181       if ( dynamic_cast<SMESHDS_GroupOnGeom*>( i_gr->second->GetGroupDS() )) {
182         _myMeshDS->RemoveGroup( i_gr->second->GetGroupDS() );
183         delete i_gr->second;
184         _mapGroup.erase( i_gr++ );
185       }
186       else
187         i_gr++;
188     }
189     _mapAncestors.Clear();
190
191     // clear SMESHDS
192     TopoDS_Shape aNullShape;
193     _myMeshDS->ShapeToMesh( aNullShape );
194
195     _shapeDiagonal = 0.0;
196   }
197
198   // set a new geometry
199   if ( !aShape.IsNull() )
200   {
201     _myMeshDS->ShapeToMesh(aShape);
202     _isShapeToMesh = true;
203     _nbSubShapes = _myMeshDS->MaxShapeIndex();
204
205     // fill map of ancestors
206     fillAncestorsMap(aShape);
207   }
208   else
209   {
210     _isShapeToMesh = false;
211     _shapeDiagonal = 0.0;
212     _myMeshDS->ShapeToMesh( PseudoShape() );
213   }
214   _isModified = false;
215 }
216
217 //=======================================================================
218 /*!
219  * \brief Return geometry to be meshed. (It may be a PseudoShape()!)
220  */
221 //=======================================================================
222
223 TopoDS_Shape SMESH_Mesh::GetShapeToMesh() const
224 {
225   return _myMeshDS->ShapeToMesh();
226 }
227
228 //=======================================================================
229 /*!
230  * \brief Return a solid which is returned by GetShapeToMesh() if
231  *        a real geometry to be meshed was not set
232  */
233 //=======================================================================
234
235 const TopoDS_Solid& SMESH_Mesh::PseudoShape()
236 {
237   static TopoDS_Solid aSolid;
238   if ( aSolid.IsNull() )
239   {
240     aSolid = BRepPrimAPI_MakeBox(1,1,1);
241   }
242   return aSolid;
243 }
244
245 //=======================================================================
246 /*!
247  * \brief Return diagonal size of bounding box of a shape
248  */
249 //=======================================================================
250
251 double SMESH_Mesh::GetShapeDiagonalSize(const TopoDS_Shape & aShape)
252 {
253   if ( !aShape.IsNull() ) {
254     Bnd_Box Box;
255     BRepBndLib::Add(aShape, Box);
256     return sqrt( Box.SquareExtent() );
257   }
258   return 0;
259 }
260
261 //=======================================================================
262 /*!
263  * \brief Return diagonal size of bounding box of shape to mesh
264  */
265 //=======================================================================
266
267 double SMESH_Mesh::GetShapeDiagonalSize() const
268 {
269   if ( _shapeDiagonal == 0. && _isShapeToMesh )
270     const_cast<SMESH_Mesh*>(this)->_shapeDiagonal = GetShapeDiagonalSize( GetShapeToMesh() );
271
272   return _shapeDiagonal;
273 }
274
275 //=======================================================================
276 /*!
277  * \brief Remove all nodes and elements
278  */
279 //=======================================================================
280
281 void SMESH_Mesh::Clear()
282 {
283   // clear mesh data
284   _myMeshDS->ClearMesh();
285
286   // update compute state of submeshes
287   if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) )
288   {
289     sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
290     sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
291     sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918)
292     sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN );
293   }
294   _isModified = false;
295 }
296
297 //=======================================================================
298 /*!
299  * \brief Remove all nodes and elements of indicated shape
300  */
301 //=======================================================================
302
303 void SMESH_Mesh::ClearSubMesh(const int theShapeId)
304 {
305   // clear sub-meshes; get ready to re-compute as a side-effect 
306   if ( SMESH_subMesh *sm = GetSubMeshContaining( theShapeId ) )
307   {
308     SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true,
309                                                              /*complexShapeFirst=*/false);
310     while ( smIt->more() )
311     {
312       sm = smIt->next();
313       TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();      
314       if ( shapeType == TopAbs_VERTEX || shapeType < TopAbs_SOLID )
315         // all other shapes depends on vertices so they are already cleaned
316         sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
317       // to recompute even if failed
318       sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
319     }
320   }
321 }
322
323 //=======================================================================
324 //function : UNVToMesh
325 //purpose  : 
326 //=======================================================================
327
328 int SMESH_Mesh::UNVToMesh(const char* theFileName)
329 {
330   if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
331   if(_isShapeToMesh)
332     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
333   _isShapeToMesh = false;
334   DriverUNV_R_SMDS_Mesh myReader;
335   myReader.SetMesh(_myMeshDS);
336   myReader.SetFile(theFileName);
337   myReader.SetMeshId(-1);
338   myReader.Perform();
339   if(MYDEBUG){
340     MESSAGE("UNVToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
341     MESSAGE("UNVToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
342     MESSAGE("UNVToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
343     MESSAGE("UNVToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
344   }
345   SMDS_MeshGroup* aGroup = (SMDS_MeshGroup*) myReader.GetGroup();
346   if (aGroup != 0) {
347     TGroupNamesMap aGroupNames = myReader.GetGroupNamesMap();
348     //const TGroupIdMap& aGroupId = myReader.GetGroupIdMap();
349     aGroup->InitSubGroupsIterator();
350     while (aGroup->MoreSubGroups()) {
351       SMDS_MeshGroup* aSubGroup = (SMDS_MeshGroup*) aGroup->NextSubGroup();
352       string aName = aGroupNames[aSubGroup];
353       int aId;
354
355       SMESH_Group* aSMESHGroup = AddGroup( aSubGroup->GetType(), aName.c_str(), aId );
356       if ( aSMESHGroup ) {
357         if(MYDEBUG) MESSAGE("UNVToMesh - group added: "<<aName);      
358         SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aSMESHGroup->GetGroupDS() );
359         if ( aGroupDS ) {
360           aGroupDS->SetStoreName(aName.c_str());
361           aSubGroup->InitIterator();
362           const SMDS_MeshElement* aElement = 0;
363           while (aSubGroup->More()) {
364             aElement = aSubGroup->Next();
365             if (aElement) {
366               aGroupDS->SMDSGroup().Add(aElement);
367             }
368           }
369           if (aElement)
370             aGroupDS->SetType(aElement->GetType());
371         }
372       }
373     }
374   }
375   return 1;
376 }
377
378 //=======================================================================
379 //function : MEDToMesh
380 //purpose  : 
381 //=======================================================================
382
383 int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
384 {
385   if(MYDEBUG) MESSAGE("MEDToMesh - theFileName = "<<theFileName<<", mesh name = "<<theMeshName);
386   if(_isShapeToMesh)
387     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
388   _isShapeToMesh = false;
389   DriverMED_R_SMESHDS_Mesh myReader;
390   myReader.SetMesh(_myMeshDS);
391   myReader.SetMeshId(-1);
392   myReader.SetFile(theFileName);
393   myReader.SetMeshName(theMeshName);
394   Driver_Mesh::Status status = myReader.Perform();
395   if(MYDEBUG){
396     MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
397     MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
398     MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
399     MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
400   }
401
402   // Reading groups (sub-meshes are out of scope of MED import functionality)
403   list<TNameAndType> aGroupNames = myReader.GetGroupNamesAndTypes();
404   if(MYDEBUG) MESSAGE("MEDToMesh - Nb groups = "<<aGroupNames.size()); 
405   int anId;
406   list<TNameAndType>::iterator name_type = aGroupNames.begin();
407   for ( ; name_type != aGroupNames.end(); name_type++ ) {
408     SMESH_Group* aGroup = AddGroup( name_type->second, name_type->first.c_str(), anId );
409     if ( aGroup ) {
410       if(MYDEBUG) MESSAGE("MEDToMesh - group added: "<<name_type->first.c_str());      
411       SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
412       if ( aGroupDS ) {
413         aGroupDS->SetStoreName( name_type->first.c_str() );
414         myReader.GetGroup( aGroupDS );
415       }
416     }
417   }
418   return (int) status;
419 }
420
421 //=======================================================================
422 //function : STLToMesh
423 //purpose  : 
424 //=======================================================================
425
426 int SMESH_Mesh::STLToMesh(const char* theFileName)
427 {
428   if(MYDEBUG) MESSAGE("STLToMesh - theFileName = "<<theFileName);
429   if(_isShapeToMesh)
430     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
431   _isShapeToMesh = false;
432   DriverSTL_R_SMDS_Mesh myReader;
433   myReader.SetMesh(_myMeshDS);
434   myReader.SetFile(theFileName);
435   myReader.SetMeshId(-1);
436   myReader.Perform();
437   if(MYDEBUG){
438     MESSAGE("STLToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
439     MESSAGE("STLToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
440     MESSAGE("STLToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
441     MESSAGE("STLToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
442   }
443   return 1;
444 }
445
446 //================================================================================
447 /*!
448  * \brief Reads the given mesh from the CGNS file
449  *  \param theFileName - name of the file
450  *  \retval int - Driver_Mesh::Status
451  */
452 //================================================================================
453
454 int SMESH_Mesh::CGNSToMesh(const char*  theFileName,
455                            const int    theMeshIndex,
456                            std::string& theMeshName)
457 {
458   DriverCGNS_Read myReader;
459   myReader.SetMesh(_myMeshDS);
460   myReader.SetFile(theFileName);
461   myReader.SetMeshId(theMeshIndex);
462   int res = myReader.Perform();
463   theMeshName = myReader.GetMeshName();
464
465   // create groups
466   SynchronizeGroups();
467
468   return res;
469 }
470
471 //=============================================================================
472 /*!
473  * 
474  */
475 //=============================================================================
476
477 SMESH_Hypothesis::Hypothesis_Status
478   SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
479                             int                  anHypId  ) throw(SALOME_Exception)
480 {
481   Unexpect aCatch(SalomeException);
482   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
483
484   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
485   if ( !subMesh || !subMesh->GetId())
486     return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
487
488   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
489   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
490   {
491     if(MYDEBUG) MESSAGE("Hypothesis ID does not give an hypothesis");
492     if(MYDEBUG) {
493       SCRUTE(_studyId);
494       SCRUTE(anHypId);
495     }
496     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
497   }
498
499   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
500   MESSAGE( "SMESH_Mesh::AddHypothesis " << anHyp->GetName() );
501
502   bool isGlobalHyp = IsMainShape( aSubShape );
503
504   // NotConformAllowed can be only global
505   if ( !isGlobalHyp )
506   {
507     // NOTE: this is not a correct way to check a name of hypothesis,
508     // there should be an attribute of hypothesis saying that it can/can't
509     // be global/local
510     string hypName = anHyp->GetName();
511     if ( hypName == "NotConformAllowed" )
512     {
513       if(MYDEBUG) MESSAGE( "Hypotesis <NotConformAllowed> can be only global" );
514       return SMESH_Hypothesis::HYP_INCOMPATIBLE;
515     }
516   }
517
518   // shape 
519
520   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
521   int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
522
523   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
524
525   // subShapes
526   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
527       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
528   {
529     event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
530
531     SMESH_Hypothesis::Hypothesis_Status ret2 =
532       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
533     if (ret2 > ret)
534       ret = ret2;
535
536     // check concurent hypotheses on ancestors
537     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
538     {
539       SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
540       while ( smIt->more() ) {
541         SMESH_subMesh* sm = smIt->next();
542         if ( sm->IsApplicableHypotesis( anHyp )) {
543           ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
544           if (ret2 > ret) {
545             ret = ret2;
546             break;
547           }
548         }
549       }
550     }
551   }
552   HasModificationsToDiscard(); // to reset _isModified flag if a mesh becomes empty
553
554   GetMeshDS()->Modified();
555
556   if(MYDEBUG) subMesh->DumpAlgoState(true);
557   if(MYDEBUG) SCRUTE(ret);
558   return ret;
559 }
560
561 //=============================================================================
562 /*!
563  * 
564  */
565 //=============================================================================
566
567 SMESH_Hypothesis::Hypothesis_Status
568   SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
569                                int anHypId)throw(SALOME_Exception)
570 {
571   Unexpect aCatch(SalomeException);
572   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
573   
574   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
575   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
576     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
577   
578   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
579   if(MYDEBUG) {
580     int hypType = anHyp->GetType();
581     SCRUTE(hypType);
582   }
583   
584   // shape 
585   
586   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
587   int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
588
589   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
590
591   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
592
593   // there may appear concurrent hyps that were covered by the removed hyp
594   if (ret < SMESH_Hypothesis::HYP_CONCURENT &&
595       subMesh->IsApplicableHypotesis( anHyp ) &&
596       subMesh->CheckConcurentHypothesis( anHyp->GetType() ) != SMESH_Hypothesis::HYP_OK)
597     ret = SMESH_Hypothesis::HYP_CONCURENT;
598
599   // subShapes
600   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
601       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is removed from father
602   {
603     event = isAlgo ? SMESH_subMesh::REMOVE_FATHER_ALGO : SMESH_subMesh::REMOVE_FATHER_HYP;
604
605     SMESH_Hypothesis::Hypothesis_Status ret2 =
606       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
607     if (ret2 > ret) // more severe
608       ret = ret2;
609
610     // check concurent hypotheses on ancestors
611     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) )
612     {
613       SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
614       while ( smIt->more() ) {
615         SMESH_subMesh* sm = smIt->next();
616         if ( sm->IsApplicableHypotesis( anHyp )) {
617           ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
618           if (ret2 > ret) {
619             ret = ret2;
620             break;
621           }
622         }
623       }
624     }
625   }
626
627   HasModificationsToDiscard(); // to reset _isModified flag if mesh become empty
628
629   GetMeshDS()->Modified();
630
631   if(MYDEBUG) subMesh->DumpAlgoState(true);
632   if(MYDEBUG) SCRUTE(ret);
633   return ret;
634 }
635
636 //=============================================================================
637 /*!
638  * 
639  */
640 //=============================================================================
641
642 const list<const SMESHDS_Hypothesis*>&
643 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
644   throw(SALOME_Exception)
645 {
646   Unexpect aCatch(SalomeException);
647   return _myMeshDS->GetHypothesis(aSubShape);
648 }
649
650 //=======================================================================
651 /*!
652  * \brief Return the hypothesis assigned to the shape
653  *  \param aSubShape    - the shape to check
654  *  \param aFilter      - the hypothesis filter
655  *  \param andAncestors - flag to check hypos assigned to ancestors of the shape
656  *  \param assignedTo   - to return the shape the found hypo is assigned to
657  *  \retval SMESH_Hypothesis* - the first hypo passed through aFilter
658  */
659 //=======================================================================
660
661 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubShape,
662                                                    const SMESH_HypoFilter& aFilter,
663                                                    const bool              andAncestors,
664                                                    TopoDS_Shape*           assignedTo) const
665 {
666   {
667     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
668     list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
669     for ( ; hyp != hypList.end(); hyp++ ) {
670       const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
671       if ( aFilter.IsOk( h, aSubShape)) {
672         if ( assignedTo ) *assignedTo = aSubShape;
673         return h;
674       }
675     }
676   }
677   if ( andAncestors )
678   {
679     // user sorted submeshes of ancestors, according to stored submesh priority
680     const list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
681     list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
682     for ( ; smIt != smList.end(); smIt++ )
683     {
684       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
685       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
686       list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
687       for ( ; hyp != hypList.end(); hyp++ ) {
688         const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
689         if (aFilter.IsOk( h, curSh )) {
690           if ( assignedTo ) *assignedTo = curSh;
691           return h;
692         }
693       }
694     }
695   }
696   return 0;
697 }
698
699 //================================================================================
700 /*!
701  * \brief Return hypothesis assigned to the shape
702   * \param aSubShape - the shape to check
703   * \param aFilter - the hypothesis filter
704   * \param aHypList - the list of the found hypotheses
705   * \param andAncestors - flag to check hypos assigned to ancestors of the shape
706   * \retval int - number of unique hypos in aHypList
707  */
708 //================================================================================
709
710 int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
711                               const SMESH_HypoFilter&             aFilter,
712                               list <const SMESHDS_Hypothesis * >& aHypList,
713                               const bool                          andAncestors) const
714 {
715   set<string> hypTypes; // to exclude same type hypos from the result list
716   int nbHyps = 0;
717
718   // only one main hypothesis is allowed
719   bool mainHypFound = false;
720
721   // fill in hypTypes
722   list<const SMESHDS_Hypothesis*>::const_iterator hyp;
723   for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ ) {
724     if ( hypTypes.insert( (*hyp)->GetName() ).second )
725       nbHyps++;
726     if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
727       mainHypFound = true;
728   }
729
730   // get hypos from aSubShape
731   {
732     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
733     for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
734       if ( aFilter.IsOk (cSMESH_Hyp( *hyp ), aSubShape) &&
735            ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
736            hypTypes.insert( (*hyp)->GetName() ).second )
737       {
738         aHypList.push_back( *hyp );
739         nbHyps++;
740         if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
741           mainHypFound = true;
742       }
743   }
744
745   // get hypos from ancestors of aSubShape
746   if ( andAncestors )
747   {
748     TopTools_MapOfShape map;
749
750     // user sorted submeshes of ancestors, according to stored submesh priority
751     const list<SMESH_subMesh*> smList = getAncestorsSubMeshes( aSubShape );
752     list<SMESH_subMesh*>::const_iterator smIt = smList.begin(); 
753     for ( ; smIt != smList.end(); smIt++ )
754     {
755       const TopoDS_Shape& curSh = (*smIt)->GetSubShape();
756      if ( !map.Add( curSh ))
757         continue;
758       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(curSh);
759       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
760         if (aFilter.IsOk( cSMESH_Hyp( *hyp ), curSh ) &&
761             ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
762             hypTypes.insert( (*hyp)->GetName() ).second )
763         {
764           aHypList.push_back( *hyp );
765           nbHyps++;
766           if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
767             mainHypFound = true;
768         }
769     }
770   }
771   return nbHyps;
772 }
773
774 //=============================================================================
775 /*!
776  * 
777  */
778 //=============================================================================
779
780 const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
781 {
782   Unexpect aCatch(SalomeException);
783   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
784   return _myMeshDS->GetScript()->GetCommands();
785 }
786
787 //=============================================================================
788 /*!
789  * 
790  */
791 //=============================================================================
792 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
793 {
794   Unexpect aCatch(SalomeException);
795   if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
796   _myMeshDS->GetScript()->Clear();
797 }
798
799 //=============================================================================
800 /*!
801  * Get or Create the SMESH_subMesh object implementation
802  */
803 //=============================================================================
804
805 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
806   throw(SALOME_Exception)
807 {
808   Unexpect aCatch(SalomeException);
809   SMESH_subMesh *aSubMesh;
810   int index = _myMeshDS->ShapeToIndex(aSubShape);
811
812   // for submeshes on GEOM Group
813   if (( !index || index > _nbSubShapes ) && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
814     TopoDS_Iterator it( aSubShape );
815     if ( it.More() )
816     {
817       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
818       if ( index > _nbSubShapes ) _nbSubShapes = index; // not to create sm for this group again
819
820       // fill map of Ancestors
821       fillAncestorsMap(aSubShape);
822     }
823   }
824 //   if ( !index )
825 //     return NULL; // neither sub-shape nor a group
826
827   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
828   if ( i_sm != _mapSubMesh.end())
829   {
830     aSubMesh = i_sm->second;
831   }
832   else
833   {
834     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
835     _mapSubMesh[index] = aSubMesh;
836     ClearMeshOrder();
837   }
838   return aSubMesh;
839 }
840
841 //=============================================================================
842 /*!
843  * Get the SMESH_subMesh object implementation. Dont create it, return null
844  * if it does not exist.
845  */
846 //=============================================================================
847
848 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape) const
849   throw(SALOME_Exception)
850 {
851   Unexpect aCatch(SalomeException);
852   SMESH_subMesh *aSubMesh = NULL;
853   
854   int index = _myMeshDS->ShapeToIndex(aSubShape);
855
856   map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(index);
857   if ( i_sm != _mapSubMesh.end())
858     aSubMesh = i_sm->second;
859
860   return aSubMesh;
861 }
862 //=============================================================================
863 /*!
864  * Get the SMESH_subMesh object implementation. Dont create it, return null
865  * if it does not exist.
866  */
867 //=============================================================================
868
869 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) const
870 throw(SALOME_Exception)
871 {
872   Unexpect aCatch(SalomeException);
873   
874   map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(aShapeID);
875   if (i_sm == _mapSubMesh.end())
876     return NULL;
877   return i_sm->second;
878 }
879 //================================================================================
880 /*!
881  * \brief Return submeshes of groups containing the given subshape
882  */
883 //================================================================================
884
885 list<SMESH_subMesh*>
886 SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
887   throw(SALOME_Exception)
888 {
889   Unexpect aCatch(SalomeException);
890   list<SMESH_subMesh*> found;
891
892   SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
893   if ( !subMesh )
894     return found;
895
896   // submeshes of groups have max IDs, so search from the map end
897   map<int, SMESH_subMesh *>::const_reverse_iterator i_sm;
898   for ( i_sm = _mapSubMesh.rbegin(); i_sm != _mapSubMesh.rend(); ++i_sm) {
899     SMESHDS_SubMesh * ds = i_sm->second->GetSubMeshDS();
900     if ( ds && ds->IsComplexSubmesh() ) {
901       TopExp_Explorer exp( i_sm->second->GetSubShape(), aSubShape.ShapeType() );
902       for ( ; exp.More(); exp.Next() ) {
903         if ( aSubShape.IsSame( exp.Current() )) {
904           found.push_back( i_sm->second );
905           break;
906         }
907       }
908     } else {
909       break;
910     }
911   }
912   return found;
913 }
914 //=======================================================================
915 //function : IsUsedHypothesis
916 //purpose  : Return True if anHyp is used to mesh aSubShape
917 //=======================================================================
918
919 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
920                                   const SMESH_subMesh* aSubMesh)
921 {
922   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
923
924   // check if anHyp can be used to mesh aSubMesh
925   if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
926     return false;
927
928   const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
929
930   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
931
932   // algorithm
933   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
934     return ( anHyp == algo );
935
936   // algorithm parameter
937   if (algo)
938   {
939     // look trough hypotheses used by algo
940     SMESH_HypoFilter hypoKind;
941     if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
942       list <const SMESHDS_Hypothesis * > usedHyps;
943       if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
944         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
945     }
946   }
947
948   // look through all assigned hypotheses
949   //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
950   return false; //GetHypothesis( aSubShape, filter, true );
951 }
952
953 //=============================================================================
954 /*!
955  *
956  */
957 //=============================================================================
958
959 const list < SMESH_subMesh * >&
960 SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
961   throw(SALOME_Exception)
962 {
963   Unexpect aCatch(SalomeException);
964   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
965   map < int, SMESH_subMesh * >::iterator itsm;
966   _subMeshesUsingHypothesisList.clear();
967   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
968   {
969     SMESH_subMesh *aSubMesh = (*itsm).second;
970     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
971       _subMeshesUsingHypothesisList.push_back(aSubMesh);
972   }
973   return _subMeshesUsingHypothesisList;
974 }
975
976 //=======================================================================
977 //function : NotifySubMeshesHypothesisModification
978 //purpose  : Say all submeshes using theChangedHyp that it has been modified
979 //=======================================================================
980
981 void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp)
982 {
983   Unexpect aCatch(SalomeException);
984
985   const SMESH_Algo *foundAlgo = 0;
986   SMESH_HypoFilter algoKind, compatibleHypoKind;
987   list <const SMESHDS_Hypothesis * > usedHyps;
988
989
990   map < int, SMESH_subMesh * >::iterator itsm;
991   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
992   {
993     SMESH_subMesh *aSubMesh = (*itsm).second;
994     if ( aSubMesh->IsApplicableHypotesis( hyp ))
995     {
996       const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
997
998       if ( !foundAlgo ) // init filter for algo search
999         algoKind.Init( THypType::IsAlgo() ).And( THypType::IsApplicableTo( aSubShape ));
1000       
1001       const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
1002         ( GetHypothesis( aSubShape, algoKind, true ));
1003
1004       if ( algo )
1005       {
1006         bool sameAlgo = ( algo == foundAlgo );
1007         if ( !sameAlgo && foundAlgo )
1008           sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
1009
1010         if ( !sameAlgo ) { // init filter for used hypos search
1011           if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
1012             continue; // algo does not use any hypothesis
1013           foundAlgo = algo;
1014         }
1015
1016         // check if hyp is used by algo
1017         usedHyps.clear();
1018         if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
1019              find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
1020         {
1021           aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
1022                                     const_cast< SMESH_Hypothesis*>( hyp ));
1023         }
1024       }
1025     }
1026   }
1027   HasModificationsToDiscard(); // to reset _isModified flag if mesh becomes empty
1028   GetMeshDS()->Modified();
1029 }
1030
1031 //=============================================================================
1032 /*!
1033  *  Auto color functionality
1034  */
1035 //=============================================================================
1036 void SMESH_Mesh::SetAutoColor(bool theAutoColor) throw(SALOME_Exception)
1037 {
1038   Unexpect aCatch(SalomeException);
1039   _isAutoColor = theAutoColor;
1040 }
1041
1042 bool SMESH_Mesh::GetAutoColor() throw(SALOME_Exception)
1043 {
1044   Unexpect aCatch(SalomeException);
1045   return _isAutoColor;
1046 }
1047
1048 //=======================================================================
1049 //function : SetIsModified
1050 //purpose  : Set the flag meaning that the mesh has been edited "manually"
1051 //=======================================================================
1052
1053 void SMESH_Mesh::SetIsModified(bool isModified)
1054 {
1055   _isModified = isModified;
1056
1057   if ( _isModified )
1058     // check if mesh becomes empty as result of modification
1059     HasModificationsToDiscard();
1060 }
1061
1062 //=======================================================================
1063 //function : HasModificationsToDiscard
1064 //purpose  : Return true if the mesh has been edited since a total re-compute
1065 //           and those modifications may prevent successful partial re-compute.
1066 //           As a side effect reset _isModified flag if mesh is empty
1067 //issue    : 0020693
1068 //=======================================================================
1069
1070 bool SMESH_Mesh::HasModificationsToDiscard() const
1071 {
1072   if ( ! _isModified )
1073     return false;
1074
1075   // return true if the next Compute() will be partial and
1076   // existing but changed elements may prevent successful re-compute
1077   bool hasComputed = false, hasNotComputed = false;
1078   map <int, SMESH_subMesh*>::const_iterator i_sm = _mapSubMesh.begin();
1079   for ( ; i_sm != _mapSubMesh.end() ; ++i_sm )
1080     switch ( i_sm->second->GetSubShape().ShapeType() )
1081     {
1082     case TopAbs_EDGE:
1083     case TopAbs_FACE:
1084     case TopAbs_SOLID:
1085       if ( i_sm->second->IsMeshComputed() )
1086         hasComputed = true;
1087       else
1088         hasNotComputed = true;
1089       if ( hasComputed && hasNotComputed)
1090         return true;
1091     }
1092
1093   if ( !hasComputed )
1094     const_cast<SMESH_Mesh*>(this)->_isModified = false;
1095
1096   return false;
1097 }
1098
1099 //================================================================================
1100 /*!
1101  * \brief Check if any groups of the same type have equal names
1102  */
1103 //================================================================================
1104
1105 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
1106 {
1107   //set<string> aGroupNames; // Corrected for Mantis issue 0020028
1108   map< SMDSAbs_ElementType, set<string> > aGroupNames;
1109   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1110   {
1111     SMESH_Group* aGroup = it->second;
1112     SMDSAbs_ElementType aType = aGroup->GetGroupDS()->GetType();
1113     string aGroupName = aGroup->GetName();
1114     aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
1115     if (!aGroupNames[aType].insert(aGroupName).second)
1116       return true;
1117   }
1118
1119   return false;
1120 }
1121
1122 //================================================================================
1123 /*!
1124  * \brief Export the mesh to a med file
1125  */
1126 //================================================================================
1127
1128 void SMESH_Mesh::ExportMED(const char *        file, 
1129                            const char*         theMeshName, 
1130                            bool                theAutoGroups,
1131                            int                 theVersion,
1132                            const SMESHDS_Mesh* meshPart) 
1133   throw(SALOME_Exception)
1134 {
1135   Unexpect aCatch(SalomeException);
1136
1137   DriverMED_W_SMESHDS_Mesh myWriter;
1138   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
1139   myWriter.SetMesh    ( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS   );
1140   if ( !theMeshName ) 
1141     myWriter.SetMeshId  ( _idDoc      );
1142   else {
1143     myWriter.SetMeshId  ( -1          );
1144     myWriter.SetMeshName( theMeshName );
1145   }
1146
1147   if ( theAutoGroups ) {
1148     myWriter.AddGroupOfNodes();
1149     myWriter.AddGroupOfEdges();
1150     myWriter.AddGroupOfFaces();
1151     myWriter.AddGroupOfVolumes();
1152   }
1153
1154   // Pass groups to writer. Provide unique group names.
1155   //set<string> aGroupNames; // Corrected for Mantis issue 0020028
1156   if ( !meshPart )
1157   {
1158     map< SMDSAbs_ElementType, set<string> > aGroupNames;
1159     char aString [256];
1160     int maxNbIter = 10000; // to guarantee cycle finish
1161     for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1162       SMESH_Group*       aGroup   = it->second;
1163       SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1164       if ( aGroupDS ) {
1165         SMDSAbs_ElementType aType = aGroupDS->GetType();
1166         string aGroupName0 = aGroup->GetName();
1167         aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
1168         string aGroupName = aGroupName0;
1169         for (int i = 1; !aGroupNames[aType].insert(aGroupName).second && i < maxNbIter; i++) {
1170           sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
1171           aGroupName = aString;
1172           aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
1173         }
1174         aGroupDS->SetStoreName( aGroupName.c_str() );
1175         myWriter.AddGroup( aGroupDS );
1176       }
1177     }
1178   }
1179   // Perform export
1180   myWriter.Perform();
1181 }
1182
1183 //================================================================================
1184 /*!
1185  * \brief Export the mesh to a DAT file
1186  */
1187 //================================================================================
1188
1189 void SMESH_Mesh::ExportDAT(const char *        file,
1190                            const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
1191 {
1192   Unexpect aCatch(SalomeException);
1193   DriverDAT_W_SMDS_Mesh myWriter;
1194   myWriter.SetFile( file );
1195   myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS );
1196   myWriter.SetMeshId(_idDoc);
1197   myWriter.Perform();
1198 }
1199
1200 //================================================================================
1201 /*!
1202  * \brief Export the mesh to an UNV file
1203  */
1204 //================================================================================
1205
1206 void SMESH_Mesh::ExportUNV(const char *        file,
1207                            const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
1208 {
1209   Unexpect aCatch(SalomeException);
1210   DriverUNV_W_SMDS_Mesh myWriter;
1211   myWriter.SetFile( file );
1212   myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS );
1213   myWriter.SetMeshId(_idDoc);
1214   //  myWriter.SetGroups(_mapGroup);
1215
1216   if ( !meshPart )
1217   {
1218     for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1219       SMESH_Group*       aGroup   = it->second;
1220       SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1221       if ( aGroupDS ) {
1222         string aGroupName = aGroup->GetName();
1223         aGroupDS->SetStoreName( aGroupName.c_str() );
1224         myWriter.AddGroup( aGroupDS );
1225       }
1226     }
1227   }
1228   myWriter.Perform();
1229 }
1230
1231 //================================================================================
1232 /*!
1233  * \brief Export the mesh to an STL file
1234  */
1235 //================================================================================
1236
1237 void SMESH_Mesh::ExportSTL(const char *        file,
1238                            const bool          isascii,
1239                            const SMESHDS_Mesh* meshPart) throw(SALOME_Exception)
1240 {
1241   Unexpect aCatch(SalomeException);
1242   DriverSTL_W_SMDS_Mesh myWriter;
1243   myWriter.SetFile( file );
1244   myWriter.SetIsAscii( isascii );
1245   myWriter.SetMesh( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS);
1246   myWriter.SetMeshId(_idDoc);
1247   myWriter.Perform();
1248 }
1249
1250 //================================================================================
1251 /*!
1252  * \brief Export the mesh to the CGNS file
1253  */
1254 //================================================================================
1255
1256 void SMESH_Mesh::ExportCGNS(const char *        file,
1257                             const SMESHDS_Mesh* meshDS)
1258 {
1259   DriverCGNS_Write myWriter;
1260   myWriter.SetFile( file );
1261   myWriter.SetMesh( const_cast<SMESHDS_Mesh*>( meshDS ));
1262   myWriter.SetMeshName( SMESH_Comment("Mesh_") << meshDS->GetPersistentId());
1263   if ( myWriter.Perform() != Driver_Mesh::DRS_OK )
1264     throw SALOME_Exception("Export failed");
1265 }
1266
1267 //================================================================================
1268 /*!
1269  * \brief Return number of nodes in the mesh
1270  */
1271 //================================================================================
1272
1273 int SMESH_Mesh::NbNodes() const throw(SALOME_Exception)
1274 {
1275   Unexpect aCatch(SalomeException);
1276   return _myMeshDS->NbNodes();
1277 }
1278
1279 //================================================================================
1280 /*!
1281  * \brief  Return number of edges of given order in the mesh
1282  */
1283 //================================================================================
1284
1285 int SMESH_Mesh::Nb0DElements() const throw(SALOME_Exception)
1286 {
1287   Unexpect aCatch(SalomeException);
1288   return _myMeshDS->GetMeshInfo().Nb0DElements();
1289 }
1290
1291 //================================================================================
1292 /*!
1293  * \brief  Return number of edges of given order in the mesh
1294  */
1295 //================================================================================
1296
1297 int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1298 {
1299   Unexpect aCatch(SalomeException);
1300   return _myMeshDS->GetMeshInfo().NbEdges(order);
1301 }
1302
1303 //================================================================================
1304 /*!
1305  * \brief Return number of faces of given order in the mesh
1306  */
1307 //================================================================================
1308
1309 int SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1310 {
1311   Unexpect aCatch(SalomeException);
1312   return _myMeshDS->GetMeshInfo().NbFaces(order);
1313 }
1314
1315 //================================================================================
1316 /*!
1317  * \brief Return the number of faces in the mesh
1318  */
1319 //================================================================================
1320
1321 int SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1322 {
1323   Unexpect aCatch(SalomeException);
1324   return _myMeshDS->GetMeshInfo().NbTriangles(order);
1325 }
1326
1327 //================================================================================
1328 /*!
1329  * \brief Return the number nodes faces in the mesh
1330  */
1331 //================================================================================
1332
1333 int SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1334 {
1335   Unexpect aCatch(SalomeException);
1336   return _myMeshDS->GetMeshInfo().NbQuadrangles(order);
1337 }
1338
1339 //================================================================================
1340 /*!
1341  * \brief Return the number of polygonal faces in the mesh
1342  */
1343 //================================================================================
1344
1345 int SMESH_Mesh::NbPolygons() const throw(SALOME_Exception)
1346 {
1347   Unexpect aCatch(SalomeException);
1348   return _myMeshDS->GetMeshInfo().NbPolygons();
1349 }
1350
1351 //================================================================================
1352 /*!
1353  * \brief Return number of volumes of given order in the mesh
1354  */
1355 //================================================================================
1356
1357 int SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1358 {
1359   Unexpect aCatch(SalomeException);
1360   return _myMeshDS->GetMeshInfo().NbVolumes(order);
1361 }
1362
1363 //================================================================================
1364 /*!
1365  * \brief  Return number of tetrahedrons of given order in the mesh
1366  */
1367 //================================================================================
1368
1369 int SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1370 {
1371   Unexpect aCatch(SalomeException);
1372   return _myMeshDS->GetMeshInfo().NbTetras(order);
1373 }
1374
1375 //================================================================================
1376 /*!
1377  * \brief  Return number of hexahedrons of given order in the mesh
1378  */
1379 //================================================================================
1380
1381 int SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1382 {
1383   Unexpect aCatch(SalomeException);
1384   return _myMeshDS->GetMeshInfo().NbHexas(order);
1385 }
1386
1387 //================================================================================
1388 /*!
1389  * \brief  Return number of pyramids of given order in the mesh
1390  */
1391 //================================================================================
1392
1393 int SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1394 {
1395   Unexpect aCatch(SalomeException);
1396   return _myMeshDS->GetMeshInfo().NbPyramids(order);
1397 }
1398
1399 //================================================================================
1400 /*!
1401  * \brief  Return number of prisms (penthahedrons) of given order in the mesh
1402  */
1403 //================================================================================
1404
1405 int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) const throw(SALOME_Exception)
1406 {
1407   Unexpect aCatch(SalomeException);
1408   return _myMeshDS->GetMeshInfo().NbPrisms(order);
1409 }
1410
1411 //================================================================================
1412 /*!
1413  * \brief  Return number of polyhedrons in the mesh
1414  */
1415 //================================================================================
1416
1417 int SMESH_Mesh::NbPolyhedrons() const throw(SALOME_Exception)
1418 {
1419   Unexpect aCatch(SalomeException);
1420   return _myMeshDS->GetMeshInfo().NbPolyhedrons();
1421 }
1422
1423 //================================================================================
1424 /*!
1425  * \brief  Return number of submeshes in the mesh
1426  */
1427 //================================================================================
1428
1429 int SMESH_Mesh::NbSubMesh() const throw(SALOME_Exception)
1430 {
1431   Unexpect aCatch(SalomeException);
1432   return _myMeshDS->NbSubMesh();
1433 }
1434
1435 //=======================================================================
1436 //function : IsNotConformAllowed
1437 //purpose  : check if a hypothesis alowing notconform mesh is present
1438 //=======================================================================
1439
1440 bool SMESH_Mesh::IsNotConformAllowed() const
1441 {
1442   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1443
1444   static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1445   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1446 }
1447
1448 //=======================================================================
1449 //function : IsMainShape
1450 //purpose  : 
1451 //=======================================================================
1452
1453 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1454 {
1455   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1456 }
1457
1458 //=============================================================================
1459 /*!
1460  *  
1461  */
1462 //=============================================================================
1463
1464 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1465                                    const char*               theName,
1466                                    int&                      theId,
1467                                    const TopoDS_Shape&       theShape,
1468                                    const SMESH_PredicatePtr& thePredicate)
1469 {
1470   if (_mapGroup.count(_groupId))
1471     return NULL;
1472   theId = _groupId;
1473   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape, thePredicate);
1474   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1475   _mapGroup[_groupId++] = aGroup;
1476   return aGroup;
1477 }
1478
1479 //================================================================================
1480 /*!
1481  * \brief Creates SMESH_Groups for not wrapped SMESHDS_Groups
1482  *  \retval bool - true if new SMESH_Groups have been created
1483  * 
1484  */
1485 //================================================================================
1486
1487 bool SMESH_Mesh::SynchronizeGroups()
1488 {
1489   int nbGroups = _mapGroup.size();
1490   const set<SMESHDS_GroupBase*>& groups = _myMeshDS->GetGroups();
1491   set<SMESHDS_GroupBase*>::const_iterator gIt = groups.begin();
1492   for ( ; gIt != groups.end(); ++gIt )
1493   {
1494     SMESHDS_GroupBase* groupDS = (SMESHDS_GroupBase*) *gIt;
1495     _groupId = groupDS->GetID();
1496     if ( !_mapGroup.count( _groupId ))
1497       _mapGroup[_groupId] = new SMESH_Group( groupDS );
1498   }
1499   if ( !_mapGroup.empty() )
1500     _groupId = _mapGroup.rbegin()->first + 1;
1501
1502   return nbGroups < _mapGroup.size();
1503 }
1504
1505 //================================================================================
1506 /*!
1507  * \brief Return iterator on all existing groups
1508  */
1509 //================================================================================
1510
1511 SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
1512 {
1513   typedef map <int, SMESH_Group *> TMap;
1514   return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
1515 }
1516
1517 //=============================================================================
1518 /*!
1519  * \brief Return a group by ID
1520  */
1521 //=============================================================================
1522
1523 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1524 {
1525   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1526     return NULL;
1527   return _mapGroup[theGroupID];
1528 }
1529
1530
1531 //=============================================================================
1532 /*!
1533  * \brief Return IDs of all groups
1534  */
1535 //=============================================================================
1536
1537 list<int> SMESH_Mesh::GetGroupIds() const
1538 {
1539   list<int> anIds;
1540   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1541     anIds.push_back( it->first );
1542   
1543   return anIds;
1544 }
1545
1546 //================================================================================
1547 /*!
1548  * \brief Set a caller of RemoveGroup() at level of CORBA API implementation.
1549  * The set upCaller will be deleted by SMESH_Mesh
1550  */
1551 //================================================================================
1552
1553 void SMESH_Mesh::SetRemoveGroupCallUp( TRmGroupCallUp* upCaller )
1554 {
1555   if ( _rmGroupCallUp ) delete _rmGroupCallUp;
1556   _rmGroupCallUp = upCaller;
1557 }
1558
1559 //=============================================================================
1560 /*!
1561  *  
1562  */
1563 //=============================================================================
1564
1565 bool SMESH_Mesh::RemoveGroup (const int theGroupID)
1566 {
1567   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1568     return false;
1569   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1570   delete _mapGroup[theGroupID];
1571   _mapGroup.erase (theGroupID);
1572   if (_rmGroupCallUp)
1573     _rmGroupCallUp->RemoveGroup( theGroupID );
1574   return true;
1575 }
1576
1577 //=======================================================================
1578 //function : GetAncestors
1579 //purpose  : return list of ancestors of theSubShape in the order
1580 //           that lower dimention shapes come first.
1581 //=======================================================================
1582
1583 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1584 {
1585   if ( _mapAncestors.Contains( theS ) )
1586     return _mapAncestors.FindFromKey( theS );
1587
1588   static TopTools_ListOfShape emptyList;
1589   return emptyList;
1590 }
1591
1592 //=======================================================================
1593 //function : Dump
1594 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1595 //=======================================================================
1596
1597 ostream& SMESH_Mesh::Dump(ostream& save)
1598 {
1599   int clause = 0;
1600   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1601   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1602   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1603   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1604   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1605   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1606   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1607   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1608   {
1609     string orderStr = isQuadratic ? "quadratic" : "linear";
1610     SMDSAbs_ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1611
1612     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1613     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1614     if ( NbFaces(order) > 0 ) {
1615       int nb3 = NbTriangles(order);
1616       int nb4 = NbQuadrangles(order);
1617       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1618       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1619       if ( nb3 + nb4 !=  NbFaces(order) ) {
1620         map<int,int> myFaceMap;
1621         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1622         while( itFaces->more( ) ) {
1623           int nbNodes = itFaces->next()->NbNodes();
1624           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1625             myFaceMap[ nbNodes ] = 0;
1626           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1627         }
1628         save << clause << ".3) Faces in detail: " << endl;
1629         map <int,int>::iterator itF;
1630         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1631           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1632       }
1633     }
1634     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1635     if ( NbVolumes(order) > 0 ) {
1636       int nb8 = NbHexas(order);
1637       int nb4 = NbTetras(order);
1638       int nb5 = NbPyramids(order);
1639       int nb6 = NbPrisms(order);
1640       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1641       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1642       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1643       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1644       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1645         map<int,int> myVolumesMap;
1646         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1647         while( itVolumes->more( ) ) {
1648           int nbNodes = itVolumes->next()->NbNodes();
1649           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1650             myVolumesMap[ nbNodes ] = 0;
1651           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1652         }
1653         save << clause << ".5) Volumes in detail: " << endl;
1654         map <int,int>::iterator itV;
1655         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1656           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1657       }
1658     }
1659     save << endl;
1660   }
1661   save << "===========================================================================" << endl;
1662   return save;
1663 }
1664
1665 //=======================================================================
1666 //function : GetElementType
1667 //purpose  : Returns type of mesh element with certain id
1668 //=======================================================================
1669
1670 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1671 {
1672   return _myMeshDS->GetElementType( id, iselem );
1673 }
1674
1675 //=============================================================================
1676 /*!
1677  *  \brief Convert group on geometry into standalone group
1678  */
1679 //=============================================================================
1680
1681 SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
1682 {
1683   SMESH_Group* aGroup = 0;
1684   map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
1685   if ( itg == _mapGroup.end() )
1686     return aGroup;
1687
1688   SMESH_Group* anOldGrp = (*itg).second;
1689   SMESHDS_GroupBase* anOldGrpDS = anOldGrp->GetGroupDS();
1690   if ( !anOldGrp || !anOldGrpDS )
1691     return aGroup;
1692
1693   // create new standalone group
1694   aGroup = new SMESH_Group (theGroupID, this, anOldGrpDS->GetType(), anOldGrp->GetName() );
1695   _mapGroup[theGroupID] = aGroup;
1696
1697   SMESHDS_Group* aNewGrpDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
1698   GetMeshDS()->RemoveGroup( anOldGrpDS );
1699   GetMeshDS()->AddGroup( aNewGrpDS );
1700
1701   // add elements (or nodes) into new created group
1702   SMDS_ElemIteratorPtr anItr = anOldGrpDS->GetElements();
1703   while ( anItr->more() )
1704     aNewGrpDS->Add( (anItr->next())->GetID() );
1705
1706   // remove old group
1707   delete anOldGrp;
1708
1709   return aGroup;
1710 }
1711
1712 //=============================================================================
1713 /*!
1714  *  \brief remove submesh order  from Mesh
1715  */
1716 //=============================================================================
1717
1718 void SMESH_Mesh::ClearMeshOrder()
1719 {
1720   _mySubMeshOrder.clear();
1721 }
1722
1723 //=============================================================================
1724 /*!
1725  *  \brief remove submesh order  from Mesh
1726  */
1727 //=============================================================================
1728
1729 void SMESH_Mesh::SetMeshOrder(const TListOfListOfInt& theOrder )
1730 {
1731   _mySubMeshOrder = theOrder;
1732 }
1733
1734 //=============================================================================
1735 /*!
1736  *  \brief return submesh order if any
1737  */
1738 //=============================================================================
1739
1740 const TListOfListOfInt& SMESH_Mesh::GetMeshOrder() const
1741 {
1742   return _mySubMeshOrder;
1743 }
1744
1745 //=============================================================================
1746 /*!
1747  *  \brief fill _mapAncestors
1748  */
1749 //=============================================================================
1750
1751 void SMESH_Mesh::fillAncestorsMap(const TopoDS_Shape& theShape)
1752 {
1753
1754   int desType, ancType;
1755   if ( !theShape.IsSame( GetShapeToMesh()) && theShape.ShapeType() == TopAbs_COMPOUND )
1756   {
1757     // a geom group is added. Insert it into lists of ancestors before
1758     // the first ancestor more complex than group members
1759     int memberType = TopoDS_Iterator( theShape ).Value().ShapeType();
1760     for ( desType = TopAbs_VERTEX; desType >= memberType; desType-- )
1761       for (TopExp_Explorer des( theShape, TopAbs_ShapeEnum( desType )); des.More(); des.Next())
1762       {
1763         if ( !_mapAncestors.Contains( des.Current() )) continue;// issue 0020982
1764         TopTools_ListOfShape& ancList = _mapAncestors.ChangeFromKey( des.Current() );
1765         TopTools_ListIteratorOfListOfShape ancIt (ancList);
1766         while ( ancIt.More() && ancIt.Value().ShapeType() >= memberType )
1767           ancIt.Next();
1768         if ( ancIt.More() )
1769           ancList.InsertBefore( theShape, ancIt );
1770       }
1771   }
1772   {
1773     for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
1774       for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
1775         TopExp::MapShapesAndAncestors ( theShape,
1776                                         (TopAbs_ShapeEnum) desType,
1777                                         (TopAbs_ShapeEnum) ancType,
1778                                         _mapAncestors );
1779   }
1780 }
1781
1782 //=============================================================================
1783 /*!
1784  * \brief sort submeshes according to stored mesh order
1785  * \param theListToSort in out list to be sorted
1786  * \return FALSE if nothing sorted
1787  */
1788 //=============================================================================
1789
1790 bool SMESH_Mesh::SortByMeshOrder(list<SMESH_subMesh*>& theListToSort) const
1791 {
1792   if ( !_mySubMeshOrder.size() || theListToSort.size() < 2)
1793     return true;
1794   
1795   bool res = false;
1796   list<SMESH_subMesh*> onlyOrderedList;
1797   // collect all ordered submeshes in one list as pointers
1798   // and get their positions within theListToSort
1799   typedef list<SMESH_subMesh*>::iterator TPosInList;
1800   map< int, TPosInList > sortedPos;
1801   TPosInList smBeg = theListToSort.begin(), smEnd = theListToSort.end();
1802   TListOfListOfInt::const_iterator listIddIt = _mySubMeshOrder.begin();
1803   for( ; listIddIt != _mySubMeshOrder.end(); listIddIt++) {
1804     const TListOfInt& listOfId = *listIddIt;
1805     TListOfInt::const_iterator idIt = listOfId.begin();
1806     for ( ; idIt != listOfId.end(); idIt++ ) {
1807       if ( SMESH_subMesh * sm = GetSubMeshContaining( *idIt )) {
1808         TPosInList smPos = find( smBeg, smEnd, sm );
1809         if ( smPos != smEnd ) {
1810           onlyOrderedList.push_back( sm );
1811           sortedPos[ distance( smBeg, smPos )] = smPos;
1812         }
1813       }
1814     }
1815   }
1816   if (onlyOrderedList.size() < 2)
1817     return res;
1818   res = true;
1819
1820   list<SMESH_subMesh*>::iterator onlyBIt = onlyOrderedList.begin();
1821   list<SMESH_subMesh*>::iterator onlyEIt = onlyOrderedList.end();
1822
1823   // iterates on ordered submeshes and insert them in detected positions
1824   map< int, TPosInList >::iterator i_pos = sortedPos.begin();
1825   for ( ; onlyBIt != onlyEIt; ++onlyBIt, ++i_pos )
1826     *(i_pos->second) = *onlyBIt;
1827
1828   return res;
1829 }
1830
1831 //=============================================================================
1832 /*!
1833  * \brief sort submeshes according to stored mesh order
1834  * \param theListToSort in out list to be sorted
1835  * \return FALSE if nothing sorted
1836  */
1837 //=============================================================================
1838
1839 list<SMESH_subMesh*> SMESH_Mesh::getAncestorsSubMeshes
1840   (const TopoDS_Shape& theSubShape) const
1841 {
1842   list<SMESH_subMesh*> listOfSubMesh;
1843   TopTools_ListIteratorOfListOfShape it( GetAncestors( theSubShape ));
1844   for (; it.More(); it.Next() )
1845     if ( SMESH_subMesh* sm = GetSubMeshContaining( it.Value() ))
1846       listOfSubMesh.push_back(sm);
1847
1848   // sort submeshes according to stored mesh order
1849   SortByMeshOrder( listOfSubMesh );
1850
1851   return listOfSubMesh;
1852 }