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