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