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