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