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