Salome HOME
Integration of PAL/SALOME V2.1.0c from OCC
[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 = aGroup->GetGroupDS();
177       aGroupDS->SetStoreName( it->c_str() );
178       myReader.GetGroup( aGroupDS );
179     }
180   }
181   return (int) status;
182 }
183
184 //=======================================================================
185 //function : STLToMesh
186 //purpose  : 
187 //=======================================================================
188
189 int SMESH_Mesh::STLToMesh(const char* theFileName)
190 {
191   if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
192   if(_isShapeToMesh)
193     throw SALOME_Exception(LOCALIZED("a shape to mesh as already been defined"));
194   _isShapeToMesh = true;
195   DriverSTL_R_SMDS_Mesh myReader;
196   myReader.SetMesh(_myMeshDS);
197   myReader.SetFile(theFileName);
198   myReader.SetMeshId(-1);
199   myReader.Perform();
200   if(MYDEBUG){
201     MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
202     MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
203     MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
204     MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
205   }
206   return 1;
207 }
208
209 //=============================================================================
210 /*!
211  * 
212  */
213 //=============================================================================
214
215 SMESH_Hypothesis::Hypothesis_Status
216   SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
217                             int                  anHypId  ) throw(SALOME_Exception)
218 {
219   Unexpect aCatch(SalomeException);
220   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
221
222   if ( _myMeshDS->IsGroupOfSubShapes( aSubShape ))
223   {
224     // return the worst but not fatal state of all group memebers
225     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
226     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
227     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
228     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
229     {
230       ret = AddHypothesis( itS.Value(), anHypId );
231       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
232         aWorstNotFatal = ret;
233       if ( ret < aBestRet )
234         aBestRet = ret;
235     }
236     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
237       return aBestRet;
238     return aWorstNotFatal;
239   }
240
241   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
242   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
243   {
244     if(MYDEBUG) MESSAGE("Hypothesis ID does not give an hypothesis");
245     if(MYDEBUG) {
246       SCRUTE(_studyId);
247       SCRUTE(anHypId);
248     }
249     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
250   }
251
252   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
253   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
254   if(MYDEBUG) SCRUTE( anHyp->GetName() );
255   int event;
256
257   bool isGlobalHyp = IsMainShape( aSubShape );
258
259   // NotConformAllowed can be only global
260   if ( !isGlobalHyp )
261   {
262     string hypName = anHyp->GetName();
263     if ( hypName == "NotConformAllowed" )
264     {
265       if(MYDEBUG) MESSAGE( "Hypotesis <NotConformAllowed> can be only global" );
266       return SMESH_Hypothesis::HYP_INCOMPATIBLE;
267     }
268   }
269
270   // shape 
271
272   if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
273     event = SMESH_subMesh::ADD_HYP;
274   else
275     event = SMESH_subMesh::ADD_ALGO;
276   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
277
278   // subShapes
279   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
280       !subMesh->IsApplicableHypotesis( anHyp )) // is added on father
281   {
282     if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
283       event = SMESH_subMesh::ADD_FATHER_HYP;
284     else
285       event = SMESH_subMesh::ADD_FATHER_ALGO;
286     SMESH_Hypothesis::Hypothesis_Status ret2 =
287       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
288     if (ret2 > ret)
289       ret = ret2;
290   }
291
292   subMesh->DumpAlgoState(true);
293   if(MYDEBUG) SCRUTE(ret);
294   return ret;
295 }
296
297 //=============================================================================
298 /*!
299  * 
300  */
301 //=============================================================================
302
303 SMESH_Hypothesis::Hypothesis_Status
304   SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
305                                int anHypId)throw(SALOME_Exception)
306 {
307   Unexpect aCatch(SalomeException);
308   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
309   
310   if ( _myMeshDS->IsGroupOfSubShapes( aSubShape ))
311   {
312     // return the worst but not fatal state of all group memebers
313     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
314     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
315     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
316     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
317     {
318       ret = RemoveHypothesis( itS.Value(), anHypId );
319       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
320         aWorstNotFatal = ret;
321       if ( ret < aBestRet )
322         aBestRet = ret;
323     }
324     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
325       return aBestRet;
326     return aWorstNotFatal;
327   }
328
329   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
330   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
331     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
332   
333   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
334   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
335   int hypType = anHyp->GetType();
336   if(MYDEBUG) SCRUTE(hypType);
337   int event;
338   
339   // shape 
340   
341   if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
342     event = SMESH_subMesh::REMOVE_HYP;
343   else
344     event = SMESH_subMesh::REMOVE_ALGO;
345   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
346   
347   // subShapes
348   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
349       !subMesh->IsApplicableHypotesis( anHyp )) // is removed from father
350     {
351       if (anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
352         event = SMESH_subMesh::REMOVE_FATHER_HYP;
353       else
354         event = SMESH_subMesh::REMOVE_FATHER_ALGO;
355       SMESH_Hypothesis::Hypothesis_Status ret2 =
356         subMesh->SubMeshesAlgoStateEngine(event, anHyp);
357       if (ret2 > ret) // more severe
358         ret = ret2;
359     }
360   
361   subMesh->DumpAlgoState(true);
362   if(MYDEBUG) SCRUTE(ret);
363   return ret;
364 }
365
366 //=============================================================================
367 /*!
368  * 
369  */
370 //=============================================================================
371
372 SMESHDS_Mesh * SMESH_Mesh::GetMeshDS()
373 {
374   return _myMeshDS;
375 }
376
377 //=============================================================================
378 /*!
379  * 
380  */
381 //=============================================================================
382
383 const list<const SMESHDS_Hypothesis*>&
384 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
385   throw(SALOME_Exception)
386 {
387   Unexpect aCatch(SalomeException);
388   return _myMeshDS->GetHypothesis(aSubShape);
389 }
390
391 //=============================================================================
392 /*!
393  * 
394  */
395 //=============================================================================
396
397 const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
398 {
399   Unexpect aCatch(SalomeException);
400   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
401   return _myMeshDS->GetScript()->GetCommands();
402 }
403
404 //=============================================================================
405 /*!
406  * 
407  */
408 //=============================================================================
409 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
410 {
411   Unexpect aCatch(SalomeException);
412   if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
413   _myMeshDS->GetScript()->Clear();
414 }
415
416 //=============================================================================
417 /*!
418  * 
419  */
420 //=============================================================================
421
422 int SMESH_Mesh::GetId()
423 {
424   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetId");
425   return _id;
426 }
427
428 //=============================================================================
429 /*!
430  * 
431  */
432 //=============================================================================
433
434 SMESH_Gen *SMESH_Mesh::GetGen()
435 {
436   return _gen;
437 }
438
439 //=============================================================================
440 /*!
441  * Get or Create the SMESH_subMesh object implementation
442  */
443 //=============================================================================
444
445 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
446 throw(SALOME_Exception)
447 {
448   Unexpect aCatch(SalomeException);
449   SMESH_subMesh *aSubMesh;
450   int index = _myMeshDS->ShapeToIndex(aSubShape);
451   
452   if (_mapSubMesh.find(index) != _mapSubMesh.end())
453     {
454       aSubMesh = _mapSubMesh[index];
455     }
456   else
457     {
458       aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
459       _mapSubMesh[index] = aSubMesh;
460     }
461   return aSubMesh;
462 }
463
464 //=============================================================================
465 /*!
466  * Get the SMESH_subMesh object implementation. Dont create it, return null
467  * if it does not exist.
468  */
469 //=============================================================================
470
471 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
472 throw(SALOME_Exception)
473 {
474   Unexpect aCatch(SalomeException);
475   bool isFound = false;
476   SMESH_subMesh *aSubMesh = NULL;
477   
478   int index = _myMeshDS->ShapeToIndex(aSubShape);
479   if (_mapSubMesh.find(index) != _mapSubMesh.end())
480     {
481       aSubMesh = _mapSubMesh[index];
482       isFound = true;
483     }
484   if (!isFound)
485     aSubMesh = NULL;
486   return aSubMesh;
487 }
488
489 //=======================================================================
490 //function : IsUsedHypothesis
491 //purpose  : Return True if anHyp is used to mesh aSubShape
492 //=======================================================================
493
494 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
495                                   const TopoDS_Shape & aSubShape)
496 {
497   // check if anHyp is applicable to aSubShape
498   SMESH_subMesh * subMesh = GetSubMeshContaining( aSubShape );
499   if (!subMesh ||
500       !subMesh->IsApplicableHypotesis(static_cast<SMESH_Hypothesis*>(anHyp)))
501     return false;
502
503   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape);
504
505   // algorithm
506   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
507     return ( anHyp == algo );
508
509   // algorithm parameter
510   if (algo)
511   {
512     // look trough hypotheses used by algo
513     const list <const SMESHDS_Hypothesis * >&usedHyps =
514       algo->GetUsedHypothesis(*this, aSubShape);
515     list <const SMESHDS_Hypothesis * >::const_iterator itl;
516     for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
517       if (anHyp == (*itl))
518         return true;
519   }
520   else
521   {
522     // look through all assigned hypotheses
523     {
524       const list <const SMESHDS_Hypothesis * >&usedHyps =
525         _myMeshDS->GetHypothesis( 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
532     // on ancestors
533     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
534     for (; it.More(); it.Next())
535     {
536       const list <const SMESHDS_Hypothesis * >&usedHyps =
537         _myMeshDS->GetHypothesis( aSubShape );
538       list <const SMESHDS_Hypothesis * >::const_iterator itl;
539       for (itl = usedHyps.begin(); itl != usedHyps.end(); itl++)
540         if (anHyp == (*itl))
541           return true;
542     }
543   }
544     
545   return false;
546 }
547
548
549 //=============================================================================
550 /*!
551  *
552  */
553 //=============================================================================
554
555 const list < SMESH_subMesh * >&
556         SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
557 throw(SALOME_Exception)
558 {
559   Unexpect aCatch(SalomeException);
560         if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
561         map < int, SMESH_subMesh * >::iterator itsm;
562         _subMeshesUsingHypothesisList.clear();
563         for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
564         {
565                 SMESH_subMesh *aSubMesh = (*itsm).second;
566                 if ( IsUsedHypothesis ( anHyp, aSubMesh->GetSubShape() ))
567                         _subMeshesUsingHypothesisList.push_back(aSubMesh);
568         }
569         return _subMeshesUsingHypothesisList;
570 }
571
572 //=============================================================================
573 /*!
574  *
575  */
576 //=============================================================================
577
578 void SMESH_Mesh::ExportMED(const char *file, const char* theMeshName, bool theAutoGroups) throw(SALOME_Exception)
579 {
580   Unexpect aCatch(SalomeException);
581   DriverMED_W_SMESHDS_Mesh myWriter;
582   myWriter.SetFile    ( file        );
583   myWriter.SetMesh    ( _myMeshDS   );
584   if ( !theMeshName ) 
585     myWriter.SetMeshId  ( _idDoc      );
586   else {
587     myWriter.SetMeshId  ( -1          );
588     myWriter.SetMeshName( theMeshName );
589   }
590
591   if ( theAutoGroups ) {
592     myWriter.AddGroupOfNodes();
593     myWriter.AddGroupOfEdges();
594     myWriter.AddGroupOfFaces();
595     myWriter.AddGroupOfVolumes();
596   }
597
598   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
599     SMESH_Group*     aGroup = it->second;
600     SMESHDS_Group* aGroupDS = aGroup->GetGroupDS();
601     aGroupDS->SetStoreName( aGroup->GetName() );
602     myWriter.AddGroup( aGroupDS );
603   }
604
605   myWriter.Perform();
606 }
607
608 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
609 {
610   Unexpect aCatch(SalomeException);
611   DriverDAT_W_SMDS_Mesh myWriter;
612   myWriter.SetFile(string(file));
613   myWriter.SetMesh(_myMeshDS);
614   myWriter.SetMeshId(_idDoc);
615   myWriter.Perform();
616 }
617
618 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
619 {
620   Unexpect aCatch(SalomeException);
621   DriverUNV_W_SMDS_Mesh myWriter;
622   myWriter.SetFile(string(file));
623   myWriter.SetMesh(_myMeshDS);
624   myWriter.SetMeshId(_idDoc);
625   myWriter.Perform();
626 }
627
628 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
629 {
630   Unexpect aCatch(SalomeException);
631   DriverSTL_W_SMDS_Mesh myWriter;
632   myWriter.SetFile(string(file));
633   myWriter.SetIsAscii( isascii );
634   myWriter.SetMesh(_myMeshDS);
635   myWriter.SetMeshId(_idDoc);
636   myWriter.Perform();
637 }
638
639 //=============================================================================
640 /*!
641  *  
642  */
643 //=============================================================================
644 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
645 {
646   Unexpect aCatch(SalomeException);
647   return _myMeshDS->NbNodes();
648 }
649
650 //=============================================================================
651 /*!
652  *  
653  */
654 //=============================================================================
655 int SMESH_Mesh::NbEdges() throw(SALOME_Exception)
656 {
657   Unexpect aCatch(SalomeException);
658   return _myMeshDS->NbEdges();
659 }
660
661 //=============================================================================
662 /*!
663  *  
664  */
665 //=============================================================================
666 int SMESH_Mesh::NbFaces() throw(SALOME_Exception)
667 {
668   Unexpect aCatch(SalomeException);
669   return _myMeshDS->NbFaces();
670 }
671
672 ///////////////////////////////////////////////////////////////////////////////
673 /// Return the number of 3 nodes faces in the mesh. This method run in O(n)
674 ///////////////////////////////////////////////////////////////////////////////
675 int SMESH_Mesh::NbTriangles() throw(SALOME_Exception)
676 {
677   Unexpect aCatch(SalomeException);
678   int Nb = 0;
679   
680   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
681   while(itFaces->more()) if(itFaces->next()->NbNodes()==3) Nb++;
682   return Nb;
683 }
684
685 ///////////////////////////////////////////////////////////////////////////////
686 /// Return the number of 4 nodes faces in the mesh. This method run in O(n)
687 ///////////////////////////////////////////////////////////////////////////////
688 int SMESH_Mesh::NbQuadrangles() 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()==4) Nb++;
695   return Nb;
696 }
697
698 //=============================================================================
699 /*!
700  *  
701  */
702 //=============================================================================
703 int SMESH_Mesh::NbVolumes() throw(SALOME_Exception)
704 {
705   Unexpect aCatch(SalomeException);
706   return _myMeshDS->NbVolumes();
707 }
708
709 int SMESH_Mesh::NbTetras() throw(SALOME_Exception)
710 {
711   Unexpect aCatch(SalomeException);
712   int Nb = 0;
713   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
714   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==4) Nb++;
715   return Nb;
716 }
717
718 int SMESH_Mesh::NbHexas() throw(SALOME_Exception)
719 {
720   Unexpect aCatch(SalomeException);
721   int Nb = 0;
722   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
723   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==8) Nb++;
724   return Nb;
725 }
726
727 int SMESH_Mesh::NbPyramids() throw(SALOME_Exception)
728 {
729   Unexpect aCatch(SalomeException);
730   int Nb = 0;
731   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
732   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==5) Nb++;
733   return Nb;
734 }
735
736 int SMESH_Mesh::NbPrisms() throw(SALOME_Exception)
737 {
738   Unexpect aCatch(SalomeException);
739   int Nb = 0;
740   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
741   while(itVolumes->more()) if(itVolumes->next()->NbNodes()==6) Nb++;
742   return Nb;
743 }
744
745 //=============================================================================
746 /*!
747  *  
748  */
749 //=============================================================================
750 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
751 {
752   Unexpect aCatch(SalomeException);
753   return _myMeshDS->NbSubMesh();
754 }
755
756 //=======================================================================
757 //function : IsNotConformAllowed
758 //purpose  : check if a hypothesis alowing notconform mesh is present
759 //=======================================================================
760
761 bool SMESH_Mesh::IsNotConformAllowed() const
762 {
763   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
764
765   const list<const SMESHDS_Hypothesis*>& listHyp =
766     _myMeshDS->GetHypothesis( _myMeshDS->ShapeToMesh() );
767   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
768   while (it!=listHyp.end())
769   {
770     const SMESHDS_Hypothesis *aHyp = *it;
771     string hypName = aHyp->GetName();
772     if ( hypName == "NotConformAllowed" )
773       return true;
774     it++;
775   }
776   return false;
777 }
778
779 //=======================================================================
780 //function : IsMainShape
781 //purpose  : 
782 //=======================================================================
783
784 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
785 {
786   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
787 }
788
789 //=============================================================================
790 /*!
791  *  
792  */
793 //=============================================================================
794
795 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
796                                    const char*               theName,
797                                    int&                      theId)
798 {
799   if (_mapGroup.find(_groupId) != _mapGroup.end())
800     return NULL;
801   theId = _groupId;
802   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName);
803   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
804   _mapGroup[_groupId++] = aGroup;
805   return aGroup;
806 }
807
808 //=============================================================================
809 /*!
810  *  
811  */
812 //=============================================================================
813
814 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
815 {
816   if (_mapGroup.find(theGroupID) == _mapGroup.end())
817     return NULL;
818   return _mapGroup[theGroupID];
819 }
820
821
822 //=============================================================================
823 /*!
824  *  
825  */
826 //=============================================================================
827
828 list<int> SMESH_Mesh::GetGroupIds()
829 {
830   list<int> anIds;
831   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
832     anIds.push_back( it->first );
833   
834   return anIds;
835 }
836
837
838 //=============================================================================
839 /*!
840  *  
841  */
842 //=============================================================================
843
844 void SMESH_Mesh::RemoveGroup (const int theGroupID)
845 {
846   if (_mapGroup.find(theGroupID) == _mapGroup.end())
847     return;
848   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
849   _mapGroup.erase (theGroupID);
850   delete _mapGroup[theGroupID];
851 }
852
853 //=======================================================================
854 //function : GetAncestors
855 //purpose  : return list of ancestors of theSubShape in the order
856 //           that lower dimention shapes come first.
857 //=======================================================================
858
859 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS)
860 {
861   if ( _mapAncestors.IsEmpty() )
862   {
863     // fill _mapAncestors
864     int desType, ancType;
865     for ( desType = TopAbs_EDGE; desType > TopAbs_COMPOUND; desType-- )
866       for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
867         TopExp::MapShapesAndAncestors (_myMeshDS->ShapeToMesh(),
868                                        (TopAbs_ShapeEnum) desType,
869                                        (TopAbs_ShapeEnum) ancType,
870                                        _mapAncestors );
871   }
872
873   if ( _mapAncestors.Contains( theS ) )
874     return _mapAncestors.FindFromKey( theS );
875
876   static TopTools_ListOfShape emptyList;
877   return emptyList;
878 }
879
880 //=======================================================================
881 //function : Dump
882 //purpose  : dumps contents of mesh to stream [ debug purposes ]
883 //=======================================================================
884 ostream& SMESH_Mesh::Dump(ostream& save)
885 {
886   save << "========================== Dump contents of mesh ==========================" << endl;
887   save << "1) Total number of nodes:     " << NbNodes() << endl;
888   save << "2) Total number of edges:     " << NbEdges() << endl;
889   save << "3) Total number of faces:     " << NbFaces() << endl;
890   if ( NbFaces() > 0 ) {
891     int nb3 = NbTriangles();
892     int nb4 = NbQuadrangles();
893     save << "3.1.) Number of triangles:    " << nb3 << endl;
894     save << "3.2.) Number of quadrangles:  " << nb4 << endl;
895     if ( nb3 + nb4 !=  NbFaces() ) {
896       map<int,int> myFaceMap;
897       SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
898       while( itFaces->more( ) ) {
899         int nbNodes = itFaces->next()->NbNodes();
900         if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
901           myFaceMap[ nbNodes ] = 0;
902         myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
903       }
904       save << "3.3.) Faces in detail: " << endl;
905       map <int,int>::iterator itF;
906       for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
907         save << "--> nb nodes: " << itF->first << " - nb elemens: " << itF->second << endl;
908     }
909   }
910   save << "4) Total number of volumes:   " << NbVolumes() << endl;
911   if ( NbVolumes() > 0 ) {
912     int nb8 = NbHexas();
913     int nb4 = NbTetras();
914     int nb5 = NbPyramids();
915     int nb6 = NbPrisms();
916     save << "4.1.) Number of hexahedrons:  " << nb8 << endl;
917     save << "4.2.) Number of tetrahedrons: " << nb4 << endl;
918     save << "4.3.) Number of prisms:       " << nb6 << endl;
919     save << "4.4.) Number of pyramides:    " << nb5 << endl;
920     if ( nb8 + nb4 + nb5 + nb6 != NbVolumes() ) {
921       map<int,int> myVolumesMap;
922       SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
923       while( itVolumes->more( ) ) {
924         int nbNodes = itVolumes->next()->NbNodes();
925         if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
926           myVolumesMap[ nbNodes ] = 0;
927         myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
928       }
929       save << "4.5.) Volumes in detail: " << endl;
930       map <int,int>::iterator itV;
931       for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
932         save << "--> nb nodes: " << itV->first << " - nb elemens: " << itV->second << endl;
933     }
934   }
935   save << "===========================================================================" << endl;
936   return save;
937 }