]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH/SMESH_Mesh.cxx
Salome HOME
[SALOME platform 0013410]: SubMesh not taken into account with Netgen 1D-2D et 1D...
[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  *  \param assignedTo   - to return the shape the found hypo is assigned to
603  *  \retval SMESH_Hypothesis* - the first hypo passed through aFilter
604  */
605 //=======================================================================
606
607 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubShape,
608                                                    const SMESH_HypoFilter& aFilter,
609                                                    const bool              andAncestors,
610                                                    TopoDS_Shape*           assignedTo) const
611 {
612   {
613     const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
614     std::list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
615     for ( ; hyp != hypList.end(); hyp++ ) {
616       const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
617       if ( aFilter.IsOk( h, aSubShape)) {
618         if ( assignedTo ) *assignedTo = aSubShape;
619         return h;
620       }
621     }
622   }
623   if ( andAncestors )
624   {
625     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
626     for (; it.More(); it.Next() )
627     {
628       const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
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, it.Value() )) {
633           if ( assignedTo ) *assignedTo = it.Value();
634           return h;
635         }
636       }
637     }
638   }
639   return 0;
640 }
641
642 //================================================================================
643 /*!
644  * \brief Return hypothesis assigned to the shape
645   * \param aSubShape - the shape to check
646   * \param aFilter - the hypothesis filter
647   * \param aHypList - the list of the found hypotheses
648   * \param andAncestors - flag to check hypos assigned to ancestors of the shape
649   * \retval int - number of unique hypos in aHypList
650  */
651 //================================================================================
652
653 int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
654                               const SMESH_HypoFilter&             aFilter,
655                               list <const SMESHDS_Hypothesis * >& aHypList,
656                               const bool                          andAncestors) const
657 {
658   set<string> hypTypes; // to exclude same type hypos from the result list
659   int nbHyps = 0;
660
661   // only one main hypothesis is allowed
662   bool mainHypFound = false;
663
664   // fill in hypTypes
665   std::list<const SMESHDS_Hypothesis*>::const_iterator hyp;
666   for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ ) {
667     if ( hypTypes.insert( (*hyp)->GetName() ).second )
668       nbHyps++;
669     if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
670       mainHypFound = true;
671   }
672
673   // get hypos from aSubShape
674   {
675     const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
676     for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
677       if ( aFilter.IsOk (cSMESH_Hyp( *hyp ), aSubShape) &&
678            ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
679            hypTypes.insert( (*hyp)->GetName() ).second )
680       {
681         aHypList.push_back( *hyp );
682         nbHyps++;
683         if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
684           mainHypFound = true;
685       }
686   }
687
688   // get hypos from ancestors of aSubShape
689   if ( andAncestors )
690   {
691     TopTools_MapOfShape map;
692     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
693     for (; it.More(); it.Next() )
694     {
695      if ( !map.Add( it.Value() ))
696         continue;
697       const std::list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
698       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
699         if (aFilter.IsOk( cSMESH_Hyp( *hyp ), it.Value() ) &&
700             ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
701             hypTypes.insert( (*hyp)->GetName() ).second )
702         {
703           aHypList.push_back( *hyp );
704           nbHyps++;
705           if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
706             mainHypFound = true;
707         }
708     }
709   }
710   return nbHyps;
711 }
712
713 //=============================================================================
714 /*!
715  * 
716  */
717 //=============================================================================
718
719 const std::list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
720 {
721   Unexpect aCatch(SalomeException);
722   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
723   return _myMeshDS->GetScript()->GetCommands();
724 }
725
726 //=============================================================================
727 /*!
728  * 
729  */
730 //=============================================================================
731 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
732 {
733   Unexpect aCatch(SalomeException);
734   if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
735   _myMeshDS->GetScript()->Clear();
736 }
737
738 //=============================================================================
739 /*!
740  * Get or Create the SMESH_subMesh object implementation
741  */
742 //=============================================================================
743
744 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
745   throw(SALOME_Exception)
746 {
747   Unexpect aCatch(SalomeException);
748   SMESH_subMesh *aSubMesh;
749   int index = _myMeshDS->ShapeToIndex(aSubShape);
750
751   // for submeshes on GEOM Group
752   if ( !index && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
753     TopoDS_Iterator it( aSubShape );
754     if ( it.More() )
755       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
756   }
757 //   if ( !index )
758 //     return NULL; // neither sub-shape nor a group
759
760   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
761   if ( i_sm != _mapSubMesh.end())
762   {
763     aSubMesh = i_sm->second;
764   }
765   else
766   {
767     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
768     _mapSubMesh[index] = aSubMesh;
769   }
770   return aSubMesh;
771 }
772
773 //=============================================================================
774 /*!
775  * Get the SMESH_subMesh object implementation. Dont create it, return null
776  * if it does not exist.
777  */
778 //=============================================================================
779
780 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape) const
781   throw(SALOME_Exception)
782 {
783   Unexpect aCatch(SalomeException);
784   SMESH_subMesh *aSubMesh = NULL;
785   
786   int index = _myMeshDS->ShapeToIndex(aSubShape);
787
788   map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(index);
789   if ( i_sm != _mapSubMesh.end())
790     aSubMesh = i_sm->second;
791
792   return aSubMesh;
793 }
794 //=============================================================================
795 /*!
796  * Get the SMESH_subMesh object implementation. Dont create it, return null
797  * if it does not exist.
798  */
799 //=============================================================================
800
801 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID) const
802 throw(SALOME_Exception)
803 {
804   Unexpect aCatch(SalomeException);
805   
806   map <int, SMESH_subMesh *>::const_iterator i_sm = _mapSubMesh.find(aShapeID);
807   if (i_sm == _mapSubMesh.end())
808     return NULL;
809   return i_sm->second;
810 }
811 //================================================================================
812 /*!
813  * \brief Return submeshes of groups containing the given subshape
814  */
815 //================================================================================
816
817 std::list<SMESH_subMesh*>
818 SMESH_Mesh::GetGroupSubMeshesContaining(const TopoDS_Shape & aSubShape) const
819   throw(SALOME_Exception)
820 {
821   Unexpect aCatch(SalomeException);
822   std::list<SMESH_subMesh*> found;
823
824   SMESH_subMesh * subMesh = GetSubMeshContaining(aSubShape);
825   if ( !subMesh )
826     return found;
827
828   // submeshes of groups have max IDs, so search from the map end
829   std::map<int, SMESH_subMesh *>::const_reverse_iterator i_sm;
830   for ( i_sm = _mapSubMesh.rbegin(); i_sm != _mapSubMesh.rend(); ++i_sm) {
831     SMESHDS_SubMesh * ds = i_sm->second->GetSubMeshDS();
832     if ( ds && ds->IsComplexSubmesh() ) {
833       TopExp_Explorer exp( i_sm->second->GetSubShape(), aSubShape.ShapeType() );
834       for ( ; exp.More(); exp.Next() ) {
835         if ( aSubShape.IsSame( exp.Current() )) {
836           found.push_back( i_sm->second );
837           break;
838         }
839       }
840     } else {
841       break;
842     }
843   }
844   return found;
845 }
846 //=======================================================================
847 //function : IsUsedHypothesis
848 //purpose  : Return True if anHyp is used to mesh aSubShape
849 //=======================================================================
850
851 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
852                                   const SMESH_subMesh* aSubMesh)
853 {
854   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
855
856   // check if anHyp can be used to mesh aSubMesh
857   if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
858     return false;
859
860   const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
861
862   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
863
864   // algorithm
865   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
866     return ( anHyp == algo );
867
868   // algorithm parameter
869   if (algo)
870   {
871     // look trough hypotheses used by algo
872     SMESH_HypoFilter hypoKind;
873     if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
874       list <const SMESHDS_Hypothesis * > usedHyps;
875       if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
876         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
877     }
878   }
879
880   // look through all assigned hypotheses
881   //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
882   return false; //GetHypothesis( aSubShape, filter, true );
883 }
884
885 //=============================================================================
886 /*!
887  *
888  */
889 //=============================================================================
890
891 const list < SMESH_subMesh * >&
892 SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
893   throw(SALOME_Exception)
894 {
895   Unexpect aCatch(SalomeException);
896   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
897   map < int, SMESH_subMesh * >::iterator itsm;
898   _subMeshesUsingHypothesisList.clear();
899   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
900   {
901     SMESH_subMesh *aSubMesh = (*itsm).second;
902     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
903       _subMeshesUsingHypothesisList.push_back(aSubMesh);
904   }
905   return _subMeshesUsingHypothesisList;
906 }
907
908 //=======================================================================
909 //function : NotifySubMeshesHypothesisModification
910 //purpose  : Say all submeshes using theChangedHyp that it has been modified
911 //=======================================================================
912
913 void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp)
914 {
915   Unexpect aCatch(SalomeException);
916
917   const SMESH_Algo *foundAlgo = 0;
918   SMESH_HypoFilter algoKind, compatibleHypoKind;
919   list <const SMESHDS_Hypothesis * > usedHyps;
920
921
922   map < int, SMESH_subMesh * >::iterator itsm;
923   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
924   {
925     SMESH_subMesh *aSubMesh = (*itsm).second;
926     if ( aSubMesh->IsApplicableHypotesis( hyp ))
927     {
928       const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
929
930       if ( !foundAlgo ) // init filter for algo search
931         algoKind.Init( THypType::IsAlgo() ).And( THypType::IsApplicableTo( aSubShape ));
932       
933       const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
934         ( GetHypothesis( aSubShape, algoKind, true ));
935
936       if ( algo )
937       {
938         bool sameAlgo = ( algo == foundAlgo );
939         if ( !sameAlgo && foundAlgo )
940           sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
941
942         if ( !sameAlgo ) { // init filter for used hypos search
943           if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
944             continue; // algo does not use any hypothesis
945           foundAlgo = algo;
946         }
947
948         // check if hyp is used by algo
949         usedHyps.clear();
950         if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
951              find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
952         {
953           aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
954                                     const_cast< SMESH_Hypothesis*>( hyp ));
955         }
956       }
957     }
958   }
959 }
960
961 //=============================================================================
962 /*!
963  *  Auto color functionality
964  */
965 //=============================================================================
966 void SMESH_Mesh::SetAutoColor(bool theAutoColor) throw(SALOME_Exception)
967 {
968   Unexpect aCatch(SalomeException);
969   _isAutoColor = theAutoColor;
970 }
971
972 bool SMESH_Mesh::GetAutoColor() throw(SALOME_Exception)
973 {
974   Unexpect aCatch(SalomeException);
975   return _isAutoColor;
976 }
977
978 //=============================================================================
979 /*! Export* methods.
980  *  To store mesh contents on disk in different formats.
981  */
982 //=============================================================================
983
984 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
985 {
986   set<string> aGroupNames;
987   for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
988     SMESH_Group* aGroup = it->second;
989     std::string aGroupName = aGroup->GetName();
990     aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
991     if (!aGroupNames.insert(aGroupName).second)
992       return true;
993   }
994
995   return false;
996 }
997
998 void SMESH_Mesh::ExportMED(const char *file, 
999                            const char* theMeshName, 
1000                            bool theAutoGroups,
1001                            int theVersion) 
1002   throw(SALOME_Exception)
1003 {
1004   Unexpect aCatch(SalomeException);
1005
1006   DriverMED_W_SMESHDS_Mesh myWriter;
1007   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
1008   myWriter.SetMesh    ( _myMeshDS   );
1009   if ( !theMeshName ) 
1010     myWriter.SetMeshId  ( _idDoc      );
1011   else {
1012     myWriter.SetMeshId  ( -1          );
1013     myWriter.SetMeshName( theMeshName );
1014   }
1015
1016   if ( theAutoGroups ) {
1017     myWriter.AddGroupOfNodes();
1018     myWriter.AddGroupOfEdges();
1019     myWriter.AddGroupOfFaces();
1020     myWriter.AddGroupOfVolumes();
1021   }
1022
1023   // Pass groups to writer. Provide unique group names.
1024   set<string> aGroupNames;
1025   char aString [256];
1026   int maxNbIter = 10000; // to guarantee cycle finish
1027   for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1028     SMESH_Group*       aGroup   = it->second;
1029     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1030     if ( aGroupDS ) {
1031       string aGroupName0 = aGroup->GetName();
1032       aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
1033       string aGroupName = aGroupName0;
1034       for (int i = 1; !aGroupNames.insert(aGroupName).second && i < maxNbIter; i++) {
1035         sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
1036         aGroupName = aString;
1037         aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
1038       }
1039       aGroupDS->SetStoreName( aGroupName.c_str() );
1040       myWriter.AddGroup( aGroupDS );
1041     }
1042   }
1043
1044   // Perform export
1045   myWriter.Perform();
1046 }
1047
1048 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
1049 {
1050   Unexpect aCatch(SalomeException);
1051   DriverDAT_W_SMDS_Mesh myWriter;
1052   myWriter.SetFile(string(file));
1053   myWriter.SetMesh(_myMeshDS);
1054   myWriter.SetMeshId(_idDoc);
1055   myWriter.Perform();
1056 }
1057
1058 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
1059 {
1060   Unexpect aCatch(SalomeException);
1061   DriverUNV_W_SMDS_Mesh myWriter;
1062   myWriter.SetFile(string(file));
1063   myWriter.SetMesh(_myMeshDS);
1064   myWriter.SetMeshId(_idDoc);
1065   //  myWriter.SetGroups(_mapGroup);
1066
1067   for ( std::map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
1068     SMESH_Group*       aGroup   = it->second;
1069     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
1070     if ( aGroupDS ) {
1071       std::string aGroupName = aGroup->GetName();
1072       aGroupDS->SetStoreName( aGroupName.c_str() );
1073       myWriter.AddGroup( aGroupDS );
1074     }
1075   }
1076   myWriter.Perform();
1077 }
1078
1079 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
1080 {
1081   Unexpect aCatch(SalomeException);
1082   DriverSTL_W_SMDS_Mesh myWriter;
1083   myWriter.SetFile(string(file));
1084   myWriter.SetIsAscii( isascii );
1085   myWriter.SetMesh(_myMeshDS);
1086   myWriter.SetMeshId(_idDoc);
1087   myWriter.Perform();
1088 }
1089
1090 //================================================================================
1091 /*!
1092  * \brief Return number of nodes in the mesh
1093  */
1094 //================================================================================
1095
1096 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
1097 {
1098   Unexpect aCatch(SalomeException);
1099   return _myMeshDS->NbNodes();
1100 }
1101
1102 //================================================================================
1103 /*!
1104  * \brief  Return number of edges of given order in the mesh
1105  */
1106 //================================================================================
1107
1108 int SMESH_Mesh::NbEdges(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1109 {
1110   Unexpect aCatch(SalomeException);
1111   return _myMeshDS->GetMeshInfo().NbEdges(order);
1112 }
1113
1114 //================================================================================
1115 /*!
1116  * \brief Return number of faces of given order in the mesh
1117  */
1118 //================================================================================
1119
1120 int SMESH_Mesh::NbFaces(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1121 {
1122   Unexpect aCatch(SalomeException);
1123   return _myMeshDS->GetMeshInfo().NbFaces(order);
1124 }
1125
1126 //================================================================================
1127 /*!
1128  * \brief Return the number of faces in the mesh
1129  */
1130 //================================================================================
1131
1132 int SMESH_Mesh::NbTriangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1133 {
1134   Unexpect aCatch(SalomeException);
1135   return _myMeshDS->GetMeshInfo().NbTriangles(order);
1136 }
1137
1138 //================================================================================
1139 /*!
1140  * \brief Return the number nodes faces in the mesh
1141  */
1142 //================================================================================
1143
1144 int SMESH_Mesh::NbQuadrangles(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1145 {
1146   Unexpect aCatch(SalomeException);
1147   return _myMeshDS->GetMeshInfo().NbQuadrangles(order);
1148 }
1149
1150 //================================================================================
1151 /*!
1152  * \brief Return the number of polygonal faces in the mesh
1153  */
1154 //================================================================================
1155
1156 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
1157 {
1158   Unexpect aCatch(SalomeException);
1159   return _myMeshDS->GetMeshInfo().NbPolygons();
1160 }
1161
1162 //================================================================================
1163 /*!
1164  * \brief Return number of volumes of given order in the mesh
1165  */
1166 //================================================================================
1167
1168 int SMESH_Mesh::NbVolumes(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1169 {
1170   Unexpect aCatch(SalomeException);
1171   return _myMeshDS->GetMeshInfo().NbVolumes(order);
1172 }
1173
1174 //================================================================================
1175 /*!
1176  * \brief  Return number of tetrahedrons of given order in the mesh
1177  */
1178 //================================================================================
1179
1180 int SMESH_Mesh::NbTetras(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1181 {
1182   Unexpect aCatch(SalomeException);
1183   return _myMeshDS->GetMeshInfo().NbTetras(order);
1184 }
1185
1186 //================================================================================
1187 /*!
1188  * \brief  Return number of hexahedrons of given order in the mesh
1189  */
1190 //================================================================================
1191
1192 int SMESH_Mesh::NbHexas(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1193 {
1194   Unexpect aCatch(SalomeException);
1195   return _myMeshDS->GetMeshInfo().NbHexas(order);
1196 }
1197
1198 //================================================================================
1199 /*!
1200  * \brief  Return number of pyramids of given order in the mesh
1201  */
1202 //================================================================================
1203
1204 int SMESH_Mesh::NbPyramids(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1205 {
1206   Unexpect aCatch(SalomeException);
1207   return _myMeshDS->GetMeshInfo().NbPyramids(order);
1208 }
1209
1210 //================================================================================
1211 /*!
1212  * \brief  Return number of prisms (penthahedrons) of given order in the mesh
1213  */
1214 //================================================================================
1215
1216 int SMESH_Mesh::NbPrisms(SMDSAbs_ElementOrder order) throw(SALOME_Exception)
1217 {
1218   Unexpect aCatch(SalomeException);
1219   return _myMeshDS->GetMeshInfo().NbPrisms(order);
1220 }
1221
1222 //================================================================================
1223 /*!
1224  * \brief  Return number of polyhedrons in the mesh
1225  */
1226 //================================================================================
1227
1228 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
1229 {
1230   Unexpect aCatch(SalomeException);
1231   return _myMeshDS->GetMeshInfo().NbPolyhedrons();
1232 }
1233
1234 //================================================================================
1235 /*!
1236  * \brief  Return number of submeshes in the mesh
1237  */
1238 //================================================================================
1239
1240 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
1241 {
1242   Unexpect aCatch(SalomeException);
1243   return _myMeshDS->NbSubMesh();
1244 }
1245
1246 //=======================================================================
1247 //function : IsNotConformAllowed
1248 //purpose  : check if a hypothesis alowing notconform mesh is present
1249 //=======================================================================
1250
1251 bool SMESH_Mesh::IsNotConformAllowed() const
1252 {
1253   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1254
1255   static SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1256   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1257 }
1258
1259 //=======================================================================
1260 //function : IsMainShape
1261 //purpose  : 
1262 //=======================================================================
1263
1264 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1265 {
1266   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1267 }
1268
1269 //=============================================================================
1270 /*!
1271  *  
1272  */
1273 //=============================================================================
1274
1275 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1276                                    const char*               theName,
1277                                    int&                      theId,
1278                                    const TopoDS_Shape&       theShape)
1279 {
1280   if (_mapGroup.find(_groupId) != _mapGroup.end())
1281     return NULL;
1282   theId = _groupId;
1283   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
1284   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1285   _mapGroup[_groupId++] = aGroup;
1286   return aGroup;
1287 }
1288
1289 //================================================================================
1290 /*!
1291  * \brief Return iterator on all existing groups
1292  */
1293 //================================================================================
1294
1295 SMESH_Mesh::GroupIteratorPtr SMESH_Mesh::GetGroups() const
1296 {
1297   typedef map <int, SMESH_Group *> TMap;
1298   return GroupIteratorPtr( new SMDS_mapIterator<TMap>( _mapGroup ));
1299 }
1300
1301 //=============================================================================
1302 /*!
1303  * \brief Return a group by ID
1304  */
1305 //=============================================================================
1306
1307 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1308 {
1309   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1310     return NULL;
1311   return _mapGroup[theGroupID];
1312 }
1313
1314
1315 //=============================================================================
1316 /*!
1317  * \brief Return IDs of all groups
1318  */
1319 //=============================================================================
1320
1321 std::list<int> SMESH_Mesh::GetGroupIds() const
1322 {
1323   std::list<int> anIds;
1324   for ( std::map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1325     anIds.push_back( it->first );
1326   
1327   return anIds;
1328 }
1329
1330
1331 //=============================================================================
1332 /*!
1333  *  
1334  */
1335 //=============================================================================
1336
1337 void SMESH_Mesh::RemoveGroup (const int theGroupID)
1338 {
1339   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1340     return;
1341   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1342   delete _mapGroup[theGroupID];
1343   _mapGroup.erase (theGroupID);
1344 }
1345
1346 //=======================================================================
1347 //function : GetAncestors
1348 //purpose  : return list of ancestors of theSubShape in the order
1349 //           that lower dimention shapes come first.
1350 //=======================================================================
1351
1352 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1353 {
1354   if ( _mapAncestors.Contains( theS ) )
1355     return _mapAncestors.FindFromKey( theS );
1356
1357   static TopTools_ListOfShape emptyList;
1358   return emptyList;
1359 }
1360
1361 //=======================================================================
1362 //function : Dump
1363 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1364 //=======================================================================
1365
1366 ostream& SMESH_Mesh::Dump(ostream& save)
1367 {
1368   int clause = 0;
1369   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1370   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1371   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1372   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1373   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1374   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1375   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1376   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1377   {
1378     string orderStr = isQuadratic ? "quadratic" : "linear";
1379     SMDSAbs_ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1380
1381     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1382     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1383     if ( NbFaces(order) > 0 ) {
1384       int nb3 = NbTriangles(order);
1385       int nb4 = NbQuadrangles(order);
1386       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1387       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1388       if ( nb3 + nb4 !=  NbFaces(order) ) {
1389         std::map<int,int> myFaceMap;
1390         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1391         while( itFaces->more( ) ) {
1392           int nbNodes = itFaces->next()->NbNodes();
1393           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1394             myFaceMap[ nbNodes ] = 0;
1395           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1396         }
1397         save << clause << ".3) Faces in detail: " << endl;
1398         map <int,int>::iterator itF;
1399         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1400           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1401       }
1402     }
1403     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1404     if ( NbVolumes(order) > 0 ) {
1405       int nb8 = NbHexas(order);
1406       int nb4 = NbTetras(order);
1407       int nb5 = NbPyramids(order);
1408       int nb6 = NbPrisms(order);
1409       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1410       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1411       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1412       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1413       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1414         std::map<int,int> myVolumesMap;
1415         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1416         while( itVolumes->more( ) ) {
1417           int nbNodes = itVolumes->next()->NbNodes();
1418           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1419             myVolumesMap[ nbNodes ] = 0;
1420           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1421         }
1422         save << clause << ".5) Volumes in detail: " << endl;
1423         map <int,int>::iterator itV;
1424         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1425           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1426       }
1427     }
1428     save << endl;
1429   }
1430   save << "===========================================================================" << endl;
1431   return save;
1432 }
1433
1434 //=======================================================================
1435 //function : GetElementType
1436 //purpose  : Returns type of mesh element with certain id
1437 //=======================================================================
1438
1439 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1440 {
1441   return _myMeshDS->GetElementType( id, iselem );
1442 }