]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH/SMESH_Mesh.cxx
Salome HOME
Correction. Allows to fix the problem with shell meshing.
[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.salome-platform.org/ or email : webmaster.salome@opencascade.com
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 "SMESH_HypoFilter.hxx"
35 #include "SMESHDS_Group.hxx"
36 #include "SMESHDS_Script.hxx"
37 #include "SMESHDS_GroupOnGeom.hxx"
38 #include "SMDS_MeshVolume.hxx"
39
40 #include "utilities.h"
41
42 #include "DriverMED_W_SMESHDS_Mesh.h"
43 #include "DriverDAT_W_SMDS_Mesh.h"
44 #include "DriverUNV_W_SMDS_Mesh.h"
45 #include "DriverSTL_W_SMDS_Mesh.h"
46
47 #include "DriverMED_R_SMESHDS_Mesh.h"
48 #include "DriverUNV_R_SMDS_Mesh.h"
49 #include "DriverSTL_R_SMDS_Mesh.h"
50
51 #include <BRepTools_WireExplorer.hxx>
52 #include <BRep_Builder.hxx>
53 #include <gp_Pnt.hxx>
54
55 #include <TCollection_AsciiString.hxx>
56 #include <TopExp.hxx>
57 #include <TopTools_ListOfShape.hxx>
58 #include <TopTools_Array1OfShape.hxx>
59 #include <TopTools_ListIteratorOfListOfShape.hxx>
60 #include <TopTools_MapOfShape.hxx>
61
62 #include <memory>
63
64 #include "Utils_ExceptHandlers.hxx"
65
66 // maximum stored group name length in MED file
67 #define MAX_MED_GROUP_NAME_LENGTH 80
68
69 #ifdef _DEBUG_
70 static int MYDEBUG = 0;
71 #else
72 static int MYDEBUG = 0;
73 #endif
74
75
76 //=============================================================================
77 /*!
78  * 
79  */
80 //=============================================================================
81
82 SMESH_Mesh::SMESH_Mesh(int theLocalId, 
83                        int theStudyId, 
84                        SMESH_Gen* theGen,
85                        bool theIsEmbeddedMode,
86                        SMESHDS_Document* theDocument):
87   _groupId( 0 )
88 {
89   INFOS("SMESH_Mesh::SMESH_Mesh(int localId)");
90   _id = theLocalId;
91   _studyId = theStudyId;
92   _gen = theGen;
93   _myDocument = theDocument;
94   _idDoc = theDocument->NewMesh(theIsEmbeddedMode);
95   _myMeshDS = theDocument->GetMesh(_idDoc);
96   _isShapeToMesh = false;
97 }
98
99 //=============================================================================
100 /*!
101  * 
102  */
103 //=============================================================================
104
105 SMESH_Mesh::~SMESH_Mesh()
106 {
107   INFOS("SMESH_Mesh::~SMESH_Mesh");
108
109   // delete groups
110   map < int, SMESH_Group * >::iterator itg;
111   for (itg = _mapGroup.begin(); itg != _mapGroup.end(); itg++) {
112     SMESH_Group *aGroup = (*itg).second;
113     delete aGroup;
114   }
115 }
116
117 //=============================================================================
118 /*!
119  * 
120  */
121 //=============================================================================
122
123 void SMESH_Mesh::ShapeToMesh(const TopoDS_Shape & aShape)
124 {
125   if(MYDEBUG) MESSAGE("SMESH_Mesh::ShapeToMesh");
126
127   if ( !_myMeshDS->ShapeToMesh().IsNull() && aShape.IsNull() )
128   {
129     // removal of a shape to mesh, delete objects referring to sub-shapes:
130     // - sub-meshes
131     map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.begin();
132     for ( ; i_sm != _mapSubMesh.end(); ++i_sm )
133       delete i_sm->second;
134     _mapSubMesh.clear();
135     //  - groups on geometry
136     map <int, SMESH_Group *>::iterator i_gr = _mapGroup.begin();
137     while ( i_gr != _mapGroup.end() ) {
138       if ( dynamic_cast<SMESHDS_GroupOnGeom*>( i_gr->second->GetGroupDS() )) {
139         _myMeshDS->RemoveGroup( i_gr->second->GetGroupDS() );
140         delete i_gr->second;
141         _mapGroup.erase( i_gr++ );
142       }
143       else
144         i_gr++;
145     }
146     _mapPropagationChains.Clear();
147   }
148   else
149   {
150     if (_isShapeToMesh)
151       throw SALOME_Exception(LOCALIZED ("a shape to mesh has already been defined"));
152   }
153   _isShapeToMesh = true;
154   _myMeshDS->ShapeToMesh(aShape);
155
156   // fill _mapAncestors
157   _mapAncestors.Clear();
158   int desType, ancType;
159   for ( desType = TopAbs_VERTEX; desType > TopAbs_COMPOUND; desType-- )
160     for ( ancType = desType - 1; ancType >= TopAbs_COMPOUND; ancType-- )
161       TopExp::MapShapesAndAncestors ( aShape,
162                                      (TopAbs_ShapeEnum) desType,
163                                      (TopAbs_ShapeEnum) ancType,
164                                      _mapAncestors );
165
166   // NRI : 24/02/03
167   //EAP: 1/9/04 TopExp::MapShapes(aShape, _subShapes); USE the same map of _myMeshDS
168 }
169
170 //=======================================================================
171 //function : UNVToMesh
172 //purpose  : 
173 //=======================================================================
174
175 int SMESH_Mesh::UNVToMesh(const char* theFileName)
176 {
177   if(MYDEBUG) MESSAGE("UNVToMesh - theFileName = "<<theFileName);
178   if(_isShapeToMesh)
179     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
180   _isShapeToMesh = true;
181   DriverUNV_R_SMDS_Mesh myReader;
182   myReader.SetMesh(_myMeshDS);
183   myReader.SetFile(theFileName);
184   myReader.SetMeshId(-1);
185   myReader.Perform();
186   if(MYDEBUG){
187     MESSAGE("UNVToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
188     MESSAGE("UNVToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
189     MESSAGE("UNVToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
190     MESSAGE("UNVToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
191   }
192   SMDS_MeshGroup* aGroup = (SMDS_MeshGroup*) myReader.GetGroup();
193   if (aGroup != 0) {
194     TGroupNamesMap aGroupNames = myReader.GetGroupNamesMap();
195     //const TGroupIdMap& aGroupId = myReader.GetGroupIdMap();
196     aGroup->InitSubGroupsIterator();
197     while (aGroup->MoreSubGroups()) {
198       SMDS_MeshGroup* aSubGroup = (SMDS_MeshGroup*) aGroup->NextSubGroup();
199       std::string aName = aGroupNames[aSubGroup];
200       int aId;
201
202       SMESH_Group* aSMESHGroup = AddGroup( aSubGroup->GetType(), aName.c_str(), aId );
203       if ( aSMESHGroup ) {
204         if(MYDEBUG) MESSAGE("UNVToMesh - group added: "<<aName);      
205         SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aSMESHGroup->GetGroupDS() );
206         if ( aGroupDS ) {
207           aGroupDS->SetStoreName(aName.c_str());
208           aSubGroup->InitIterator();
209           const SMDS_MeshElement* aElement = 0;
210           while (aSubGroup->More()) {
211             aElement = aSubGroup->Next();
212             if (aElement) {
213               aGroupDS->SMDSGroup().Add(aElement);
214             }
215           }
216           if (aElement)
217             aGroupDS->SetType(aElement->GetType());
218         }
219       }
220     }
221   }
222   return 1;
223 }
224
225 //=======================================================================
226 //function : MEDToMesh
227 //purpose  : 
228 //=======================================================================
229
230 int SMESH_Mesh::MEDToMesh(const char* theFileName, const char* theMeshName)
231 {
232   if(MYDEBUG) MESSAGE("MEDToMesh - theFileName = "<<theFileName<<", mesh name = "<<theMeshName);
233   if(_isShapeToMesh)
234     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
235   _isShapeToMesh = true;
236   DriverMED_R_SMESHDS_Mesh myReader;
237   myReader.SetMesh(_myMeshDS);
238   myReader.SetMeshId(-1);
239   myReader.SetFile(theFileName);
240   myReader.SetMeshName(theMeshName);
241   Driver_Mesh::Status status = myReader.Perform();
242   if(MYDEBUG){
243     MESSAGE("MEDToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
244     MESSAGE("MEDToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
245     MESSAGE("MEDToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
246     MESSAGE("MEDToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
247   }
248
249   // Reading groups (sub-meshes are out of scope of MED import functionality)
250   list<TNameAndType> aGroupNames = myReader.GetGroupNamesAndTypes();
251   if(MYDEBUG) MESSAGE("MEDToMesh - Nb groups = "<<aGroupNames.size()); 
252   int anId;
253   list<TNameAndType>::iterator name_type = aGroupNames.begin();
254   for ( ; name_type != aGroupNames.end(); name_type++ ) {
255     SMESH_Group* aGroup = AddGroup( name_type->second, name_type->first.c_str(), anId );
256     if ( aGroup ) {
257       if(MYDEBUG) MESSAGE("MEDToMesh - group added: "<<name_type->first.c_str());      
258       SMESHDS_Group* aGroupDS = dynamic_cast<SMESHDS_Group*>( aGroup->GetGroupDS() );
259       if ( aGroupDS ) {
260         aGroupDS->SetStoreName( name_type->first.c_str() );
261         myReader.GetGroup( aGroupDS );
262       }
263     }
264   }
265   return (int) status;
266 }
267
268 //=======================================================================
269 //function : STLToMesh
270 //purpose  : 
271 //=======================================================================
272
273 int SMESH_Mesh::STLToMesh(const char* theFileName)
274 {
275   if(MYDEBUG) MESSAGE("STLToMesh - theFileName = "<<theFileName);
276   if(_isShapeToMesh)
277     throw SALOME_Exception(LOCALIZED("a shape to mesh has already been defined"));
278   _isShapeToMesh = true;
279   DriverSTL_R_SMDS_Mesh myReader;
280   myReader.SetMesh(_myMeshDS);
281   myReader.SetFile(theFileName);
282   myReader.SetMeshId(-1);
283   myReader.Perform();
284   if(MYDEBUG){
285     MESSAGE("STLToMesh - _myMeshDS->NbNodes() = "<<_myMeshDS->NbNodes());
286     MESSAGE("STLToMesh - _myMeshDS->NbEdges() = "<<_myMeshDS->NbEdges());
287     MESSAGE("STLToMesh - _myMeshDS->NbFaces() = "<<_myMeshDS->NbFaces());
288     MESSAGE("STLToMesh - _myMeshDS->NbVolumes() = "<<_myMeshDS->NbVolumes());
289   }
290   return 1;
291 }
292
293 //=============================================================================
294 /*!
295  * 
296  */
297 //=============================================================================
298
299 SMESH_Hypothesis::Hypothesis_Status
300   SMESH_Mesh::AddHypothesis(const TopoDS_Shape & aSubShape,
301                             int                  anHypId  ) throw(SALOME_Exception)
302 {
303   Unexpect aCatch(SalomeException);
304   if(MYDEBUG) MESSAGE("SMESH_Mesh::AddHypothesis");
305
306   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
307   if ( !subMesh || !subMesh->GetId())
308     return SMESH_Hypothesis::HYP_BAD_SUBSHAPE;
309
310   SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
311   if ( subMeshDS && subMeshDS->IsComplexSubmesh() ) // group of sub-shapes and maybe of not sub-
312   {
313     MESSAGE("AddHypothesis() to complex submesh");
314     // return the worst but not fatal state of all group memebers
315     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
316     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
317     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
318     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
319     {
320       if ( !GetMeshDS()->ShapeToIndex( itS.Value() ))
321         continue; // not sub-shape
322       ret = AddHypothesis( itS.Value(), anHypId );
323       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
324         aWorstNotFatal = ret;
325       if ( ret < aBestRet )
326         aBestRet = ret;
327     }
328     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
329       return aBestRet;
330     return aWorstNotFatal;
331   }
332
333   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
334   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
335   {
336     if(MYDEBUG) MESSAGE("Hypothesis ID does not give an hypothesis");
337     if(MYDEBUG) {
338       SCRUTE(_studyId);
339       SCRUTE(anHypId);
340     }
341     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
342   }
343
344   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
345   MESSAGE( "SMESH_Mesh::AddHypothesis " << anHyp->GetName() );
346
347   bool isGlobalHyp = IsMainShape( aSubShape );
348
349   // NotConformAllowed can be only global
350   if ( !isGlobalHyp )
351   {
352     string hypName = anHyp->GetName();
353     if ( hypName == "NotConformAllowed" )
354     {
355       if(MYDEBUG) MESSAGE( "Hypotesis <NotConformAllowed> can be only global" );
356       return SMESH_Hypothesis::HYP_INCOMPATIBLE;
357     }
358   }
359
360   // shape 
361
362   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
363   int event = isAlgo ? SMESH_subMesh::ADD_ALGO : SMESH_subMesh::ADD_HYP;
364
365   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
366
367   // subShapes
368   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
369       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is added on father
370   {
371     event = isAlgo ? SMESH_subMesh::ADD_FATHER_ALGO : SMESH_subMesh::ADD_FATHER_HYP;
372
373     SMESH_Hypothesis::Hypothesis_Status ret2 =
374       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
375     if (ret2 > ret)
376       ret = ret2;
377
378     // check concurent hypotheses on ansestors
379     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !isGlobalHyp )
380     {
381       const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn();
382       map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin();
383       for ( ; smIt != smMap.end(); smIt++ ) {
384         if ( smIt->second->IsApplicableHypotesis( anHyp )) {
385           ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() );
386           if (ret2 > ret) {
387             ret = ret2;
388             break;
389           }
390         }
391       }
392     }
393   }
394
395   if(MYDEBUG) subMesh->DumpAlgoState(true);
396   SCRUTE(ret);
397   return ret;
398 }
399
400 //=============================================================================
401 /*!
402  * 
403  */
404 //=============================================================================
405
406 SMESH_Hypothesis::Hypothesis_Status
407   SMESH_Mesh::RemoveHypothesis(const TopoDS_Shape & aSubShape,
408                                int anHypId)throw(SALOME_Exception)
409 {
410   Unexpect aCatch(SalomeException);
411   if(MYDEBUG) MESSAGE("SMESH_Mesh::RemoveHypothesis");
412   
413   SMESH_subMesh *subMesh = GetSubMesh(aSubShape);
414   SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
415   if ( subMeshDS && subMeshDS->IsComplexSubmesh() )
416   {
417     // return the worst but not fatal state of all group memebers
418     SMESH_Hypothesis::Hypothesis_Status aBestRet, aWorstNotFatal, ret;
419     aBestRet = SMESH_Hypothesis::HYP_BAD_DIM;
420     aWorstNotFatal = SMESH_Hypothesis::HYP_OK;
421     for ( TopoDS_Iterator itS ( aSubShape ); itS.More(); itS.Next())
422     {
423       if ( !GetMeshDS()->ShapeToIndex( itS.Value() ))
424         continue; // not sub-shape
425       ret = RemoveHypothesis( itS.Value(), anHypId );
426       if ( !SMESH_Hypothesis::IsStatusFatal( ret ) && ret > aWorstNotFatal )
427         aWorstNotFatal = ret;
428       if ( ret < aBestRet )
429         aBestRet = ret;
430     }
431     if ( SMESH_Hypothesis::IsStatusFatal( aBestRet ))
432       return aBestRet;
433     return aWorstNotFatal;
434   }
435
436   StudyContextStruct *sc = _gen->GetStudyContext(_studyId);
437   if (sc->mapHypothesis.find(anHypId) == sc->mapHypothesis.end())
438     throw SALOME_Exception(LOCALIZED("hypothesis does not exist"));
439   
440   SMESH_Hypothesis *anHyp = sc->mapHypothesis[anHypId];
441   int hypType = anHyp->GetType();
442   if(MYDEBUG) SCRUTE(hypType);
443   
444   // shape 
445   
446   bool isAlgo = ( !anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO );
447   int event = isAlgo ? SMESH_subMesh::REMOVE_ALGO : SMESH_subMesh::REMOVE_HYP;
448
449   SMESH_Hypothesis::Hypothesis_Status ret = subMesh->AlgoStateEngine(event, anHyp);
450
451   // there may appear concurrent hyps that were covered by the removed hyp
452   if (ret < SMESH_Hypothesis::HYP_CONCURENT &&
453       subMesh->IsApplicableHypotesis( anHyp ) &&
454       subMesh->CheckConcurentHypothesis( anHyp->GetType() ) != SMESH_Hypothesis::HYP_OK)
455     ret = SMESH_Hypothesis::HYP_CONCURENT;
456
457   // subShapes
458   if (!SMESH_Hypothesis::IsStatusFatal(ret) &&
459       anHyp->GetDim() <= SMESH_Gen::GetShapeDim(aSubShape)) // is removed from father
460   {
461     event = isAlgo ? SMESH_subMesh::REMOVE_FATHER_ALGO : SMESH_subMesh::REMOVE_FATHER_HYP;
462
463     SMESH_Hypothesis::Hypothesis_Status ret2 =
464       subMesh->SubMeshesAlgoStateEngine(event, anHyp);
465     if (ret2 > ret) // more severe
466       ret = ret2;
467
468     // check concurent hypotheses on ansestors
469     if (ret < SMESH_Hypothesis::HYP_CONCURENT && !IsMainShape( aSubShape ) )
470     {
471       const map < int, SMESH_subMesh * >& smMap = subMesh->DependsOn();
472       map < int, SMESH_subMesh * >::const_iterator smIt = smMap.begin();
473       for ( ; smIt != smMap.end(); smIt++ ) {
474         if ( smIt->second->IsApplicableHypotesis( anHyp )) {
475           ret2 = smIt->second->CheckConcurentHypothesis( anHyp->GetType() );
476           if (ret2 > ret) {
477             ret = ret2;
478             break;
479           }
480         }
481       }
482     }
483   }
484   
485   if(MYDEBUG) subMesh->DumpAlgoState(true);
486   if(MYDEBUG) SCRUTE(ret);
487   return ret;
488 }
489
490 //=============================================================================
491 /*!
492  * 
493  */
494 //=============================================================================
495
496 SMESHDS_Mesh * SMESH_Mesh::GetMeshDS()
497 {
498   return _myMeshDS;
499 }
500
501 //=============================================================================
502 /*!
503  * 
504  */
505 //=============================================================================
506
507 const list<const SMESHDS_Hypothesis*>&
508 SMESH_Mesh::GetHypothesisList(const TopoDS_Shape & aSubShape) const
509   throw(SALOME_Exception)
510 {
511   Unexpect aCatch(SalomeException);
512   return _myMeshDS->GetHypothesis(aSubShape);
513 }
514
515 //=======================================================================
516 //function : GetHypothesis
517 //purpose  : 
518 //=======================================================================
519
520 const SMESH_Hypothesis * SMESH_Mesh::GetHypothesis(const TopoDS_Shape &    aSubShape,
521                                                    const SMESH_HypoFilter& aFilter,
522                                                    const bool              andAncestors) const
523 {
524   {
525     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
526     list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
527     for ( ; hyp != hypList.end(); hyp++ ) {
528       const SMESH_Hypothesis * h = static_cast<const SMESH_Hypothesis*>( *hyp );
529       if ( aFilter.IsOk( h, aSubShape))
530         return h;
531     }
532   }
533   if ( andAncestors )
534   {
535     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
536     for (; it.More(); it.Next() )
537     {
538       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
539       list<const SMESHDS_Hypothesis*>::const_iterator hyp = hypList.begin();
540       for ( ; hyp != hypList.end(); hyp++ ) {
541         const SMESH_Hypothesis * h = static_cast<const SMESH_Hypothesis*>( *hyp );
542         if (aFilter.IsOk( h, it.Value() ))
543           return h;
544       }
545     }
546   }
547   return 0;
548 }
549
550 //=======================================================================
551 //function : GetHypotheses
552 //purpose  : 
553 //=======================================================================
554
555 //================================================================================
556 /*!
557  * \brief Return hypothesis assigned to the shape
558   * \param aSubShape - the shape to check
559   * \param aFilter - the hypothesis filter
560   * \param aHypList - the list of the found hypotheses
561   * \param andAncestors - flag to check hypos assigned to ancestors of the shape
562   * \retval int - number of unique hypos in aHypList
563  */
564 //================================================================================
565
566 int SMESH_Mesh::GetHypotheses(const TopoDS_Shape &                aSubShape,
567                               const SMESH_HypoFilter&             aFilter,
568                               list <const SMESHDS_Hypothesis * >& aHypList,
569                               const bool                          andAncestors) const
570 {
571   set<string> hypTypes; // to exclude same type hypos from the result list
572   int nbHyps = 0;
573
574   // fill in hypTypes
575   list<const SMESHDS_Hypothesis*>::const_iterator hyp;
576   for ( hyp = aHypList.begin(); hyp != aHypList.end(); hyp++ )
577     if ( hypTypes.insert( (*hyp)->GetName() ).second )
578       nbHyps++;
579
580   // get hypos from aSubShape
581   {
582     const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(aSubShape);
583     for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
584       if ( aFilter.IsOk (static_cast<const SMESH_Hypothesis*>( *hyp ), aSubShape) &&
585            hypTypes.insert( (*hyp)->GetName() ).second )
586       {
587         aHypList.push_back( *hyp );
588         nbHyps++;
589       }
590   }
591
592   // get hypos from ancestors of aSubShape
593   if ( andAncestors )
594   {
595     TopTools_MapOfShape map;
596     TopTools_ListIteratorOfListOfShape it( GetAncestors( aSubShape ));
597     for (; it.More(); it.Next() )
598     {
599      if ( !map.Add( it.Value() ))
600         continue;
601       const list<const SMESHDS_Hypothesis*>& hypList = _myMeshDS->GetHypothesis(it.Value());
602       for ( hyp = hypList.begin(); hyp != hypList.end(); hyp++ )
603         if (aFilter.IsOk( static_cast<const SMESH_Hypothesis*>( *hyp ), it.Value() ) &&
604             hypTypes.insert( (*hyp)->GetName() ).second ) {
605           aHypList.push_back( *hyp );
606           nbHyps++;
607         }
608     }
609   }
610   return nbHyps;
611 }
612
613 //=============================================================================
614 /*!
615  * 
616  */
617 //=============================================================================
618
619 const list<SMESHDS_Command*> & SMESH_Mesh::GetLog() throw(SALOME_Exception)
620 {
621   Unexpect aCatch(SalomeException);
622   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetLog");
623   return _myMeshDS->GetScript()->GetCommands();
624 }
625
626 //=============================================================================
627 /*!
628  * 
629  */
630 //=============================================================================
631 void SMESH_Mesh::ClearLog() throw(SALOME_Exception)
632 {
633   Unexpect aCatch(SalomeException);
634   if(MYDEBUG) MESSAGE("SMESH_Mesh::ClearLog");
635   _myMeshDS->GetScript()->Clear();
636 }
637
638 //=============================================================================
639 /*!
640  * 
641  */
642 //=============================================================================
643
644 int SMESH_Mesh::GetId()
645 {
646   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetId");
647   return _id;
648 }
649
650 //=============================================================================
651 /*!
652  * 
653  */
654 //=============================================================================
655
656 SMESH_Gen *SMESH_Mesh::GetGen()
657 {
658   return _gen;
659 }
660
661 //=============================================================================
662 /*!
663  * Get or Create the SMESH_subMesh object implementation
664  */
665 //=============================================================================
666
667 SMESH_subMesh *SMESH_Mesh::GetSubMesh(const TopoDS_Shape & aSubShape)
668   throw(SALOME_Exception)
669 {
670   Unexpect aCatch(SalomeException);
671   SMESH_subMesh *aSubMesh;
672   int index = _myMeshDS->ShapeToIndex(aSubShape);
673
674   // for submeshes on GEOM Group
675   if ( !index && aSubShape.ShapeType() == TopAbs_COMPOUND ) {
676     TopoDS_Iterator it( aSubShape );
677     if ( it.More() )
678       index = _myMeshDS->AddCompoundSubmesh( aSubShape, it.Value().ShapeType() );
679   }
680 //   if ( !index )
681 //     return NULL; // neither sub-shape nor a group
682
683   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
684   if ( i_sm != _mapSubMesh.end())
685   {
686     aSubMesh = i_sm->second;
687   }
688   else
689   {
690     aSubMesh = new SMESH_subMesh(index, this, _myMeshDS, aSubShape);
691     _mapSubMesh[index] = aSubMesh;
692   }
693   return aSubMesh;
694 }
695
696 //=============================================================================
697 /*!
698  * Get the SMESH_subMesh object implementation. Dont create it, return null
699  * if it does not exist.
700  */
701 //=============================================================================
702
703 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const TopoDS_Shape & aSubShape)
704   throw(SALOME_Exception)
705 {
706   Unexpect aCatch(SalomeException);
707   SMESH_subMesh *aSubMesh = NULL;
708   
709   int index = _myMeshDS->ShapeToIndex(aSubShape);
710
711   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(index);
712   if ( i_sm != _mapSubMesh.end())
713     aSubMesh = i_sm->second;
714
715   return aSubMesh;
716 }
717
718 //=============================================================================
719 /*!
720  * Get the SMESH_subMesh object implementation. Dont create it, return null
721  * if it does not exist.
722  */
723 //=============================================================================
724
725 SMESH_subMesh *SMESH_Mesh::GetSubMeshContaining(const int aShapeID)
726 throw(SALOME_Exception)
727 {
728   Unexpect aCatch(SalomeException);
729   
730   map <int, SMESH_subMesh *>::iterator i_sm = _mapSubMesh.find(aShapeID);
731   if (i_sm == _mapSubMesh.end())
732     return NULL;
733   return i_sm->second;
734 }
735
736 //=======================================================================
737 //function : IsUsedHypothesis
738 //purpose  : Return True if anHyp is used to mesh aSubShape
739 //=======================================================================
740
741 bool SMESH_Mesh::IsUsedHypothesis(SMESHDS_Hypothesis * anHyp,
742                                   const SMESH_subMesh* aSubMesh)
743 {
744   SMESH_Hypothesis* hyp = static_cast<SMESH_Hypothesis*>(anHyp);
745
746   // check if anHyp can be used to mesh aSubMesh
747   if ( !aSubMesh || !aSubMesh->IsApplicableHypotesis( hyp ))
748     return false;
749
750   const TopoDS_Shape & aSubShape = const_cast<SMESH_subMesh*>( aSubMesh )->GetSubShape();
751
752   SMESH_Algo *algo = _gen->GetAlgo(*this, aSubShape );
753
754   // algorithm
755   if (anHyp->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
756     return ( anHyp == algo );
757
758   // algorithm parameter
759   if (algo)
760   {
761     // look trough hypotheses used by algo
762     SMESH_HypoFilter hypoKind;
763     if ( algo->InitCompatibleHypoFilter( hypoKind, !hyp->IsAuxiliary() )) {
764       list <const SMESHDS_Hypothesis * > usedHyps;
765       if ( GetHypotheses( aSubShape, hypoKind, usedHyps, true ))
766         return ( find( usedHyps.begin(), usedHyps.end(), anHyp ) != usedHyps.end() );
767     }
768   }
769
770   // look through all assigned hypotheses
771   //SMESH_HypoFilter filter( SMESH_HypoFilter::Is( hyp ));
772   return false; //GetHypothesis( aSubShape, filter, true );
773 }
774
775 //=============================================================================
776 /*!
777  *
778  */
779 //=============================================================================
780
781 const list < SMESH_subMesh * >&
782 SMESH_Mesh::GetSubMeshUsingHypothesis(SMESHDS_Hypothesis * anHyp)
783   throw(SALOME_Exception)
784 {
785   Unexpect aCatch(SalomeException);
786   if(MYDEBUG) MESSAGE("SMESH_Mesh::GetSubMeshUsingHypothesis");
787   map < int, SMESH_subMesh * >::iterator itsm;
788   _subMeshesUsingHypothesisList.clear();
789   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
790   {
791     SMESH_subMesh *aSubMesh = (*itsm).second;
792     if ( IsUsedHypothesis ( anHyp, aSubMesh ))
793       _subMeshesUsingHypothesisList.push_back(aSubMesh);
794   }
795   return _subMeshesUsingHypothesisList;
796 }
797
798 //=======================================================================
799 //function : NotifySubMeshesHypothesisModification
800 //purpose  : Say all submeshes using theChangedHyp that it has been modified
801 //=======================================================================
802
803 void SMESH_Mesh::NotifySubMeshesHypothesisModification(const SMESH_Hypothesis* theChangedHyp)
804 {
805   Unexpect aCatch(SalomeException);
806
807   const SMESH_Hypothesis* hyp = static_cast<const SMESH_Hypothesis*>(theChangedHyp);
808
809   const SMESH_Algo *foundAlgo = 0;
810   SMESH_HypoFilter algoKind( SMESH_HypoFilter::IsAlgo() );
811   SMESH_HypoFilter compatibleHypoKind;
812   list <const SMESHDS_Hypothesis * > usedHyps;
813
814
815   map < int, SMESH_subMesh * >::iterator itsm;
816   for (itsm = _mapSubMesh.begin(); itsm != _mapSubMesh.end(); itsm++)
817   {
818     SMESH_subMesh *aSubMesh = (*itsm).second;
819     if ( aSubMesh->IsApplicableHypotesis( hyp ))
820     {
821       const TopoDS_Shape & aSubShape = aSubMesh->GetSubShape();
822
823       if ( !foundAlgo ) // init filter for algo search
824         algoKind.And( algoKind.IsApplicableTo( aSubShape ));
825       
826       const SMESH_Algo *algo = static_cast<const SMESH_Algo*>
827         ( GetHypothesis( aSubShape, algoKind, true ));
828
829       if ( algo )
830       {
831         bool sameAlgo = ( algo == foundAlgo );
832         if ( !sameAlgo && foundAlgo )
833           sameAlgo = ( strcmp( algo->GetName(), foundAlgo->GetName() ) == 0);
834
835         if ( !sameAlgo ) { // init filter for used hypos search
836           if ( !algo->InitCompatibleHypoFilter( compatibleHypoKind, !hyp->IsAuxiliary() ))
837             continue; // algo does not use any hypothesis
838           foundAlgo = algo;
839         }
840
841         // check if hyp is used by algo
842         usedHyps.clear();
843         if ( GetHypotheses( aSubShape, compatibleHypoKind, usedHyps, true ) &&
844              find( usedHyps.begin(), usedHyps.end(), hyp ) != usedHyps.end() )
845         {
846           aSubMesh->ComputeStateEngine(SMESH_subMesh::MODIF_HYP);
847
848           if ( algo->GetDim() == 1 && IsPropagationHypothesis( aSubShape ))
849             CleanMeshOnPropagationChain( aSubShape );
850         }
851       }
852     }
853   }
854 }
855
856 //=============================================================================
857 /*! Export* methods.
858  *  To store mesh contents on disk in different formats.
859  */
860 //=============================================================================
861
862 bool SMESH_Mesh::HasDuplicatedGroupNamesMED()
863 {
864   set<string> aGroupNames;
865   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
866     SMESH_Group* aGroup = it->second;
867     string aGroupName = aGroup->GetName();
868     aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
869     if (!aGroupNames.insert(aGroupName).second)
870       return true;
871   }
872
873   return false;
874 }
875
876 void SMESH_Mesh::ExportMED(const char *file, 
877                            const char* theMeshName, 
878                            bool theAutoGroups,
879                            int theVersion) 
880   throw(SALOME_Exception)
881 {
882   Unexpect aCatch(SalomeException);
883
884   DriverMED_W_SMESHDS_Mesh myWriter;
885   myWriter.SetFile    ( file, MED::EVersion(theVersion) );
886   myWriter.SetMesh    ( _myMeshDS   );
887   if ( !theMeshName ) 
888     myWriter.SetMeshId  ( _idDoc      );
889   else {
890     myWriter.SetMeshId  ( -1          );
891     myWriter.SetMeshName( theMeshName );
892   }
893
894   if ( theAutoGroups ) {
895     myWriter.AddGroupOfNodes();
896     myWriter.AddGroupOfEdges();
897     myWriter.AddGroupOfFaces();
898     myWriter.AddGroupOfVolumes();
899   }
900
901   // Pass groups to writer. Provide unique group names.
902   set<string> aGroupNames;
903   char aString [256];
904   int maxNbIter = 10000; // to guarantee cycle finish
905   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
906     SMESH_Group*       aGroup   = it->second;
907     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
908     if ( aGroupDS ) {
909       string aGroupName0 = aGroup->GetName();
910       aGroupName0.resize(MAX_MED_GROUP_NAME_LENGTH);
911       string aGroupName = aGroupName0;
912       for (int i = 1; !aGroupNames.insert(aGroupName).second && i < maxNbIter; i++) {
913         sprintf(&aString[0], "GR_%d_%s", i, aGroupName0.c_str());
914         aGroupName = aString;
915         aGroupName.resize(MAX_MED_GROUP_NAME_LENGTH);
916       }
917       aGroupDS->SetStoreName( aGroupName.c_str() );
918       myWriter.AddGroup( aGroupDS );
919     }
920   }
921
922   // Perform export
923   myWriter.Perform();
924 }
925
926 void SMESH_Mesh::ExportDAT(const char *file) throw(SALOME_Exception)
927 {
928   Unexpect aCatch(SalomeException);
929   DriverDAT_W_SMDS_Mesh myWriter;
930   myWriter.SetFile(string(file));
931   myWriter.SetMesh(_myMeshDS);
932   myWriter.SetMeshId(_idDoc);
933   myWriter.Perform();
934 }
935
936 void SMESH_Mesh::ExportUNV(const char *file) throw(SALOME_Exception)
937 {
938   Unexpect aCatch(SalomeException);
939   DriverUNV_W_SMDS_Mesh myWriter;
940   myWriter.SetFile(string(file));
941   myWriter.SetMesh(_myMeshDS);
942   myWriter.SetMeshId(_idDoc);
943   //  myWriter.SetGroups(_mapGroup);
944
945   for ( map<int, SMESH_Group*>::iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ ) {
946     SMESH_Group*       aGroup   = it->second;
947     SMESHDS_GroupBase* aGroupDS = aGroup->GetGroupDS();
948     if ( aGroupDS ) {
949       string aGroupName = aGroup->GetName();
950       aGroupDS->SetStoreName( aGroupName.c_str() );
951       myWriter.AddGroup( aGroupDS );
952     }
953   }
954   myWriter.Perform();
955 }
956
957 void SMESH_Mesh::ExportSTL(const char *file, const bool isascii) throw(SALOME_Exception)
958 {
959   Unexpect aCatch(SalomeException);
960   DriverSTL_W_SMDS_Mesh myWriter;
961   myWriter.SetFile(string(file));
962   myWriter.SetIsAscii( isascii );
963   myWriter.SetMesh(_myMeshDS);
964   myWriter.SetMeshId(_idDoc);
965   myWriter.Perform();
966 }
967
968 //=============================================================================
969 /*!
970  *  
971  */
972 //=============================================================================
973 int SMESH_Mesh::NbNodes() throw(SALOME_Exception)
974 {
975   Unexpect aCatch(SalomeException);
976   return _myMeshDS->NbNodes();
977 }
978
979 //=============================================================================
980 /*!
981  *  
982  */
983 //=============================================================================
984 int SMESH_Mesh::NbEdges(ElementOrder order) throw(SALOME_Exception)
985 {
986   Unexpect aCatch(SalomeException);
987   if (order == ORDER_ANY)
988     return _myMeshDS->NbEdges();
989
990   int Nb = 0;
991   SMDS_EdgeIteratorPtr it = _myMeshDS->edgesIterator();
992   while (it->more()) {
993     const SMDS_MeshEdge* cur = it->next();
994     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
995          order == ORDER_QUADRATIC && cur->IsQuadratic() )
996       Nb++;
997   }
998   return Nb;
999 }
1000
1001 //=============================================================================
1002 /*!
1003  *  
1004  */
1005 //=============================================================================
1006 int SMESH_Mesh::NbFaces(ElementOrder order) throw(SALOME_Exception)
1007 {
1008   Unexpect aCatch(SalomeException);
1009   if (order == ORDER_ANY)
1010     return _myMeshDS->NbFaces();
1011
1012   int Nb = 0;
1013   SMDS_FaceIteratorPtr it = _myMeshDS->facesIterator();
1014   while (it->more()) {
1015     const SMDS_MeshFace* cur = it->next();
1016     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1017          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1018       Nb++;
1019   }
1020   return Nb;
1021 }
1022
1023 ///////////////////////////////////////////////////////////////////////////////
1024 /// Return the number of 3 nodes faces in the mesh. This method run in O(n)
1025 ///////////////////////////////////////////////////////////////////////////////
1026 int SMESH_Mesh::NbTriangles(ElementOrder order) throw(SALOME_Exception)
1027 {
1028   Unexpect aCatch(SalomeException);
1029   int Nb = 0;
1030   
1031   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1032   while (itFaces->more()) {
1033     const SMDS_MeshFace* curFace = itFaces->next();
1034     int nbnod = curFace->NbNodes();
1035     if ( !curFace->IsPoly() && 
1036          ( order == ORDER_ANY && (nbnod==3 || nbnod==6) ||
1037            order == ORDER_LINEAR && nbnod==3 ||
1038            order == ORDER_QUADRATIC && nbnod==6 ) )
1039       Nb++;
1040   }
1041   return Nb;
1042 }
1043
1044 ///////////////////////////////////////////////////////////////////////////////
1045 /// Return the number of 4 nodes faces in the mesh. This method run in O(n)
1046 ///////////////////////////////////////////////////////////////////////////////
1047 int SMESH_Mesh::NbQuadrangles(ElementOrder order) throw(SALOME_Exception)
1048 {
1049   Unexpect aCatch(SalomeException);
1050   int Nb = 0;
1051   
1052   SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1053   while (itFaces->more()) {
1054     const SMDS_MeshFace* curFace = itFaces->next();
1055     int nbnod = curFace->NbNodes();
1056     if ( !curFace->IsPoly() && 
1057          ( order == ORDER_ANY && (nbnod==4 || nbnod==8) ||
1058            order == ORDER_LINEAR && nbnod==4 ||
1059            order == ORDER_QUADRATIC && nbnod==8 ) )
1060       Nb++;
1061   }
1062   return Nb;
1063 }
1064
1065 ///////////////////////////////////////////////////////////////////////////////
1066 /// Return the number of polygonal faces in the mesh. This method run in O(n)
1067 ///////////////////////////////////////////////////////////////////////////////
1068 int SMESH_Mesh::NbPolygons() throw(SALOME_Exception)
1069 {
1070   Unexpect aCatch(SalomeException);
1071   int Nb = 0;
1072   SMDS_FaceIteratorPtr itFaces = _myMeshDS->facesIterator();
1073   while (itFaces->more())
1074     if (itFaces->next()->IsPoly()) Nb++;
1075   return Nb;
1076 }
1077
1078 //=============================================================================
1079 /*!
1080  *  
1081  */
1082 //=============================================================================
1083 int SMESH_Mesh::NbVolumes(ElementOrder order) throw(SALOME_Exception)
1084 {
1085   Unexpect aCatch(SalomeException);
1086   if (order == ORDER_ANY)
1087     return _myMeshDS->NbVolumes();
1088
1089   int Nb = 0;
1090   SMDS_VolumeIteratorPtr it = _myMeshDS->volumesIterator();
1091   while (it->more()) {
1092     const SMDS_MeshVolume* cur = it->next();
1093     if ( order == ORDER_LINEAR && !cur->IsQuadratic() ||
1094          order == ORDER_QUADRATIC && cur->IsQuadratic() )
1095       Nb++;
1096   }
1097   return Nb;
1098 }
1099
1100 int SMESH_Mesh::NbTetras(ElementOrder order) throw(SALOME_Exception)
1101 {
1102   Unexpect aCatch(SalomeException);
1103   int Nb = 0;
1104   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1105   while (itVolumes->more()) {
1106     const SMDS_MeshVolume* curVolume = itVolumes->next();
1107     int nbnod = curVolume->NbNodes();
1108     if ( !curVolume->IsPoly() && 
1109          ( order == ORDER_ANY && (nbnod==4 || nbnod==10) ||
1110            order == ORDER_LINEAR && nbnod==4 ||
1111            order == ORDER_QUADRATIC && nbnod==10 ) )
1112       Nb++;
1113   }
1114   return Nb;
1115 }
1116
1117 int SMESH_Mesh::NbHexas(ElementOrder order) throw(SALOME_Exception)
1118 {
1119   Unexpect aCatch(SalomeException);
1120   int Nb = 0;
1121   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1122   while (itVolumes->more()) {
1123     const SMDS_MeshVolume* curVolume = itVolumes->next();
1124     int nbnod = curVolume->NbNodes();
1125     if ( !curVolume->IsPoly() && 
1126          ( order == ORDER_ANY && (nbnod==8 || nbnod==20) ||
1127            order == ORDER_LINEAR && nbnod==8 ||
1128            order == ORDER_QUADRATIC && nbnod==20 ) )
1129       Nb++;
1130   }
1131   return Nb;
1132 }
1133
1134 int SMESH_Mesh::NbPyramids(ElementOrder order) throw(SALOME_Exception)
1135 {
1136   Unexpect aCatch(SalomeException);
1137   int Nb = 0;
1138   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1139   while (itVolumes->more()) {
1140     const SMDS_MeshVolume* curVolume = itVolumes->next();
1141     int nbnod = curVolume->NbNodes();
1142     if ( !curVolume->IsPoly() && 
1143          ( order == ORDER_ANY && (nbnod==5 || nbnod==13) ||
1144            order == ORDER_LINEAR && nbnod==5 ||
1145            order == ORDER_QUADRATIC && nbnod==13 ) )
1146       Nb++;
1147   }
1148   return Nb;
1149 }
1150
1151 int SMESH_Mesh::NbPrisms(ElementOrder order) throw(SALOME_Exception)
1152 {
1153   Unexpect aCatch(SalomeException);
1154   int Nb = 0;
1155   SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1156   while (itVolumes->more()) {
1157     const SMDS_MeshVolume* curVolume = itVolumes->next();
1158     int nbnod = curVolume->NbNodes();
1159     if ( !curVolume->IsPoly() && 
1160          ( order == ORDER_ANY && (nbnod==6 || nbnod==15) ||
1161            order == ORDER_LINEAR && nbnod==6 ||
1162            order == ORDER_QUADRATIC && nbnod==15 ) )
1163       Nb++;
1164   }
1165   return Nb;
1166 }
1167
1168 int SMESH_Mesh::NbPolyhedrons() throw(SALOME_Exception)
1169 {
1170   Unexpect aCatch(SalomeException);
1171   int Nb = 0;
1172   SMDS_VolumeIteratorPtr itVolumes = _myMeshDS->volumesIterator();
1173   while (itVolumes->more())
1174     if (itVolumes->next()->IsPoly()) Nb++;
1175   return Nb;
1176 }
1177
1178 //=============================================================================
1179 /*!
1180  *  
1181  */
1182 //=============================================================================
1183 int SMESH_Mesh::NbSubMesh() throw(SALOME_Exception)
1184 {
1185   Unexpect aCatch(SalomeException);
1186   return _myMeshDS->NbSubMesh();
1187 }
1188
1189 //=======================================================================
1190 //function : IsNotConformAllowed
1191 //purpose  : check if a hypothesis alowing notconform mesh is present
1192 //=======================================================================
1193
1194 bool SMESH_Mesh::IsNotConformAllowed() const
1195 {
1196   if(MYDEBUG) MESSAGE("SMESH_Mesh::IsNotConformAllowed");
1197
1198   SMESH_HypoFilter filter( SMESH_HypoFilter::HasName( "NotConformAllowed" ));
1199   return GetHypothesis( _myMeshDS->ShapeToMesh(), filter, false );
1200 }
1201
1202 //=======================================================================
1203 //function : IsMainShape
1204 //purpose  : 
1205 //=======================================================================
1206
1207 bool SMESH_Mesh::IsMainShape(const TopoDS_Shape& theShape) const
1208 {
1209   return theShape.IsSame(_myMeshDS->ShapeToMesh() );
1210 }
1211
1212 //=============================================================================
1213 /*!
1214  *  
1215  */
1216 //=============================================================================
1217
1218 SMESH_Group* SMESH_Mesh::AddGroup (const SMDSAbs_ElementType theType,
1219                                    const char*               theName,
1220                                    int&                      theId,
1221                                    const TopoDS_Shape&       theShape)
1222 {
1223   if (_mapGroup.find(_groupId) != _mapGroup.end())
1224     return NULL;
1225   theId = _groupId;
1226   SMESH_Group* aGroup = new SMESH_Group (theId, this, theType, theName, theShape);
1227   GetMeshDS()->AddGroup( aGroup->GetGroupDS() );
1228   _mapGroup[_groupId++] = aGroup;
1229   return aGroup;
1230 }
1231
1232 //=============================================================================
1233 /*!
1234  *  
1235  */
1236 //=============================================================================
1237
1238 SMESH_Group* SMESH_Mesh::GetGroup (const int theGroupID)
1239 {
1240   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1241     return NULL;
1242   return _mapGroup[theGroupID];
1243 }
1244
1245
1246 //=============================================================================
1247 /*!
1248  *  
1249  */
1250 //=============================================================================
1251
1252 list<int> SMESH_Mesh::GetGroupIds()
1253 {
1254   list<int> anIds;
1255   for ( map<int, SMESH_Group*>::const_iterator it = _mapGroup.begin(); it != _mapGroup.end(); it++ )
1256     anIds.push_back( it->first );
1257   
1258   return anIds;
1259 }
1260
1261
1262 //=============================================================================
1263 /*!
1264  *  
1265  */
1266 //=============================================================================
1267
1268 void SMESH_Mesh::RemoveGroup (const int theGroupID)
1269 {
1270   if (_mapGroup.find(theGroupID) == _mapGroup.end())
1271     return;
1272   GetMeshDS()->RemoveGroup( _mapGroup[theGroupID]->GetGroupDS() );
1273   delete _mapGroup[theGroupID];
1274   _mapGroup.erase (theGroupID);
1275 }
1276
1277 //=============================================================================
1278 /*!
1279  *  IsLocal1DHypothesis
1280  *  Returns a local 1D hypothesis used for theEdge
1281  */
1282 //=============================================================================
1283 const SMESH_Hypothesis* SMESH_Mesh::IsLocal1DHypothesis (const TopoDS_Shape& theEdge)
1284 {
1285   SMESH_HypoFilter hypo ( SMESH_HypoFilter::HasDim( 1 ));
1286   hypo.AndNot( hypo.IsAlgo() ).AndNot( hypo.IsAssignedTo( GetMeshDS()->ShapeToMesh() ));
1287
1288   return GetHypothesis( theEdge, hypo, true );
1289 }
1290
1291 //=============================================================================
1292 /*!
1293  *  IsPropagationHypothesis
1294  */
1295 //=============================================================================
1296 bool SMESH_Mesh::IsPropagationHypothesis (const TopoDS_Shape& theEdge)
1297 {
1298   return _mapPropagationChains.Contains(theEdge);
1299 }
1300
1301 //=============================================================================
1302 /*!
1303  *  IsPropagatedHypothesis
1304  */
1305 //=============================================================================
1306 bool SMESH_Mesh::IsPropagatedHypothesis (const TopoDS_Shape& theEdge,
1307                                          TopoDS_Shape&       theMainEdge)
1308 {
1309   int nbChains = _mapPropagationChains.Extent();
1310   for (int i = 1; i <= nbChains; i++) {
1311     //const TopTools_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
1312     const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromIndex(i);
1313     if (aChain.Contains(theEdge)) {
1314       theMainEdge = _mapPropagationChains.FindKey(i);
1315       return true;
1316     }
1317   }
1318
1319   return false;
1320 }
1321 //=============================================================================
1322 /*!
1323  *  IsReversedInChain
1324  */
1325 //=============================================================================
1326
1327 bool SMESH_Mesh::IsReversedInChain (const TopoDS_Shape& theEdge,
1328                                     const TopoDS_Shape& theMainEdge)
1329 {
1330   if ( !theMainEdge.IsNull() && !theEdge.IsNull() &&
1331       _mapPropagationChains.Contains( theMainEdge ))
1332   {
1333     const SMESH_IndexedMapOfShape& aChain =
1334       _mapPropagationChains.FindFromKey( theMainEdge );
1335     int index = aChain.FindIndex( theEdge );
1336     if ( index )
1337       return aChain(index).Orientation() == TopAbs_REVERSED;
1338   }
1339   return false;
1340 }
1341
1342 //=============================================================================
1343 /*!
1344  *  CleanMeshOnPropagationChain
1345  */
1346 //=============================================================================
1347 void SMESH_Mesh::CleanMeshOnPropagationChain (const TopoDS_Shape& theMainEdge)
1348 {
1349   const SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.FindFromKey(theMainEdge);
1350   int i, nbEdges = aChain.Extent();
1351   for (i = 1; i <= nbEdges; i++) {
1352     TopoDS_Shape anEdge = aChain.FindKey(i);
1353     SMESH_subMesh *subMesh = GetSubMesh(anEdge);
1354     SMESHDS_SubMesh *subMeshDS = subMesh->GetSubMeshDS();
1355     if (subMeshDS && subMeshDS->NbElements() > 0) {
1356       subMesh->ComputeStateEngine(SMESH_subMesh::CLEAN);
1357     }
1358   }
1359 }
1360
1361 //=============================================================================
1362 /*!
1363  *  RebuildPropagationChains
1364  *  Rebuild all existing propagation chains.
1365  *  Have to be used, if 1D hypothesis have been assigned/removed to/from any edge
1366  */
1367 //=============================================================================
1368 bool SMESH_Mesh::RebuildPropagationChains()
1369 {
1370   bool ret = true;
1371
1372   // Clean all chains, because they can be not up-to-date
1373   int i, nbChains = _mapPropagationChains.Extent();
1374   for (i = 1; i <= nbChains; i++) {
1375     TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
1376     CleanMeshOnPropagationChain(aMainEdge);
1377     _mapPropagationChains.ChangeFromIndex(i).Clear();
1378   }
1379
1380   // Build all chains
1381   for (i = 1; i <= nbChains; i++) {
1382     TopoDS_Shape aMainEdge = _mapPropagationChains.FindKey(i);
1383     if (!BuildPropagationChain(aMainEdge))
1384       ret = false;
1385     CleanMeshOnPropagationChain(aMainEdge);
1386   }
1387
1388   return ret;
1389 }
1390
1391 //=============================================================================
1392 /*!
1393  *  RemovePropagationChain
1394  *  Have to be used, if Propagation hypothesis is removed from <theMainEdge>
1395  */
1396 //=============================================================================
1397 bool SMESH_Mesh::RemovePropagationChain (const TopoDS_Shape& theMainEdge)
1398 {
1399   if (!_mapPropagationChains.Contains(theMainEdge))
1400     return false;
1401
1402   // Clean mesh elements and nodes, built on the chain
1403   CleanMeshOnPropagationChain(theMainEdge);
1404
1405   // Clean the chain
1406   _mapPropagationChains.ChangeFromKey(theMainEdge).Clear();
1407
1408   // Remove the chain from the map
1409   int i = _mapPropagationChains.FindIndex(theMainEdge);
1410   if ( i == _mapPropagationChains.Extent() )
1411     _mapPropagationChains.RemoveLast();
1412   else {
1413     TopoDS_Vertex anEmptyShape;
1414     BRep_Builder BB;
1415     BB.MakeVertex(anEmptyShape, gp_Pnt(0,0,0), 0.1);
1416     SMESH_IndexedMapOfShape anEmptyMap;
1417     _mapPropagationChains.Substitute(i, anEmptyShape, anEmptyMap);
1418   }
1419
1420   return true;
1421 }
1422
1423 //=============================================================================
1424 /*!
1425  *  BuildPropagationChain
1426  */
1427 //=============================================================================
1428 bool SMESH_Mesh::BuildPropagationChain (const TopoDS_Shape& theMainEdge)
1429 {
1430   if (theMainEdge.ShapeType() != TopAbs_EDGE) return true;
1431
1432   // Add new chain, if there is no
1433   if (!_mapPropagationChains.Contains(theMainEdge)) {
1434     SMESH_IndexedMapOfShape aNewChain;
1435     _mapPropagationChains.Add(theMainEdge, aNewChain);
1436   }
1437
1438   // Check presence of 1D hypothesis to be propagated
1439   const SMESH_Hypothesis* aMainHyp = IsLocal1DHypothesis(theMainEdge);
1440   if (!aMainHyp) {
1441     MESSAGE("Warning: There is no 1D hypothesis to propagate. Please, assign.");
1442     return true;
1443   }
1444
1445   // Edges, on which the 1D hypothesis will be propagated from <theMainEdge>
1446   SMESH_IndexedMapOfShape& aChain = _mapPropagationChains.ChangeFromKey(theMainEdge);
1447   if (aChain.Extent() > 0) {
1448     CleanMeshOnPropagationChain(theMainEdge);
1449     aChain.Clear();
1450   }
1451
1452   // At first put <theMainEdge> in the chain
1453   aChain.Add(theMainEdge);
1454
1455   // List of edges, added to chain on the previous cycle pass
1456   TopTools_ListOfShape listPrevEdges;
1457   listPrevEdges.Append(theMainEdge.Oriented( TopAbs_FORWARD ));
1458
1459 //   5____4____3____4____5____6
1460 //   |    |    |    |    |    |
1461 //   |    |    |    |    |    |
1462 //   4____3____2____3____4____5
1463 //   |    |    |    |    |    |      Number in the each knot of
1464 //   |    |    |    |    |    |      grid indicates cycle pass,
1465 //   3____2____1____2____3____4      on which corresponding edge
1466 //   |    |    |    |    |    |      (perpendicular to the plane
1467 //   |    |    |    |    |    |      of view) will be found.
1468 //   2____1____0____1____2____3
1469 //   |    |    |    |    |    |
1470 //   |    |    |    |    |    |
1471 //   3____2____1____2____3____4
1472
1473   // Collect all edges pass by pass
1474   while (listPrevEdges.Extent() > 0) {
1475     // List of edges, added to chain on this cycle pass
1476     TopTools_ListOfShape listCurEdges;
1477
1478     // Find the next portion of edges
1479     TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
1480     for (; itE.More(); itE.Next()) {
1481       TopoDS_Shape anE = itE.Value();
1482
1483       // Iterate on faces, having edge <anE>
1484       TopTools_ListIteratorOfListOfShape itA (GetAncestors(anE));
1485       for (; itA.More(); itA.Next()) {
1486         TopoDS_Shape aW = itA.Value();
1487
1488         // There are objects of different type among the ancestors of edge
1489         if (aW.ShapeType() == TopAbs_WIRE) {
1490           TopoDS_Shape anOppE;
1491
1492           BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
1493           Standard_Integer nb = 1, found = 0;
1494           TopTools_Array1OfShape anEdges (1,4);
1495           for (; aWE.More(); aWE.Next(), nb++) {
1496             if (nb > 4) {
1497               found = 0;
1498               break;
1499             }
1500             anEdges(nb) = aWE.Current();
1501             if (!_mapAncestors.Contains(anEdges(nb))) {
1502               MESSAGE("WIRE EXPLORER HAVE GIVEN AN INVALID EDGE !!!");
1503               break;
1504             }
1505             if (anEdges(nb).IsSame(anE)) found = nb;
1506           }
1507
1508           if (nb == 5 && found > 0) {
1509             // Quadrangle face found, get an opposite edge
1510             Standard_Integer opp = found + 2;
1511             if (opp > 4) opp -= 4;
1512             anOppE = anEdges(opp);
1513
1514             // add anOppE to aChain if ...
1515             if (!aChain.Contains(anOppE)) { // ... anOppE is not in aChain
1516               if (!IsLocal1DHypothesis(anOppE)) { // ... no other 1d hyp on anOppE
1517                 TopoDS_Shape aMainEdgeForOppEdge; // ... no other hyp is propagated to anOppE
1518                 if (!IsPropagatedHypothesis(anOppE, aMainEdgeForOppEdge))
1519                 {
1520                   // Add found edge to the chain oriented so that to
1521                   // have it co-directed with a forward MainEdge
1522                   TopAbs_Orientation ori = anE.Orientation();
1523                   if ( anEdges(opp).Orientation() == anEdges(found).Orientation() )
1524                     ori = TopAbs::Reverse( ori );
1525                   anOppE.Orientation( ori );
1526                   aChain.Add(anOppE);
1527                   listCurEdges.Append(anOppE);
1528                 }
1529                 else {
1530                   // Collision!
1531                   MESSAGE("Error: Collision between propagated hypotheses");
1532                   CleanMeshOnPropagationChain(theMainEdge);
1533                   aChain.Clear();
1534                   return ( aMainHyp == IsLocal1DHypothesis(aMainEdgeForOppEdge) );
1535                 }
1536               }
1537             }
1538           } // if (nb == 5 && found > 0)
1539         } // if (aF.ShapeType() == TopAbs_WIRE)
1540       } // for (; itF.More(); itF.Next())
1541     } // for (; itE.More(); itE.Next())
1542
1543     listPrevEdges = listCurEdges;
1544   } // while (listPrevEdges.Extent() > 0)
1545
1546   CleanMeshOnPropagationChain(theMainEdge);
1547   return true;
1548 }
1549
1550 //=======================================================================
1551 //function : GetAncestors
1552 //purpose  : return list of ancestors of theSubShape in the order
1553 //           that lower dimention shapes come first.
1554 //=======================================================================
1555
1556 const TopTools_ListOfShape& SMESH_Mesh::GetAncestors(const TopoDS_Shape& theS) const
1557 {
1558   if ( _mapAncestors.Contains( theS ) )
1559     return _mapAncestors.FindFromKey( theS );
1560
1561   static TopTools_ListOfShape emptyList;
1562   return emptyList;
1563 }
1564
1565 //=======================================================================
1566 //function : Dump
1567 //purpose  : dumps contents of mesh to stream [ debug purposes ]
1568 //=======================================================================
1569 ostream& SMESH_Mesh::Dump(ostream& save)
1570 {
1571   int clause = 0;
1572   save << "========================== Dump contents of mesh ==========================" << endl << endl;
1573   save << ++clause << ") Total number of nodes:   \t"    << NbNodes() << endl;
1574   save << ++clause << ") Total number of edges:   \t"    << NbEdges() << endl;
1575   save << ++clause << ") Total number of faces:   \t"    << NbFaces() << endl;
1576   save << ++clause << ") Total number of polygons:\t"    << NbPolygons() << endl;
1577   save << ++clause << ") Total number of volumes:\t"     << NbVolumes() << endl;
1578   save << ++clause << ") Total number of polyhedrons:\t" << NbPolyhedrons() << endl << endl;
1579   for ( int isQuadratic = 0; isQuadratic < 2; ++isQuadratic )
1580   {
1581     string orderStr = isQuadratic ? "quadratic" : "linear";
1582     ElementOrder order  = isQuadratic ? ORDER_QUADRATIC : ORDER_LINEAR;
1583
1584     save << ++clause << ") Total number of " << orderStr << " edges:\t" << NbEdges(order) << endl;
1585     save << ++clause << ") Total number of " << orderStr << " faces:\t" << NbFaces(order) << endl;
1586     if ( NbFaces(order) > 0 ) {
1587       int nb3 = NbTriangles(order);
1588       int nb4 = NbQuadrangles(order);
1589       save << clause << ".1) Number of " << orderStr << " triangles:  \t" << nb3 << endl;
1590       save << clause << ".2) Number of " << orderStr << " quadrangles:\t" << nb4 << endl;
1591       if ( nb3 + nb4 !=  NbFaces(order) ) {
1592         map<int,int> myFaceMap;
1593         SMDS_FaceIteratorPtr itFaces=_myMeshDS->facesIterator();
1594         while( itFaces->more( ) ) {
1595           int nbNodes = itFaces->next()->NbNodes();
1596           if ( myFaceMap.find( nbNodes ) == myFaceMap.end() )
1597             myFaceMap[ nbNodes ] = 0;
1598           myFaceMap[ nbNodes ] = myFaceMap[ nbNodes ] + 1;
1599         }
1600         save << clause << ".3) Faces in detail: " << endl;
1601         map <int,int>::iterator itF;
1602         for (itF = myFaceMap.begin(); itF != myFaceMap.end(); itF++)
1603           save << "--> nb nodes: " << itF->first << " - nb elemens:\t" << itF->second << endl;
1604       }
1605     }
1606     save << ++clause << ") Total number of " << orderStr << " volumes:\t" << NbVolumes(order) << endl;
1607     if ( NbVolumes(order) > 0 ) {
1608       int nb8 = NbHexas(order);
1609       int nb4 = NbTetras(order);
1610       int nb5 = NbPyramids(order);
1611       int nb6 = NbPrisms(order);
1612       save << clause << ".1) Number of " << orderStr << " hexahedrons:\t" << nb8 << endl;
1613       save << clause << ".2) Number of " << orderStr << " tetrahedrons:\t" << nb4 << endl;
1614       save << clause << ".3) Number of " << orderStr << " prisms:      \t" << nb6 << endl;
1615       save << clause << ".4) Number of " << orderStr << " pyramids:\t" << nb5 << endl;
1616       if ( nb8 + nb4 + nb5 + nb6 != NbVolumes(order) ) {
1617         map<int,int> myVolumesMap;
1618         SMDS_VolumeIteratorPtr itVolumes=_myMeshDS->volumesIterator();
1619         while( itVolumes->more( ) ) {
1620           int nbNodes = itVolumes->next()->NbNodes();
1621           if ( myVolumesMap.find( nbNodes ) == myVolumesMap.end() )
1622             myVolumesMap[ nbNodes ] = 0;
1623           myVolumesMap[ nbNodes ] = myVolumesMap[ nbNodes ] + 1;
1624         }
1625         save << clause << ".5) Volumes in detail: " << endl;
1626         map <int,int>::iterator itV;
1627         for (itV = myVolumesMap.begin(); itV != myVolumesMap.end(); itV++)
1628           save << "--> nb nodes: " << itV->first << " - nb elemens:\t" << itV->second << endl;
1629       }
1630     }
1631     save << endl;
1632   }
1633   save << "===========================================================================" << endl;
1634   return save;
1635 }
1636
1637 //=======================================================================
1638 //function : GetElementType
1639 //purpose  : Returns type of mesh element with certain id
1640 //=======================================================================
1641 SMDSAbs_ElementType SMESH_Mesh::GetElementType( const int id, const bool iselem )
1642 {
1643   return _myMeshDS->GetElementType( id, iselem );
1644 }