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