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