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