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