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