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