Salome HOME
PAL16842 (Genertion of groups when a mesh is transformed)
[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
41 #include "utilities.h"
42
43 #include "DriverMED_W_SMESHDS_Mesh.h"
44 #include "DriverDAT_W_SMDS_Mesh.h"
45 #include "DriverUNV_W_SMDS_Mesh.h"
46 #include "DriverSTL_W_SMDS_Mesh.h"
47
48 #include "DriverMED_R_SMESHDS_Mesh.h"
49 #include "DriverUNV_R_SMDS_Mesh.h"
50 #include "DriverSTL_R_SMDS_Mesh.h"
51
52 #include <BRepPrimAPI_MakeBox.hxx>
53 #include <TopExp.hxx>
54 #include <TopExp_Explorer.hxx>
55 #include <TopTools_ListIteratorOfListOfShape.hxx>
56 #include <TopTools_ListOfShape.hxx>
57 #include <TopTools_MapOfShape.hxx>
58 #include <TopoDS_Iterator.hxx>
59
60 #include "Utils_ExceptHandlers.hxx"
61
62 // maximum stored group name length in MED file
63 #define MAX_MED_GROUP_NAME_LENGTH 80
64
65 #ifdef _DEBUG_
66 static int MYDEBUG = 0;
67 #else
68 static int MYDEBUG = 0;
69 #endif
70
71 #define cSMESH_Hyp(h) static_cast<const SMESH_Hypothesis*>(h)
72
73 typedef SMESH_HypoFilter THypType;
74
75 //=============================================================================
76 /*!
77  * 
78  */
79 //=============================================================================
80
81 SMESH_Mesh::SMESH_Mesh(int               theLocalId, 
82                        int               theStudyId, 
83                        SMESH_Gen*        theGen,
84                        bool              theIsEmbeddedMode,
85                        SMESHDS_Document* theDocument):
86   _groupId( 0 )
87 {
88   MESSAGE("SMESH_Mesh::SMESH_Mesh(int localId)");
89   _id            = theLocalId;
90   _studyId       = theStudyId;
91   _gen           = theGen;
92   _myDocument    = theDocument;
93   _idDoc         = theDocument->NewMesh(theIsEmbeddedMode);
94   _myMeshDS      = theDocument->GetMesh(_idDoc);
95   _isShapeToMesh = false;
96   _isAutoColor   = 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 = false;
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 = false;
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 = false;
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 /*!
905  *  Auto color functionality
906  */
907 //=============================================================================
908 void SMESH_Mesh::SetAutoColor(bool theAutoColor) throw(SALOME_Exception)
909 {
910   Unexpect aCatch(SalomeException);
911   _isAutoColor = theAutoColor;
912 }
913
914 bool SMESH_Mesh::GetAutoColor() throw(SALOME_Exception)
915 {
916   Unexpect aCatch(SalomeException);
917   return _isAutoColor;
918 }
919
920 //=============================================================================
921 /*! Export* methods.
922  *  To store mesh contents on disk in different formats.
923  */
924 //=============================================================================
925
926 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
927 {
928   set<string> aGroupNames;
929   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
930     SMESH_Group* aGroup = it->second;
931     string aGroupName = aGroup->GetName();
932     aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
933     if (!aGroupNames.insert(aGroupName).second)
934       return true;
935   }
936
937   return false;
938 }
939
940 void SMESH_Mesh::ExportMED(const char *file, 
941                            const char* theMeshName, 
942                            bool theAutoGroups,
943                            int theVersion) 
944   throw(SALOME_Exception)
945 {
946   Unexpect aCatch(SalomeException);
947
948   DriverMED_W_SMESHDS_Mesh myWriter;
949   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
950   myWriter.SetMesh    ( _myMeshDS   );
951   if ( !theMeshName ) 
952     myWriter.SetMeshId  ( _idDoc      );
953   else {
954     myWriter.SetMeshId  ( -1          );
955     myWriter.SetMeshName( theMeshName );
956   }
957
958   if ( theAutoGroups ) {
959     myWriter.AddGroupOfNodes();
960     myWriter.AddGroupOfEdges();
961     myWriter.AddGroupOfFaces();
962     myWriter.AddGroupOfVolumes();
963   }
964
965   // Pass groups to writer. Provide unique group names.
966   set<string> aGroupNames;
967   char aString [256];
968   int maxNbIter = 10000; // to guarantee cycle finish
969   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
970     SMESH_Group*       aGroup   = it->second;
971     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
972     if ( aGroupDS ) {
973       string aGroupName0 = aGroup->GetName();
974       aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
975       string aGroupName = aGroupName0;
976       for (int i = 1; !aGroupNames.insert(aGroupName).second && i < maxNbIter; i++) {
977         sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
978         aGroupName = aString;
979         aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
980       }
981       aGroupDS->SetStoreName( aGroupName.c_str() );
982       myWriter.AddGroup( aGroupDS );
983     }
984   }
985
986   // Perform export
987   myWriter.Perform();
988 }
989
990 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
991 {
992   Unexpect aCatch(SalomeException);
993   DriverDAT_W_SMDS_Mesh myWriter;
994   myWriter.SetFile(string(file));
995   myWriter.SetMesh(_myMeshDS);
996   myWriter.SetMeshId(_idDoc);
997   myWriter.Perform();
998 }
999
1000 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
1001 {
1002   Unexpect aCatch(SalomeException);
1003   DriverUNV_W_SMDS_Mesh myWriter;
1004   myWriter.SetFile(string(file));
1005   myWriter.SetMesh(_myMeshDS);
1006   myWriter.SetMeshId(_idDoc);
1007   //  myWriter.SetGroups(_mapGroup);
1008
1009   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1010     SMESH_Group*       aGroup   = it->second;
1011     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1012     if ( aGroupDS ) {
1013       string aGroupName = aGroup->GetName();
1014       aGroupDS->SetStoreName( aGroupName.c_str() );
1015       myWriter.AddGroup( aGroupDS );
1016     }
1017   }
1018   myWriter.Perform();
1019 }
1020
1021 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
1022 {
1023   Unexpect aCatch(SalomeException);
1024   DriverSTL_W_SMDS_Mesh myWriter;
1025   myWriter.SetFile(string(file));
1026   myWriter.SetIsAscii( isascii );
1027   myWriter.SetMesh(_myMeshDS);
1028   myWriter.SetMeshId(_idDoc);
1029   myWriter.Perform();
1030 }
1031
1032 //================================================================================
1033 /*!
1034  * \brief Return number of nodes in the mesh
1035  */
1036 //================================================================================
1037
1038 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
1039 {
1040   Unexpect aCatch(SalomeException);
1041   return _myMeshDS->NbNodes();
1042 }
1043
1044 //================================================================================
1045 /*!
1046  * \brief  Return number of edges of given order in the mesh
1047  */
1048 //================================================================================
1049
1050 int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1051 {
1052   Unexpect aCatch(SalomeException);
1053   return _myMeshDS->GetMeshInfo().NbEdges(order);
1054 }
1055
1056 //================================================================================
1057 /*!
1058  * \brief Return number of faces of given order in the mesh
1059  */
1060 //================================================================================
1061
1062 int SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1063 {
1064   Unexpect aCatch(SalomeException);
1065   return _myMeshDS->GetMeshInfo().NbFaces(order);
1066 }
1067
1068 //================================================================================
1069 /*!
1070  * \brief Return the number of faces in the mesh
1071  */
1072 //================================================================================
1073
1074 int SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1075 {
1076   Unexpect aCatch(SalomeException);
1077   return _myMeshDS->GetMeshInfo().NbTriangles(order);
1078 }
1079
1080 //================================================================================
1081 /*!
1082  * \brief Return the number nodes faces in the mesh
1083  */
1084 //================================================================================
1085
1086 int SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1087 {
1088   Unexpect aCatch(SalomeException);
1089   return _myMeshDS->GetMeshInfo().NbQuadrangles(order);
1090 }
1091
1092 //================================================================================
1093 /*!
1094  * \brief Return the number of polygonal faces in the mesh
1095  */
1096 //================================================================================
1097
1098 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
1099 {
1100   Unexpect aCatch(SalomeException);
1101   return _myMeshDS->GetMeshInfo().NbPolygons();
1102 }
1103
1104 //================================================================================
1105 /*!
1106  * \brief Return number of volumes of given order in the mesh
1107  */
1108 //================================================================================
1109
1110 int SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1111 {
1112   Unexpect aCatch(SalomeException);
1113   return _myMeshDS->GetMeshInfo().NbVolumes(order);
1114 }
1115
1116 //================================================================================
1117 /*!
1118  * \brief  Return number of tetrahedrons of given order in the mesh
1119  */
1120 //================================================================================
1121
1122 int SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1123 {
1124   Unexpect aCatch(SalomeException);
1125   return _myMeshDS->GetMeshInfo().NbTetras(order);
1126 }
1127
1128 //================================================================================
1129 /*!
1130  * \brief  Return number of hexahedrons of given order in the mesh
1131  */
1132 //================================================================================
1133
1134 int SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1135 {
1136   Unexpect aCatch(SalomeException);
1137   return _myMeshDS->GetMeshInfo().NbHexas(order);
1138 }
1139
1140 //================================================================================
1141 /*!
1142  * \brief  Return number of pyramids of given order in the mesh
1143  */
1144 //================================================================================
1145
1146 int SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1147 {
1148   Unexpect aCatch(SalomeException);
1149   return _myMeshDS->GetMeshInfo().NbPyramids(order);
1150 }
1151
1152 //================================================================================
1153 /*!
1154  * \brief  Return number of prisms (penthahedrons) of given order in the mesh
1155  */
1156 //================================================================================
1157
1158 int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1159 {
1160   Unexpect aCatch(SalomeException);
1161   return _myMeshDS->GetMeshInfo().NbPrisms(order);
1162 }
1163
1164 //================================================================================
1165 /*!
1166  * \brief  Return number of polyhedrons in the mesh
1167  */
1168 //================================================================================
1169
1170 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
1171 {
1172   Unexpect aCatch(SalomeException);
1173   return _myMeshDS->GetMeshInfo().NbPolyhedrons();
1174 }
1175
1176 //================================================================================
1177 /*!
1178  * \brief  Return number of submeshes in the mesh
1179  */
1180 //================================================================================
1181
1182 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
1183 {
1184   Unexpect aCatch(SalomeException);
1185   return _myMeshDS->NbSubMesh();
1186 }
1187
1188 //=======================================================================
1189 //function : IsNotConformAllowed
1190 //purpose  : check if a hypothesis alowing notconform mesh is present
1191 //=======================================================================
1192
1193 bool SMESH_Mesh::IsNotConformAllowed() const
1194 {
1195   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1196
1197   static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1198   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1199 }
1200
1201 //=======================================================================
1202 //function : IsMainShape
1203 //purpose  : 
1204 //=======================================================================
1205
1206 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1207 {
1208   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1209 }
1210
1211 //=============================================================================
1212 /*!
1213  *  
1214  */
1215 //=============================================================================
1216
1217 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1218                                    const char*               theName,
1219                                    int&                      theId,
1220                                    const TopoDS_Shape&       theShape)
1221 {
1222   if (_mapGroup.find(_groupId) != _mapGroup.end())
1223     return NULL;
1224   theId = _groupId;
1225   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
1226   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1227   _mapGroup[_groupId++] = aGroup;
1228   return aGroup;
1229 }
1230
1231 //=============================================================================
1232 /*!
1233  *  
1234  */
1235 //=============================================================================
1236
1237 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1238 {
1239   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1240     return NULL;
1241   return _mapGroup[theGroupID];
1242 }
1243
1244
1245 //=============================================================================
1246 /*!
1247  *  
1248  */
1249 //=============================================================================
1250
1251 list<int> SMESH_Mesh::GetGroupIds()
1252 {
1253   list<int> anIds;
1254   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1255     anIds.push_back( it->first );
1256   
1257   return anIds;
1258 }
1259
1260
1261 //=============================================================================
1262 /*!
1263  *  
1264  */
1265 //=============================================================================
1266
1267 void SMESH_Mesh::RemoveGroup (const int theGroupID)
1268 {
1269   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1270     return;
1271   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1272   delete _mapGroup[theGroupID];
1273   _mapGroup.erase (theGroupID);
1274 }
1275
1276 //=======================================================================
1277 //function : GetAncestors
1278 //purpose  : return list of ancestors of theSubShape in the order
1279 //           that lower dimention shapes come first.
1280 //=======================================================================
1281
1282 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1283 {
1284   if ( _mapAncestors.Contains( theS ) )
1285     return _mapAncestors.FindFromKey( theS );
1286
1287   static TopTools_ListOfShape emptyList;
1288   return emptyList;
1289 }
1290
1291 //=======================================================================
1292 //function : Dump
1293 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1294 //=======================================================================
1295
1296 ostream& SMESH_Mesh::Dump(ostream& save)
1297 {
1298   int clause = 0;
1299   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1300   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1301   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1302   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1303   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1304   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1305   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1306   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1307   {
1308     string orderStr = isQuadratic ? "quadratic" : "linear";
1309     SMDSAbs_ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1310
1311     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1312     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1313     if ( NbFaces(order) > 0 ) {
1314       int nb3 = NbTriangles(order);
1315       int nb4 = NbQuadrangles(order);
1316       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1317       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1318       if ( nb3 + nb4 !=  NbFaces(order) ) {
1319         map<int,int> myFaceMap;
1320         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1321         while( itFaces->more( ) ) {
1322           int nbNodes = itFaces->next()->NbNodes();
1323           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1324             myFaceMap[ nbNodes ] = 0;
1325           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1326         }
1327         save << clause << ".3) Faces in detail: " << endl;
1328         map <int,int>::iterator itF;
1329         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1330           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1331       }
1332     }
1333     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1334     if ( NbVolumes(order) > 0 ) {
1335       int nb8 = NbHexas(order);
1336       int nb4 = NbTetras(order);
1337       int nb5 = NbPyramids(order);
1338       int nb6 = NbPrisms(order);
1339       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1340       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1341       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1342       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1343       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1344         map<int,int> myVolumesMap;
1345         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1346         while( itVolumes->more( ) ) {
1347           int nbNodes = itVolumes->next()->NbNodes();
1348           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1349             myVolumesMap[ nbNodes ] = 0;
1350           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1351         }
1352         save << clause << ".5) Volumes in detail: " << endl;
1353         map <int,int>::iterator itV;
1354         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1355           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1356       }
1357     }
1358     save << endl;
1359   }
1360   save << "===========================================================================" << endl;
1361   return save;
1362 }
1363
1364 //=======================================================================
1365 //function : GetElementType
1366 //purpose  : Returns type of mesh element with certain id
1367 //=======================================================================
1368
1369 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1370 {
1371   return _myMeshDS->GetElementType( id, iselem );
1372 }