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