Salome HOME
Integrate improvement PAL13615 from V3_2_0_maintainance
[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     _mapPropagationChains.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 = true;
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 = true;
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 = true;
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     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
367       return aBestRet;
368     return aWorstNotFatal;
369   }
370
371   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
372   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
373   {
374     if(MYDEBUG) MESSAGE("Hypothesis ID does not give an hypothesis");
375     if(MYDEBUG) {
376       SCRUTE(_studyId);
377       SCRUTE(anHypId);
378     }
379     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
380   }
381
382   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
383   MESSAGE( "SMESH_Mesh::AddHypothesis " << anHyp->GetName() );
384
385   bool isGlobalHyp = IsMainShape( aSubShape );
386
387   // NotConformAllowed can be only global
388   if ( !isGlobalHyp )
389   {
390     string hypName = anHyp->GetName();
391     if ( hypName == "NotConformAllowed" )
392     {
393       if(MYDEBUG) MESSAGE( "Hypotesis <NotConformAllowed> can be only global" );
394       return SMESH_Hypothesis::HYP_INCOMPATIBLE;
395     }
396   }
397
398   // shape 
399
400   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
401   int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
402
403   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
404
405   // subShapes
406   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
407       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
408   {
409     event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
410
411     SMESH_Hypothesis::Hypothesis_Status ret2 =
412       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
413     if (ret2 > ret)
414       ret = ret2;
415
416     // check concurent hypotheses on ansestors
417     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
418     {
419       SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
420       while ( smIt->more() ) {
421         SMESH_subMesh* sm = smIt->next();
422         if ( sm->IsApplicableHypotesis( anHyp )) {
423           ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
424           if (ret2 > ret) {
425             ret = ret2;
426             break;
427           }
428         }
429       }
430     }
431   }
432
433   if(MYDEBUG) subMesh->DumpAlgoState(true);
434   SCRUTE(ret);
435   return ret;
436 }
437
438 //=============================================================================
439 /*!
440  * 
441  */
442 //=============================================================================
443
444 SMESH_Hypothesis::Hypothesis_Status
445   SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
446                                int anHypId)throw(SALOME_Exception)
447 {
448   Unexpect aCatch(SalomeException);
449   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
450   
451   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
452   SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
453   if ( subMeshDS && subMeshDS->IsComplexSubmesh() )
454   {
455     // return the worst but not fatal state of all group memebers
456     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
457     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
458     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
459     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
460     {
461       if ( !GetMeshDS()->ShapeToIndex( itS.Value() ))
462         continue; // not sub-shape
463       ret = RemoveHypothesis( itS.Value(), anHypId );
464       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
465         aWorstNotFatal = ret;
466       if ( ret < aBestRet )
467         aBestRet = ret;
468     }
469     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
470       return aBestRet;
471     return aWorstNotFatal;
472   }
473
474   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
475   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
476     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
477   
478   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
479   int hypType = anHyp->GetType();
480   if(MYDEBUG) SCRUTE(hypType);
481   
482   // shape 
483   
484   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
485   int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
486
487   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
488
489   // there may appear concurrent hyps that were covered by the removed hyp
490   if (ret < SMESH_Hypothesis::HYP_CONCURENT &&
491       subMesh->IsApplicableHypotesis( anHyp ) &&
492       subMesh->CheckConcurentHypothesis( anHyp->GetType() ) != SMESH_Hypothesis::HYP_OK)
493     ret = SMESH_Hypothesis::HYP_CONCURENT;
494
495   // subShapes
496   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
497       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is removed from father
498   {
499     event = isAlgo ? SMESH_subMesh::REMOVE_FATHER_ALGO : SMESH_subMesh::REMOVE_FATHER_HYP;
500
501     SMESH_Hypothesis::Hypothesis_Status ret2 =
502       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
503     if (ret2 > ret) // more severe
504       ret = ret2;
505
506     // check concurent hypotheses on ansestors
507     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) )
508     {
509       SMESH_subMeshIteratorPtr smIt = subMesh->getDependsOnIterator(false,false);
510       while ( smIt->more() ) {
511         SMESH_subMesh* sm = smIt->next();
512         if ( sm->IsApplicableHypotesis( anHyp )) {
513           ret2 = sm->CheckConcurentHypothesis( anHyp->GetType() );
514           if (ret2 > ret) {
515             ret = ret2;
516             break;
517           }
518         }
519       }
520     }
521   }
522   
523   if(MYDEBUG) subMesh->DumpAlgoState(true);
524   if(MYDEBUG) SCRUTE(ret);
525   return ret;
526 }
527
528 //=============================================================================
529 /*!
530  * 
531  */
532 //=============================================================================
533
534 const list<const SMESHDS_Hypothesis*>&
535 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
536   throw(SALOME_Exception)
537 {
538   Unexpect aCatch(SalomeException);
539   return _myMeshDS->GetHypothesis(aSubShape);
540 }
541
542 //=======================================================================
543 /*!
544  * \brief Return the hypothesis assigned to the shape
545   * \param aSubShape - the shape to check
546   * \param aFilter - the hypothesis filter
547   * \param andAncestors - flag to check hypos assigned to ancestors of the shape
548   * \retval SMESH_Hypothesis* - the first hypo passed through aFilter
549  */
550 //=======================================================================
551
552 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubShape,
553                                                    const SMESH_HypoFilter& aFilter,
554                                                    const bool              andAncestors) const
555 {
556   {
557     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
558     list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
559     for ( ; hyp != hypList.end(); hyp++ ) {
560       const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
561       if ( aFilter.IsOk( h, aSubShape))
562         return h;
563     }
564   }
565   if ( andAncestors )
566   {
567     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
568     for (; it.More(); it.Next() )
569     {
570       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
571       list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
572       for ( ; hyp != hypList.end(); hyp++ ) {
573         const SMESH_Hypothesis * h = cSMESH_Hyp( *hyp );
574         if (aFilter.IsOk( h, it.Value() ))
575           return h;
576       }
577     }
578   }
579   return 0;
580 }
581
582 //================================================================================
583 /*!
584  * \brief Return hypothesis assigned to the shape
585   * \param aSubShape - the shape to check
586   * \param aFilter - the hypothesis filter
587   * \param aHypList - the list of the found hypotheses
588   * \param andAncestors - flag to check hypos assigned to ancestors of the shape
589   * \retval int - number of unique hypos in aHypList
590  */
591 //================================================================================
592
593 int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
594                               const SMESH_HypoFilter&             aFilter,
595                               list <const SMESHDS_Hypothesis * >& aHypList,
596                               const bool                          andAncestors) const
597 {
598   set<string> hypTypes; // to exclude same type hypos from the result list
599   int nbHyps = 0;
600
601   // only one main hypothesis is allowed
602   bool mainHypFound = false;
603
604   // fill in hypTypes
605   list<const SMESHDS_Hypothesis*>::const_iterator hyp;
606   for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ ) {
607     if ( hypTypes.insert( (*hyp)->GetName() ).second )
608       nbHyps++;
609     if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
610       mainHypFound = true;
611   }
612
613   // get hypos from aSubShape
614   {
615     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
616     for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
617       if ( aFilter.IsOk (cSMESH_Hyp( *hyp ), aSubShape) &&
618            ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
619            hypTypes.insert( (*hyp)->GetName() ).second )
620       {
621         aHypList.push_back( *hyp );
622         nbHyps++;
623         if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
624           mainHypFound = true;
625       }
626   }
627
628   // get hypos from ancestors of aSubShape
629   if ( andAncestors )
630   {
631     TopTools_MapOfShape map;
632     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
633     for (; it.More(); it.Next() )
634     {
635      if ( !map.Add( it.Value() ))
636         continue;
637       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
638       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
639         if (aFilter.IsOk( cSMESH_Hyp( *hyp ), it.Value() ) &&
640             ( cSMESH_Hyp(*hyp)->IsAuxiliary() || !mainHypFound ) &&
641             hypTypes.insert( (*hyp)->GetName() ).second )
642         {
643           aHypList.push_back( *hyp );
644           nbHyps++;
645           if ( !cSMESH_Hyp(*hyp)->IsAuxiliary() )
646             mainHypFound = true;
647         }
648     }
649   }
650   return nbHyps;
651 }
652
653 //=============================================================================
654 /*!
655  * 
656  */
657 //=============================================================================
658
659 const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
660 {
661   Unexpect aCatch(SalomeException);
662   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
663   return _myMeshDS->GetScript()->GetCommands();
664 }
665
666 //=============================================================================
667 /*!
668  * 
669  */
670 //=============================================================================
671 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
672 {
673   Unexpect aCatch(SalomeException);
674   if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
675   _myMeshDS->GetScript()->Clear();
676 }
677
678 //=============================================================================
679 /*!
680  * Get or Create the SMESH_subMesh object implementation
681  */
682 //=============================================================================
683
684 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
685   throw(SALOME_Exception)
686 {
687   Unexpect aCatch(SalomeException);
688   SMESH_subMesh *aSubMesh;
689   int index = _myMeshDS->ShapeToIndex(aSubShape);
690
691   // for submeshes on GEOM Group
692   if ( !index && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
693     TopoDS_Iterator it( aSubShape );
694     if ( it.More() )
695       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
696   }
697 //   if ( !index )
698 //     return NULL; // neither sub-shape nor a group
699
700   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
701   if ( i_sm != _mapSubMesh.end())
702   {
703     aSubMesh = i_sm->second;
704   }
705   else
706   {
707     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
708     _mapSubMesh[index] = aSubMesh;
709   }
710   return aSubMesh;
711 }
712
713 //=============================================================================
714 /*!
715  * Get the SMESH_subMesh object implementation. Dont create it, return null
716  * if it does not exist.
717  */
718 //=============================================================================
719
720 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
721   throw(SALOME_Exception)
722 {
723   Unexpect aCatch(SalomeException);
724   SMESH_subMesh *aSubMesh = NULL;
725   
726   int index = _myMeshDS->ShapeToIndex(aSubShape);
727
728   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
729   if ( i_sm != _mapSubMesh.end())
730     aSubMesh = i_sm->second;
731
732   return aSubMesh;
733 }
734
735 //=============================================================================
736 /*!
737  * Get the SMESH_subMesh object implementation. Dont create it, return null
738  * if it does not exist.
739  */
740 //=============================================================================
741
742 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID)
743 throw(SALOME_Exception)
744 {
745   Unexpect aCatch(SalomeException);
746   
747   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(aShapeID);
748   if (i_sm == _mapSubMesh.end())
749     return NULL;
750   return i_sm->second;
751 }
752
753 //=======================================================================
754 //function : IsUsedHypothesis
755 //purpose  : Return True if anHyp is used to mesh aSubShape
756 //=======================================================================
757
758 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
759                                   const SMESH_subMesh* aSubMesh)
760 {
761   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
762
763   // check if anHyp can be used to mesh aSubMesh
764   if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
765     return false;
766
767   const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
768
769   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
770
771   // algorithm
772   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
773     return ( anHyp == algo );
774
775   // algorithm parameter
776   if (algo)
777   {
778     // look trough hypotheses used by algo
779     SMESH_HypoFilter hypoKind;
780     if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
781       list <const SMESHDS_Hypothesis * > usedHyps;
782       if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
783         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
784     }
785   }
786
787   // look through all assigned hypotheses
788   //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
789   return false; //GetHypothesis( aSubShape, filter, true );
790 }
791
792 //=============================================================================
793 /*!
794  *
795  */
796 //=============================================================================
797
798 const list < SMESH_subMesh * >&
799 SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
800   throw(SALOME_Exception)
801 {
802   Unexpect aCatch(SalomeException);
803   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
804   map < int, SMESH_subMesh * >::iterator itsm;
805   _subMeshesUsingHypothesisList.clear();
806   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
807   {
808     SMESH_subMesh *aSubMesh = (*itsm).second;
809     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
810       _subMeshesUsingHypothesisList.push_back(aSubMesh);
811   }
812   return _subMeshesUsingHypothesisList;
813 }
814
815 //=======================================================================
816 //function : NotifySubMeshesHypothesisModification
817 //purpose  : Say all submeshes using theChangedHyp that it has been modified
818 //=======================================================================
819
820 void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* hyp)
821 {
822   Unexpect aCatch(SalomeException);
823
824   const SMESH_Algo *foundAlgo = 0;
825   SMESH_HypoFilter algoKind, compatibleHypoKind;
826   list <const SMESHDS_Hypothesis * > usedHyps;
827
828
829   map < int, SMESH_subMesh * >::iterator itsm;
830   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
831   {
832     SMESH_subMesh *aSubMesh = (*itsm).second;
833     if ( aSubMesh->IsApplicableHypotesis( hyp ))
834     {
835       const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
836
837       if ( !foundAlgo ) // init filter for algo search
838         algoKind.Init( THypType::IsAlgo() ).And( THypType::IsApplicableTo( aSubShape ));
839       
840       const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
841         ( GetHypothesis( aSubShape, algoKind, true ));
842
843       if ( algo )
844       {
845         bool sameAlgo = ( algo == foundAlgo );
846         if ( !sameAlgo && foundAlgo )
847           sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
848
849         if ( !sameAlgo ) { // init filter for used hypos search
850           if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
851             continue; // algo does not use any hypothesis
852           foundAlgo = algo;
853         }
854
855         // check if hyp is used by algo
856         usedHyps.clear();
857         if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
858              find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
859         {
860           aSubMesh->AlgoStateEngine(SMESH_subMesh::MODIF_HYP,
861                                     const_cast< SMESH_Hypothesis*>( hyp ));
862
863           if ( algo->GetDim() == 1 && IsPropagationHypothesis( aSubShape ))
864             CleanMeshOnPropagationChain( aSubShape );
865         }
866       }
867     }
868   }
869 }
870
871 //=============================================================================
872 /*! Export* methods.
873  *  To store mesh contents on disk in different formats.
874  */
875 //=============================================================================
876
877 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
878 {
879   set<string> aGroupNames;
880   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
881     SMESH_Group* aGroup = it->second;
882     string aGroupName = aGroup->GetName();
883     aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
884     if (!aGroupNames.insert(aGroupName).second)
885       return true;
886   }
887
888   return false;
889 }
890
891 void SMESH_Mesh::ExportMED(const char *file, 
892                            const char* theMeshName, 
893                            bool theAutoGroups,
894                            int theVersion) 
895   throw(SALOME_Exception)
896 {
897   Unexpect aCatch(SalomeException);
898
899   DriverMED_W_SMESHDS_Mesh myWriter;
900   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
901   myWriter.SetMesh    ( _myMeshDS   );
902   if ( !theMeshName ) 
903     myWriter.SetMeshId  ( _idDoc      );
904   else {
905     myWriter.SetMeshId  ( -1          );
906     myWriter.SetMeshName( theMeshName );
907   }
908
909   if ( theAutoGroups ) {
910     myWriter.AddGroupOfNodes();
911     myWriter.AddGroupOfEdges();
912     myWriter.AddGroupOfFaces();
913     myWriter.AddGroupOfVolumes();
914   }
915
916   // Pass groups to writer. Provide unique group names.
917   set<string> aGroupNames;
918   char aString [256];
919   int maxNbIter = 10000; // to guarantee cycle finish
920   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
921     SMESH_Group*       aGroup   = it->second;
922     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
923     if ( aGroupDS ) {
924       string aGroupName0 = aGroup->GetName();
925       aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
926       string aGroupName = aGroupName0;
927       for (int i = 1; !aGroupNames.insert(aGroupName).second && i < maxNbIter; i++) {
928         sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
929         aGroupName = aString;
930         aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
931       }
932       aGroupDS->SetStoreName( aGroupName.c_str() );
933       myWriter.AddGroup( aGroupDS );
934     }
935   }
936
937   // Perform export
938   myWriter.Perform();
939 }
940
941 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
942 {
943   Unexpect aCatch(SalomeException);
944   DriverDAT_W_SMDS_Mesh myWriter;
945   myWriter.SetFile(string(file));
946   myWriter.SetMesh(_myMeshDS);
947   myWriter.SetMeshId(_idDoc);
948   myWriter.Perform();
949 }
950
951 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
952 {
953   Unexpect aCatch(SalomeException);
954   DriverUNV_W_SMDS_Mesh myWriter;
955   myWriter.SetFile(string(file));
956   myWriter.SetMesh(_myMeshDS);
957   myWriter.SetMeshId(_idDoc);
958   //  myWriter.SetGroups(_mapGroup);
959
960   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
961     SMESH_Group*       aGroup   = it->second;
962     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
963     if ( aGroupDS ) {
964       string aGroupName = aGroup->GetName();
965       aGroupDS->SetStoreName( aGroupName.c_str() );
966       myWriter.AddGroup( aGroupDS );
967     }
968   }
969   myWriter.Perform();
970 }
971
972 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
973 {
974   Unexpect aCatch(SalomeException);
975   DriverSTL_W_SMDS_Mesh myWriter;
976   myWriter.SetFile(string(file));
977   myWriter.SetIsAscii( isascii );
978   myWriter.SetMesh(_myMeshDS);
979   myWriter.SetMeshId(_idDoc);
980   myWriter.Perform();
981 }
982
983 //=============================================================================
984 /*!
985  *  
986  */
987 //=============================================================================
988 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
989 {
990   Unexpect aCatch(SalomeException);
991   return _myMeshDS->NbNodes();
992 }
993
994 //=============================================================================
995 /*!
996  *  
997  */
998 //=============================================================================
999 int SMESH_Mesh::NbEdges(ElementOrder order) throw(SALOME_Exception)
1000 {
1001   Unexpect aCatch(SalomeException);
1002   if (order == ORDER_ANY)
1003     return _myMeshDS->NbEdges();
1004
1005   int Nb = 0;
1006   SMDS_EdgeIteratorPtr it = _myMeshDS->edgesIterator();
1007   while (it->more()) {
1008     const SMDS_MeshEdge* cur = it->next();
1009     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1010          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1011       Nb++;
1012   }
1013   return Nb;
1014 }
1015
1016 //=============================================================================
1017 /*!
1018  *  
1019  */
1020 //=============================================================================
1021 int SMESH_Mesh::NbFaces(ElementOrder order) throw(SALOME_Exception)
1022 {
1023   Unexpect aCatch(SalomeException);
1024   if (order == ORDER_ANY)
1025     return _myMeshDS->NbFaces();
1026
1027   int Nb = 0;
1028   SMDS_FaceIteratorPtr it = _myMeshDS->facesIterator();
1029   while (it->more()) {
1030     const SMDS_MeshFace* cur = it->next();
1031     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1032          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1033       Nb++;
1034   }
1035   return Nb;
1036 }
1037
1038 ///////////////////////////////////////////////////////////////////////////////
1039 /// Return the number of 3 nodes faces in the mesh. This method run in O(n)
1040 ///////////////////////////////////////////////////////////////////////////////
1041 int SMESH_Mesh::NbTriangles(ElementOrder order) throw(SALOME_Exception)
1042 {
1043   Unexpect aCatch(SalomeException);
1044   int Nb = 0;
1045   
1046   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1047   while (itFaces->more()) {
1048     const SMDS_MeshFace* curFace = itFaces->next();
1049     int nbnod = curFace->NbNodes();
1050     if ( !curFace->IsPoly() && 
1051          ( order == ORDER_ANY && (nbnod==3 || nbnod==6) ||
1052            order == ORDER_LINEAR && nbnod==3 ||
1053            order == ORDER_QUADRATIC && nbnod==6 ) )
1054       Nb++;
1055   }
1056   return Nb;
1057 }
1058
1059 ///////////////////////////////////////////////////////////////////////////////
1060 /// Return the number of 4 nodes faces in the mesh. This method run in O(n)
1061 ///////////////////////////////////////////////////////////////////////////////
1062 int SMESH_Mesh::NbQuadrangles(ElementOrder order) throw(SALOME_Exception)
1063 {
1064   Unexpect aCatch(SalomeException);
1065   int Nb = 0;
1066   
1067   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1068   while (itFaces->more()) {
1069     const SMDS_MeshFace* curFace = itFaces->next();
1070     int nbnod = curFace->NbNodes();
1071     if ( !curFace->IsPoly() && 
1072          ( order == ORDER_ANY && (nbnod==4 || nbnod==8) ||
1073            order == ORDER_LINEAR && nbnod==4 ||
1074            order == ORDER_QUADRATIC && nbnod==8 ) )
1075       Nb++;
1076   }
1077   return Nb;
1078 }
1079
1080 ///////////////////////////////////////////////////////////////////////////////
1081 /// Return the number of polygonal faces in the mesh. This method run in O(n)
1082 ///////////////////////////////////////////////////////////////////////////////
1083 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
1084 {
1085   Unexpect aCatch(SalomeException);
1086   int Nb = 0;
1087   SMDS_FaceIteratorPtr itFaces = _myMeshDS->facesIterator();
1088   while (itFaces->more())
1089     if (itFaces->next()->IsPoly()) Nb++;
1090   return Nb;
1091 }
1092
1093 //=============================================================================
1094 /*!
1095  *  
1096  */
1097 //=============================================================================
1098 int SMESH_Mesh::NbVolumes(ElementOrder order) throw(SALOME_Exception)
1099 {
1100   Unexpect aCatch(SalomeException);
1101   if (order == ORDER_ANY)
1102     return _myMeshDS->NbVolumes();
1103
1104   int Nb = 0;
1105   SMDS_VolumeIteratorPtr it = _myMeshDS->volumesIterator();
1106   while (it->more()) {
1107     const SMDS_MeshVolume* cur = it->next();
1108     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1109          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1110       Nb++;
1111   }
1112   return Nb;
1113 }
1114
1115 int SMESH_Mesh::NbTetras(ElementOrder order) throw(SALOME_Exception)
1116 {
1117   Unexpect aCatch(SalomeException);
1118   int Nb = 0;
1119   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1120   while (itVolumes->more()) {
1121     const SMDS_MeshVolume* curVolume = itVolumes->next();
1122     int nbnod = curVolume->NbNodes();
1123     if ( !curVolume->IsPoly() && 
1124          ( order == ORDER_ANY && (nbnod==4 || nbnod==10) ||
1125            order == ORDER_LINEAR && nbnod==4 ||
1126            order == ORDER_QUADRATIC && nbnod==10 ) )
1127       Nb++;
1128   }
1129   return Nb;
1130 }
1131
1132 int SMESH_Mesh::NbHexas(ElementOrder order) throw(SALOME_Exception)
1133 {
1134   Unexpect aCatch(SalomeException);
1135   int Nb = 0;
1136   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1137   while (itVolumes->more()) {
1138     const SMDS_MeshVolume* curVolume = itVolumes->next();
1139     int nbnod = curVolume->NbNodes();
1140     if ( !curVolume->IsPoly() && 
1141          ( order == ORDER_ANY && (nbnod==8 || nbnod==20) ||
1142            order == ORDER_LINEAR && nbnod==8 ||
1143            order == ORDER_QUADRATIC && nbnod==20 ) )
1144       Nb++;
1145   }
1146   return Nb;
1147 }
1148
1149 int SMESH_Mesh::NbPyramids(ElementOrder order) throw(SALOME_Exception)
1150 {
1151   Unexpect aCatch(SalomeException);
1152   int Nb = 0;
1153   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1154   while (itVolumes->more()) {
1155     const SMDS_MeshVolume* curVolume = itVolumes->next();
1156     int nbnod = curVolume->NbNodes();
1157     if ( !curVolume->IsPoly() && 
1158          ( order == ORDER_ANY && (nbnod==5 || nbnod==13) ||
1159            order == ORDER_LINEAR && nbnod==5 ||
1160            order == ORDER_QUADRATIC && nbnod==13 ) )
1161       Nb++;
1162   }
1163   return Nb;
1164 }
1165
1166 int SMESH_Mesh::NbPrisms(ElementOrder order) throw(SALOME_Exception)
1167 {
1168   Unexpect aCatch(SalomeException);
1169   int Nb = 0;
1170   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1171   while (itVolumes->more()) {
1172     const SMDS_MeshVolume* curVolume = itVolumes->next();
1173     int nbnod = curVolume->NbNodes();
1174     if ( !curVolume->IsPoly() && 
1175          ( order == ORDER_ANY && (nbnod==6 || nbnod==15) ||
1176            order == ORDER_LINEAR && nbnod==6 ||
1177            order == ORDER_QUADRATIC && nbnod==15 ) )
1178       Nb++;
1179   }
1180   return Nb;
1181 }
1182
1183 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
1184 {
1185   Unexpect aCatch(SalomeException);
1186   int Nb = 0;
1187   SMDS_VolumeIteratorPtr itVolumes = _myMeshDS->volumesIterator();
1188   while (itVolumes->more())
1189     if (itVolumes->next()->IsPoly()) Nb++;
1190   return Nb;
1191 }
1192
1193 //=============================================================================
1194 /*!
1195  *  
1196  */
1197 //=============================================================================
1198 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
1199 {
1200   Unexpect aCatch(SalomeException);
1201   return _myMeshDS->NbSubMesh();
1202 }
1203
1204 //=======================================================================
1205 //function : IsNotConformAllowed
1206 //purpose  : check if a hypothesis alowing notconform mesh is present
1207 //=======================================================================
1208
1209 bool SMESH_Mesh::IsNotConformAllowed() const
1210 {
1211   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1212
1213   SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1214   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1215 }
1216
1217 //=======================================================================
1218 //function : IsMainShape
1219 //purpose  : 
1220 //=======================================================================
1221
1222 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1223 {
1224   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1225 }
1226
1227 //=============================================================================
1228 /*!
1229  *  
1230  */
1231 //=============================================================================
1232
1233 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1234                                    const char*               theName,
1235                                    int&                      theId,
1236                                    const TopoDS_Shape&       theShape)
1237 {
1238   if (_mapGroup.find(_groupId) != _mapGroup.end())
1239     return NULL;
1240   theId = _groupId;
1241   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
1242   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1243   _mapGroup[_groupId++] = aGroup;
1244   return aGroup;
1245 }
1246
1247 //=============================================================================
1248 /*!
1249  *  
1250  */
1251 //=============================================================================
1252
1253 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1254 {
1255   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1256     return NULL;
1257   return _mapGroup[theGroupID];
1258 }
1259
1260
1261 //=============================================================================
1262 /*!
1263  *  
1264  */
1265 //=============================================================================
1266
1267 list<int> SMESH_Mesh::GetGroupIds()
1268 {
1269   list<int> anIds;
1270   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1271     anIds.push_back( it->first );
1272   
1273   return anIds;
1274 }
1275
1276
1277 //=============================================================================
1278 /*!
1279  *  
1280  */
1281 //=============================================================================
1282
1283 void SMESH_Mesh::RemoveGroup (const int theGroupID)
1284 {
1285   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1286     return;
1287   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1288   delete _mapGroup[theGroupID];
1289   _mapGroup.erase (theGroupID);
1290 }
1291
1292 //=============================================================================
1293 /*!
1294  *  IsLocal1DHypothesis
1295  *  Returns a local 1D hypothesis used for theEdge
1296  */
1297 //=============================================================================
1298 const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge)
1299 {
1300   SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 ));
1301   hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() ));
1302
1303   return GetHypothesis( theEdge, hypo, true );
1304 }
1305
1306 //=============================================================================
1307 /*!
1308  *  IsPropagationHypothesis
1309  */
1310 //=============================================================================
1311 bool SMESH_Mesh::IsPropagationHypothesis (const TopoDS_Shape& theEdge)
1312 {
1313   return _mapPropagationChains.Contains(theEdge);
1314 }
1315
1316 //=============================================================================
1317 /*!
1318  *  IsPropagatedHypothesis
1319  */
1320 //=============================================================================
1321 bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge,
1322                                          TopoDS_Shape&       theMainEdge)
1323 {
1324   int nbChains = _mapPropagationChains.Extent();
1325   for (int i = 1; i <= nbChains; i++) {
1326     //const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
1327     const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
1328     if (aChain.Contains(theEdge)) {
1329       theMainEdge = _mapPropagationChains.FindKey(i);
1330       return true;
1331     }
1332   }
1333
1334   return false;
1335 }
1336 //=============================================================================
1337 /*!
1338  *  IsReversedInChain
1339  */
1340 //=============================================================================
1341
1342 bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge,
1343                                     const TopoDS_Shape& theMainEdge)
1344 {
1345   if ( !theMainEdge.IsNull() && !theEdge.IsNull() &&
1346       _mapPropagationChains.Contains( theMainEdge ))
1347   {
1348     const SMESH_IndexedMapOfShape& aChain =
1349       _mapPropagationChains.FindFromKey( theMainEdge );
1350     int index = aChain.FindIndex( theEdge );
1351     if ( index )
1352       return aChain(index).Orientation() == TopAbs_REVERSED;
1353   }
1354   return false;
1355 }
1356
1357 //=============================================================================
1358 /*!
1359  *  CleanMeshOnPropagationChain
1360  */
1361 //=============================================================================
1362 void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge)
1363 {
1364   const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(theMainEdge);
1365   int i, nbEdges = aChain.Extent();
1366   for (i = 1; i <= nbEdges; i++) {
1367     TopoDS_Shape anEdge = aChain.FindKey(i);
1368     SMESH_subMesh *subMesh = GetSubMesh(anEdge);
1369     SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
1370     if (subMeshDS && subMeshDS->NbElements() > 0) {
1371       subMesh->ComputeStateEngine(SMESH_subMesh::CLEAN);
1372     }
1373   }
1374 }
1375
1376 //=============================================================================
1377 /*!
1378  *  RebuildPropagationChains
1379  *  Rebuild all existing propagation chains.
1380  *  Have to be used, if 1D hypothesis have been assigned/removed to/from any edge
1381  */
1382 //=============================================================================
1383 bool SMESH_Mesh::RebuildPropagationChains()
1384 {
1385   bool ret = true;
1386
1387   // Clean all chains, because they can be not up-to-date
1388   int i, nbChains = _mapPropagationChains.Extent();
1389   for (i = 1; i <= nbChains; i++) {
1390     TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
1391     CleanMeshOnPropagationChain(aMainEdge);
1392     _mapPropagationChains.ChangeFromIndex(i).Clear();
1393   }
1394
1395   // Build all chains
1396   for (i = 1; i <= nbChains; i++) {
1397     TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
1398     if (!BuildPropagationChain(aMainEdge))
1399       ret = false;
1400     CleanMeshOnPropagationChain(aMainEdge);
1401   }
1402
1403   return ret;
1404 }
1405
1406 //=============================================================================
1407 /*!
1408  *  RemovePropagationChain
1409  *  Have to be used, if Propagation hypothesis is removed from <theMainEdge>
1410  */
1411 //=============================================================================
1412 bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge)
1413 {
1414   if (!_mapPropagationChains.Contains(theMainEdge))
1415     return false;
1416
1417   // Clean mesh elements and nodes, built on the chain
1418   CleanMeshOnPropagationChain(theMainEdge);
1419
1420   // Clean the chain
1421   _mapPropagationChains.ChangeFromKey(theMainEdge).Clear();
1422
1423   // Remove the chain from the map
1424   int i = _mapPropagationChains.FindIndex(theMainEdge);
1425   if ( i == _mapPropagationChains.Extent() )
1426     _mapPropagationChains.RemoveLast();
1427   else {
1428     TopoDS_Vertex anEmptyShape;
1429     BRep_Builder BB;
1430     BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1);
1431     SMESH_IndexedMapOfShape anEmptyMap;
1432     _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap);
1433   }
1434
1435   return true;
1436 }
1437
1438 //=============================================================================
1439 /*!
1440  *  BuildPropagationChain
1441  */
1442 //=============================================================================
1443 bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
1444 {
1445   if (theMainEdge.ShapeType() != TopAbs_EDGE) return true;
1446
1447   // Add new chain, if there is no
1448   if (!_mapPropagationChains.Contains(theMainEdge)) {
1449     SMESH_IndexedMapOfShape aNewChain;
1450     _mapPropagationChains.Add(theMainEdge, aNewChain);
1451   }
1452
1453   // Check presence of 1D hypothesis to be propagated
1454   const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge);
1455   if (!aMainHyp) {
1456     MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign.");
1457     return true;
1458   }
1459
1460   // Edges, on which the 1D hypothesis will be propagated from <theMainEdge>
1461   SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge);
1462   if (aChain.Extent() > 0) {
1463     CleanMeshOnPropagationChain(theMainEdge);
1464     aChain.Clear();
1465   }
1466
1467   // At first put <theMainEdge> in the chain
1468   aChain.Add(theMainEdge);
1469
1470   // List of edges, added to chain on the previous cycle pass
1471   TopTools_ListOfShape listPrevEdges;
1472   listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD ));
1473
1474 //   5____4____3____4____5____6
1475 //   |    |    |    |    |    |
1476 //   |    |    |    |    |    |
1477 //   4____3____2____3____4____5
1478 //   |    |    |    |    |    |      Number in the each knot of
1479 //   |    |    |    |    |    |      grid indicates cycle pass,
1480 //   3____2____1____2____3____4      on which corresponding edge
1481 //   |    |    |    |    |    |      (perpendicular to the plane
1482 //   |    |    |    |    |    |      of view) will be found.
1483 //   2____1____0____1____2____3
1484 //   |    |    |    |    |    |
1485 //   |    |    |    |    |    |
1486 //   3____2____1____2____3____4
1487
1488   // Collect all edges pass by pass
1489   while (listPrevEdges.Extent() > 0) {
1490     // List of edges, added to chain on this cycle pass
1491     TopTools_ListOfShape listCurEdges;
1492
1493     // Find the next portion of edges
1494     TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
1495     for (; itE.More(); itE.Next()) {
1496       TopoDS_Shape anE = itE.Value();
1497
1498       // Iterate on faces, having edge <anE>
1499       TopTools_ListIteratorOfListOfShape itA (GetAncestors(anE));
1500       for (; itA.More(); itA.Next()) {
1501         TopoDS_Shape aW = itA.Value();
1502
1503         // There are objects of different type among the ancestors of edge
1504         if (aW.ShapeType() == TopAbs_WIRE) {
1505           TopoDS_Shape anOppE;
1506
1507           BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
1508           Standard_Integer nb = 1, found = 0;
1509           TopTools_Array1OfShape anEdges (1,4);
1510           for (; aWE.More(); aWE.Next(), nb++) {
1511             if (nb > 4) {
1512               found = 0;
1513               break;
1514             }
1515             anEdges(nb) = aWE.Current();
1516             if (!_mapAncestors.Contains(anEdges(nb))) {
1517               MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!");
1518               break;
1519             }
1520             if (anEdges(nb).IsSame(anE)) found = nb;
1521           }
1522
1523           if (nb == 5 && found > 0) {
1524             // Quadrangle face found, get an opposite edge
1525             Standard_Integer opp = found + 2;
1526             if (opp > 4) opp -= 4;
1527             anOppE = anEdges(opp);
1528
1529             // add anOppE to aChain if ...
1530             if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
1531               if (!IsLocal1DHypothesis(anOppE)) { // ... no other 1d hyp on anOppE
1532                 TopoDS_Shape aMainEdgeForOppEdge; // ... no other hyp is propagated to anOppE
1533                 if (!IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge))
1534                 {
1535                   // Add found edge to the chain oriented so that to
1536                   // have it co-directed with a forward MainEdge
1537                   TopAbs_Orientation ori = anE.Orientation();
1538                   if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
1539                     ori = TopAbs::Reverse( ori );
1540                   anOppE.Orientation( ori );
1541                   aChain.Add(anOppE);
1542                   listCurEdges.Append(anOppE);
1543                 }
1544                 else {
1545                   // Collision!
1546                   MESSAGE("Error: Collision between propagated hypotheses");
1547                   CleanMeshOnPropagationChain(theMainEdge);
1548                   aChain.Clear();
1549                   return ( aMainHyp == IsLocal1DHypothesis(aMainEdgeForOppEdge) );
1550                 }
1551               }
1552             }
1553           } // if (nb == 5 && found > 0)
1554         } // if (aF.ShapeType() == TopAbs_WIRE)
1555       } // for (; itF.More(); itF.Next())
1556     } // for (; itE.More(); itE.Next())
1557
1558     listPrevEdges = listCurEdges;
1559   } // while (listPrevEdges.Extent() > 0)
1560
1561   CleanMeshOnPropagationChain(theMainEdge);
1562   return true;
1563 }
1564
1565 //=======================================================================
1566 //function : GetAncestors
1567 //purpose  : return list of ancestors of theSubShape in the order
1568 //           that lower dimention shapes come first.
1569 //=======================================================================
1570
1571 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1572 {
1573   if ( _mapAncestors.Contains( theS ) )
1574     return _mapAncestors.FindFromKey( theS );
1575
1576   static TopTools_ListOfShape emptyList;
1577   return emptyList;
1578 }
1579
1580 //=======================================================================
1581 //function : Dump
1582 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1583 //=======================================================================
1584 ostream& SMESH_Mesh::Dump(ostream& save)
1585 {
1586   int clause = 0;
1587   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1588   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1589   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1590   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1591   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1592   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1593   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1594   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1595   {
1596     string orderStr = isQuadratic ? "quadratic" : "linear";
1597     ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1598
1599     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1600     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1601     if ( NbFaces(order) > 0 ) {
1602       int nb3 = NbTriangles(order);
1603       int nb4 = NbQuadrangles(order);
1604       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1605       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1606       if ( nb3 + nb4 !=  NbFaces(order) ) {
1607         map<int,int> myFaceMap;
1608         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1609         while( itFaces->more( ) ) {
1610           int nbNodes = itFaces->next()->NbNodes();
1611           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1612             myFaceMap[ nbNodes ] = 0;
1613           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1614         }
1615         save << clause << ".3) Faces in detail: " << endl;
1616         map <int,int>::iterator itF;
1617         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1618           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1619       }
1620     }
1621     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1622     if ( NbVolumes(order) > 0 ) {
1623       int nb8 = NbHexas(order);
1624       int nb4 = NbTetras(order);
1625       int nb5 = NbPyramids(order);
1626       int nb6 = NbPrisms(order);
1627       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1628       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1629       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1630       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1631       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1632         map<int,int> myVolumesMap;
1633         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1634         while( itVolumes->more( ) ) {
1635           int nbNodes = itVolumes->next()->NbNodes();
1636           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1637             myVolumesMap[ nbNodes ] = 0;
1638           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1639         }
1640         save << clause << ".5) Volumes in detail: " << endl;
1641         map <int,int>::iterator itV;
1642         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1643           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1644       }
1645     }
1646     save << endl;
1647   }
1648   save << "===========================================================================" << endl;
1649   return save;
1650 }
1651
1652 //=======================================================================
1653 //function : GetElementType
1654 //purpose  : Returns type of mesh element with certain id
1655 //=======================================================================
1656 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1657 {
1658   return _myMeshDS->GetElementType( id, iselem );
1659 }