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