Salome HOME
correct previous integration (Porting to Python 2.6)
[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     {
843       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
844       if ( index > _nbSubShapes ) _nbSubShapes = index; // not to create sm for this group again
845     }
846   }
847 //   if ( !index )
848 //     return NULL; // neither sub-shape nor a group
849
850   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
851   if ( i_sm != _mapSubMesh.end())
852   {
853     aSubMesh = i_sm->second;
854   }
855   else
856   {
857     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
858     _mapSubMesh[index] = aSubMesh;
859   }
860   return aSubMesh;
861 }
862
863 //=============================================================================
864 /*!
865  * Get the SMESH_subMesh object implementation. Dont create it, return null
866  * if it does not exist.
867  */
868 //=============================================================================
869
870 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape) const
871   throw(SALOME_Exception)
872 {
873   Unexpect aCatch(SalomeException);
874   SMESH_subMesh *aSubMesh = NULL;
875   
876   int index = _myMeshDS->ShapeToIndex(aSubShape);
877
878   map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(index);
879   if ( i_sm != _mapSubMesh.end())
880     aSubMesh = i_sm->second;
881
882   return aSubMesh;
883 }
884 //=============================================================================
885 /*!
886  * Get the SMESH_subMesh object implementation. Dont create it, return null
887  * if it does not exist.
888  */
889 //=============================================================================
890
891 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) const
892 throw(SALOME_Exception)
893 {
894   Unexpect aCatch(SalomeException);
895   
896   map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(aShapeID);
897   if (i_sm == _mapSubMesh.end())
898     return NULL;
899   return i_sm->second;
900 }
901 //================================================================================
902 /*!
903  * \brief Return submeshes of groups containing the given subshape
904  */
905 //================================================================================
906
907 std::list<SMESH_subMesh*>
908 SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
909   throw(SALOME_Exception)
910 {
911   Unexpect aCatch(SalomeException);
912   std::list<SMESH_subMesh*> found;
913
914   SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
915   if ( !subMesh )
916     return found;
917
918   // submeshes of groups have max IDs, so search from the map end
919   std::map<int, SMESH_subMesh *>::const_reverse_iterator i_sm;
920   for ( i_sm = _mapSubMesh.rbegin(); i_sm != _mapSubMesh.rend(); ++i_sm) {
921     SMESHDS_SubMesh * ds = i_sm->second->GetSubMeshDS();
922     if ( ds && ds->IsComplexSubmesh() ) {
923       TopExp_Explorer exp( i_sm->second->GetSubShape(), aSubShape.ShapeType() );
924       for ( ; exp.More(); exp.Next() ) {
925         if ( aSubShape.IsSame( exp.Current() )) {
926           found.push_back( i_sm->second );
927           break;
928         }
929       }
930     } else {
931       break;
932     }
933   }
934   return found;
935 }
936 //=======================================================================
937 //function : IsUsedHypothesis
938 //purpose  : Return True if anHyp is used to mesh aSubShape
939 //=======================================================================
940
941 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
942                                   const SMESH_subMesh* aSubMesh)
943 {
944   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
945
946   // check if anHyp can be used to mesh aSubMesh
947   if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
948     return false;
949
950   const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
951
952   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
953
954   // algorithm
955   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
956     return ( anHyp == algo );
957
958   // algorithm parameter
959   if (algo)
960   {
961     // look trough hypotheses used by algo
962     SMESH_HypoFilter hypoKind;
963     if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
964       list <const SMESHDS_Hypothesis * > usedHyps;
965       if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
966         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
967     }
968   }
969
970   // look through all assigned hypotheses
971   //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
972   return false; //GetHypothesis( aSubShape, filter, true );
973 }
974
975 //=============================================================================
976 /*!
977  *
978  */
979 //=============================================================================
980
981 const list < SMESH_subMesh * >&
982 SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
983   throw(SALOME_Exception)
984 {
985   Unexpect aCatch(SalomeException);
986   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
987   map < int, SMESH_subMesh * >::iterator itsm;
988   _subMeshesUsingHypothesisList.clear();
989   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
990   {
991     SMESH_subMesh *aSubMesh = (*itsm).second;
992     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
993       _subMeshesUsingHypothesisList.push_back(aSubMesh);
994   }
995   return _subMeshesUsingHypothesisList;
996 }
997
998 //=======================================================================
999 //function : NotifySubMeshesHypothesisModification
1000 //purpose  : Say all submeshes using theChangedHyp that it has been modified
1001 //=======================================================================
1002
1003 void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp)
1004 {
1005   Unexpect aCatch(SalomeException);
1006
1007   const SMESH_Algo *foundAlgo = 0;
1008   SMESH_HypoFilter algoKind, compatibleHypoKind;
1009   list <const SMESHDS_Hypothesis * > usedHyps;
1010
1011
1012   map < int, SMESH_subMesh * >::iterator itsm;
1013   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
1014   {
1015     SMESH_subMesh *aSubMesh = (*itsm).second;
1016     if ( aSubMesh->IsApplicableHypotesis( hyp ))
1017     {
1018       const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
1019
1020       if ( !foundAlgo ) // init filter for algo search
1021         algoKind.Init( THypType::IsAlgo() ).And( THypType::IsApplicableTo( aSubShape ));
1022       
1023       const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
1024         ( GetHypothesis( aSubShape, algoKind, true ));
1025
1026       if ( algo )
1027       {
1028         bool sameAlgo = ( algo == foundAlgo );
1029         if ( !sameAlgo && foundAlgo )
1030           sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
1031
1032         if ( !sameAlgo ) { // init filter for used hypos search
1033           if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
1034             continue; // algo does not use any hypothesis
1035           foundAlgo = algo;
1036         }
1037
1038         // check if hyp is used by algo
1039         usedHyps.clear();
1040         if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
1041              find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
1042         {
1043           aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
1044                                     const_cast< SMESH_Hypothesis*>( hyp ));
1045         }
1046       }
1047     }
1048   }
1049 }
1050
1051 //=============================================================================
1052 /*!
1053  *  Auto color functionality
1054  */
1055 //=============================================================================
1056 void SMESH_Mesh::SetAutoColor(bool theAutoColor) throw(SALOME_Exception)
1057 {
1058   Unexpect aCatch(SalomeException);
1059   _isAutoColor = theAutoColor;
1060 }
1061
1062 bool SMESH_Mesh::GetAutoColor() throw(SALOME_Exception)
1063 {
1064   Unexpect aCatch(SalomeException);
1065   return _isAutoColor;
1066 }
1067
1068 //=============================================================================
1069 /*! Export* methods.
1070  *  To store mesh contents on disk in different formats.
1071  */
1072 //=============================================================================
1073
1074 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
1075 {
1076   set<string> aGroupNames;
1077   for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1078     SMESH_Group* aGroup = it->second;
1079     std::string aGroupName = aGroup->GetName();
1080     aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
1081     if (!aGroupNames.insert(aGroupName).second)
1082       return true;
1083   }
1084
1085   return false;
1086 }
1087
1088 void SMESH_Mesh::ExportMED(const char *file, 
1089                            const char* theMeshName, 
1090                            bool theAutoGroups,
1091                            int theVersion) 
1092   throw(SALOME_Exception)
1093 {
1094   Unexpect aCatch(SalomeException);
1095
1096   DriverMED_W_SMESHDS_Mesh myWriter;
1097   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
1098   myWriter.SetMesh    ( _myMeshDS   );
1099   if ( !theMeshName ) 
1100     myWriter.SetMeshId  ( _idDoc      );
1101   else {
1102     myWriter.SetMeshId  ( -1          );
1103     myWriter.SetMeshName( theMeshName );
1104   }
1105
1106   if ( theAutoGroups ) {
1107     myWriter.AddGroupOfNodes();
1108     myWriter.AddGroupOfEdges();
1109     myWriter.AddGroupOfFaces();
1110     myWriter.AddGroupOfVolumes();
1111   }
1112
1113   // Pass groups to writer. Provide unique group names.
1114   set<string> aGroupNames;
1115   char aString [256];
1116   int maxNbIter = 10000; // to guarantee cycle finish
1117   for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1118     SMESH_Group*       aGroup   = it->second;
1119     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1120     if ( aGroupDS ) {
1121       string aGroupName0 = aGroup->GetName();
1122       aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
1123       string aGroupName = aGroupName0;
1124       for (int i = 1; !aGroupNames.insert(aGroupName).second && i < maxNbIter; i++) {
1125         sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
1126         aGroupName = aString;
1127         aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
1128       }
1129       aGroupDS->SetStoreName( aGroupName.c_str() );
1130       myWriter.AddGroup( aGroupDS );
1131     }
1132   }
1133
1134   // Perform export
1135   myWriter.Perform();
1136 }
1137
1138 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
1139 {
1140   Unexpect aCatch(SalomeException);
1141   DriverDAT_W_SMDS_Mesh myWriter;
1142   myWriter.SetFile(string(file));
1143   myWriter.SetMesh(_myMeshDS);
1144   myWriter.SetMeshId(_idDoc);
1145   myWriter.Perform();
1146 }
1147
1148 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
1149 {
1150   Unexpect aCatch(SalomeException);
1151   DriverUNV_W_SMDS_Mesh myWriter;
1152   myWriter.SetFile(string(file));
1153   myWriter.SetMesh(_myMeshDS);
1154   myWriter.SetMeshId(_idDoc);
1155   //  myWriter.SetGroups(_mapGroup);
1156
1157   for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1158     SMESH_Group*       aGroup   = it->second;
1159     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1160     if ( aGroupDS ) {
1161       std::string aGroupName = aGroup->GetName();
1162       aGroupDS->SetStoreName( aGroupName.c_str() );
1163       myWriter.AddGroup( aGroupDS );
1164     }
1165   }
1166   myWriter.Perform();
1167 }
1168
1169 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
1170 {
1171   Unexpect aCatch(SalomeException);
1172   DriverSTL_W_SMDS_Mesh myWriter;
1173   myWriter.SetFile(string(file));
1174   myWriter.SetIsAscii( isascii );
1175   myWriter.SetMesh(_myMeshDS);
1176   myWriter.SetMeshId(_idDoc);
1177   myWriter.Perform();
1178 }
1179
1180 //================================================================================
1181 /*!
1182  * \brief Return number of nodes in the mesh
1183  */
1184 //================================================================================
1185
1186 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
1187 {
1188   Unexpect aCatch(SalomeException);
1189   return _myMeshDS->NbNodes();
1190 }
1191
1192 //================================================================================
1193 /*!
1194  * \brief  Return number of edges of given order in the mesh
1195  */
1196 //================================================================================
1197
1198 int SMESH_Mesh::Nb0DElements() throw(SALOME_Exception)
1199 {
1200   Unexpect aCatch(SalomeException);
1201   return _myMeshDS->GetMeshInfo().Nb0DElements();
1202 }
1203
1204 //================================================================================
1205 /*!
1206  * \brief  Return number of edges of given order in the mesh
1207  */
1208 //================================================================================
1209
1210 int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1211 {
1212   Unexpect aCatch(SalomeException);
1213   return _myMeshDS->GetMeshInfo().NbEdges(order);
1214 }
1215
1216 //================================================================================
1217 /*!
1218  * \brief Return number of faces of given order in the mesh
1219  */
1220 //================================================================================
1221
1222 int SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1223 {
1224   Unexpect aCatch(SalomeException);
1225   return _myMeshDS->GetMeshInfo().NbFaces(order);
1226 }
1227
1228 //================================================================================
1229 /*!
1230  * \brief Return the number of faces in the mesh
1231  */
1232 //================================================================================
1233
1234 int SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1235 {
1236   Unexpect aCatch(SalomeException);
1237   return _myMeshDS->GetMeshInfo().NbTriangles(order);
1238 }
1239
1240 //================================================================================
1241 /*!
1242  * \brief Return the number nodes faces in the mesh
1243  */
1244 //================================================================================
1245
1246 int SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1247 {
1248   Unexpect aCatch(SalomeException);
1249   return _myMeshDS->GetMeshInfo().NbQuadrangles(order);
1250 }
1251
1252 //================================================================================
1253 /*!
1254  * \brief Return the number of polygonal faces in the mesh
1255  */
1256 //================================================================================
1257
1258 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
1259 {
1260   Unexpect aCatch(SalomeException);
1261   return _myMeshDS->GetMeshInfo().NbPolygons();
1262 }
1263
1264 //================================================================================
1265 /*!
1266  * \brief Return number of volumes of given order in the mesh
1267  */
1268 //================================================================================
1269
1270 int SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1271 {
1272   Unexpect aCatch(SalomeException);
1273   return _myMeshDS->GetMeshInfo().NbVolumes(order);
1274 }
1275
1276 //================================================================================
1277 /*!
1278  * \brief  Return number of tetrahedrons of given order in the mesh
1279  */
1280 //================================================================================
1281
1282 int SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1283 {
1284   Unexpect aCatch(SalomeException);
1285   return _myMeshDS->GetMeshInfo().NbTetras(order);
1286 }
1287
1288 //================================================================================
1289 /*!
1290  * \brief  Return number of hexahedrons of given order in the mesh
1291  */
1292 //================================================================================
1293
1294 int SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1295 {
1296   Unexpect aCatch(SalomeException);
1297   return _myMeshDS->GetMeshInfo().NbHexas(order);
1298 }
1299
1300 //================================================================================
1301 /*!
1302  * \brief  Return number of pyramids of given order in the mesh
1303  */
1304 //================================================================================
1305
1306 int SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1307 {
1308   Unexpect aCatch(SalomeException);
1309   return _myMeshDS->GetMeshInfo().NbPyramids(order);
1310 }
1311
1312 //================================================================================
1313 /*!
1314  * \brief  Return number of prisms (penthahedrons) of given order in the mesh
1315  */
1316 //================================================================================
1317
1318 int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1319 {
1320   Unexpect aCatch(SalomeException);
1321   return _myMeshDS->GetMeshInfo().NbPrisms(order);
1322 }
1323
1324 //================================================================================
1325 /*!
1326  * \brief  Return number of polyhedrons in the mesh
1327  */
1328 //================================================================================
1329
1330 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
1331 {
1332   Unexpect aCatch(SalomeException);
1333   return _myMeshDS->GetMeshInfo().NbPolyhedrons();
1334 }
1335
1336 //================================================================================
1337 /*!
1338  * \brief  Return number of submeshes in the mesh
1339  */
1340 //================================================================================
1341
1342 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
1343 {
1344   Unexpect aCatch(SalomeException);
1345   return _myMeshDS->NbSubMesh();
1346 }
1347
1348 //=======================================================================
1349 //function : IsNotConformAllowed
1350 //purpose  : check if a hypothesis alowing notconform mesh is present
1351 //=======================================================================
1352
1353 bool SMESH_Mesh::IsNotConformAllowed() const
1354 {
1355   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1356
1357   static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1358   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1359 }
1360
1361 //=======================================================================
1362 //function : IsMainShape
1363 //purpose  : 
1364 //=======================================================================
1365
1366 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1367 {
1368   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1369 }
1370
1371 //=============================================================================
1372 /*!
1373  *  
1374  */
1375 //=============================================================================
1376
1377 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1378                                    const char*               theName,
1379                                    int&                      theId,
1380                                    const TopoDS_Shape&       theShape)
1381 {
1382   if (_mapGroup.find(_groupId) != _mapGroup.end())
1383     return NULL;
1384   theId = _groupId;
1385   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
1386   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1387   _mapGroup[_groupId++] = aGroup;
1388   return aGroup;
1389 }
1390
1391 //================================================================================
1392 /*!
1393  * \brief Return iterator on all existing groups
1394  */
1395 //================================================================================
1396
1397 SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
1398 {
1399   typedef map <int, SMESH_Group *> TMap;
1400   return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
1401 }
1402
1403 //=============================================================================
1404 /*!
1405  * \brief Return a group by ID
1406  */
1407 //=============================================================================
1408
1409 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1410 {
1411   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1412     return NULL;
1413   return _mapGroup[theGroupID];
1414 }
1415
1416
1417 //=============================================================================
1418 /*!
1419  * \brief Return IDs of all groups
1420  */
1421 //=============================================================================
1422
1423 std::list<int> SMESH_Mesh::GetGroupIds() const
1424 {
1425   std::list<int> anIds;
1426   for ( std::map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1427     anIds.push_back( it->first );
1428   
1429   return anIds;
1430 }
1431
1432
1433 //=============================================================================
1434 /*!
1435  *  
1436  */
1437 //=============================================================================
1438
1439 void SMESH_Mesh::RemoveGroup (const int theGroupID)
1440 {
1441   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1442     return;
1443   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1444   delete _mapGroup[theGroupID];
1445   _mapGroup.erase (theGroupID);
1446 }
1447
1448 //=======================================================================
1449 //function : GetAncestors
1450 //purpose  : return list of ancestors of theSubShape in the order
1451 //           that lower dimention shapes come first.
1452 //=======================================================================
1453
1454 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1455 {
1456   if ( _mapAncestors.Contains( theS ) )
1457     return _mapAncestors.FindFromKey( theS );
1458
1459   static TopTools_ListOfShape emptyList;
1460   return emptyList;
1461 }
1462
1463 //=======================================================================
1464 //function : Dump
1465 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1466 //=======================================================================
1467
1468 ostream& SMESH_Mesh::Dump(ostream& save)
1469 {
1470   int clause = 0;
1471   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1472   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1473   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1474   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1475   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1476   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1477   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1478   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1479   {
1480     string orderStr = isQuadratic ? "quadratic" : "linear";
1481     SMDSAbs_ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1482
1483     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1484     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1485     if ( NbFaces(order) > 0 ) {
1486       int nb3 = NbTriangles(order);
1487       int nb4 = NbQuadrangles(order);
1488       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1489       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1490       if ( nb3 + nb4 !=  NbFaces(order) ) {
1491         std::map<int,int> myFaceMap;
1492         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1493         while( itFaces->more( ) ) {
1494           int nbNodes = itFaces->next()->NbNodes();
1495           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1496             myFaceMap[ nbNodes ] = 0;
1497           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1498         }
1499         save << clause << ".3) Faces in detail: " << endl;
1500         map <int,int>::iterator itF;
1501         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1502           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1503       }
1504     }
1505     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1506     if ( NbVolumes(order) > 0 ) {
1507       int nb8 = NbHexas(order);
1508       int nb4 = NbTetras(order);
1509       int nb5 = NbPyramids(order);
1510       int nb6 = NbPrisms(order);
1511       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1512       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1513       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1514       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1515       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1516         std::map<int,int> myVolumesMap;
1517         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1518         while( itVolumes->more( ) ) {
1519           int nbNodes = itVolumes->next()->NbNodes();
1520           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1521             myVolumesMap[ nbNodes ] = 0;
1522           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1523         }
1524         save << clause << ".5) Volumes in detail: " << endl;
1525         map <int,int>::iterator itV;
1526         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1527           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1528       }
1529     }
1530     save << endl;
1531   }
1532   save << "===========================================================================" << endl;
1533   return save;
1534 }
1535
1536 //=======================================================================
1537 //function : GetElementType
1538 //purpose  : Returns type of mesh element with certain id
1539 //=======================================================================
1540
1541 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1542 {
1543   return _myMeshDS->GetElementType( id, iselem );
1544 }
1545
1546 //=============================================================================
1547 /*!
1548  *  \brief Convert group on geometry into standalone group
1549  */
1550 //=============================================================================
1551
1552 SMESH_Group* SMESH_Mesh::ConvertToStandalone ( int theGroupID )
1553 {
1554   SMESH_Group* aGroup = 0;
1555   std::map < int, SMESH_Group * >::iterator itg = _mapGroup.find( theGroupID );
1556   if ( itg == _mapGroup.end() )
1557     return aGroup;
1558
1559   SMESH_Group* anOldGrp = (*itg).second;
1560   SMESHDS_GroupBase* anOldGrpDS = anOldGrp->GetGroupDS();
1561   if ( !anOldGrp || !anOldGrpDS )
1562     return aGroup;
1563
1564   // create new standalone group
1565   aGroup = new SMESH_Group (theGroupID, this, anOldGrpDS->GetType(), anOldGrp->GetName() );
1566   _mapGroup[theGroupID] = aGroup;
1567
1568   SMESHDS_Group* aNewGrpDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
1569   GetMeshDS()->RemoveGroup( anOldGrpDS );
1570   GetMeshDS()->AddGroup( aNewGrpDS );
1571
1572   // add elements (or nodes) into new created group
1573   SMDS_ElemIteratorPtr anItr = anOldGrpDS->GetElements();
1574   while ( anItr->more() )
1575     aNewGrpDS->Add( (anItr->next())->GetID() );
1576
1577   // remove old group
1578   delete anOldGrp;
1579
1580   return aGroup;
1581 }
1582