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