Salome HOME
Nerge with PAL/SALOME 2.1.0d
[modules/smesh.git] / src / SMESH / SMESH_Mesh.cxx
1 //  SMESH SMESH : implementaion of SMESH idl descriptions
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : SMESH_Mesh.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESH_Mesh.hxx"
30 #include "SMESH_subMesh.hxx"
31 #include "SMESH_Gen.hxx"
32 #include "SMESH_Hypothesis.hxx"
33 #include "SMESH_Group.hxx"
34 #include "SMESHDS_Group.hxx"
35 #include "SMESHDS_Script.hxx"
36 #include "SMDS_MeshVolume.hxx"
37
38 #include "utilities.h"
39
40 #include "DriverMED_W_SMESHDS_Mesh.h"
41 #include "DriverDAT_W_SMDS_Mesh.h"
42 #include "DriverUNV_W_SMDS_Mesh.h"
43 #include "DriverSTL_W_SMDS_Mesh.h"
44
45 #include "DriverMED_R_SMESHDS_Mesh.h"
46 #include "DriverUNV_R_SMDS_Mesh.h"
47 #include "DriverSTL_R_SMDS_Mesh.h"
48
49 #include <TCollection_AsciiString.hxx>
50 #include <memory>
51 #include <TopTools_ListOfShape.hxx>
52 #include <TopExp.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54 #include "Utils_ExceptHandlers.hxx"
55
56 #ifdef _DEBUG_
57 static int MYDEBUG = 0;
58 #else
59 static int MYDEBUG = 0;
60 #endif
61
62
63 //=============================================================================
64 /*!
65  * 
66  */
67 //=============================================================================
68
69 SMESH_Mesh::SMESH_Mesh(int localId, int studyId, SMESH_Gen * gen, SMESHDS_Document * myDocument)
70 : _groupId( 0 )
71 {
72   INFOS("SMESH_Mesh::SMESH_Mesh(int localId)");
73         _id = localId;
74         _studyId = studyId;
75         _gen = gen;
76         _myDocument = myDocument;
77         _idDoc = _myDocument->NewMesh();
78         _myMeshDS = _myDocument->GetMesh(_idDoc);
79         _isShapeToMesh = false;
80 }
81
82 //=============================================================================
83 /*!
84  * 
85  */
86 //=============================================================================
87
88 SMESH_Mesh::~SMESH_Mesh()
89 {
90   INFOS("SMESH_Mesh::~SMESH_Mesh");
91
92   // delete groups
93   map < int, SMESH_Group * >::iterator itg;
94   for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
95     SMESH_Group *aGroup = (*itg).second;
96     delete aGroup;
97   }
98 }
99
100 //=============================================================================
101 /*!
102  * 
103  */
104 //=============================================================================
105
106 void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape){
107   if(MYDEBUG) MESSAGE("SMESH_Mesh::ShapeToMesh");
108   if (_isShapeToMesh)
109     throw
110       SALOME_Exception(LOCALIZED
111                        ("a shape to mesh as already been defined"));
112   _isShapeToMesh = true;
113   _myMeshDS->ShapeToMesh(aShape);
114   
115   // NRI : 24/02/03
116   //EAP: 1/9/04 TopExp::MapShapes(aShape, _subShapes); USE the same map of _myMeshDS
117 }
118
119 //=======================================================================
120 //function : UNVToMesh
121 //purpose  : 
122 //=======================================================================
123
124 int SMESH_Mesh::UNVToMesh(const char* theFileName)
125 {
126   if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
127   if(_isShapeToMesh)
128     throw SALOME_Exception(LOCALIZED("a shape to mesh as already been defined"));
129   _isShapeToMesh = true;
130   DriverUNV_R_SMDS_Mesh myReader;
131   myReader.SetMesh(_myMeshDS);
132   myReader.SetFile(theFileName);
133   myReader.SetMeshId(-1);
134   myReader.Perform();
135   if(MYDEBUG){
136     MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
137     MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
138     MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
139     MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
140   }
141   return 1;
142 }
143
144 //=======================================================================
145 //function : MEDToMesh
146 //purpose  : 
147 //=======================================================================
148
149 int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
150 {
151   if(MYDEBUG) MESSAGE("MEDToMesh - theFileName = "<<theFileName<<", mesh name = "<<theMeshName);
152   if(_isShapeToMesh)
153     throw SALOME_Exception(LOCALIZED("a shape to mesh as already been defined"));
154   _isShapeToMesh = true;
155   DriverMED_R_SMESHDS_Mesh myReader;
156   myReader.SetMesh(_myMeshDS);
157   myReader.SetMeshId(-1);
158   myReader.SetFile(theFileName);
159   myReader.SetMeshName(theMeshName);
160   Driver_Mesh::Status status = myReader.Perform();
161   if(MYDEBUG){
162     MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
163     MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
164     MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
165     MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
166   }
167
168   // Reading groups (sub-meshes are out of scope of MED import functionality)
169   list<string> aGroupNames = myReader.GetGroupNames();
170   if(MYDEBUG) MESSAGE("MEDToMesh - Nb groups = "<<aGroupNames.size()); 
171   int anId;
172   for ( list<string>::iterator it = aGroupNames.begin(); it != aGroupNames.end(); it++ ) {
173     SMESH_Group* aGroup = AddGroup( SMDSAbs_All, it->c_str(), anId );
174     if ( aGroup ) {
175       if(MYDEBUG) MESSAGE("MEDToMesh - group added: "<<it->c_str());      
176       SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
177       if ( aGroupDS ) {
178         aGroupDS->SetStoreName( it->c_str() );
179         myReader.GetGroup( aGroupDS );
180       }
181     }
182   }
183   return (int) status;
184 }
185
186 //=======================================================================
187 //function : STLToMesh
188 //purpose  : 
189 //=======================================================================
190
191 int SMESH_Mesh::STLToMesh(const char* theFileName)
192 {
193   if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
194   if(_isShapeToMesh)
195     throw SALOME_Exception(LOCALIZED("a shape to mesh as already been defined"));
196   _isShapeToMesh = true;
197   DriverSTL_R_SMDS_Mesh myReader;
198   myReader.SetMesh(_myMeshDS);
199   myReader.SetFile(theFileName);
200   myReader.SetMeshId(-1);
201   myReader.Perform();
202   if(MYDEBUG){
203     MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
204     MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
205     MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
206     MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
207   }
208   return 1;
209 }
210
211 //=============================================================================
212 /*!
213  * 
214  */
215 //=============================================================================
216
217 SMESH_Hypothesis::Hypothesis_Status
218   SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
219                             int                  anHypId  ) throw(SALOME_Exception)
220 {
221   Unexpect aCatch(SalomeException);
222   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
223
224   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
225   SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
226   if ( subMeshDS && subMeshDS->IsComplexSubmesh() )
227   {
228     // return the worst but not fatal state of all group memebers
229     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
230     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
231     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
232     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
233     {
234       ret = AddHypothesis( itS.Value(), anHypId );
235       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
236         aWorstNotFatal = ret;
237       if ( ret < aBestRet )
238         aBestRet = ret;
239     }
240     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
241       return aBestRet;
242     return aWorstNotFatal;
243   }
244
245   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
246   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
247   {
248     if(MYDEBUG) MESSAGE("Hypothesis ID does not give an hypothesis");
249     if(MYDEBUG) {
250       SCRUTE(_studyId);
251       SCRUTE(anHypId);
252     }
253     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
254   }
255
256   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
257   if(MYDEBUG) SCRUTE( anHyp->GetName() );
258   int event;
259
260   bool isGlobalHyp = IsMainShape( aSubShape );
261
262   // NotConformAllowed can be only global
263   if ( !isGlobalHyp )
264   {
265     string hypName = anHyp->GetName();
266     if ( hypName == "NotConformAllowed" )
267     {
268       if(MYDEBUG) MESSAGE( "Hypotesis <NotConformAllowed> can be only global" );
269       return SMESH_Hypothesis::HYP_INCOMPATIBLE;
270     }
271   }
272
273   // shape 
274
275   if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
276     event = SMESH_subMesh::ADD_HYP;
277   else
278     event = SMESH_subMesh::ADD_ALGO;
279   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
280
281   // subShapes
282   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
283       !subMesh->IsApplicableHypotesis( anHyp )) // is added on father
284   {
285     if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
286       event = SMESH_subMesh::ADD_FATHER_HYP;
287     else
288       event = SMESH_subMesh::ADD_FATHER_ALGO;
289     SMESH_Hypothesis::Hypothesis_Status ret2 =
290       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
291     if (ret2 > ret)
292       ret = ret2;
293   }
294
295   subMesh->DumpAlgoState(true);
296   if(MYDEBUG) SCRUTE(ret);
297   return ret;
298 }
299
300 //=============================================================================
301 /*!
302  * 
303  */
304 //=============================================================================
305
306 SMESH_Hypothesis::Hypothesis_Status
307   SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
308                                int anHypId)throw(SALOME_Exception)
309 {
310   Unexpect aCatch(SalomeException);
311   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
312   
313   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
314   SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
315   if ( subMeshDS && subMeshDS->IsComplexSubmesh() )
316   {
317     // return the worst but not fatal state of all group memebers
318     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
319     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
320     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
321     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
322     {
323       ret = RemoveHypothesis( itS.Value(), anHypId );
324       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
325         aWorstNotFatal = ret;
326       if ( ret < aBestRet )
327         aBestRet = ret;
328     }
329     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
330       return aBestRet;
331     return aWorstNotFatal;
332   }
333
334   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
335   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
336     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
337   
338   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
339   int hypType = anHyp->GetType();
340   if(MYDEBUG) SCRUTE(hypType);
341   int event;
342   
343   // shape 
344   
345   if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
346     event = SMESH_subMesh::REMOVE_HYP;
347   else
348     event = SMESH_subMesh::REMOVE_ALGO;
349   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
350   
351   // subShapes
352   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
353       !subMesh->IsApplicableHypotesis( anHyp )) // is removed from father
354     {
355       if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
356         event = SMESH_subMesh::REMOVE_FATHER_HYP;
357       else
358         event = SMESH_subMesh::REMOVE_FATHER_ALGO;
359       SMESH_Hypothesis::Hypothesis_Status ret2 =
360         subMesh->SubMeshesAlgoStateEngine(event, anHyp);
361       if (ret2 > ret) // more severe
362         ret = ret2;
363     }
364   
365   subMesh->DumpAlgoState(true);
366   if(MYDEBUG) SCRUTE(ret);
367   return ret;
368 }
369
370 //=============================================================================
371 /*!
372  * 
373  */
374 //=============================================================================
375
376 SMESHDS_Mesh * SMESH_Mesh::GetMeshDS()
377 {
378   return _myMeshDS;
379 }
380
381 //=============================================================================
382 /*!
383  * 
384  */
385 //=============================================================================
386
387 const list<const SMESHDS_Hypothesis*>&
388 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
389   throw(SALOME_Exception)
390 {
391   Unexpect aCatch(SalomeException);
392   return _myMeshDS->GetHypothesis(aSubShape);
393 }
394
395 //=============================================================================
396 /*!
397  * 
398  */
399 //=============================================================================
400
401 const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
402 {
403   Unexpect aCatch(SalomeException);
404   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
405   return _myMeshDS->GetScript()->GetCommands();
406 }
407
408 //=============================================================================
409 /*!
410  * 
411  */
412 //=============================================================================
413 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
414 {
415   Unexpect aCatch(SalomeException);
416   if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
417   _myMeshDS->GetScript()->Clear();
418 }
419
420 //=============================================================================
421 /*!
422  * 
423  */
424 //=============================================================================
425
426 int SMESH_Mesh::GetId()
427 {
428   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetId");
429   return _id;
430 }
431
432 //=============================================================================
433 /*!
434  * 
435  */
436 //=============================================================================
437
438 SMESH_Gen *SMESH_Mesh::GetGen()
439 {
440   return _gen;
441 }
442
443 //=============================================================================
444 /*!
445  * Get or Create the SMESH_subMesh object implementation
446  */
447 //=============================================================================
448
449 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
450 throw(SALOME_Exception)
451 {
452   Unexpect aCatch(SalomeException);
453   SMESH_subMesh *aSubMesh;
454   int index = _myMeshDS->ShapeToIndex(aSubShape);
455   
456   // for submeshes on GEOM Group
457   if ( !index && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
458     TopoDS_Iterator it( aSubShape );
459     if ( it.More() )
460       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
461   }
462
463   if (_mapSubMesh.find(index) != _mapSubMesh.end())
464     {
465       aSubMesh = _mapSubMesh[index];
466     }
467   else
468     {
469       aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
470       _mapSubMesh[index] = aSubMesh;
471     }
472   return aSubMesh;
473 }
474
475 //=============================================================================
476 /*!
477  * Get the SMESH_subMesh object implementation. Dont create it, return null
478  * if it does not exist.
479  */
480 //=============================================================================
481
482 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
483 throw(SALOME_Exception)
484 {
485   Unexpect aCatch(SalomeException);
486   bool isFound = false;
487   SMESH_subMesh *aSubMesh = NULL;
488   
489   int index = _myMeshDS->ShapeToIndex(aSubShape);
490   if (_mapSubMesh.find(index) != _mapSubMesh.end())
491     {
492       aSubMesh = _mapSubMesh[index];
493       isFound = true;
494     }
495   if (!isFound)
496     aSubMesh = NULL;
497   return aSubMesh;
498 }
499
500 //=======================================================================
501 //function : IsUsedHypothesis
502 //purpose  : Return True if anHyp is used to mesh aSubShape
503 //=======================================================================
504
505 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
506                                   const TopoDS_Shape & aSubShape)
507 {
508   // check if anHyp is applicable to aSubShape
509   SMESH_subMesh * subMesh = GetSubMeshContaining( aSubShape );
510   if (!subMesh ||
511       !subMesh->IsApplicableHypotesis(static_cast<SMESH_Hypothesis*>(anHyp)))
512     return false;
513
514   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape);
515
516   // algorithm
517   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
518     return ( anHyp == algo );
519
520   // algorithm parameter
521   if (algo)
522   {
523     // look trough hypotheses used by algo
524     const list <const SMESHDS_Hypothesis * >&usedHyps =
525       algo->GetUsedHypothesis(*this, aSubShape);
526     list <const SMESHDS_Hypothesis * >::const_iterator itl;
527     for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
528       if (anHyp == (*itl))
529         return true;
530   }
531   else
532   {
533     // look through all assigned hypotheses
534     {
535       const list <const SMESHDS_Hypothesis * >&usedHyps =
536         _myMeshDS->GetHypothesis( aSubShape );
537       list <const SMESHDS_Hypothesis * >::const_iterator itl;
538       for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
539         if (anHyp == (*itl))
540           return true;
541     }
542
543     // on ancestors
544     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
545     for (; it.More(); it.Next())
546     {
547       const list <const SMESHDS_Hypothesis * >&usedHyps =
548         _myMeshDS->GetHypothesis( aSubShape );
549       list <const SMESHDS_Hypothesis * >::const_iterator itl;
550       for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
551         if (anHyp == (*itl))
552           return true;
553     }
554   }
555     
556   return false;
557 }
558
559
560 //=============================================================================
561 /*!
562  *
563  */
564 //=============================================================================
565
566 const list < SMESH_subMesh * >&
567         SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
568 throw(SALOME_Exception)
569 {
570   Unexpect aCatch(SalomeException);
571         if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
572         map < int, SMESH_subMesh * >::iterator itsm;
573         _subMeshesUsingHypothesisList.clear();
574         for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
575         {
576                 SMESH_subMesh *aSubMesh = (*itsm).second;
577                 if ( IsUsedHypothesis ( anHyp, aSubMesh->GetSubShape() ))
578                         _subMeshesUsingHypothesisList.push_back(aSubMesh);
579         }
580         return _subMeshesUsingHypothesisList;
581 }
582
583 //=============================================================================
584 /*!
585  *
586  */
587 //=============================================================================
588
589 void SMESH_Mesh::ExportMED(const char *file, const char* theMeshName, bool theAutoGroups) throw(SALOME_Exception)
590 {
591   Unexpect aCatch(SalomeException);
592   DriverMED_W_SMESHDS_Mesh myWriter;
593   myWriter.SetFile    ( file        );
594   myWriter.SetMesh    ( _myMeshDS   );
595   if ( !theMeshName ) 
596     myWriter.SetMeshId  ( _idDoc      );
597   else {
598     myWriter.SetMeshId  ( -1          );
599     myWriter.SetMeshName( theMeshName );
600   }
601
602   if ( theAutoGroups ) {
603     myWriter.AddGroupOfNodes();
604     myWriter.AddGroupOfEdges();
605     myWriter.AddGroupOfFaces();
606     myWriter.AddGroupOfVolumes();
607   }
608
609   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
610     SMESH_Group*       aGroup   = it->second;
611     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
612     if ( aGroupDS ) {
613       aGroupDS->SetStoreName( aGroup->GetName() );
614       myWriter.AddGroup( aGroupDS );
615     }
616   }
617
618   myWriter.Perform();
619 }
620
621 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
622 {
623   Unexpect aCatch(SalomeException);
624   DriverDAT_W_SMDS_Mesh myWriter;
625   myWriter.SetFile(string(file));
626   myWriter.SetMesh(_myMeshDS);
627   myWriter.SetMeshId(_idDoc);
628   myWriter.Perform();
629 }
630
631 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
632 {
633   Unexpect aCatch(SalomeException);
634   DriverUNV_W_SMDS_Mesh myWriter;
635   myWriter.SetFile(string(file));
636   myWriter.SetMesh(_myMeshDS);
637   myWriter.SetMeshId(_idDoc);
638   myWriter.Perform();
639 }
640
641 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
642 {
643   Unexpect aCatch(SalomeException);
644   DriverSTL_W_SMDS_Mesh myWriter;
645   myWriter.SetFile(string(file));
646   myWriter.SetIsAscii( isascii );
647   myWriter.SetMesh(_myMeshDS);
648   myWriter.SetMeshId(_idDoc);
649   myWriter.Perform();
650 }
651
652 //=============================================================================
653 /*!
654  *  
655  */
656 //=============================================================================
657 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
658 {
659   Unexpect aCatch(SalomeException);
660   return _myMeshDS->NbNodes();
661 }
662
663 //=============================================================================
664 /*!
665  *  
666  */
667 //=============================================================================
668 int SMESH_Mesh::NbEdges() throw(SALOME_Exception)
669 {
670   Unexpect aCatch(SalomeException);
671   return _myMeshDS->NbEdges();
672 }
673
674 //=============================================================================
675 /*!
676  *  
677  */
678 //=============================================================================
679 int SMESH_Mesh::NbFaces() throw(SALOME_Exception)
680 {
681   Unexpect aCatch(SalomeException);
682   return _myMeshDS->NbFaces();
683 }
684
685 ///////////////////////////////////////////////////////////////////////////////
686 /// Return the number of 3 nodes faces in the mesh. This method run in O(n)
687 ///////////////////////////////////////////////////////////////////////////////
688 int SMESH_Mesh::NbTriangles() throw(SALOME_Exception)
689 {
690   Unexpect aCatch(SalomeException);
691   int Nb = 0;
692   
693   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
694   while(itFaces->more()) if(itFaces->next()->NbNodes()==3) Nb++;
695   return Nb;
696 }
697
698 ///////////////////////////////////////////////////////////////////////////////
699 /// Return the number of 4 nodes faces in the mesh. This method run in O(n)
700 ///////////////////////////////////////////////////////////////////////////////
701 int SMESH_Mesh::NbQuadrangles() throw(SALOME_Exception)
702 {
703   Unexpect aCatch(SalomeException);
704   int Nb = 0;
705   
706   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
707   while(itFaces->more()) if(itFaces->next()->NbNodes()==4) Nb++;
708   return Nb;
709 }
710
711 //=============================================================================
712 /*!
713  *  
714  */
715 //=============================================================================
716 int SMESH_Mesh::NbVolumes() throw(SALOME_Exception)
717 {
718   Unexpect aCatch(SalomeException);
719   return _myMeshDS->NbVolumes();
720 }
721
722 int SMESH_Mesh::NbTetras() throw(SALOME_Exception)
723 {
724   Unexpect aCatch(SalomeException);
725   int Nb = 0;
726   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
727   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==4) Nb++;
728   return Nb;
729 }
730
731 int SMESH_Mesh::NbHexas() throw(SALOME_Exception)
732 {
733   Unexpect aCatch(SalomeException);
734   int Nb = 0;
735   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
736   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==8) Nb++;
737   return Nb;
738 }
739
740 int SMESH_Mesh::NbPyramids() throw(SALOME_Exception)
741 {
742   Unexpect aCatch(SalomeException);
743   int Nb = 0;
744   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
745   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==5) Nb++;
746   return Nb;
747 }
748
749 int SMESH_Mesh::NbPrisms() throw(SALOME_Exception)
750 {
751   Unexpect aCatch(SalomeException);
752   int Nb = 0;
753   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
754   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==6) Nb++;
755   return Nb;
756 }
757
758 //=============================================================================
759 /*!
760  *  
761  */
762 //=============================================================================
763 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
764 {
765   Unexpect aCatch(SalomeException);
766   return _myMeshDS->NbSubMesh();
767 }
768
769 //=======================================================================
770 //function : IsNotConformAllowed
771 //purpose  : check if a hypothesis alowing notconform mesh is present
772 //=======================================================================
773
774 bool SMESH_Mesh::IsNotConformAllowed() const
775 {
776   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
777
778   const list<const SMESHDS_Hypothesis*>& listHyp =
779     _myMeshDS->GetHypothesis( _myMeshDS->ShapeToMesh() );
780   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
781   while (it!=listHyp.end())
782   {
783     const SMESHDS_Hypothesis *aHyp = *it;
784     string hypName = aHyp->GetName();
785     if ( hypName == "NotConformAllowed" )
786       return true;
787     it++;
788   }
789   return false;
790 }
791
792 //=======================================================================
793 //function : IsMainShape
794 //purpose  : 
795 //=======================================================================
796
797 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
798 {
799   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
800 }
801
802 //=============================================================================
803 /*!
804  *  
805  */
806 //=============================================================================
807
808 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
809                                    const char*               theName,
810                                    int&                      theId,
811                                    const TopoDS_Shape&       theShape)
812 {
813   if (_mapGroup.find(_groupId) != _mapGroup.end())
814     return NULL;
815   theId = _groupId;
816   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
817   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
818   _mapGroup[_groupId++] = aGroup;
819   return aGroup;
820 }
821
822 //=============================================================================
823 /*!
824  *  
825  */
826 //=============================================================================
827
828 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
829 {
830   if (_mapGroup.find(theGroupID) == _mapGroup.end())
831     return NULL;
832   return _mapGroup[theGroupID];
833 }
834
835
836 //=============================================================================
837 /*!
838  *  
839  */
840 //=============================================================================
841
842 list<int> SMESH_Mesh::GetGroupIds()
843 {
844   list<int> anIds;
845   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
846     anIds.push_back( it->first );
847   
848   return anIds;
849 }
850
851
852 //=============================================================================
853 /*!
854  *  
855  */
856 //=============================================================================
857
858 void SMESH_Mesh::RemoveGroup (const int theGroupID)
859 {
860   if (_mapGroup.find(theGroupID) == _mapGroup.end())
861     return;
862   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
863   _mapGroup.erase (theGroupID);
864   delete _mapGroup[theGroupID];
865 }
866
867 //=======================================================================
868 //function : GetAncestors
869 //purpose  : return list of ancestors of theSubShape in the order
870 //           that lower dimention shapes come first.
871 //=======================================================================
872
873 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS)
874 {
875   if ( _mapAncestors.IsEmpty() )
876   {
877     // fill _mapAncestors
878     int desType, ancType;
879     for ( desType = TopAbs_EDGE; desType > TopAbs_COMPOUND; desType-- )
880       for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
881         TopExp::MapShapesAndAncestors (_myMeshDS->ShapeToMesh(),
882                                        (TopAbs_ShapeEnum) desType,
883                                        (TopAbs_ShapeEnum) ancType,
884                                        _mapAncestors );
885   }
886
887   if ( _mapAncestors.Contains( theS ) )
888     return _mapAncestors.FindFromKey( theS );
889
890   static TopTools_ListOfShape emptyList;
891   return emptyList;
892 }
893
894 //=======================================================================
895 //function : Dump
896 //purpose  : dumps contents of mesh to stream [ debug purposes ]
897 //=======================================================================
898 ostream& SMESH_Mesh::Dump(ostream& save)
899 {
900   save << "========================== Dump contents of mesh ==========================" << endl;
901   save << "1) Total number of nodes:     " << NbNodes() << endl;
902   save << "2) Total number of edges:     " << NbEdges() << endl;
903   save << "3) Total number of faces:     " << NbFaces() << endl;
904   if ( NbFaces() > 0 ) {
905     int nb3 = NbTriangles();
906     int nb4 = NbQuadrangles();
907     save << "3.1.) Number of triangles:    " << nb3 << endl;
908     save << "3.2.) Number of quadrangles:  " << nb4 << endl;
909     if ( nb3 + nb4 !=  NbFaces() ) {
910       map<int,int> myFaceMap;
911       SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
912       while( itFaces->more( ) ) {
913         int nbNodes = itFaces->next()->NbNodes();
914         if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
915           myFaceMap[ nbNodes ] = 0;
916         myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
917       }
918       save << "3.3.) Faces in detail: " << endl;
919       map <int,int>::iterator itF;
920       for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
921         save << "--> nb nodes: " << itF->first << " - nb elemens: " << itF->second << endl;
922     }
923   }
924   save << "4) Total number of volumes:   " << NbVolumes() << endl;
925   if ( NbVolumes() > 0 ) {
926     int nb8 = NbHexas();
927     int nb4 = NbTetras();
928     int nb5 = NbPyramids();
929     int nb6 = NbPrisms();
930     save << "4.1.) Number of hexahedrons:  " << nb8 << endl;
931     save << "4.2.) Number of tetrahedrons: " << nb4 << endl;
932     save << "4.3.) Number of prisms:       " << nb6 << endl;
933     save << "4.4.) Number of pyramides:    " << nb5 << endl;
934     if ( nb8 + nb4 + nb5 + nb6 != NbVolumes() ) {
935       map<int,int> myVolumesMap;
936       SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
937       while( itVolumes->more( ) ) {
938         int nbNodes = itVolumes->next()->NbNodes();
939         if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
940           myVolumesMap[ nbNodes ] = 0;
941         myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
942       }
943       save << "4.5.) Volumes in detail: " << endl;
944       map <int,int>::iterator itV;
945       for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
946         save << "--> nb nodes: " << itV->first << " - nb elemens: " << itV->second << endl;
947     }
948   }
949   save << "===========================================================================" << endl;
950   return save;
951 }