Salome HOME
#18963 Minimize compiler warnings
[modules/smesh.git] / src / SMESH / SMESH_Gen.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
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 //  SMESH SMESH : implementation of SMESH idl descriptions
24 //  File   : SMESH_Gen.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //
28
29 //#define CHRONODEF
30
31 #include "SMESH_Gen.hxx"
32
33 #include "SMDS_Mesh.hxx"
34 #include "SMDS_MeshElement.hxx"
35 #include "SMDS_MeshNode.hxx"
36 #include "SMESHDS_Document.hxx"
37 #include "SMESH_HypoFilter.hxx"
38 #include "SMESH_Mesh.hxx"
39 #include "SMESH_MesherHelper.hxx"
40 #include "SMESH_subMesh.hxx"
41
42 #include "utilities.h"
43 #include "OpUtil.hxx"
44 #include "Utils_ExceptHandlers.hxx"
45
46 #include <TopoDS_Iterator.hxx>
47 #include <TopoDS.hxx>
48
49 #include "memoire.h"
50
51 #ifdef WIN32
52   #include <windows.h>
53 #endif
54
55 #include <Basics_Utils.hxx>
56
57 using namespace std;
58
59 // Environment variable separator
60 #ifdef WIN32
61   #define env_sep ';'
62 #else
63   #define env_sep ':'
64 #endif
65
66 namespace
67 {
68   // a structure used to nullify SMESH_Gen field of SMESH_Hypothesis,
69   // which is needed for SMESH_Hypothesis not deleted before ~SMESH_Gen()
70   struct _Hyp : public SMESH_Hypothesis
71   {
72     void NullifyGen()
73     {
74       _gen = 0;
75     }
76   };
77
78   //================================================================================
79   /*!
80    * \brief Fill a map of shapes with all sub-shape of a sub-mesh
81    */
82   //================================================================================
83
84   TopTools_IndexedMapOfShape * fillAllowed( SMESH_subMesh*               sm,
85                                             const bool                   toFill,
86                                             TopTools_IndexedMapOfShape * allowedSub )
87   {
88     if ( !toFill || !allowedSub )
89     {
90       return nullptr;
91     }
92     if ( allowedSub->IsEmpty() )
93     {
94       allowedSub->ReSize( sm->DependsOn().size() + 1 );
95       allowedSub->Add( sm->GetSubShape() );
96       for ( const auto & key_sm : sm->DependsOn() )
97         allowedSub->Add( key_sm.second->GetSubShape() );
98     }
99     return allowedSub;
100   }
101 }
102
103 //=============================================================================
104 /*!
105  *  Constructor
106  */
107 //=============================================================================
108
109 SMESH_Gen::SMESH_Gen()
110 {
111   _studyContext = new StudyContextStruct;
112   _studyContext->myDocument = new SMESHDS_Document();
113   _localId = 0;
114   _hypId   = 0;
115   _segmentation = _nbSegments = 10;
116   _compute_canceled = false;
117 }
118
119 //=============================================================================
120 /*!
121  * Destructor
122  */
123 //=============================================================================
124
125 SMESH_Gen::~SMESH_Gen()
126 {
127   std::map < int, SMESH_Hypothesis * >::iterator i_hyp = _studyContext->mapHypothesis.begin();
128   for ( ; i_hyp != _studyContext->mapHypothesis.end(); ++i_hyp )
129   {
130     if ( _Hyp* h = static_cast< _Hyp*>( i_hyp->second ))
131       h->NullifyGen();
132   }
133   delete _studyContext->myDocument;
134   delete _studyContext;
135 }
136
137 //=============================================================================
138 /*!
139  * Creates a mesh in a study.
140  * if (theIsEmbeddedMode) { mesh modification commands are not logged }
141  */
142 //=============================================================================
143
144 SMESH_Mesh* SMESH_Gen::CreateMesh(bool theIsEmbeddedMode)
145 {
146   Unexpect aCatch(SalomeException);
147
148   // create a new SMESH_mesh object
149   SMESH_Mesh *aMesh = new SMESH_Mesh(_localId++,
150                                      this,
151                                      theIsEmbeddedMode,
152                                      _studyContext->myDocument);
153   _studyContext->mapMesh[_localId-1] = aMesh;
154
155   return aMesh;
156 }
157
158 //=============================================================================
159 /*
160  * Compute a mesh
161  */
162 //=============================================================================
163
164 bool SMESH_Gen::Compute(SMESH_Mesh &                aMesh,
165                         const TopoDS_Shape &        aShape,
166                         const int                   aFlags /*= COMPACT_MESH*/,
167                         const ::MeshDimension       aDim /*=::MeshDim_3D*/,
168                         TSetOfInt*                  aShapesId /*=0*/,
169                         TopTools_IndexedMapOfShape* anAllowedSubShapes/*=0*/)
170 {
171   MEMOSTAT;
172
173   const bool   aShapeOnly = aFlags & SHAPE_ONLY;
174   const bool     anUpward = aFlags & UPWARD;
175   const bool aCompactMesh = aFlags & COMPACT_MESH;
176
177   bool ret = true;
178
179   SMESH_subMesh *sm, *shapeSM = aMesh.GetSubMesh(aShape);
180
181   const bool includeSelf = true;
182   const bool complexShapeFirst = true;
183   const int  globalAlgoDim = 100;
184
185   SMESH_subMeshIteratorPtr smIt;
186
187   // Fix of Issue 22150. Due to !BLSURF->OnlyUnaryInput(), BLSURF computes edges
188   // that must be computed by Projection 1D-2D while the Projection asks to compute
189   // one face only.
190   SMESH_subMesh::compute_event computeEvent =
191     aShapeOnly ? SMESH_subMesh::COMPUTE_SUBMESH : SMESH_subMesh::COMPUTE;
192   if ( !aMesh.HasShapeToMesh() )
193     computeEvent = SMESH_subMesh::COMPUTE_NOGEOM; // if several algos and no geometry
194
195   TopTools_IndexedMapOfShape *allowedSubShapes = anAllowedSubShapes, allowedSub;
196   if ( aShapeOnly && !allowedSubShapes )
197     allowedSubShapes = &allowedSub;
198
199   if ( anUpward ) // is called from the below code in this method
200   {
201     // ===============================================
202     // Mesh all the sub-shapes starting from vertices
203     // ===============================================
204
205     smIt = shapeSM->getDependsOnIterator(includeSelf, !complexShapeFirst);
206     while ( smIt->more() )
207     {
208       SMESH_subMesh* smToCompute = smIt->next();
209
210       // do not mesh vertices of a pseudo shape
211       const TopoDS_Shape&        shape = smToCompute->GetSubShape();
212       const TopAbs_ShapeEnum shapeType = shape.ShapeType();
213       if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
214         continue;
215
216       // check for preview dimension limitations
217       if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
218       {
219         // clear compute state not to show previous compute errors
220         //  if preview invoked less dimension less than previous
221         smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
222         continue;
223       }
224
225       if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
226       {
227         if (_compute_canceled)
228           return false;
229         smToCompute->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
230         setCurrentSubMesh( smToCompute );
231         smToCompute->ComputeStateEngine( computeEvent );
232         setCurrentSubMesh( nullptr );
233         smToCompute->SetAllowedSubShapes( nullptr );
234       }
235
236       // we check all the sub-meshes here and detect if any of them failed to compute
237       if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE &&
238           ( shapeType != TopAbs_EDGE || !SMESH_Algo::isDegenerated( TopoDS::Edge( shape ))))
239         ret = false;
240       else if ( aShapesId )
241         aShapesId->insert( smToCompute->GetId() );
242     }
243     //aMesh.GetMeshDS()->Modified();
244     return ret;
245   }
246   else
247   {
248     // ================================================================
249     // Apply algos that do NOT require discreteized boundaries
250     // ("all-dimensional") and do NOT support sub-meshes, starting from
251     // the most complex shapes and collect sub-meshes with algos that 
252     // DO support sub-meshes
253     // ================================================================
254
255     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes[4]; // for each dim
256
257     // map to sort sm with same dim algos according to dim of
258     // the shape the algo assigned to (issue 0021217).
259     // Other issues influenced the algo applying order:
260     // 21406, 21556, 21893, 20206
261     multimap< int, SMESH_subMesh* > shDim2sm;
262     multimap< int, SMESH_subMesh* >::reverse_iterator shDim2smIt;
263     TopoDS_Shape algoShape;
264     int prevShapeDim = -1, aShapeDim;
265
266     smIt = shapeSM->getDependsOnIterator(includeSelf, complexShapeFirst);
267     while ( smIt->more() )
268     {
269       SMESH_subMesh* smToCompute = smIt->next();
270       if ( smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE )
271         continue;
272
273       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
274       aShapeDim = GetShapeDim( aSubShape );
275       if ( aShapeDim < 1 ) break;
276       
277       // check for preview dimension limitations
278       if ( aShapesId && aShapeDim > (int)aDim )
279         continue;
280
281       SMESH_Algo* algo = GetAlgo( smToCompute, &algoShape );
282       if ( algo && !algo->NeedDiscreteBoundary() )
283       {
284         if ( algo->SupportSubmeshes() )
285         {
286           // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
287           // so that more local algos to go first
288           if ( prevShapeDim != aShapeDim )
289           {
290             prevShapeDim = aShapeDim;
291             for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
292               if ( shDim2smIt->first == globalAlgoDim )
293                 smWithAlgoSupportingSubmeshes[ aShapeDim ].push_back( shDim2smIt->second );
294               else
295                 smWithAlgoSupportingSubmeshes[ aShapeDim ].push_front( shDim2smIt->second );
296             shDim2sm.clear();
297           }
298           // add smToCompute to shDim2sm map
299           if ( algoShape.IsSame( aMesh.GetShapeToMesh() ))
300           {
301             aShapeDim = globalAlgoDim; // to compute last
302           }
303           else
304           {
305             aShapeDim = GetShapeDim( algoShape );
306             if ( algoShape.ShapeType() == TopAbs_COMPOUND )
307             {
308               TopoDS_Iterator it( algoShape );
309               aShapeDim += GetShapeDim( it.Value() );
310             }
311           }
312           shDim2sm.insert( make_pair( aShapeDim, smToCompute ));
313         }
314         else // Compute w/o support of sub-meshes
315         {
316           if (_compute_canceled)
317             return false;
318           smToCompute->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
319           setCurrentSubMesh( smToCompute );
320           smToCompute->ComputeStateEngine( computeEvent );
321           setCurrentSubMesh( nullptr );
322           smToCompute->SetAllowedSubShapes( nullptr );
323           if ( aShapesId )
324             aShapesId->insert( smToCompute->GetId() );
325         }
326       }
327     }
328     // reload sub-meshes from shDim2sm into smWithAlgoSupportingSubmeshes
329     for ( shDim2smIt = shDim2sm.rbegin(); shDim2smIt != shDim2sm.rend(); ++shDim2smIt )
330       if ( shDim2smIt->first == globalAlgoDim )
331         smWithAlgoSupportingSubmeshes[3].push_back( shDim2smIt->second );
332       else
333         smWithAlgoSupportingSubmeshes[0].push_front( shDim2smIt->second );
334
335     // ======================================================
336     // Apply all-dimensional algorithms supporing sub-meshes
337     // ======================================================
338
339     std::vector< SMESH_subMesh* > smVec;
340     for ( aShapeDim = 0; aShapeDim < 4; ++aShapeDim )
341     {
342       // ------------------------------------------------
343       // sort list of sub-meshes according to mesh order
344       // ------------------------------------------------
345       smVec.assign( smWithAlgoSupportingSubmeshes[ aShapeDim ].begin(),
346                     smWithAlgoSupportingSubmeshes[ aShapeDim ].end() );
347       aMesh.SortByMeshOrder( smVec );
348
349       // ------------------------------------------------------------
350       // compute sub-meshes with local uni-dimensional algos under
351       // sub-meshes with all-dimensional algos
352       // ------------------------------------------------------------
353       // start from lower shapes
354       for ( size_t i = 0; i < smVec.size(); ++i )
355       {
356         sm = smVec[i];
357
358         // get a shape the algo is assigned to
359         if ( !GetAlgo( sm, & algoShape ))
360           continue; // strange...
361
362         // look for more local algos
363         smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
364         while ( smIt->more() )
365         {
366           SMESH_subMesh* smToCompute = smIt->next();
367
368           const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
369           const int aShapeDim = GetShapeDim( aSubShape );
370           if ( aShapeDim < 1 ) continue;
371
372           // check for preview dimension limitations
373           if ( aShapesId && GetShapeDim( aSubShape.ShapeType() ) > (int)aDim )
374             continue;
375
376           SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
377           filter
378             .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
379             .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
380
381           if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true))
382           {
383             if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
384             TopTools_IndexedMapOfShape* localAllowed = allowedSubShapes;
385             if ( localAllowed && localAllowed->IsEmpty() )
386               localAllowed = 0; // prevent fillAllowed() with  aSubShape
387
388             SMESH_Hypothesis::Hypothesis_Status status;
389             if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
390               // mesh a lower smToCompute starting from vertices
391               Compute( aMesh, aSubShape, aFlags | SHAPE_ONLY_UPWARD, aDim, aShapesId, localAllowed );
392           }
393         }
394       }
395       // --------------------------------
396       // apply the all-dimensional algos
397       // --------------------------------
398       for ( size_t i = 0; i < smVec.size(); ++i )
399       {
400         sm = smVec[i];
401         if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
402         {
403           const TopAbs_ShapeEnum shapeType = sm->GetSubShape().ShapeType();
404           // check for preview dimension limitations
405           if ( aShapesId && GetShapeDim( shapeType ) > (int)aDim )
406             continue;
407
408           if (_compute_canceled)
409             return false;
410           sm->SetAllowedSubShapes( fillAllowed( shapeSM, aShapeOnly, allowedSubShapes ));
411           setCurrentSubMesh( sm );
412           sm->ComputeStateEngine( computeEvent );
413           setCurrentSubMesh( NULL );
414           sm->SetAllowedSubShapes( nullptr );
415           if ( aShapesId )
416             aShapesId->insert( sm->GetId() );
417         }
418       }
419     } // loop on shape dimensions
420
421     // -----------------------------------------------
422     // mesh the rest sub-shapes starting from vertices
423     // -----------------------------------------------
424     ret = Compute( aMesh, aShape, aFlags | UPWARD, aDim, aShapesId, allowedSubShapes );
425   }
426
427   MEMOSTAT;
428
429   // fix quadratic mesh by bending iternal links near concave boundary
430   if ( aCompactMesh && // a final compute
431        aShape.IsSame( aMesh.GetShapeToMesh() ) &&
432        !aShapesId && // not preview
433        ret ) // everything is OK
434   {
435     SMESH_MesherHelper aHelper( aMesh );
436     if ( aHelper.IsQuadraticMesh() != SMESH_MesherHelper::LINEAR )
437     {
438       aHelper.FixQuadraticElements( shapeSM->GetComputeError() );
439     }
440   }
441
442   if ( aCompactMesh )
443   {
444     aMesh.GetMeshDS()->Modified();
445     aMesh.GetMeshDS()->CompactMesh();
446   }
447   return ret;
448 }
449
450 //=============================================================================
451 /*!
452  * Prepare Compute a mesh
453  */
454 //=============================================================================
455 void SMESH_Gen::PrepareCompute(SMESH_Mesh &          /*aMesh*/,
456                                const TopoDS_Shape &  /*aShape*/)
457 {
458   _compute_canceled = false;
459   resetCurrentSubMesh();
460 }
461
462 //=============================================================================
463 /*!
464  * Cancel Compute a mesh
465  */
466 //=============================================================================
467 void SMESH_Gen::CancelCompute(SMESH_Mesh &          /*aMesh*/,
468                               const TopoDS_Shape &  /*aShape*/)
469 {
470   _compute_canceled = true;
471   if ( const SMESH_subMesh* sm = GetCurrentSubMesh() )
472   {
473     const_cast< SMESH_subMesh* >( sm )->ComputeStateEngine( SMESH_subMesh::COMPUTE_CANCELED );
474   }
475   resetCurrentSubMesh();
476 }
477
478 //================================================================================
479 /*!
480  * \brief Returns a sub-mesh being currently computed
481  */
482 //================================================================================
483
484 const SMESH_subMesh* SMESH_Gen::GetCurrentSubMesh() const
485 {
486   return _sm_current.empty() ? 0 : _sm_current.back();
487 }
488
489 //================================================================================
490 /*!
491  * \brief Sets a sub-mesh being currently computed.
492  *
493  * An algorithm can call Compute() for a sub-shape, hence we keep a stack of sub-meshes
494  */
495 //================================================================================
496
497 void SMESH_Gen::setCurrentSubMesh(SMESH_subMesh* sm)
498 {
499   if ( sm )
500     _sm_current.push_back( sm );
501
502   else if ( !_sm_current.empty() )
503     _sm_current.pop_back();
504 }
505
506 void SMESH_Gen::resetCurrentSubMesh()
507 {
508   _sm_current.clear();
509 }
510
511 //=============================================================================
512 /*!
513  * Evaluate a mesh
514  */
515 //=============================================================================
516
517 bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
518                          const TopoDS_Shape &  aShape,
519                          MapShapeNbElems&      aResMap,
520                          const bool            anUpward,
521                          TSetOfInt*            aShapesId)
522 {
523   bool ret = true;
524
525   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
526
527   const bool includeSelf = true;
528   const bool complexShapeFirst = true;
529   SMESH_subMeshIteratorPtr smIt;
530
531   if ( anUpward ) { // is called from below code here
532     // -----------------------------------------------
533     // mesh all the sub-shapes starting from vertices
534     // -----------------------------------------------
535     smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
536     while ( smIt->more() ) {
537       SMESH_subMesh* smToCompute = smIt->next();
538
539       // do not mesh vertices of a pseudo shape
540       const TopAbs_ShapeEnum shapeType = smToCompute->GetSubShape().ShapeType();
541       //if ( !aMesh.HasShapeToMesh() && shapeType == TopAbs_VERTEX )
542       //  continue;
543       if ( !aMesh.HasShapeToMesh() ) {
544         if( shapeType == TopAbs_VERTEX || shapeType == TopAbs_WIRE ||
545             shapeType == TopAbs_SHELL )
546           continue;
547       }
548
549       smToCompute->Evaluate(aResMap);
550       if( aShapesId )
551         aShapesId->insert( smToCompute->GetId() );
552     }
553     return ret;
554   }
555   else {
556     // -----------------------------------------------------------------
557     // apply algos that DO NOT require Discreteized boundaries and DO NOT
558     // support sub-meshes, starting from the most complex shapes
559     // and collect sub-meshes with algos that DO support sub-meshes
560     // -----------------------------------------------------------------
561     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes;
562     smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
563     while ( smIt->more() ) {
564       SMESH_subMesh* smToCompute = smIt->next();
565       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
566       const int aShapeDim = GetShapeDim( aSubShape );
567       if ( aShapeDim < 1 ) break;
568       
569       SMESH_Algo* algo = GetAlgo( smToCompute );
570       if ( algo && !algo->NeedDiscreteBoundary() ) {
571         if ( algo->SupportSubmeshes() ) {
572           smWithAlgoSupportingSubmeshes.push_front( smToCompute );
573         }
574         else {
575           smToCompute->Evaluate(aResMap);
576           if ( aShapesId )
577             aShapesId->insert( smToCompute->GetId() );
578         }
579       }
580     }
581
582     // ------------------------------------------------------------
583     // sort list of meshes according to mesh order
584     // ------------------------------------------------------------
585     std::vector< SMESH_subMesh* > smVec( smWithAlgoSupportingSubmeshes.begin(),
586                                          smWithAlgoSupportingSubmeshes.end() );
587     aMesh.SortByMeshOrder( smVec );
588
589     // ------------------------------------------------------------
590     // compute sub-meshes under shapes with algos that DO NOT require
591     // Discreteized boundaries and DO support sub-meshes
592     // ------------------------------------------------------------
593     // start from lower shapes
594     for ( size_t i = 0; i < smVec.size(); ++i )
595     {
596       sm = smVec[i];
597
598       // get a shape the algo is assigned to
599       TopoDS_Shape algoShape;
600       if ( !GetAlgo( sm, & algoShape ))
601         continue; // strange...
602
603       // look for more local algos
604       smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
605       while ( smIt->more() ) {
606         SMESH_subMesh* smToCompute = smIt->next();
607
608         const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
609         const int aShapeDim = GetShapeDim( aSubShape );
610         if ( aShapeDim < 1 ) continue;
611
612         SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
613         filter
614           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
615           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape, aMesh ));
616
617         if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( smToCompute, filter, true ))
618         {
619           if ( ! subAlgo->NeedDiscreteBoundary() ) continue;
620           SMESH_Hypothesis::Hypothesis_Status status;
621           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
622             // mesh a lower smToCompute starting from vertices
623             Evaluate( aMesh, aSubShape, aResMap, /*anUpward=*/true, aShapesId );
624         }
625       }
626     }
627     // ----------------------------------------------------------
628     // apply the algos that do not require Discreteized boundaries
629     // ----------------------------------------------------------
630     for ( size_t i = 0; i < smVec.size(); ++i )
631     {
632       sm = smVec[i];
633       sm->Evaluate(aResMap);
634       if ( aShapesId )
635         aShapesId->insert( sm->GetId() );
636     }
637
638     // -----------------------------------------------
639     // mesh the rest sub-shapes starting from vertices
640     // -----------------------------------------------
641     ret = Evaluate( aMesh, aShape, aResMap, /*anUpward=*/true, aShapesId );
642   }
643
644   return ret;
645 }
646
647
648 //=======================================================================
649 //function : checkConformIgnoredAlgos
650 //purpose  :
651 //=======================================================================
652
653 static bool checkConformIgnoredAlgos(SMESH_Mesh&               aMesh,
654                                      SMESH_subMesh*            aSubMesh,
655                                      const SMESH_Algo*         aGlobIgnoAlgo,
656                                      const SMESH_Algo*         aLocIgnoAlgo,
657                                      bool &                    checkConform,
658                                      set<SMESH_subMesh*>&      aCheckedMap,
659                                      list< SMESH_Gen::TAlgoStateError > & theErrors)
660 {
661   ASSERT( aSubMesh );
662   if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX)
663     return true;
664
665
666   bool ret = true;
667
668   const list<const SMESHDS_Hypothesis*>& listHyp =
669     aMesh.GetMeshDS()->GetHypothesis( aSubMesh->GetSubShape() );
670   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
671   for ( ; it != listHyp.end(); it++)
672   {
673     const SMESHDS_Hypothesis * aHyp = *it;
674     if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
675       continue;
676
677     const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp);
678     ASSERT ( algo );
679
680     if ( aLocIgnoAlgo ) // algo is hidden by a local algo of upper dim
681     {
682       theErrors.push_back( SMESH_Gen::TAlgoStateError() );
683       theErrors.back().Set( SMESH_Hypothesis::HYP_HIDDEN_ALGO, algo, false );
684       INFOS( "Local <" << algo->GetName() << "> is hidden by local <"
685             << aLocIgnoAlgo->GetName() << ">");
686     }
687     else
688     {
689       bool       isGlobal = (aMesh.IsMainShape( aSubMesh->GetSubShape() ));
690       int             dim = algo->GetDim();
691       int aMaxGlobIgnoDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->GetDim() : -1 );
692       bool    isNeededDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->NeedLowerHyps( dim ) : false );
693
694       if (( dim < aMaxGlobIgnoDim && !isNeededDim ) &&
695           ( isGlobal || !aGlobIgnoAlgo->SupportSubmeshes() ))
696       {
697         // algo is hidden by a global algo
698         theErrors.push_back( SMESH_Gen::TAlgoStateError() );
699         theErrors.back().Set( SMESH_Hypothesis::HYP_HIDDEN_ALGO, algo, true );
700         INFOS( ( isGlobal ? "Global" : "Local" )
701               << " <" << algo->GetName() << "> is hidden by global <"
702               << aGlobIgnoAlgo->GetName() << ">");
703       }
704       else if ( !algo->NeedDiscreteBoundary() && !isGlobal)
705       {
706         // local algo is not hidden and hides algos on sub-shapes
707         if (checkConform && !aSubMesh->IsConform( algo ))
708         {
709           ret = false;
710           checkConform = false; // no more check conformity
711           INFOS( "ERROR: Local <" << algo->GetName() <<
712                 "> would produce not conform mesh: "
713                 "<Not Conform Mesh Allowed> hypothesis is missing");
714           theErrors.push_back( SMESH_Gen::TAlgoStateError() );
715           theErrors.back().Set( SMESH_Hypothesis::HYP_NOTCONFORM, algo, false );
716         }
717
718         // sub-algos will be hidden by a local <algo> if <algo> does not support sub-meshes
719         if ( algo->SupportSubmeshes() )
720           algo = 0;
721         SMESH_subMeshIteratorPtr revItSub =
722           aSubMesh->getDependsOnIterator( /*includeSelf=*/false, /*complexShapeFirst=*/true);
723         bool checkConform2 = false;
724         while ( revItSub->more() )
725         {
726           SMESH_subMesh* sm = revItSub->next();
727           checkConformIgnoredAlgos (aMesh, sm, aGlobIgnoAlgo,
728                                     algo, checkConform2, aCheckedMap, theErrors);
729           aCheckedMap.insert( sm );
730         }
731       }
732     }
733   }
734
735   return ret;
736 }
737
738 //=======================================================================
739 //function : checkMissing
740 //purpose  : notify on missing hypothesis
741 //           Return false if algo or hipothesis is missing
742 //=======================================================================
743
744 static bool checkMissing(SMESH_Gen*                aGen,
745                          SMESH_Mesh&               aMesh,
746                          SMESH_subMesh*            aSubMesh,
747                          const int                 aTopAlgoDim,
748                          bool*                     globalChecked,
749                          const bool                checkNoAlgo,
750                          set<SMESH_subMesh*>&      aCheckedMap,
751                          list< SMESH_Gen::TAlgoStateError > & theErrors)
752 {
753   switch ( aSubMesh->GetSubShape().ShapeType() )
754   {
755   case TopAbs_EDGE:
756   case TopAbs_FACE:
757   case TopAbs_SOLID: break; // check this sub-mesh, it can be meshed
758   default:
759     return true; // not meshable sub-mesh
760   }
761   if ( aCheckedMap.count( aSubMesh ))
762     return true;
763
764   int ret = true;
765   SMESH_Algo* algo = 0;
766
767   switch (aSubMesh->GetAlgoState())
768   {
769   case SMESH_subMesh::NO_ALGO: {
770     if (checkNoAlgo)
771     {
772       // should there be any algo?
773       int shapeDim = SMESH_Gen::GetShapeDim( aSubMesh->GetSubShape() );
774       if (aTopAlgoDim > shapeDim)
775       {
776         MESSAGE( "ERROR: " << shapeDim << "D algorithm is missing" );
777         ret = false;
778         theErrors.push_back( SMESH_Gen::TAlgoStateError() );
779         theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, shapeDim, true );
780       }
781     }
782     return ret;
783   }
784   case SMESH_subMesh::MISSING_HYP: {
785     // notify if an algo missing hyp is attached to aSubMesh
786     algo = aSubMesh->GetAlgo();
787     ASSERT( algo );
788     bool IsGlobalHypothesis = aGen->IsGlobalHypothesis( algo, aMesh );
789     if (!IsGlobalHypothesis || !globalChecked[ algo->GetDim() ])
790     {
791       TAlgoStateErrorName errName = SMESH_Hypothesis::HYP_MISSING;
792       SMESH_Hypothesis::Hypothesis_Status status;
793       algo->CheckHypothesis( aMesh, aSubMesh->GetSubShape(), status );
794       if ( status == SMESH_Hypothesis::HYP_BAD_PARAMETER ) {
795         MESSAGE( "ERROR: hypothesis of " << (IsGlobalHypothesis ? "Global " : "Local ")
796                  << "<" << algo->GetName() << "> has a bad parameter value");
797         errName = status;
798       } else if ( status == SMESH_Hypothesis::HYP_BAD_GEOMETRY ) {
799         MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ")
800                  << "<" << algo->GetName() << "> assigned to mismatching geometry");
801         errName = status;
802       } else {
803         MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ")
804                  << "<" << algo->GetName() << "> misses some hypothesis");
805       }
806       if (IsGlobalHypothesis)
807         globalChecked[ algo->GetDim() ] = true;
808       theErrors.push_back( SMESH_Gen::TAlgoStateError() );
809       theErrors.back().Set( errName, algo, IsGlobalHypothesis );
810     }
811     ret = false;
812     break;
813   }
814   case SMESH_subMesh::HYP_OK:
815     algo = aSubMesh->GetAlgo();
816     ret = true;
817     if (!algo->NeedDiscreteBoundary())
818     {
819       SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false,
820                                                                        /*complexShapeFirst=*/false);
821       while ( itsub->more() )
822         aCheckedMap.insert( itsub->next() );
823     }
824     break;
825   default: ASSERT(0);
826   }
827
828   // do not check under algo that hides sub-algos or
829   // re-start checking NO_ALGO state
830   ASSERT (algo);
831   bool isTopLocalAlgo =
832     ( aTopAlgoDim <= algo->GetDim() && !aGen->IsGlobalHypothesis( algo, aMesh ));
833   if (!algo->NeedDiscreteBoundary() || isTopLocalAlgo)
834   {
835     bool checkNoAlgo2 = ( algo->NeedDiscreteBoundary() );
836     SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false,
837                                                                      /*complexShapeFirst=*/true);
838     while ( itsub->more() )
839     {
840       // sub-meshes should not be checked further more
841       SMESH_subMesh* sm = itsub->next();
842
843       if (isTopLocalAlgo)
844       {
845         //check algo on sub-meshes
846         int aTopAlgoDim2 = algo->GetDim();
847         if (!checkMissing (aGen, aMesh, sm, aTopAlgoDim2,
848                            globalChecked, checkNoAlgo2, aCheckedMap, theErrors))
849         {
850           ret = false;
851           if (sm->GetAlgoState() == SMESH_subMesh::NO_ALGO )
852             checkNoAlgo2 = false;
853         }
854       }
855       aCheckedMap.insert( sm );
856     }
857   }
858   return ret;
859 }
860
861 //=======================================================================
862 //function : CheckAlgoState
863 //purpose  : notify on bad state of attached algos, return false
864 //           if Compute() would fail because of some algo bad state
865 //=======================================================================
866
867 bool SMESH_Gen::CheckAlgoState(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
868 {
869   list< TAlgoStateError > errors;
870   return GetAlgoState( aMesh, aShape, errors );
871 }
872
873 //=======================================================================
874 //function : GetAlgoState
875 //purpose  : notify on bad state of attached algos, return false
876 //           if Compute() would fail because of some algo bad state
877 //           theErrors list contains problems description
878 //=======================================================================
879
880 bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
881                              const TopoDS_Shape&       theShape,
882                              list< TAlgoStateError > & theErrors)
883 {
884   bool ret = true;
885   bool hasAlgo = false;
886
887   SMESH_subMesh*          sm = theMesh.GetSubMesh(theShape);
888   const SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
889   TopoDS_Shape     mainShape = meshDS->ShapeToMesh();
890
891   // -----------------
892   // get global algos
893   // -----------------
894
895   const SMESH_Algo* aGlobAlgoArr[] = {0,0,0,0};
896
897   const list<const SMESHDS_Hypothesis*>& listHyp = meshDS->GetHypothesis( mainShape );
898   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
899   for ( ; it != listHyp.end(); it++)
900   {
901     const SMESHDS_Hypothesis * aHyp = *it;
902     if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
903       continue;
904
905     const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp);
906     ASSERT ( algo );
907
908     int dim = algo->GetDim();
909     aGlobAlgoArr[ dim ] = algo;
910
911     hasAlgo = true;
912   }
913
914   // --------------------------------------------------------
915   // info on algos that will be ignored because of ones that
916   // don't NeedDiscreteBoundary() attached to super-shapes,
917   // check that a conform mesh will be produced
918   // --------------------------------------------------------
919
920
921   // find a global algo possibly hiding sub-algos
922   int dim;
923   const SMESH_Algo* aGlobIgnoAlgo = 0;
924   for (dim = 3; dim > 0; dim--)
925   {
926     if (aGlobAlgoArr[ dim ] &&
927         !aGlobAlgoArr[ dim ]->NeedDiscreteBoundary() /*&&
928         !aGlobAlgoArr[ dim ]->SupportSubmeshes()*/ )
929     {
930       aGlobIgnoAlgo = aGlobAlgoArr[ dim ];
931       break;
932     }
933   }
934
935   set<SMESH_subMesh*> aCheckedSubs;
936   bool checkConform = ( !theMesh.IsNotConformAllowed() );
937
938   // loop on theShape and its sub-shapes
939   SMESH_subMeshIteratorPtr revItSub = sm->getDependsOnIterator( /*includeSelf=*/true,
940                                                                 /*complexShapeFirst=*/true);
941   while ( revItSub->more() )
942   {
943     SMESH_subMesh* smToCheck = revItSub->next();
944     if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
945       break;
946
947     if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked
948       if (!checkConformIgnoredAlgos (theMesh, smToCheck, aGlobIgnoAlgo,
949                                      0, checkConform, aCheckedSubs, theErrors))
950         ret = false;
951
952     if ( smToCheck->GetAlgoState() != SMESH_subMesh::NO_ALGO )
953       hasAlgo = true;
954   }
955
956   // ----------------------------------------------------------------
957   // info on missing hypothesis and find out if all needed algos are
958   // well defined
959   // ----------------------------------------------------------------
960
961   // find max dim of global algo
962   int aTopAlgoDim = 0;
963   for (dim = 3; dim > 0; dim--)
964   {
965     if (aGlobAlgoArr[ dim ])
966     {
967       aTopAlgoDim = dim;
968       break;
969     }
970   }
971   bool checkNoAlgo = theMesh.HasShapeToMesh() ? bool( aTopAlgoDim ) : false;
972   bool globalChecked[] = { false, false, false, false };
973
974   // loop on theShape and its sub-shapes
975   aCheckedSubs.clear();
976   revItSub = sm->getDependsOnIterator( /*includeSelf=*/true, /*complexShapeFirst=*/true);
977   while ( revItSub->more() )
978   {
979     SMESH_subMesh* smToCheck = revItSub->next();
980     if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
981       break;
982
983     if (!checkMissing (this, theMesh, smToCheck, aTopAlgoDim,
984                        globalChecked, checkNoAlgo, aCheckedSubs, theErrors))
985     {
986       ret = false;
987       if (smToCheck->GetAlgoState() == SMESH_subMesh::NO_ALGO )
988         checkNoAlgo = false;
989     }
990   }
991
992   if ( !hasAlgo ) {
993     ret = false;
994     theErrors.push_back( TAlgoStateError() );
995     theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, theMesh.HasShapeToMesh() ? 1 : 3, true );
996   }
997
998   return ret;
999 }
1000
1001 //=======================================================================
1002 //function : IsGlobalHypothesis
1003 //purpose  : check if theAlgo is attached to the main shape
1004 //=======================================================================
1005
1006 bool SMESH_Gen::IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& aMesh)
1007 {
1008   SMESH_HypoFilter filter( SMESH_HypoFilter::Is( theHyp ));
1009   return aMesh.GetHypothesis( aMesh.GetMeshDS()->ShapeToMesh(), filter, false );
1010 }
1011
1012 //================================================================================
1013 /*!
1014  * \brief Return paths to xml files of plugins
1015  */
1016 //================================================================================
1017
1018 std::vector< std::string > SMESH_Gen::GetPluginXMLPaths()
1019 {
1020   // Get paths to xml files of plugins
1021   vector< string > xmlPaths;
1022   string sep;
1023   if ( const char* meshersList = getenv("SMESH_MeshersList") )
1024   {
1025     string meshers = meshersList, plugin;
1026     string::size_type from = 0, pos;
1027     while ( from < meshers.size() )
1028     {
1029       // cut off plugin name
1030       pos = meshers.find( env_sep, from );
1031       if ( pos != string::npos )
1032         plugin = meshers.substr( from, pos-from );
1033       else
1034         plugin = meshers.substr( from ), pos = meshers.size();
1035       from = pos + 1;
1036
1037       // get PLUGIN_ROOT_DIR path
1038       string rootDirVar, pluginSubDir = plugin;
1039       if ( plugin == "StdMeshers" )
1040         rootDirVar = "SMESH", pluginSubDir = "smesh";
1041       else
1042         for ( pos = 0; pos < plugin.size(); ++pos )
1043           rootDirVar += toupper( plugin[pos] );
1044       rootDirVar += "_ROOT_DIR";
1045
1046       const char* rootDir = getenv( rootDirVar.c_str() );
1047       if ( !rootDir || strlen(rootDir) == 0 )
1048       {
1049         rootDirVar = plugin + "_ROOT_DIR"; // HexoticPLUGIN_ROOT_DIR
1050         rootDir = getenv( rootDirVar.c_str() );
1051         if ( !rootDir || strlen(rootDir) == 0 ) continue;
1052       }
1053
1054       // get a separator from rootDir
1055       for ( int i = strlen( rootDir )-1; i >= 0 && sep.empty(); --i )
1056         if ( rootDir[i] == '/' || rootDir[i] == '\\' )
1057         {
1058           sep = rootDir[i];
1059           break;
1060         }
1061 #ifdef WIN32
1062       if (sep.empty() ) sep = "\\";
1063 #else
1064       if (sep.empty() ) sep = "/";
1065 #endif
1066
1067       // get a path to resource file
1068       string xmlPath = rootDir;
1069       if ( xmlPath[ xmlPath.size()-1 ] != sep[0] )
1070         xmlPath += sep;
1071       xmlPath += "share" + sep + "salome" + sep + "resources" + sep;
1072       for ( pos = 0; pos < pluginSubDir.size(); ++pos )
1073         xmlPath += tolower( pluginSubDir[pos] );
1074       xmlPath += sep + plugin + ".xml";
1075       bool fileOK;
1076 #ifdef WIN32
1077 #ifdef UNICODE
1078       const wchar_t* path = Kernel_Utils::decode_s(xmlPath);
1079 #else
1080       const char* path = xmlPath.c_str();
1081 #endif
1082       fileOK = (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES);
1083 #ifdef UNICODE
1084       delete path;
1085 #endif
1086 #else
1087       fileOK = (access(xmlPath.c_str(), F_OK) == 0);
1088 #endif
1089       if ( fileOK )
1090         xmlPaths.push_back( xmlPath );
1091     }
1092   }
1093
1094   return xmlPaths;
1095 }
1096
1097 //=============================================================================
1098 /*!
1099  * Finds algo to mesh a shape. Optionally returns a shape the found algo is bound to
1100  */
1101 //=============================================================================
1102
1103 SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
1104                                const TopoDS_Shape & aShape,
1105                                TopoDS_Shape*        assignedTo)
1106 {
1107   return GetAlgo( aMesh.GetSubMesh( aShape ), assignedTo );
1108 }
1109
1110 //=============================================================================
1111 /*!
1112  * Finds algo to mesh a sub-mesh. Optionally returns a shape the found algo is bound to
1113  */
1114 //=============================================================================
1115
1116 SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_subMesh * aSubMesh,
1117                                TopoDS_Shape*   assignedTo)
1118 {
1119   if ( !aSubMesh ) return 0;
1120
1121   const TopoDS_Shape & aShape = aSubMesh->GetSubShape();
1122   SMESH_Mesh&          aMesh  = *aSubMesh->GetFather();
1123
1124   SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
1125   if ( aMesh.HasShapeToMesh() )
1126     filter.And( filter.IsApplicableTo( aShape ));
1127
1128   typedef SMESH_Algo::Features AlgoData;
1129
1130   TopoDS_Shape assignedToShape;
1131   SMESH_Algo* algo =
1132     (SMESH_Algo*) aMesh.GetHypothesis( aSubMesh, filter, true, &assignedToShape );
1133
1134   if ( algo &&
1135        aShape.ShapeType() == TopAbs_FACE &&
1136        !aShape.IsSame( assignedToShape ) &&
1137        SMESH_MesherHelper::NbAncestors( aShape, aMesh, TopAbs_SOLID ) > 1 )
1138   {
1139     // Issue 0021559. If there is another 2D algo with different types of output
1140     // elements that can be used to mesh aShape, and 3D algos on adjacent SOLIDs
1141     // have different types of input elements, we choose a most appropriate 2D algo.
1142
1143     // try to find a concurrent 2D algo
1144     filter.AndNot( filter.Is( algo ));
1145     TopoDS_Shape assignedToShape2;
1146     SMESH_Algo* algo2 =
1147       (SMESH_Algo*) aMesh.GetHypothesis( aSubMesh, filter, true, &assignedToShape2 );
1148     if ( algo2 &&                                                  // algo found
1149          !assignedToShape2.IsSame( aMesh.GetShapeToMesh() ) &&     // algo is local
1150          ( SMESH_MesherHelper::GetGroupType( assignedToShape2 ) == // algo of the same level
1151            SMESH_MesherHelper::GetGroupType( assignedToShape )) &&
1152          aMesh.IsOrderOK( aMesh.GetSubMesh( assignedToShape2 ),    // no forced order
1153                           aMesh.GetSubMesh( assignedToShape  )))
1154     {
1155       // get algos on the adjacent SOLIDs
1156       filter.Init( filter.IsAlgo() ).And( filter.HasDim( 3 ));
1157       vector< SMESH_Algo* > algos3D;
1158       PShapeIteratorPtr solidIt = SMESH_MesherHelper::GetAncestors( aShape, aMesh,
1159                                                                     TopAbs_SOLID );
1160       while ( const TopoDS_Shape* solid = solidIt->next() )
1161         if ( SMESH_Algo* algo3D = (SMESH_Algo*) aMesh.GetHypothesis( *solid, filter, true ))
1162         {
1163           algos3D.push_back( algo3D );
1164           filter.AndNot( filter.HasName( algo3D->GetName() ));
1165         }
1166       // check compatibility of algos
1167       if ( algos3D.size() > 1 )
1168       {
1169         const AlgoData& algoData    = algo->SMESH_Algo::GetFeatures();
1170         const AlgoData& algoData2   = algo2->SMESH_Algo::GetFeatures();
1171         const AlgoData& algoData3d0 = algos3D[0]->SMESH_Algo::GetFeatures();
1172         const AlgoData& algoData3d1 = algos3D[1]->SMESH_Algo::GetFeatures();
1173         if (( algoData2.IsCompatible( algoData3d0 ) &&
1174               algoData2.IsCompatible( algoData3d1 ))
1175             &&
1176             !(algoData.IsCompatible( algoData3d0 ) &&
1177               algoData.IsCompatible( algoData3d1 )))
1178           algo = algo2;
1179       }
1180     }
1181   }
1182
1183   if ( assignedTo && algo )
1184     * assignedTo = assignedToShape;
1185
1186   return algo;
1187 }
1188
1189 //=============================================================================
1190 /*!
1191  * Returns StudyContextStruct for a study
1192  */
1193 //=============================================================================
1194
1195 StudyContextStruct *SMESH_Gen::GetStudyContext()
1196 {
1197   return _studyContext;
1198 }
1199
1200 //================================================================================
1201 /*!
1202  * \brief Return shape dimension by TopAbs_ShapeEnum
1203  */
1204 //================================================================================
1205
1206 int SMESH_Gen::GetShapeDim(const TopAbs_ShapeEnum & aShapeType)
1207 {
1208   static vector<int> dim;
1209   if ( dim.empty() )
1210   {
1211     dim.resize( TopAbs_SHAPE, -1 );
1212     dim[ TopAbs_COMPOUND ]  = MeshDim_3D;
1213     dim[ TopAbs_COMPSOLID ] = MeshDim_3D;
1214     dim[ TopAbs_SOLID ]     = MeshDim_3D;
1215     dim[ TopAbs_SHELL ]     = MeshDim_2D;
1216     dim[ TopAbs_FACE  ]     = MeshDim_2D;
1217     dim[ TopAbs_WIRE ]      = MeshDim_1D;
1218     dim[ TopAbs_EDGE ]      = MeshDim_1D;
1219     dim[ TopAbs_VERTEX ]    = MeshDim_0D;
1220   }
1221   return dim[ aShapeType ];
1222 }
1223
1224 //=============================================================================
1225 /*!
1226  * Generate a new id unique within this Gen
1227  */
1228 //=============================================================================
1229
1230 int SMESH_Gen::GetANewId()
1231 {
1232   return _hypId++;
1233 }