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