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