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