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