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