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