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