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