Salome HOME
0020725: EDF 1242 SMESH : Crash avec Convert lin--> quad avec BLSURF/GHS3D on 64bits
[modules/smesh.git] / src / SMESH / SMESH_Gen.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH SMESH : implementaion of SMESH idl descriptions
23 //  File   : SMESH_Gen.cxx
24 //  Author : Paul RASCLE, EDF
25 //  Module : SMESH
26
27 #include "SMESH_Gen.hxx"
28 #include "SMESH_subMesh.hxx"
29 #include "SMESH_HypoFilter.hxx"
30 #include "SMESHDS_Document.hxx"
31 #include "SMDS_MeshElement.hxx"
32 #include "SMDS_MeshNode.hxx"
33
34 #include "utilities.h"
35 #include "OpUtil.hxx"
36 #include "Utils_ExceptHandlers.hxx"
37
38 #include <gp_Pnt.hxx>
39 #include <BRep_Tool.hxx>
40 #include <TopTools_ListOfShape.hxx>
41 #include <TopTools_ListIteratorOfListOfShape.hxx>
42
43 using namespace std;
44
45 //=============================================================================
46 /*!
47  *  Constructor
48  */
49 //=============================================================================
50
51 SMESH_Gen::SMESH_Gen()
52 {
53   MESSAGE("SMESH_Gen::SMESH_Gen");
54   _localId = 0;
55   _hypId = 0;
56   _segmentation = _nbSegments = 10;
57 }
58
59 //=============================================================================
60 /*!
61  * Destructor
62  */
63 //=============================================================================
64
65 SMESH_Gen::~SMESH_Gen()
66 {
67   MESSAGE("SMESH_Gen::~SMESH_Gen");
68 }
69
70 //=============================================================================
71 /*!
72  * Creates a mesh in a study.
73  * if (theIsEmbeddedMode) { mesh modification commands are not logged }
74  */
75 //=============================================================================
76
77 SMESH_Mesh* SMESH_Gen::CreateMesh(int theStudyId, bool theIsEmbeddedMode)
78   throw(SALOME_Exception)
79 {
80   Unexpect aCatch(SalomeException);
81   MESSAGE("SMESH_Gen::CreateMesh");
82
83   // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document
84   StudyContextStruct *aStudyContext = GetStudyContext(theStudyId);
85
86   // create a new SMESH_mesh object
87   SMESH_Mesh *aMesh = new SMESH_Mesh(_localId++,
88                                      theStudyId,
89                                      this,
90                                      theIsEmbeddedMode,
91                                      aStudyContext->myDocument);
92   aStudyContext->mapMesh[_localId] = aMesh;
93
94   return aMesh;
95 }
96
97 //=============================================================================
98 /*!
99  * Compute a mesh
100  */
101 //=============================================================================
102
103 bool SMESH_Gen::Compute(SMESH_Mesh &          aMesh,
104                         const TopoDS_Shape &  aShape,
105                         const bool            anUpward,
106                         const ::MeshDimension aDim,
107                         TSetOfInt*            aShapesId)
108 {
109   MESSAGE("SMESH_Gen::Compute");
110
111   bool ret = true;
112
113   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
114
115   const bool includeSelf = true;
116   const bool complexShapeFirst = true;
117
118   SMESH_subMeshIteratorPtr smIt;
119
120   if ( anUpward ) // is called from below code here
121   {
122     // -----------------------------------------------
123     // mesh all the subshapes starting from vertices
124     // -----------------------------------------------
125     smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
126     while ( smIt->more() )
127     {
128       SMESH_subMesh* smToCompute = smIt->next();
129
130       // do not mesh vertices of a pseudo shape
131       const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType();
132       if ( !aMesh.HasShapeToMesh() && aShType == TopAbs_VERTEX )
133         continue;
134
135       // check for preview dimension limitations
136       if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
137       {
138         // clear compute state to not show previous compute errors
139         //  if preview invoked less dimension less than previous
140         smToCompute->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE );
141         continue;
142       }
143
144       if (smToCompute->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
145         smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE );
146
147       // we check all the submeshes here and detect if any of them failed to compute
148       if (smToCompute->GetComputeState() == SMESH_subMesh::FAILED_TO_COMPUTE)
149         ret = false;
150       else if ( aShapesId )
151         aShapesId->insert( smToCompute->GetId() );
152     }
153     return ret;
154   }
155   else
156   {
157     // -----------------------------------------------------------------
158     // apply algos that DO NOT require descretized boundaries and DO NOT
159     // support submeshes, starting from the most complex shapes
160     // and collect submeshes with algos that DO support submeshes
161     // -----------------------------------------------------------------
162     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes;
163     smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
164     while ( smIt->more() )
165     {
166       SMESH_subMesh* smToCompute = smIt->next();
167       if ( smToCompute->GetComputeState() != SMESH_subMesh::READY_TO_COMPUTE )
168         continue;
169
170       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
171       const int aShapeDim = GetShapeDim( aSubShape );
172       if ( aShapeDim < 1 ) break;
173       
174       // check for preview dimension limitations
175       if ( aShapesId && aShapeDim > (int)aDim )
176         continue;
177
178       SMESH_Algo* algo = GetAlgo( aMesh, aSubShape );
179       if ( algo && !algo->NeedDescretBoundary() )
180       {
181         if ( algo->SupportSubmeshes() )
182           smWithAlgoSupportingSubmeshes.push_front( smToCompute );
183         else
184         {
185           smToCompute->ComputeStateEngine( SMESH_subMesh::COMPUTE );
186           if ( aShapesId )
187             aShapesId->insert( smToCompute->GetId() );
188         }
189       }
190     }
191     
192     // ------------------------------------------------------------
193     // sort list of meshes according to mesh order
194     // ------------------------------------------------------------
195     aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
196
197     // ------------------------------------------------------------
198     // compute submeshes under shapes with algos that DO NOT require
199     // descretized boundaries and DO support submeshes
200     // ------------------------------------------------------------
201     list< SMESH_subMesh* >::iterator subIt, subEnd;
202     subIt  = smWithAlgoSupportingSubmeshes.begin();
203     subEnd = smWithAlgoSupportingSubmeshes.end();
204     // start from lower shapes
205     for ( ; subIt != subEnd; ++subIt )
206     {
207       sm = *subIt;
208
209       // get a shape the algo is assigned to
210       TopoDS_Shape algoShape;
211       if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
212         continue; // strange...
213
214       // look for more local algos
215       smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
216       while ( smIt->more() )
217       {
218         SMESH_subMesh* smToCompute = smIt->next();
219
220         const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
221         const int aShapeDim = GetShapeDim( aSubShape );
222         //if ( aSubShape.ShapeType() == TopAbs_VERTEX ) continue;
223         if ( aShapeDim < 1 ) continue;
224
225         // check for preview dimension limitations
226         if ( aShapesId && GetShapeDim( aSubShape.ShapeType() ) > (int)aDim )
227           continue;
228         
229         SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
230         filter
231           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
232           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape ));
233
234         if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
235           SMESH_Hypothesis::Hypothesis_Status status;
236           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
237             // mesh a lower smToCompute starting from vertices
238             Compute( aMesh, aSubShape, /*anUpward=*/true, aDim, aShapesId );
239         }
240       }
241     }
242     // ----------------------------------------------------------
243     // apply the algos that do not require descretized boundaries
244     // ----------------------------------------------------------
245     for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
246     {
247       sm = *subIt;
248       if ( sm->GetComputeState() == SMESH_subMesh::READY_TO_COMPUTE)
249       {
250         const TopAbs_ShapeEnum aShType = sm->GetSubShape().ShapeType();
251         // check for preview dimension limitations
252         if ( aShapesId && GetShapeDim( aShType ) > (int)aDim )
253           continue;
254
255         sm->ComputeStateEngine( SMESH_subMesh::COMPUTE );
256         if ( aShapesId )
257           aShapesId->insert( sm->GetId() );
258       }
259     }
260     // -----------------------------------------------
261     // mesh the rest subshapes starting from vertices
262     // -----------------------------------------------
263     ret = Compute( aMesh, aShape, /*anUpward=*/true, aDim, aShapesId );
264   }
265
266   MESSAGE( "VSR - SMESH_Gen::Compute() finished, OK = " << ret);
267   return ret;
268 }
269
270
271 //=============================================================================
272 /*!
273  * Evaluate a mesh
274  */
275 //=============================================================================
276
277 bool SMESH_Gen::Evaluate(SMESH_Mesh &          aMesh,
278                          const TopoDS_Shape &  aShape,
279                          MapShapeNbElems&      aResMap,
280                          const bool            anUpward,
281                          TSetOfInt*            aShapesId)
282 {
283   MESSAGE("SMESH_Gen::Evaluate");
284
285   bool ret = true;
286
287   SMESH_subMesh *sm = aMesh.GetSubMesh(aShape);
288
289   const bool includeSelf = true;
290   const bool complexShapeFirst = true;
291   SMESH_subMeshIteratorPtr smIt;
292
293   if ( anUpward ) { // is called from below code here
294     // -----------------------------------------------
295     // mesh all the subshapes starting from vertices
296     // -----------------------------------------------
297     smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst);
298     while ( smIt->more() ) {
299       SMESH_subMesh* smToCompute = smIt->next();
300
301       // do not mesh vertices of a pseudo shape
302       const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType();
303       //if ( !aMesh.HasShapeToMesh() && aShType == TopAbs_VERTEX )
304       //  continue;
305       if ( !aMesh.HasShapeToMesh() ) {
306         if( aShType == TopAbs_VERTEX || aShType == TopAbs_WIRE ||
307             aShType == TopAbs_SHELL )
308           continue;
309       }
310
311       smToCompute->Evaluate(aResMap);
312       if( aShapesId )
313         aShapesId->insert( smToCompute->GetId() );
314     }
315     return ret;
316   }
317   else {
318     // -----------------------------------------------------------------
319     // apply algos that DO NOT require descretized boundaries and DO NOT
320     // support submeshes, starting from the most complex shapes
321     // and collect submeshes with algos that DO support submeshes
322     // -----------------------------------------------------------------
323     list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes;
324     smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst);
325     while ( smIt->more() ) {
326       SMESH_subMesh* smToCompute = smIt->next();
327       const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
328       const int aShapeDim = GetShapeDim( aSubShape );
329       if ( aShapeDim < 1 ) break;
330       
331       SMESH_Algo* algo = GetAlgo( aMesh, aSubShape );
332       if ( algo && !algo->NeedDescretBoundary() ) {
333         if ( algo->SupportSubmeshes() ) {
334           smWithAlgoSupportingSubmeshes.push_front( smToCompute );
335         }
336         else {
337           smToCompute->Evaluate(aResMap);
338           if ( aShapesId )
339             aShapesId->insert( smToCompute->GetId() );
340         }
341       }
342     }
343
344     // ------------------------------------------------------------
345     // sort list of meshes according to mesh order
346     // ------------------------------------------------------------
347     aMesh.SortByMeshOrder( smWithAlgoSupportingSubmeshes );
348
349     // ------------------------------------------------------------
350     // compute submeshes under shapes with algos that DO NOT require
351     // descretized boundaries and DO support submeshes
352     // ------------------------------------------------------------
353     list< SMESH_subMesh* >::iterator subIt, subEnd;
354     subIt  = smWithAlgoSupportingSubmeshes.begin();
355     subEnd = smWithAlgoSupportingSubmeshes.end();
356     // start from lower shapes
357     for ( ; subIt != subEnd; ++subIt ) {
358       sm = *subIt;
359
360       // get a shape the algo is assigned to
361       TopoDS_Shape algoShape;
362       if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape ))
363         continue; // strange...
364
365       // look for more local algos
366       smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst);
367       while ( smIt->more() ) {
368         SMESH_subMesh* smToCompute = smIt->next();
369
370         const TopoDS_Shape& aSubShape = smToCompute->GetSubShape();
371         const int aShapeDim = GetShapeDim( aSubShape );
372         if ( aShapeDim < 1 ) continue;
373
374         //const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType();
375
376         SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
377         filter
378           .And( SMESH_HypoFilter::IsApplicableTo( aSubShape ))
379           .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape ));
380
381         if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) {
382           SMESH_Hypothesis::Hypothesis_Status status;
383           if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status ))
384             // mesh a lower smToCompute starting from vertices
385             Evaluate( aMesh, aSubShape, aResMap, /*anUpward=*/true, aShapesId );
386         }
387       }
388     }
389     // ----------------------------------------------------------
390     // apply the algos that do not require descretized boundaries
391     // ----------------------------------------------------------
392     for ( subIt = smWithAlgoSupportingSubmeshes.begin(); subIt != subEnd; ++subIt )
393     {
394       sm = *subIt;
395       sm->Evaluate(aResMap);
396       if ( aShapesId )
397         aShapesId->insert( sm->GetId() );
398     }
399
400     // -----------------------------------------------
401     // mesh the rest subshapes starting from vertices
402     // -----------------------------------------------
403     ret = Evaluate( aMesh, aShape, aResMap, /*anUpward=*/true, aShapesId );
404   }
405
406   MESSAGE( "VSR - SMESH_Gen::Evaluate() finished, OK = " << ret);
407   return ret;
408 }
409
410
411 //=======================================================================
412 //function : checkConformIgnoredAlgos
413 //purpose  :
414 //=======================================================================
415
416 static bool checkConformIgnoredAlgos(SMESH_Mesh&               aMesh,
417                                      SMESH_subMesh*            aSubMesh,
418                                      const SMESH_Algo*         aGlobIgnoAlgo,
419                                      const SMESH_Algo*         aLocIgnoAlgo,
420                                      bool &                    checkConform,
421                                      set<SMESH_subMesh*>&      aCheckedMap,
422                                      list< SMESH_Gen::TAlgoStateError > & theErrors)
423 {
424   ASSERT( aSubMesh );
425   if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX)
426     return true;
427
428
429   bool ret = true;
430
431   const list<const SMESHDS_Hypothesis*>& listHyp =
432     aMesh.GetMeshDS()->GetHypothesis( aSubMesh->GetSubShape() );
433   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
434   for ( ; it != listHyp.end(); it++)
435   {
436     const SMESHDS_Hypothesis * aHyp = *it;
437     if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
438       continue;
439
440     const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp);
441     ASSERT ( algo );
442
443     if ( aLocIgnoAlgo ) // algo is hidden by a local algo of upper dim
444     {
445       INFOS( "Local <" << algo->GetName() << "> is hidden by local <"
446             << aLocIgnoAlgo->GetName() << ">");
447     }
448     else
449     {
450       bool isGlobal = (aMesh.IsMainShape( aSubMesh->GetSubShape() ));
451       int dim = algo->GetDim();
452       int aMaxGlobIgnoDim = ( aGlobIgnoAlgo ? aGlobIgnoAlgo->GetDim() : -1 );
453
454       if ( dim < aMaxGlobIgnoDim )
455       {
456         // algo is hidden by a global algo
457         INFOS( ( isGlobal ? "Global" : "Local" )
458               << " <" << algo->GetName() << "> is hidden by global <"
459               << aGlobIgnoAlgo->GetName() << ">");
460       }
461       else if ( !algo->NeedDescretBoundary() && !isGlobal)
462       {
463         // local algo is not hidden and hides algos on sub-shapes
464         if (checkConform && !aSubMesh->IsConform( algo ))
465         {
466           ret = false;
467           checkConform = false; // no more check conformity
468           INFOS( "ERROR: Local <" << algo->GetName() <<
469                 "> would produce not conform mesh: "
470                 "<Not Conform Mesh Allowed> hypotesis is missing");
471           theErrors.push_back( SMESH_Gen::TAlgoStateError() );
472           theErrors.back().Set( SMESH_Hypothesis::HYP_NOTCONFORM, algo, false );
473         }
474
475         // sub-algos will be hidden by a local <algo>
476         SMESH_subMeshIteratorPtr revItSub =
477           aSubMesh->getDependsOnIterator( /*includeSelf=*/false, /*complexShapeFirst=*/true);
478         bool checkConform2 = false;
479         while ( revItSub->more() )
480         {
481           SMESH_subMesh* sm = revItSub->next();
482           checkConformIgnoredAlgos (aMesh, sm, aGlobIgnoAlgo,
483                                     algo, checkConform2, aCheckedMap, theErrors);
484           aCheckedMap.insert( sm );
485         }
486       }
487     }
488   }
489
490   return ret;
491 }
492
493 //=======================================================================
494 //function : checkMissing
495 //purpose  : notify on missing hypothesis
496 //           Return false if algo or hipothesis is missing
497 //=======================================================================
498
499 static bool checkMissing(SMESH_Gen*                aGen,
500                          SMESH_Mesh&               aMesh,
501                          SMESH_subMesh*            aSubMesh,
502                          const int                 aTopAlgoDim,
503                          bool*                     globalChecked,
504                          const bool                checkNoAlgo,
505                          set<SMESH_subMesh*>&      aCheckedMap,
506                          list< SMESH_Gen::TAlgoStateError > & theErrors)
507 {
508   if ( aSubMesh->GetSubShape().ShapeType() == TopAbs_VERTEX)
509     return true;
510
511   //MESSAGE("=====checkMissing");
512
513   int ret = true;
514   SMESH_Algo* algo = 0;
515
516   switch (aSubMesh->GetAlgoState())
517   {
518   case SMESH_subMesh::NO_ALGO: {
519     if (checkNoAlgo)
520     {
521       // should there be any algo?
522       int shapeDim = SMESH_Gen::GetShapeDim( aSubMesh->GetSubShape() );
523       if (aTopAlgoDim > shapeDim)
524       {
525         MESSAGE( "ERROR: " << shapeDim << "D algorithm is missing" );
526         ret = false;
527         theErrors.push_back( SMESH_Gen::TAlgoStateError() );
528         theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, shapeDim, true );
529       }
530     }
531     return ret;
532   }
533   case SMESH_subMesh::MISSING_HYP: {
534     // notify if an algo missing hyp is attached to aSubMesh
535     algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() );
536     ASSERT( algo );
537     bool IsGlobalHypothesis = aGen->IsGlobalHypothesis( algo, aMesh );
538     if (!IsGlobalHypothesis || !globalChecked[ algo->GetDim() ])
539     {
540       TAlgoStateErrorName errName = SMESH_Hypothesis::HYP_MISSING;
541       SMESH_Hypothesis::Hypothesis_Status status;
542       algo->CheckHypothesis( aMesh, aSubMesh->GetSubShape(), status );
543       if ( status == SMESH_Hypothesis::HYP_BAD_PARAMETER ) {
544         MESSAGE( "ERROR: hypothesis of " << (IsGlobalHypothesis ? "Global " : "Local ")
545                  << "<" << algo->GetName() << "> has a bad parameter value");
546         errName = status;
547       } else if ( status == SMESH_Hypothesis::HYP_BAD_GEOMETRY ) {
548         MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ")
549                  << "<" << algo->GetName() << "> assigned to mismatching geometry");
550         errName = status;
551       } else {
552         MESSAGE( "ERROR: " << (IsGlobalHypothesis ? "Global " : "Local ")
553                  << "<" << algo->GetName() << "> misses some hypothesis");
554       }
555       if (IsGlobalHypothesis)
556         globalChecked[ algo->GetDim() ] = true;
557       theErrors.push_back( SMESH_Gen::TAlgoStateError() );
558       theErrors.back().Set( errName, algo, IsGlobalHypothesis );
559     }
560     ret = false;
561     break;
562   }
563   case SMESH_subMesh::HYP_OK:
564     algo = aGen->GetAlgo( aMesh, aSubMesh->GetSubShape() );
565     ret = true;
566     break;
567   default: ASSERT(0);
568   }
569
570   // do not check under algo that hides sub-algos or
571   // re-start checking NO_ALGO state
572   ASSERT (algo);
573   bool isTopLocalAlgo =
574     ( aTopAlgoDim <= algo->GetDim() && !aGen->IsGlobalHypothesis( algo, aMesh ));
575   if (!algo->NeedDescretBoundary() || isTopLocalAlgo)
576   {
577     bool checkNoAlgo2 = ( algo->NeedDescretBoundary() );
578     SMESH_subMeshIteratorPtr itsub = aSubMesh->getDependsOnIterator( /*includeSelf=*/false,
579                                                                      /*complexShapeFirst=*/false);
580     while ( itsub->more() )
581     {
582       // sub-meshes should not be checked further more
583       SMESH_subMesh* sm = itsub->next();
584       aCheckedMap.insert( sm );
585
586       if (isTopLocalAlgo)
587       {
588         //check algo on sub-meshes
589         int aTopAlgoDim2 = algo->GetDim();
590         if (!checkMissing (aGen, aMesh, sm, aTopAlgoDim2,
591                            globalChecked, checkNoAlgo2, aCheckedMap, theErrors))
592         {
593           ret = false;
594           if (sm->GetAlgoState() == SMESH_subMesh::NO_ALGO )
595             checkNoAlgo2 = false;
596         }
597       }
598     }
599   }
600   return ret;
601 }
602
603 //=======================================================================
604 //function : CheckAlgoState
605 //purpose  : notify on bad state of attached algos, return false
606 //           if Compute() would fail because of some algo bad state
607 //=======================================================================
608
609 bool SMESH_Gen::CheckAlgoState(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape)
610 {
611   list< TAlgoStateError > errors;
612   return GetAlgoState( aMesh, aShape, errors );
613 }
614
615 //=======================================================================
616 //function : GetAlgoState
617 //purpose  : notify on bad state of attached algos, return false
618 //           if Compute() would fail because of some algo bad state
619 //           theErrors list contains problems description
620 //=======================================================================
621
622 bool SMESH_Gen::GetAlgoState(SMESH_Mesh&               theMesh,
623                              const TopoDS_Shape&       theShape,
624                              list< TAlgoStateError > & theErrors)
625 {
626   //MESSAGE("SMESH_Gen::CheckAlgoState");
627
628   bool ret = true;
629   bool hasAlgo = false;
630
631   SMESH_subMesh* sm = theMesh.GetSubMesh(theShape);
632   const SMESHDS_Mesh* meshDS = theMesh.GetMeshDS();
633   TopoDS_Shape mainShape = meshDS->ShapeToMesh();
634
635   // -----------------
636   // get global algos
637   // -----------------
638
639   const SMESH_Algo* aGlobAlgoArr[] = {0,0,0,0};
640
641   const list<const SMESHDS_Hypothesis*>& listHyp = meshDS->GetHypothesis( mainShape );
642   list<const SMESHDS_Hypothesis*>::const_iterator it=listHyp.begin();
643   for ( ; it != listHyp.end(); it++)
644   {
645     const SMESHDS_Hypothesis * aHyp = *it;
646     if (aHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO)
647       continue;
648
649     const SMESH_Algo* algo = dynamic_cast<const SMESH_Algo*> (aHyp);
650     ASSERT ( algo );
651
652     int dim = algo->GetDim();
653     aGlobAlgoArr[ dim ] = algo;
654
655     hasAlgo = true;
656   }
657
658   // --------------------------------------------------------
659   // info on algos that will be ignored because of ones that
660   // don't NeedDescretBoundary() attached to super-shapes,
661   // check that a conform mesh will be produced
662   // --------------------------------------------------------
663
664
665   // find a global algo possibly hiding sub-algos
666   int dim;
667   const SMESH_Algo* aGlobIgnoAlgo = 0;
668   for (dim = 3; dim > 0; dim--)
669   {
670     if (aGlobAlgoArr[ dim ] &&
671         !aGlobAlgoArr[ dim ]->NeedDescretBoundary())
672     {
673       aGlobIgnoAlgo = aGlobAlgoArr[ dim ];
674       break;
675     }
676   }
677
678   set<SMESH_subMesh*> aCheckedSubs;
679   bool checkConform = ( !theMesh.IsNotConformAllowed() );
680
681   // loop on theShape and its sub-shapes
682   SMESH_subMeshIteratorPtr revItSub = sm->getDependsOnIterator( /*includeSelf=*/true,
683                                                                 /*complexShapeFirst=*/true);
684   while ( revItSub->more() )
685   {
686     SMESH_subMesh* smToCheck = revItSub->next();
687     if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
688       break;
689
690     if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked
691       if (!checkConformIgnoredAlgos (theMesh, smToCheck, aGlobIgnoAlgo,
692                                      0, checkConform, aCheckedSubs, theErrors))
693         ret = false;
694
695     if ( smToCheck->GetAlgoState() != SMESH_subMesh::NO_ALGO )
696       hasAlgo = true;
697   }
698
699   // ----------------------------------------------------------------
700   // info on missing hypothesis and find out if all needed algos are
701   // well defined
702   // ----------------------------------------------------------------
703
704   //MESSAGE( "---info on missing hypothesis and find out if all needed algos are");
705
706   // find max dim of global algo
707   int aTopAlgoDim = 0;
708   for (dim = 3; dim > 0; dim--)
709   {
710     if (aGlobAlgoArr[ dim ])
711     {
712       aTopAlgoDim = dim;
713       break;
714     }
715   }
716   bool checkNoAlgo = theMesh.HasShapeToMesh() ? bool( aTopAlgoDim ) : false;
717   bool globalChecked[] = { false, false, false, false };
718
719   // loop on theShape and its sub-shapes
720   aCheckedSubs.clear();
721   revItSub = sm->getDependsOnIterator( /*includeSelf=*/true, /*complexShapeFirst=*/true);
722   while ( revItSub->more() )
723   {
724     SMESH_subMesh* smToCheck = revItSub->next();
725     if ( smToCheck->GetSubShape().ShapeType() == TopAbs_VERTEX)
726       break;
727
728     if ( aCheckedSubs.insert( smToCheck ).second ) // not yet checked
729       if (!checkMissing (this, theMesh, smToCheck, aTopAlgoDim,
730                          globalChecked, checkNoAlgo, aCheckedSubs, theErrors))
731       {
732         ret = false;
733         if (smToCheck->GetAlgoState() == SMESH_subMesh::NO_ALGO )
734           checkNoAlgo = false;
735       }
736   }
737
738   if ( !hasAlgo ) {
739     ret = false;
740     INFOS( "None algorithm attached" );
741     theErrors.push_back( TAlgoStateError() );
742     theErrors.back().Set( SMESH_Hypothesis::HYP_MISSING, 1, true );
743   }
744
745   return ret;
746 }
747
748 //=======================================================================
749 //function : IsGlobalHypothesis
750 //purpose  : check if theAlgo is attached to the main shape
751 //=======================================================================
752
753 bool SMESH_Gen::IsGlobalHypothesis(const SMESH_Hypothesis* theHyp, SMESH_Mesh& aMesh)
754 {
755   SMESH_HypoFilter filter( SMESH_HypoFilter::Is( theHyp ));
756   return aMesh.GetHypothesis( aMesh.GetMeshDS()->ShapeToMesh(), filter, false );
757 }
758
759 //=============================================================================
760 /*!
761  * Finds algo to mesh a shape. Optionally returns a shape the found algo is bound to
762  */
763 //=============================================================================
764
765 SMESH_Algo *SMESH_Gen::GetAlgo(SMESH_Mesh &         aMesh,
766                                const TopoDS_Shape & aShape,
767                                TopoDS_Shape*        assignedTo)
768 {
769   SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() );
770   filter.And( filter.IsApplicableTo( aShape ));
771
772   return (SMESH_Algo*) aMesh.GetHypothesis( aShape, filter, true, assignedTo );
773 }
774
775 //=============================================================================
776 /*!
777  * Returns StudyContextStruct for a study
778  */
779 //=============================================================================
780
781 StudyContextStruct *SMESH_Gen::GetStudyContext(int studyId)
782 {
783   // Get studyContext, create it if it does'nt exist, with a SMESHDS_Document
784
785   if (_mapStudyContext.find(studyId) == _mapStudyContext.end())
786   {
787     _mapStudyContext[studyId] = new StudyContextStruct;
788     _mapStudyContext[studyId]->myDocument = new SMESHDS_Document(studyId);
789   }
790   StudyContextStruct *myStudyContext = _mapStudyContext[studyId];
791   return myStudyContext;
792 }
793
794 //================================================================================
795 /*!
796  * \brief Return shape dimension by TopAbs_ShapeEnum
797  */
798 //================================================================================
799
800 int SMESH_Gen::GetShapeDim(const TopAbs_ShapeEnum & aShapeType)
801 {
802   static vector<int> dim;
803   if ( dim.empty() )
804   {
805     dim.resize( TopAbs_SHAPE, -1 );
806     dim[ TopAbs_COMPOUND ]  = MeshDim_3D;
807     dim[ TopAbs_COMPSOLID ] = MeshDim_3D;
808     dim[ TopAbs_SOLID ]     = MeshDim_3D;
809     dim[ TopAbs_SHELL ]     = MeshDim_3D;
810     dim[ TopAbs_FACE  ]     = MeshDim_2D;
811     dim[ TopAbs_WIRE ]      = MeshDim_1D;
812     dim[ TopAbs_EDGE ]      = MeshDim_1D;
813     dim[ TopAbs_VERTEX ]    = MeshDim_0D;
814   }
815   return dim[ aShapeType ];
816 }
817
818 //=============================================================================
819 /*!
820  * Genarate a new id unique withing this Gen
821  */
822 //=============================================================================
823
824 int SMESH_Gen::GetANewId()
825 {
826   return _hypId++;
827 }