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