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