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