Salome HOME
PAL16774,PAL16631(SALOME crash after a mesh computation that failed because of lack...
[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  *  
989  */
990 //=============================================================================
991 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
992 {
993   Unexpect aCatch(SalomeException);
994   return _myMeshDS->NbNodes();
995 }
996
997 //=============================================================================
998 /*!
999  *  
1000  */
1001 //=============================================================================
1002 int SMESH_Mesh::NbEdges(ElementOrder order) throw(SALOME_Exception)
1003 {
1004   Unexpect aCatch(SalomeException);
1005   if (order == ORDER_ANY)
1006     return _myMeshDS->NbEdges();
1007
1008   int Nb = 0;
1009   SMDS_EdgeIteratorPtr it = _myMeshDS->edgesIterator();
1010   while (it->more()) {
1011     const SMDS_MeshEdge* cur = it->next();
1012     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1013          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1014       Nb++;
1015   }
1016   return Nb;
1017 }
1018
1019 //=============================================================================
1020 /*!
1021  *  
1022  */
1023 //=============================================================================
1024 int SMESH_Mesh::NbFaces(ElementOrder order) throw(SALOME_Exception)
1025 {
1026   Unexpect aCatch(SalomeException);
1027   if (order == ORDER_ANY)
1028     return _myMeshDS->NbFaces();
1029
1030   int Nb = 0;
1031   SMDS_FaceIteratorPtr it = _myMeshDS->facesIterator();
1032   while (it->more()) {
1033     const SMDS_MeshFace* cur = it->next();
1034     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1035          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1036       Nb++;
1037   }
1038   return Nb;
1039 }
1040
1041 ///////////////////////////////////////////////////////////////////////////////
1042 /// Return the number of 3 nodes faces in the mesh. This method run in O(n)
1043 ///////////////////////////////////////////////////////////////////////////////
1044 int SMESH_Mesh::NbTriangles(ElementOrder order) throw(SALOME_Exception)
1045 {
1046   Unexpect aCatch(SalomeException);
1047   int Nb = 0;
1048   
1049   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1050   while (itFaces->more()) {
1051     const SMDS_MeshFace* curFace = itFaces->next();
1052     int nbnod = curFace->NbNodes();
1053     if ( !curFace->IsPoly() && 
1054          ( order == ORDER_ANY && (nbnod==3 || nbnod==6) ||
1055            order == ORDER_LINEAR && nbnod==3 ||
1056            order == ORDER_QUADRATIC && nbnod==6 ) )
1057       Nb++;
1058   }
1059   return Nb;
1060 }
1061
1062 ///////////////////////////////////////////////////////////////////////////////
1063 /// Return the number of 4 nodes faces in the mesh. This method run in O(n)
1064 ///////////////////////////////////////////////////////////////////////////////
1065 int SMESH_Mesh::NbQuadrangles(ElementOrder order) throw(SALOME_Exception)
1066 {
1067   Unexpect aCatch(SalomeException);
1068   int Nb = 0;
1069   
1070   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1071   while (itFaces->more()) {
1072     const SMDS_MeshFace* curFace = itFaces->next();
1073     int nbnod = curFace->NbNodes();
1074     if ( !curFace->IsPoly() && 
1075          ( order == ORDER_ANY && (nbnod==4 || nbnod==8) ||
1076            order == ORDER_LINEAR && nbnod==4 ||
1077            order == ORDER_QUADRATIC && nbnod==8 ) )
1078       Nb++;
1079   }
1080   return Nb;
1081 }
1082
1083 ///////////////////////////////////////////////////////////////////////////////
1084 /// Return the number of polygonal faces in the mesh. This method run in O(n)
1085 ///////////////////////////////////////////////////////////////////////////////
1086 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
1087 {
1088   Unexpect aCatch(SalomeException);
1089   int Nb = 0;
1090   SMDS_FaceIteratorPtr itFaces = _myMeshDS->facesIterator();
1091   while (itFaces->more())
1092     if (itFaces->next()->IsPoly()) Nb++;
1093   return Nb;
1094 }
1095
1096 //=============================================================================
1097 /*!
1098  *  
1099  */
1100 //=============================================================================
1101 int SMESH_Mesh::NbVolumes(ElementOrder order) throw(SALOME_Exception)
1102 {
1103   Unexpect aCatch(SalomeException);
1104   if (order == ORDER_ANY)
1105     return _myMeshDS->NbVolumes();
1106
1107   int Nb = 0;
1108   SMDS_VolumeIteratorPtr it = _myMeshDS->volumesIterator();
1109   while (it->more()) {
1110     const SMDS_MeshVolume* cur = it->next();
1111     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1112          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1113       Nb++;
1114   }
1115   return Nb;
1116 }
1117
1118 int SMESH_Mesh::NbTetras(ElementOrder order) throw(SALOME_Exception)
1119 {
1120   Unexpect aCatch(SalomeException);
1121   int Nb = 0;
1122   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1123   while (itVolumes->more()) {
1124     const SMDS_MeshVolume* curVolume = itVolumes->next();
1125     int nbnod = curVolume->NbNodes();
1126     if ( !curVolume->IsPoly() && 
1127          ( order == ORDER_ANY && (nbnod==4 || nbnod==10) ||
1128            order == ORDER_LINEAR && nbnod==4 ||
1129            order == ORDER_QUADRATIC && nbnod==10 ) )
1130       Nb++;
1131   }
1132   return Nb;
1133 }
1134
1135 int SMESH_Mesh::NbHexas(ElementOrder order) throw(SALOME_Exception)
1136 {
1137   Unexpect aCatch(SalomeException);
1138   int Nb = 0;
1139   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1140   while (itVolumes->more()) {
1141     const SMDS_MeshVolume* curVolume = itVolumes->next();
1142     int nbnod = curVolume->NbNodes();
1143     if ( !curVolume->IsPoly() && 
1144          ( order == ORDER_ANY && (nbnod==8 || nbnod==20) ||
1145            order == ORDER_LINEAR && nbnod==8 ||
1146            order == ORDER_QUADRATIC && nbnod==20 ) )
1147       Nb++;
1148   }
1149   return Nb;
1150 }
1151
1152 int SMESH_Mesh::NbPyramids(ElementOrder order) throw(SALOME_Exception)
1153 {
1154   Unexpect aCatch(SalomeException);
1155   int Nb = 0;
1156   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1157   while (itVolumes->more()) {
1158     const SMDS_MeshVolume* curVolume = itVolumes->next();
1159     int nbnod = curVolume->NbNodes();
1160     if ( !curVolume->IsPoly() && 
1161          ( order == ORDER_ANY && (nbnod==5 || nbnod==13) ||
1162            order == ORDER_LINEAR && nbnod==5 ||
1163            order == ORDER_QUADRATIC && nbnod==13 ) )
1164       Nb++;
1165   }
1166   return Nb;
1167 }
1168
1169 int SMESH_Mesh::NbPrisms(ElementOrder order) throw(SALOME_Exception)
1170 {
1171   Unexpect aCatch(SalomeException);
1172   int Nb = 0;
1173   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1174   while (itVolumes->more()) {
1175     const SMDS_MeshVolume* curVolume = itVolumes->next();
1176     int nbnod = curVolume->NbNodes();
1177     if ( !curVolume->IsPoly() && 
1178          ( order == ORDER_ANY && (nbnod==6 || nbnod==15) ||
1179            order == ORDER_LINEAR && nbnod==6 ||
1180            order == ORDER_QUADRATIC && nbnod==15 ) )
1181       Nb++;
1182   }
1183   return Nb;
1184 }
1185
1186 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
1187 {
1188   Unexpect aCatch(SalomeException);
1189   int Nb = 0;
1190   SMDS_VolumeIteratorPtr itVolumes = _myMeshDS->volumesIterator();
1191   while (itVolumes->more())
1192     if (itVolumes->next()->IsPoly()) Nb++;
1193   return Nb;
1194 }
1195
1196 //=============================================================================
1197 /*!
1198  *  
1199  */
1200 //=============================================================================
1201 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
1202 {
1203   Unexpect aCatch(SalomeException);
1204   return _myMeshDS->NbSubMesh();
1205 }
1206
1207 //=======================================================================
1208 //function : IsNotConformAllowed
1209 //purpose  : check if a hypothesis alowing notconform mesh is present
1210 //=======================================================================
1211
1212 bool SMESH_Mesh::IsNotConformAllowed() const
1213 {
1214   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1215
1216   SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1217   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1218 }
1219
1220 //=======================================================================
1221 //function : IsMainShape
1222 //purpose  : 
1223 //=======================================================================
1224
1225 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1226 {
1227   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1228 }
1229
1230 //=============================================================================
1231 /*!
1232  *  
1233  */
1234 //=============================================================================
1235
1236 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1237                                    const char*               theName,
1238                                    int&                      theId,
1239                                    const TopoDS_Shape&       theShape)
1240 {
1241   if (_mapGroup.find(_groupId) != _mapGroup.end())
1242     return NULL;
1243   theId = _groupId;
1244   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
1245   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1246   _mapGroup[_groupId++] = aGroup;
1247   return aGroup;
1248 }
1249
1250 //=============================================================================
1251 /*!
1252  *  
1253  */
1254 //=============================================================================
1255
1256 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1257 {
1258   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1259     return NULL;
1260   return _mapGroup[theGroupID];
1261 }
1262
1263
1264 //=============================================================================
1265 /*!
1266  *  
1267  */
1268 //=============================================================================
1269
1270 list<int> SMESH_Mesh::GetGroupIds()
1271 {
1272   list<int> anIds;
1273   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1274     anIds.push_back( it->first );
1275   
1276   return anIds;
1277 }
1278
1279
1280 //=============================================================================
1281 /*!
1282  *  
1283  */
1284 //=============================================================================
1285
1286 void SMESH_Mesh::RemoveGroup (const int theGroupID)
1287 {
1288   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1289     return;
1290   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1291   delete _mapGroup[theGroupID];
1292   _mapGroup.erase (theGroupID);
1293 }
1294
1295 //=======================================================================
1296 //function : GetAncestors
1297 //purpose  : return list of ancestors of theSubShape in the order
1298 //           that lower dimention shapes come first.
1299 //=======================================================================
1300
1301 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1302 {
1303   if ( _mapAncestors.Contains( theS ) )
1304     return _mapAncestors.FindFromKey( theS );
1305
1306   static TopTools_ListOfShape emptyList;
1307   return emptyList;
1308 }
1309
1310 //=======================================================================
1311 //function : Dump
1312 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1313 //=======================================================================
1314
1315 ostream& SMESH_Mesh::Dump(ostream& save)
1316 {
1317   int clause = 0;
1318   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1319   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1320   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1321   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1322   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1323   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1324   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1325   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1326   {
1327     string orderStr = isQuadratic ? "quadratic" : "linear";
1328     ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1329
1330     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1331     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1332     if ( NbFaces(order) > 0 ) {
1333       int nb3 = NbTriangles(order);
1334       int nb4 = NbQuadrangles(order);
1335       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1336       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1337       if ( nb3 + nb4 !=  NbFaces(order) ) {
1338         map<int,int> myFaceMap;
1339         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1340         while( itFaces->more( ) ) {
1341           int nbNodes = itFaces->next()->NbNodes();
1342           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1343             myFaceMap[ nbNodes ] = 0;
1344           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1345         }
1346         save << clause << ".3) Faces in detail: " << endl;
1347         map <int,int>::iterator itF;
1348         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1349           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1350       }
1351     }
1352     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1353     if ( NbVolumes(order) > 0 ) {
1354       int nb8 = NbHexas(order);
1355       int nb4 = NbTetras(order);
1356       int nb5 = NbPyramids(order);
1357       int nb6 = NbPrisms(order);
1358       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1359       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1360       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1361       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1362       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1363         map<int,int> myVolumesMap;
1364         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1365         while( itVolumes->more( ) ) {
1366           int nbNodes = itVolumes->next()->NbNodes();
1367           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1368             myVolumesMap[ nbNodes ] = 0;
1369           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1370         }
1371         save << clause << ".5) Volumes in detail: " << endl;
1372         map <int,int>::iterator itV;
1373         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1374           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1375       }
1376     }
1377     save << endl;
1378   }
1379   save << "===========================================================================" << endl;
1380   return save;
1381 }
1382
1383 //=======================================================================
1384 //function : GetElementType
1385 //purpose  : Returns type of mesh element with certain id
1386 //=======================================================================
1387
1388 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1389 {
1390   return _myMeshDS->GetElementType( id, iselem );
1391 }