Salome HOME
PAL13473 (Build repetitive mesh):
[modules/smesh.git] / src / SMESH / SMESH_subMesh.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_subMesh.cxx
25 //  Author : Paul RASCLE, EDF
26 //  Module : SMESH
27 //  $Header$
28
29 using namespace std;
30 #include "SMESH_subMesh.hxx"
31
32 #include "SMESH_subMeshEventListener.hxx"
33 #include "SMESH_Gen.hxx"
34 #include "SMESH_Mesh.hxx"
35 #include "SMESH_Hypothesis.hxx"
36 #include "SMESH_Algo.hxx"
37 #include "SMESH_HypoFilter.hxx"
38
39 #include "utilities.h"
40 #include "OpUtil.hxx"
41
42 #include <BRep_Builder.hxx>
43
44 #include <TopExp.hxx>
45 #include <TopoDS_Compound.hxx>
46 #include <TopTools_MapOfShape.hxx>
47 #include <TopTools_ListOfShape.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
49 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
50
51 #ifdef _DEBUG_
52 #include <gp_Pnt.hxx>
53 #include <BRep_Tool.hxx>
54 #include <TopoDS.hxx>
55 #include <TopTools_IndexedMapOfShape.hxx>
56 #endif
57
58 #include <Standard_Failure.hxx>
59 #include <Standard_ErrorHandler.hxx>
60
61 //=============================================================================
62 /*!
63  *  default constructor:
64  */
65 //=============================================================================
66
67 SMESH_subMesh::SMESH_subMesh(int Id, SMESH_Mesh * father, SMESHDS_Mesh * meshDS,
68         const TopoDS_Shape & aSubShape)
69 {
70         _subShape = aSubShape;
71         _meshDS = meshDS;
72         _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
73         _father = father;
74         _Id = Id;
75         _dependenceAnalysed = false;
76
77         if (_subShape.ShapeType() == TopAbs_VERTEX)
78         {
79                 _algoState = HYP_OK;
80                 _computeState = READY_TO_COMPUTE;
81         }
82         else
83         {
84           _algoState = NO_ALGO;
85           _computeState = NOT_READY;
86         }
87 }
88
89 //=============================================================================
90 /*!
91  *
92  */
93 //=============================================================================
94
95 SMESH_subMesh::~SMESH_subMesh()
96 {
97   MESSAGE("SMESH_subMesh::~SMESH_subMesh");
98   // ****
99 }
100
101 //=============================================================================
102 /*!
103  *
104  */
105 //=============================================================================
106
107 int SMESH_subMesh::GetId() const
108 {
109   //MESSAGE("SMESH_subMesh::GetId");
110   return _Id;
111 }
112
113 //=============================================================================
114 /*!
115  *
116  */
117 //=============================================================================
118
119 SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
120 {
121   // submesh appears in DS only when a mesher set nodes and elements on it
122   if (_subMeshDS==NULL)
123   {
124     _subMeshDS = _meshDS->MeshElements(_subShape);      // may be null ...
125 //     if (_subMeshDS==NULL)
126 //     {
127 //       MESSAGE("problem... subMesh still empty");
128 //     }
129   }
130   return _subMeshDS;
131 }
132
133 //=============================================================================
134 /*!
135  *
136  */
137 //=============================================================================
138
139 SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
140 {
141   if ( !GetSubMeshDS() )
142     _meshDS->NewSubMesh( _meshDS->ShapeToIndex( _subShape ) );
143
144   return GetSubMeshDS();
145 }
146
147 //=============================================================================
148 /*!
149  *
150  */
151 //=============================================================================
152
153 SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
154 {
155   const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
156   SMESH_subMesh *firstToCompute = 0;
157
158   map < int, SMESH_subMesh * >::const_iterator itsub;
159   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
160   {
161     SMESH_subMesh *sm = (*itsub).second;
162     bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
163     if (readyToCompute)
164     {
165       firstToCompute = sm;
166       break;
167     }
168   }
169   if (firstToCompute)
170   {
171     return firstToCompute;      // a subMesh of this
172   }
173   if (_computeState == READY_TO_COMPUTE)
174   {
175     return this;                // this
176   }
177   return 0;                     // nothing to compute
178 }
179
180 //=============================================================================
181 /*!
182  *
183  */
184 //=============================================================================
185
186 bool SMESH_subMesh::SubMeshesComputed()
187 {
188   //MESSAGE("SMESH_subMesh::SubMeshesComputed");
189   const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
190
191   int myDim = SMESH_Gen::GetShapeDim( _subShape );
192   int dimToCheck = myDim - 1;
193   bool subMeshesComputed = true;
194   map < int, SMESH_subMesh * >::const_iterator itsub;
195   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
196   {
197     SMESH_subMesh *sm = (*itsub).second;
198     const TopoDS_Shape & ss = sm->GetSubShape();
199     // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense
200     // in checking of existence of edges if the algo needs only faces. Moreover,
201     // degenerated edges may have no submesh, as after computing NETGEN_2D.
202     int dim = SMESH_Gen::GetShapeDim( ss );
203     if (dim < dimToCheck)
204       continue;
205     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
206     // PAL10974.
207     // There are some tricks with compute states, e.g. Penta_3D leaves
208     // one face with READY_TO_COMPUTE state in order to be able to
209     // recompute 3D when a locale triangle hypo changes (see PAL7428).
210     // So we check if mesh is really present
211     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
212                       (ds && ( ds->GetNodes()->more() || ds->GetElements()->more() )));
213     if (!computeOk)
214     {
215       int type = ss.ShapeType();
216
217       subMeshesComputed = false;
218
219       switch (type)
220       {
221       case TopAbs_COMPOUND:
222         {
223           MESSAGE("The not computed sub mesh is a COMPOUND");
224           break;
225         }
226       case TopAbs_COMPSOLID:
227         {
228           MESSAGE("The not computed sub mesh is a COMPSOLID");
229           break;
230         }
231       case TopAbs_SHELL:
232         {
233           MESSAGE("The not computed sub mesh is a SHEL");
234           break;
235         }
236       case TopAbs_WIRE:
237         {
238           MESSAGE("The not computed sub mesh is a WIRE");
239           break;
240         }
241       case TopAbs_SOLID:
242         {
243           MESSAGE("The not computed sub mesh is a SOLID");
244           break;
245         }
246       case TopAbs_FACE:
247         {
248           MESSAGE("The not computed sub mesh is a FACE");
249           break;
250         }
251       case TopAbs_EDGE:
252         {
253           MESSAGE("The not computed sub mesh is a EDGE");
254           break;
255         }
256       default:
257         {
258           MESSAGE("The not computed sub mesh is of unknown type");
259           break;
260         }
261       }
262
263       break;
264     }
265   }
266   return subMeshesComputed;
267 }
268
269 //=============================================================================
270 /*!
271  *
272  */
273 //=============================================================================
274
275 bool SMESH_subMesh::SubMeshesReady()
276 {
277   MESSAGE("SMESH_subMesh::SubMeshesReady");
278   const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
279
280   bool subMeshesReady = true;
281   map < int, SMESH_subMesh * >::const_iterator itsub;
282   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
283   {
284     SMESH_subMesh *sm = (*itsub).second;
285     bool computeOk = ((sm->GetComputeState() == COMPUTE_OK)
286                       || (sm->GetComputeState() == READY_TO_COMPUTE));
287     if (!computeOk)
288     {
289       subMeshesReady = false;
290       SCRUTE(sm->GetId());
291       break;
292     }
293   }
294   return subMeshesReady;
295 }
296
297 //=============================================================================
298 /*!
299  * Construct dependence on first level subMeshes. complex shapes (compsolid,
300  * shell, wire) are not analysed the same way as simple shapes (solid, face,
301  * edge).
302  * For collection shapes (compsolid, shell, wire) prepare a list of submeshes
303  * with possible multiples occurences. Multiples occurences corresponds to
304  * internal frontiers within shapes of the collection and must not be keeped.
305  * See FinalizeDependence.
306  */
307 //=============================================================================
308
309 const map < int, SMESH_subMesh * >&SMESH_subMesh::DependsOn()
310 {
311   if (_dependenceAnalysed)
312     return _mapDepend;
313
314   //MESSAGE("SMESH_subMesh::DependsOn");
315
316   int type = _subShape.ShapeType();
317   //SCRUTE(type);
318   switch (type)
319   {
320   case TopAbs_COMPOUND:
321     {
322       //MESSAGE("compound");
323       for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
324            exp.Next())
325       {
326         InsertDependence(exp.Current());
327       }
328       for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More();
329            exp.Next())
330       {
331           InsertDependence(exp.Current());      //only shell not in solid
332       }
333       for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();
334            exp.Next())
335       {
336         InsertDependence(exp.Current());
337       }
338       for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();
339            exp.Next())
340       {
341         InsertDependence(exp.Current());
342       }
343       break;
344     }
345   case TopAbs_COMPSOLID:
346     {
347                 //MESSAGE("compsolid");
348       for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();
349            exp.Next())
350       {
351         InsertDependence(exp.Current());
352       }
353       break;
354     }
355   case TopAbs_SHELL:
356     {
357       //MESSAGE("shell");
358       for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
359            exp.Next())
360       {
361         InsertDependence(exp.Current());
362       }
363       break;
364     }
365   case TopAbs_WIRE:
366     {
367       //MESSAGE("wire");
368       for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
369            exp.Next())
370       {
371         InsertDependence(exp.Current());
372       }
373       break;
374     }
375   case TopAbs_SOLID:
376     {
377       //MESSAGE("solid");
378       for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();
379            exp.Next())
380       {
381         InsertDependence(exp.Current());
382       }
383       break;
384     }
385   case TopAbs_FACE:
386     {
387       //MESSAGE("face");
388       for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();
389            exp.Next())
390       {
391         InsertDependence(exp.Current());
392       }
393       break;
394     }
395   case TopAbs_EDGE:
396     {
397       //MESSAGE("edge");
398       for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More();
399            exp.Next())
400       {
401                         InsertDependence(exp.Current());
402                       }
403       break;
404     }
405   case TopAbs_VERTEX:
406     {
407       break;
408     }
409   default:
410     {
411       break;
412     }
413   }
414   _dependenceAnalysed = true;
415   return _mapDepend;
416 }
417
418 //=============================================================================
419 /*!
420  * For simple Shapes (solid, face, edge): add subMesh into dependence list.
421  */
422 //=============================================================================
423
424 void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
425 {
426   //MESSAGE("SMESH_subMesh::InsertDependence");
427   SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
428   int type = aSubShape.ShapeType();
429   int ordType = 9 - type;               // 2 = Vertex, 8 = CompSolid
430   int cle = aSubMesh->GetId();
431   cle += 10000000 * ordType;    // sort map by ordType then index
432   if ( _mapDepend.find( cle ) == _mapDepend.end())
433   {
434     _mapDepend[cle] = aSubMesh;
435     const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
436     _mapDepend.insert( subMap.begin(), subMap.end() );
437   }
438 }
439
440 //=============================================================================
441 /*!
442  *
443  */
444 //=============================================================================
445
446 const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
447 {
448         //MESSAGE("SMESH_subMesh::GetSubShape");
449         return _subShape;
450 }
451
452
453 //=======================================================================
454 //function : CanAddHypothesis
455 //purpose  : return true if theHypothesis can be attached to me:
456 //           its dimention is checked
457 //=======================================================================
458
459 bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
460 {
461   int aHypDim   = theHypothesis->GetDim();
462   int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
463   if ( aHypDim <= aShapeDim )
464     return true;
465 //   if ( aHypDim < aShapeDim )
466 //     return ( _father->IsMainShape( _subShape ));
467
468   return false;
469 }
470
471 //=======================================================================
472 //function : IsApplicableHypotesis
473 //purpose  :
474 //=======================================================================
475
476 bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
477                                           const TopAbs_ShapeEnum  theShapeType)
478 {
479   if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
480     // algorithm
481     return ( theHypothesis->GetShapeType() & (1<< theShapeType));
482
483   // hypothesis
484   switch ( theShapeType ) {
485   case TopAbs_EDGE:
486   case TopAbs_FACE:
487   case TopAbs_SOLID:
488     return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
489
490   case TopAbs_SHELL:
491     // Special case for algorithms, building 2D mesh on a whole shell.
492     // Before this fix there was a problem after restoring from study,
493     // because in that case algorithm is assigned before hypothesis
494     // (on shell in problem case) and hypothesis is checked on faces
495     // (because it is 2D), where we have NO_ALGO state.
496     // Now 2D hypothesis is also applicable to shells.
497     return (theHypothesis->GetDim() == 2 || theHypothesis->GetDim() == 3);
498
499 //   case TopAbs_WIRE:
500 //   case TopAbs_COMPSOLID:
501 //   case TopAbs_COMPOUND:
502   default:;
503   }
504   return false;
505 }
506
507 //=============================================================================
508 /*!
509  *
510  */
511 //=============================================================================
512
513 SMESH_Hypothesis::Hypothesis_Status
514   SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
515 {
516   //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
517   //SCRUTE(_algoState);
518   //SCRUTE(event);
519
520   // **** les retour des evenement shape sont significatifs
521   // (add ou remove fait ou non)
522   // le retour des evenement father n'indiquent pas que add ou remove fait
523
524   SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
525
526   int dim = SMESH_Gen::GetShapeDim(_subShape);
527
528   if (dim < 1)
529   {
530     _algoState = HYP_OK;
531     if (event == ADD_HYP || event == ADD_ALGO)
532       return SMESH_Hypothesis::HYP_BAD_DIM; // do not allow to assign any hyp
533     else
534       return SMESH_Hypothesis::HYP_OK;
535   }
536
537   SMESH_Gen* gen   =_father->GetGen();
538   SMESH_Algo* algo = 0;
539   int oldAlgoState = _algoState;
540   bool modifiedHyp = false;  // if set to true, force event MODIF_ALGO_STATE
541                              // in ComputeStateEngine
542
543   // ----------------------
544   // check mesh conformity
545   // ----------------------
546   if (event == ADD_ALGO)
547   {
548     if (IsApplicableHypotesis( anHyp ) &&
549         !_father->IsNotConformAllowed() &&
550         !IsConform( static_cast< SMESH_Algo* >( anHyp )))
551       return SMESH_Hypothesis::HYP_NOTCONFORM;
552   }
553
554   // ----------------------------------
555   // add a hypothesis to DS if possible
556   // ----------------------------------
557   if (event == ADD_HYP || event == ADD_ALGO)
558   {
559     if ( ! CanAddHypothesis( anHyp ))
560       return SMESH_Hypothesis::HYP_BAD_DIM;
561
562     if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
563       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
564
565     if ( !_meshDS->AddHypothesis(_subShape, anHyp))
566       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
567
568     // Serve Propagation of 1D hypothesis
569     if (event == ADD_HYP) {
570       bool isPropagationOk = true;
571       bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 );
572
573       if ( isPropagationHyp ) {
574         TopExp_Explorer exp (_subShape, TopAbs_EDGE);
575         TopTools_MapOfShape aMap;
576         for (; exp.More(); exp.Next()) {
577           if (aMap.Add(exp.Current())) {
578             if (!_father->BuildPropagationChain(exp.Current())) {
579               isPropagationOk = false;
580             }
581           }
582         }
583       }
584       else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
585         TopExp_Explorer exp (_subShape, TopAbs_EDGE);
586         TopTools_MapOfShape aMap;
587         for (; exp.More(); exp.Next()) {
588           if (aMap.Add(exp.Current())) {
589             TopoDS_Shape aMainEdge;
590             if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) {
591               isPropagationOk = _father->RebuildPropagationChains();
592             } else if (_father->IsPropagationHypothesis(exp.Current())) {
593               isPropagationOk = _father->BuildPropagationChain(exp.Current());
594             } else {
595             }
596           }
597         }
598       } else {
599       }
600
601       if ( isPropagationOk ) {
602         if ( isPropagationHyp )
603           return ret; // nothing more to do for "Propagation" hypothesis
604       }
605       else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
606         ret = SMESH_Hypothesis::HYP_CONCURENT;
607       }
608     } // Serve Propagation of 1D hypothesis
609   }
610
611   // --------------------------
612   // remove a hypothesis from DS
613   // --------------------------
614   if (event == REMOVE_HYP || event == REMOVE_ALGO)
615   {
616     if (!_meshDS->RemoveHypothesis(_subShape, anHyp))
617       return SMESH_Hypothesis::HYP_OK; // nothing changes
618
619     // Serve Propagation of 1D hypothesis
620     if (event == REMOVE_HYP)
621     {
622       bool isPropagationOk = true;
623       SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
624       bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape );
625
626       if ( isPropagationHyp )
627       {
628         TopExp_Explorer exp (_subShape, TopAbs_EDGE);
629         TopTools_MapOfShape aMap;
630         for (; exp.More(); exp.Next()) {
631           if (aMap.Add(exp.Current()) &&
632               !_father->GetHypothesis( exp.Current(), propagFilter, true )) {
633             // no more Propagation on the current edge
634             if (!_father->RemovePropagationChain(exp.Current())) {
635               return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
636             }
637           }
638         }
639         // rebuild propagation chains, because removing one
640         // chain can resolve concurention, existing before
641         isPropagationOk = _father->RebuildPropagationChains();
642       }
643       else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
644       {
645         isPropagationOk = _father->RebuildPropagationChains();
646       }
647
648       if ( isPropagationOk ) {
649         if ( isPropagationHyp )
650           return ret; // nothing more to do for "Propagation" hypothesis
651       }
652       else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
653         ret = SMESH_Hypothesis::HYP_CONCURENT;
654       }
655     } // Serve Propagation of 1D hypothesis
656     else // event == REMOVE_ALGO
657     {
658       algo = dynamic_cast<SMESH_Algo*> (anHyp);
659       if (!algo->NeedDescretBoundary())
660       {
661         // clean all mesh in the tree of the current submesh;
662         // we must perform it now because later
663         // we will have no information about the type of the removed algo
664         CleanDependants();
665         ComputeStateEngine( CLEAN );
666         CleanDependsOn();
667       }
668     }
669   }
670
671   // ------------------
672   // analyse algo state
673   // ------------------
674   if (!IsApplicableHypotesis( anHyp ))
675     return ret; // not applicable hypotheses do not change algo state
676
677   switch (_algoState)
678   {
679
680     // ----------------------------------------------------------------------
681
682   case NO_ALGO:
683     switch (event) {
684     case ADD_HYP:
685       break;
686     case ADD_ALGO: {
687       algo = gen->GetAlgo((*_father), _subShape);
688       ASSERT(algo);
689       if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
690         SetAlgoState(HYP_OK);
691       else if ( algo->IsStatusFatal( aux_ret )) {
692         _meshDS->RemoveHypothesis(_subShape, anHyp);
693         ret = aux_ret;
694       }
695       else
696         SetAlgoState(MISSING_HYP);
697       break;
698     }
699     case REMOVE_HYP:
700       break;
701     case REMOVE_ALGO:
702       break;
703     case ADD_FATHER_HYP:
704       break;
705     case ADD_FATHER_ALGO: {    // Algo just added in father
706       algo = gen->GetAlgo((*_father), _subShape);
707       ASSERT(algo);
708       if ( algo == anHyp ) {
709         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
710           SetAlgoState(HYP_OK);
711         else
712           SetAlgoState(MISSING_HYP);
713       }
714       break;
715     }
716     case REMOVE_FATHER_HYP:
717       break;
718     case REMOVE_FATHER_ALGO: {
719       algo = gen->GetAlgo((*_father), _subShape);
720       if (algo)
721       {
722         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
723             SetAlgoState(HYP_OK);
724         else
725           SetAlgoState(MISSING_HYP);
726       }
727       break;
728     }
729     default:
730       ASSERT(0);
731       break;
732     }
733     break;
734
735     // ----------------------------------------------------------------------
736
737   case MISSING_HYP:
738     switch (event)
739     {
740     case ADD_HYP: {
741       algo = gen->GetAlgo((*_father), _subShape);
742       ASSERT(algo);
743       if ( algo->CheckHypothesis((*_father),_subShape, ret ))
744         SetAlgoState(HYP_OK);
745       if (SMESH_Hypothesis::IsStatusFatal( ret ))
746         _meshDS->RemoveHypothesis(_subShape, anHyp);
747       else if (!_father->IsUsedHypothesis( anHyp, this ))
748       {
749         _meshDS->RemoveHypothesis(_subShape, anHyp);
750         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
751       }
752       break;
753     }
754     case ADD_ALGO: {           //already existing algo : on father ?
755       algo = gen->GetAlgo((*_father), _subShape);
756       ASSERT(algo);
757       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
758         SetAlgoState(HYP_OK);
759       else if ( algo->IsStatusFatal( aux_ret )) {
760         _meshDS->RemoveHypothesis(_subShape, anHyp);
761         ret = aux_ret;
762       }
763       else
764         SetAlgoState(MISSING_HYP);
765       break;
766     }
767     case REMOVE_HYP:
768       break;
769     case REMOVE_ALGO: {        // perhaps a father algo applies ?
770       algo = gen->GetAlgo((*_father), _subShape);
771       if (algo == NULL)  // no more algo applying on subShape...
772       {
773         SetAlgoState(NO_ALGO);
774       }
775       else
776       {
777         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
778           SetAlgoState(HYP_OK);
779         else
780           SetAlgoState(MISSING_HYP);
781       }
782       break;
783     }
784     case ADD_FATHER_HYP: {
785       algo = gen->GetAlgo((*_father), _subShape);
786       ASSERT(algo);
787       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
788         SetAlgoState(HYP_OK);
789       else
790         SetAlgoState(MISSING_HYP);
791       break;
792     }
793     case ADD_FATHER_ALGO: { // new father algo
794       algo = gen->GetAlgo((*_father), _subShape);
795       ASSERT( algo );
796       if ( algo == anHyp ) {
797         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
798           SetAlgoState(HYP_OK);
799         else
800           SetAlgoState(MISSING_HYP);
801       }
802       break;
803     }
804     case REMOVE_FATHER_HYP:    // nothing to do
805       break;
806     case REMOVE_FATHER_ALGO: {
807       algo = gen->GetAlgo((*_father), _subShape);
808       if (algo == NULL)  // no more applying algo on father
809       {
810         SetAlgoState(NO_ALGO);
811       }
812       else
813       {
814         if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
815           SetAlgoState(HYP_OK);
816         else
817           SetAlgoState(MISSING_HYP);
818       }
819       break;
820     }
821     default:
822       ASSERT(0);
823       break;
824     }
825     break;
826
827     // ----------------------------------------------------------------------
828
829   case HYP_OK:
830     switch (event)
831     {
832     case ADD_HYP: {
833       algo = gen->GetAlgo((*_father), _subShape);
834       ASSERT(algo);
835       if (!algo->CheckHypothesis((*_father),_subShape, ret ))
836       {
837         if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
838           // ret should be fatal: anHyp was not added
839           ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
840       }
841       else if (!_father->IsUsedHypothesis(  anHyp, this ))
842         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
843
844       if (SMESH_Hypothesis::IsStatusFatal( ret ))
845       {
846         MESSAGE("do not add extra hypothesis");
847         _meshDS->RemoveHypothesis(_subShape, anHyp);
848       }
849       else
850       {
851         modifiedHyp = true;
852       }
853       break;
854     }
855     case ADD_ALGO: {           //already existing algo : on father ?
856       algo = gen->GetAlgo((*_father), _subShape);
857       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
858         // check if algo changes
859         SMESH_HypoFilter f;
860         f.Init(   SMESH_HypoFilter::IsAlgo() );
861         f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
862         f.AndNot( SMESH_HypoFilter::Is( algo ));
863         const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
864         if (prevAlgo &&
865             string(algo->GetName()) != string(prevAlgo->GetName()) )
866           modifiedHyp = true;
867       }
868       else
869         SetAlgoState(MISSING_HYP);
870       break;
871     }
872     case REMOVE_HYP: {
873       algo = gen->GetAlgo((*_father), _subShape);
874       ASSERT(algo);
875       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
876         SetAlgoState(HYP_OK);
877       else
878         SetAlgoState(MISSING_HYP);
879       modifiedHyp = true;
880       break;
881     }
882     case REMOVE_ALGO: {         // perhaps a father algo applies ?
883       algo = gen->GetAlgo((*_father), _subShape);
884       if (algo == NULL)   // no more algo applying on subShape...
885       {
886         SetAlgoState(NO_ALGO);
887       }
888       else
889       {
890         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
891           // check if algo remains
892           if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
893             modifiedHyp = true;
894         }
895         else
896           SetAlgoState(MISSING_HYP);
897       }
898       break;
899     }
900     case ADD_FATHER_HYP: {  // new father hypothesis ?
901       algo = gen->GetAlgo((*_father), _subShape);
902       ASSERT(algo);
903       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
904       {
905         if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
906           modifiedHyp = true;
907       }
908       else
909         SetAlgoState(MISSING_HYP);
910       break;
911     }
912     case ADD_FATHER_ALGO: {
913       algo = gen->GetAlgo((*_father), _subShape);
914       if ( algo == anHyp ) { // a new algo on father
915         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
916           // check if algo changes
917           SMESH_HypoFilter f;
918           f.Init(   SMESH_HypoFilter::IsAlgo() );
919           f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
920           f.AndNot( SMESH_HypoFilter::Is( algo ));
921           const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
922           if (prevAlgo &&
923               string(algo->GetName()) != string(prevAlgo->GetName()) )
924             modifiedHyp = true;
925         }
926         else
927           SetAlgoState(MISSING_HYP);
928       }
929       break;
930     }
931     case REMOVE_FATHER_HYP: {
932       algo = gen->GetAlgo((*_father), _subShape);
933       ASSERT(algo);
934       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
935         // is there the same local hyp or maybe a new father algo applied?
936         if ( !GetSimilarAttached( _subShape, anHyp ) )
937           modifiedHyp = true;
938       }
939       else
940         SetAlgoState(MISSING_HYP);
941       break;
942     }
943     case REMOVE_FATHER_ALGO: {
944       algo = gen->GetAlgo((*_father), _subShape);
945       if (algo == NULL)  // no more applying algo on father
946       {
947         SetAlgoState(NO_ALGO);
948       }
949       else
950       {
951         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
952           // check if algo changes
953           if ( string(algo->GetName()) != string( anHyp->GetName()) )
954             modifiedHyp = true;
955         }
956         else
957           SetAlgoState(MISSING_HYP);
958       }
959       break;
960     }
961     default:
962       ASSERT(0);
963       break;
964     }
965     break;
966
967     // ----------------------------------------------------------------------
968
969   default:
970     ASSERT(0);
971     break;
972   }
973
974   if ( _algoState != oldAlgoState )
975   {
976     if (_algoState == HYP_OK )
977       algo->SetEventListener( this );
978     if ( oldAlgoState == HYP_OK )
979       DeleteOwnListeners();
980   }
981   NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
982
983   if (_algoState != oldAlgoState || modifiedHyp)
984     ComputeStateEngine(MODIF_ALGO_STATE);
985
986   return ret;
987 }
988
989
990 //=======================================================================
991 //function : IsConform
992 //purpose  : check if a conform mesh will be produced by the Algo
993 //=======================================================================
994
995 bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
996 {
997 //  MESSAGE( "SMESH_subMesh::IsConform" );
998
999   if ( !theAlgo ) return false;
1000
1001   // check only algo that doesn't NeedDescretBoundary(): because mesh made
1002   // on a sub-shape will be ignored by theAlgo
1003   if ( theAlgo->NeedDescretBoundary() )
1004     return true;
1005
1006   SMESH_Gen* gen =_father->GetGen();
1007
1008   // only local algo is to be checked
1009   if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
1010     return true;
1011
1012   // check algo attached to adjacent shapes
1013
1014   // loop on one level down sub-meshes
1015   TopoDS_Iterator itsub( _subShape );
1016   for (; itsub.More(); itsub.Next())
1017   {
1018     // loop on adjacent subShapes
1019     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
1020     for (; it.More(); it.Next())
1021     {
1022       const TopoDS_Shape& adjacent = it.Value();
1023       if ( _subShape.IsSame( adjacent )) continue;
1024       if ( adjacent.ShapeType() != _subShape.ShapeType())
1025         break;
1026
1027       // check algo attached to smAdjacent
1028       SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
1029       if (algo &&
1030           //algo != theAlgo &&
1031           !algo->NeedDescretBoundary() /*&&
1032           !gen->IsGlobalHypothesis( algo, *_father )*/)
1033         return false; // NOT CONFORM MESH WILL BE PRODUCED
1034     }
1035   }
1036
1037   return true;
1038 }
1039
1040 //=============================================================================
1041 /*!
1042  *
1043  */
1044 //=============================================================================
1045
1046 void SMESH_subMesh::SetAlgoState(int state)
1047 {
1048   _algoState = state;
1049 }
1050
1051 //=============================================================================
1052 /*!
1053  *
1054  */
1055 //=============================================================================
1056 SMESH_Hypothesis::Hypothesis_Status
1057   SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
1058                                           SMESH_Hypothesis * anHyp)
1059 {
1060   //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
1061   SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
1062   //EAP: a wire (dim==1) should notify edges (dim==1)
1063   //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
1064   if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
1065   {
1066     const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1067
1068     map < int, SMESH_subMesh * >::const_iterator itsub;
1069     for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1070     {
1071       SMESH_subMesh *sm = (*itsub).second;
1072       SMESH_Hypothesis::Hypothesis_Status ret2 =
1073         sm->AlgoStateEngine(event, anHyp);
1074       if ( ret2 > ret )
1075         ret = ret2;
1076     }
1077   }
1078   return ret;
1079 }
1080
1081 //=============================================================================
1082 /*!
1083  *
1084  */
1085 //=============================================================================
1086
1087 void SMESH_subMesh::CleanDependsOn()
1088 {
1089   //MESSAGE("SMESH_subMesh::CleanDependsOn");
1090
1091   const map < int, SMESH_subMesh * >&dependson = DependsOn();
1092   map < int, SMESH_subMesh * >::const_iterator its;
1093   for (its = dependson.begin(); its != dependson.end(); its++)
1094   {
1095     SMESH_subMesh *sm = (*its).second;
1096     sm->ComputeStateEngine(CLEAN);
1097   }
1098 }
1099
1100 //=============================================================================
1101 /*!
1102  *
1103  */
1104 //=============================================================================
1105
1106 void SMESH_subMesh::DumpAlgoState(bool isMain)
1107 {
1108         int dim = SMESH_Gen::GetShapeDim(_subShape);
1109 //   if (dim < 1) return;
1110         if (isMain)
1111         {
1112                 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1113
1114                 map < int, SMESH_subMesh * >::const_iterator itsub;
1115                 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1116                 {
1117                         SMESH_subMesh *sm = (*itsub).second;
1118                         sm->DumpAlgoState(false);
1119                 }
1120         }
1121         int type = _subShape.ShapeType();
1122         MESSAGE("dim = " << dim << " type of shape " << type);
1123         switch (_algoState)
1124         {
1125         case NO_ALGO:
1126                 MESSAGE(" AlgoState = NO_ALGO");
1127                 break;
1128         case MISSING_HYP:
1129                 MESSAGE(" AlgoState = MISSING_HYP");
1130                 break;
1131         case HYP_OK:
1132                 MESSAGE(" AlgoState = HYP_OK");
1133                 break;
1134         }
1135         switch (_computeState)
1136         {
1137         case NOT_READY:
1138                 MESSAGE(" ComputeState = NOT_READY");
1139                 break;
1140         case READY_TO_COMPUTE:
1141                 MESSAGE(" ComputeState = READY_TO_COMPUTE");
1142                 break;
1143         case COMPUTE_OK:
1144                 MESSAGE(" ComputeState = COMPUTE_OK");
1145                 break;
1146         case FAILED_TO_COMPUTE:
1147                 MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
1148                 break;
1149         }
1150 }
1151
1152 //================================================================================
1153 /*!
1154  * \brief Remove nodes and elements bound to submesh
1155   * \param subMesh - submesh containing nodes and elements
1156  */
1157 //================================================================================
1158
1159 static void cleanSubMesh( SMESH_subMesh * subMesh )
1160 {
1161   if (subMesh) {
1162     if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
1163       SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
1164       SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
1165       while (ite->more()) {
1166         const SMDS_MeshElement * elt = ite->next();
1167         //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
1168         //meshDS->RemoveElement(elt);
1169         meshDS->RemoveFreeElement(elt, subMeshDS);
1170       }
1171
1172       SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
1173       while (itn->more()) {
1174         const SMDS_MeshNode * node = itn->next();
1175         //MESSAGE( " RM node: "<<node->GetID());
1176         //meshDS->RemoveNode(node);
1177         meshDS->RemoveFreeNode(node, subMeshDS);
1178       }
1179     }
1180   }
1181 }
1182
1183 //=============================================================================
1184 /*!
1185  *
1186  */
1187 //=============================================================================
1188
1189 bool SMESH_subMesh::ComputeStateEngine(int event)
1190 {
1191   //MESSAGE("SMESH_subMesh::ComputeStateEngine");
1192   //SCRUTE(_computeState);
1193   //SCRUTE(event);
1194
1195   int dim = SMESH_Gen::GetShapeDim(_subShape);
1196
1197   if (dim < 1)
1198   {
1199     if ( IsMeshComputed() )
1200       _computeState = COMPUTE_OK;
1201     else
1202       _computeState = READY_TO_COMPUTE;
1203     return true;
1204   }
1205   SMESH_Gen *gen = _father->GetGen();
1206   SMESH_Algo *algo = 0;
1207   bool ret = true;
1208   SMESH_Hypothesis::Hypothesis_Status hyp_status;
1209   algo_state oldAlgoState = (algo_state) GetAlgoState();
1210
1211   switch (_computeState)
1212   {
1213
1214     // ----------------------------------------------------------------------
1215
1216   case NOT_READY:
1217     switch (event)
1218     {
1219     case MODIF_HYP:
1220     case MODIF_ALGO_STATE:
1221       algo = gen->GetAlgo((*_father), _subShape);
1222       if (algo && !algo->NeedDescretBoundary())
1223         CleanDependsOn(); // clean sub-meshes with event CLEAN
1224       if (algo)
1225       {
1226         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1227         if (ret)
1228           _computeState = READY_TO_COMPUTE;
1229       }
1230       if ( _computeState == READY_TO_COMPUTE )
1231           SetAlgoState(HYP_OK);
1232       else
1233           SetAlgoState(MISSING_HYP);
1234       break;
1235     case COMPUTE:               // nothing to do
1236       break;
1237     case CLEAN:
1238       CleanDependants();
1239       RemoveSubMeshElementsAndNodes();
1240       break;
1241     case SUBMESH_COMPUTED:      // nothing to do
1242       break;
1243     case SUBMESH_RESTORED:
1244       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1245       break;
1246     case MESH_ENTITY_REMOVED:
1247       break;
1248     case CHECK_COMPUTE_STATE:
1249       if ( IsMeshComputed() )
1250         _computeState = COMPUTE_OK;
1251       break;
1252     default:
1253       ASSERT(0);
1254       break;
1255     }
1256     break;
1257
1258     // ----------------------------------------------------------------------
1259
1260   case READY_TO_COMPUTE:
1261     switch (event)
1262     {
1263     case MODIF_HYP:
1264     case MODIF_ALGO_STATE:
1265       algo = gen->GetAlgo((*_father), _subShape);
1266       if (algo && !algo->NeedDescretBoundary())
1267         CleanDependsOn(); // clean sub-meshes with event CLEAN
1268       _computeState = NOT_READY;
1269       if (algo)
1270       {
1271         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1272         if (ret) {
1273           SetAlgoState(HYP_OK); // it might be KO if BAD_PARAM_VALUE
1274           _computeState = READY_TO_COMPUTE;
1275         }
1276         else
1277           SetAlgoState(MISSING_HYP);
1278       }
1279       break;
1280     case COMPUTE:
1281       {
1282         algo = gen->GetAlgo((*_father), _subShape);
1283         ASSERT(algo);
1284         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1285         if (!ret)
1286         {
1287           MESSAGE("***** verify compute state *****");
1288           _computeState = NOT_READY;
1289           SetAlgoState(MISSING_HYP);
1290           break;
1291         }
1292         // check submeshes needed
1293         if (algo->NeedDescretBoundary())
1294           ret = SubMeshesComputed();
1295         if (!ret)
1296         {
1297           MESSAGE("Some SubMeshes not computed");
1298           _computeState = FAILED_TO_COMPUTE;
1299           break;
1300         }
1301         // compute
1302         CleanDependants();
1303         RemoveSubMeshElementsAndNodes();
1304         {
1305           try {
1306 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1307             OCC_CATCH_SIGNALS;
1308 #endif
1309             if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
1310               ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
1311             else
1312               ret = algo->Compute((*_father), _subShape);
1313           }
1314           catch (Standard_Failure) {
1315             MESSAGE( "Exception in algo->Compute() ");
1316             ret = false;
1317           }
1318         }
1319         if (!ret)
1320         {
1321           MESSAGE("problem in algo execution: failed to compute");
1322           // release ALGO from responsibilty of partially built mesh
1323           RemoveSubMeshElementsAndNodes();
1324           _computeState = FAILED_TO_COMPUTE;
1325           if (!algo->NeedDescretBoundary())
1326             UpdateSubMeshState( FAILED_TO_COMPUTE );
1327
1328 #ifdef _DEBUG_
1329           // Show vertices location of a failed shape
1330           cout << algo->GetName() << " failed on shape with the following vertices:" << endl;
1331           TopTools_IndexedMapOfShape vMap;
1332           TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
1333           for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
1334             gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
1335             cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
1336           }
1337 #endif
1338           break;
1339         }
1340         else
1341         {
1342           _computeState = COMPUTE_OK;
1343           UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
1344           if (!algo->NeedDescretBoundary())
1345             UpdateSubMeshState( COMPUTE_OK );
1346         }
1347       }
1348       break;
1349     case CLEAN:
1350       CleanDependants();
1351       RemoveSubMeshElementsAndNodes();
1352       _computeState = NOT_READY;
1353       algo = gen->GetAlgo((*_father), _subShape);
1354       if (algo)
1355       {
1356         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1357         if (ret)
1358           _computeState = READY_TO_COMPUTE;
1359         else
1360           SetAlgoState(MISSING_HYP);
1361       }
1362       break;
1363     case SUBMESH_COMPUTED:      // nothing to do
1364       break;
1365     case SUBMESH_RESTORED:
1366       // check if a mesh is already computed that may
1367       // happen after retrieval from a file
1368       ComputeStateEngine( CHECK_COMPUTE_STATE );
1369       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1370       break;
1371     case MESH_ENTITY_REMOVED:
1372       break;
1373     case CHECK_COMPUTE_STATE:
1374       if ( IsMeshComputed() )
1375         _computeState = COMPUTE_OK;
1376       break;
1377     default:
1378       ASSERT(0);
1379       break;
1380     }
1381     break;
1382
1383     // ----------------------------------------------------------------------
1384
1385   case COMPUTE_OK:
1386     switch (event)
1387     {
1388     case MODIF_HYP:
1389     case MODIF_ALGO_STATE:
1390       ComputeStateEngine( CLEAN );
1391       algo = gen->GetAlgo((*_father), _subShape);
1392       if (algo && !algo->NeedDescretBoundary())
1393         CleanDependsOn(); // clean sub-meshes with event CLEAN
1394       break;
1395     case COMPUTE:               // nothing to do
1396       break;
1397     case CLEAN:
1398       CleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
1399       RemoveSubMeshElementsAndNodes();
1400       _computeState = NOT_READY;
1401       algo = gen->GetAlgo((*_father), _subShape);
1402       if (algo)
1403       {
1404         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1405         if (ret)
1406           _computeState = READY_TO_COMPUTE;
1407         else
1408           SetAlgoState(MISSING_HYP);
1409       }
1410       break;
1411     case SUBMESH_COMPUTED:      // nothing to do
1412       break;
1413     case SUBMESH_RESTORED:
1414       ComputeStateEngine( CHECK_COMPUTE_STATE );
1415       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1416       break;
1417     case MESH_ENTITY_REMOVED:
1418       UpdateDependantsState( CHECK_COMPUTE_STATE );
1419       ComputeStateEngine( CHECK_COMPUTE_STATE );
1420       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1421       break;
1422     case CHECK_COMPUTE_STATE:
1423       if ( !IsMeshComputed() )
1424         if (_algoState == HYP_OK)
1425           _computeState = READY_TO_COMPUTE;
1426         else
1427           _computeState = NOT_READY;
1428       break;
1429     default:
1430       ASSERT(0);
1431       break;
1432     }
1433     break;
1434
1435     // ----------------------------------------------------------------------
1436
1437   case FAILED_TO_COMPUTE:
1438     switch (event)
1439     {
1440     case MODIF_HYP:
1441       if (_algoState == HYP_OK)
1442         _computeState = READY_TO_COMPUTE;
1443       else
1444         _computeState = NOT_READY;
1445       break;
1446     case MODIF_ALGO_STATE:
1447       if (_algoState == HYP_OK)
1448         _computeState = READY_TO_COMPUTE;
1449       else
1450         _computeState = NOT_READY;
1451       break;
1452     case COMPUTE:      // nothing to do
1453       break;
1454     case CLEAN:
1455       CleanDependants(); // submeshes dependent on me should be cleaned as well
1456       RemoveSubMeshElementsAndNodes();
1457       if (_algoState == HYP_OK)
1458         _computeState = READY_TO_COMPUTE;
1459       else
1460         _computeState = NOT_READY;
1461       break;
1462     case SUBMESH_COMPUTED:      // allow retry compute
1463       if (_algoState == HYP_OK)
1464         _computeState = READY_TO_COMPUTE;
1465       else
1466         _computeState = NOT_READY;
1467       break;
1468     case SUBMESH_RESTORED:
1469       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1470       break;
1471     case MESH_ENTITY_REMOVED:
1472       break;
1473     case CHECK_COMPUTE_STATE:
1474       if ( IsMeshComputed() )
1475         _computeState = COMPUTE_OK;
1476       else
1477         if (_algoState == HYP_OK)
1478           _computeState = READY_TO_COMPUTE;
1479         else
1480           _computeState = NOT_READY;
1481       break;
1482     default:
1483       ASSERT(0);
1484       break;
1485     }
1486     break;
1487
1488     // ----------------------------------------------------------------------
1489   default:
1490     ASSERT(0);
1491     break;
1492   }
1493
1494   if ( _algoState != oldAlgoState )
1495   {
1496     if (_algoState == HYP_OK && algo )
1497       algo->SetEventListener( this );
1498     if ( oldAlgoState == HYP_OK )
1499       DeleteOwnListeners();
1500   }
1501   NotifyListenersOnEvent( event, COMPUTE_EVENT );
1502
1503   //SCRUTE(_computeState);
1504   return ret;
1505 }
1506
1507 //=======================================================================
1508 //function : ApplyToCollection
1509 //purpose  : Apply theAlgo to all subshapes in theCollection
1510 //=======================================================================
1511
1512 bool SMESH_subMesh::ApplyToCollection (SMESH_Algo*         theAlgo,
1513                                        const TopoDS_Shape& theCollection)
1514 {
1515   MESSAGE("SMESH_subMesh::ApplyToCollection");
1516   ASSERT ( !theAlgo->NeedDescretBoundary() );
1517
1518   bool ret = false;
1519
1520
1521   ret = theAlgo->Compute( *_father, theCollection );
1522
1523   // set _computeState of subshapes
1524   TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
1525   for ( ; anExplorer.More(); anExplorer.Next() )
1526   {
1527     const TopoDS_Shape& aSubShape = anExplorer.Current();
1528     SMESH_subMesh* subMesh = _father->GetSubMeshContaining( aSubShape );
1529     if ( subMesh )
1530     {
1531       if (ret)
1532       {
1533         subMesh->_computeState = COMPUTE_OK;
1534         subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
1535         subMesh->UpdateSubMeshState( COMPUTE_OK );
1536       }
1537       else
1538       {
1539         subMesh->_computeState = FAILED_TO_COMPUTE;
1540       }
1541     }
1542   }
1543   return ret;
1544 }
1545
1546
1547 //=======================================================================
1548 //function : UpdateSubMeshState
1549 //purpose  :
1550 //=======================================================================
1551
1552 void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
1553 {
1554   const map<int, SMESH_subMesh*>& smMap = DependsOn();
1555   map<int, SMESH_subMesh*>::const_iterator itsub;
1556   for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1557   {
1558     SMESH_subMesh* sm = (*itsub).second;
1559     sm->_computeState = theState;
1560   }
1561 }
1562
1563 //=======================================================================
1564 //function : ComputeSubMeshStateEngine
1565 //purpose  :
1566 //=======================================================================
1567
1568 void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
1569 {
1570   const map<int, SMESH_subMesh*>& smMap = DependsOn();
1571   map<int, SMESH_subMesh*>::const_iterator itsub;
1572   for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1573   {
1574     SMESH_subMesh* sm = (*itsub).second;
1575     sm->ComputeStateEngine(event);
1576   }
1577 }
1578
1579 //=======================================================================
1580 //function : UpdateDependantsState
1581 //purpose  :
1582 //=======================================================================
1583
1584 void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
1585 {
1586   //MESSAGE("SMESH_subMesh::UpdateDependantsState");
1587   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1588   for (; it.More(); it.Next())
1589   {
1590     const TopoDS_Shape& ancestor = it.Value();
1591     SMESH_subMesh *aSubMesh =
1592       _father->GetSubMeshContaining(ancestor);
1593     if (aSubMesh)
1594       aSubMesh->ComputeStateEngine( theEvent );
1595   }
1596 }
1597
1598 //=============================================================================
1599 /*!
1600  *
1601  */
1602 //=============================================================================
1603
1604 void SMESH_subMesh::CleanDependants()
1605 {
1606   int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
1607
1608   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1609   for (; it.More(); it.Next())
1610   {
1611     const TopoDS_Shape& ancestor = it.Value();
1612     if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
1613       // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
1614       // will erase mesh on other shapes in a compound
1615       if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
1616         SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
1617         if (aSubMesh)
1618           aSubMesh->ComputeStateEngine(CLEAN);
1619       }
1620     }
1621   }
1622 }
1623
1624 //=============================================================================
1625 /*!
1626  *
1627  */
1628 //=============================================================================
1629
1630 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
1631 {
1632   //SCRUTE(_subShape.ShapeType());
1633
1634   cleanSubMesh( this );
1635
1636   // algo may bind a submesh not to _subShape, eg 3D algo
1637   // sets nodes on SHELL while _subShape may be SOLID
1638
1639   int dim = SMESH_Gen::GetShapeDim( _subShape );
1640   int type = _subShape.ShapeType() + 1;
1641   for ( ; type <= TopAbs_EDGE; type++) {
1642     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1643     {
1644       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1645       for ( ; exp.More(); exp.Next() )
1646         cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
1647     }
1648     else
1649       break;
1650   }
1651 }
1652
1653 //=======================================================================
1654 //function : IsMeshComputed
1655 //purpose  : check if _subMeshDS contains mesh elements
1656 //=======================================================================
1657
1658 bool SMESH_subMesh::IsMeshComputed() const
1659 {
1660   // algo may bind a submesh not to _subShape, eg 3D algo
1661   // sets nodes on SHELL while _subShape may be SOLID
1662
1663   int dim = SMESH_Gen::GetShapeDim( _subShape );
1664   int type = _subShape.ShapeType();
1665   for ( ; type <= TopAbs_VERTEX; type++) {
1666     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1667     {
1668       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1669       for ( ; exp.More(); exp.Next() )
1670       {
1671         SMESHDS_SubMesh * smDS = _meshDS->MeshElements( exp.Current() );
1672         if ( smDS && ( smDS->NbElements() || smDS->NbNodes()))
1673           return true;
1674       }
1675     }
1676     else
1677       break;
1678   }
1679
1680   return false;
1681 }
1682
1683
1684 //=======================================================================
1685 //function : GetCollection
1686 //purpose  : return a shape containing all sub-shapes of the MainShape that can be
1687 //           meshed at once along with _subShape
1688 //=======================================================================
1689
1690 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
1691 {
1692   MESSAGE("SMESH_subMesh::GetCollection");
1693   ASSERT (!theAlgo->NeedDescretBoundary());
1694
1695   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
1696
1697   if ( mainShape.IsSame( _subShape ))
1698     return _subShape;
1699
1700   const bool ignoreAuxiliaryHyps = false;
1701   list<const SMESHDS_Hypothesis*> aUsedHyp =
1702     theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
1703
1704   // put in a compound all shapes with the same hypothesis assigned
1705   // and a good ComputState
1706
1707   TopoDS_Compound aCompound;
1708   BRep_Builder aBuilder;
1709   aBuilder.MakeCompound( aCompound );
1710
1711   TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
1712   for ( ; anExplorer.More(); anExplorer.Next() )
1713   {
1714     const TopoDS_Shape& S = anExplorer.Current();
1715     SMESH_subMesh* subMesh = _father->GetSubMesh( S );
1716     SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
1717
1718     if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
1719         anAlgo == theAlgo &&
1720         anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
1721     {
1722       aBuilder.Add( aCompound, S );
1723     }
1724   }
1725
1726   return aCompound;
1727 }
1728
1729 //=======================================================================
1730 //function : GetSimilarAttached
1731 //purpose  : return a hypothesis attached to theShape.
1732 //           If theHyp is provided, similar but not same hypotheses
1733 //           is returned; else only applicable ones having theHypType
1734 //           is returned
1735 //=======================================================================
1736
1737 const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&      theShape,
1738                                                           const SMESH_Hypothesis * theHyp,
1739                                                           const int                theHypType)
1740 {
1741   SMESH_HypoFilter hypoKind;
1742   hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
1743   if ( theHyp ) {
1744     hypoKind.And   ( hypoKind.HasDim( theHyp->GetDim() ));
1745     hypoKind.AndNot( hypoKind.Is( theHyp ));
1746     if ( theHyp->IsAuxiliary() )
1747       hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
1748     else
1749       hypoKind.AndNot( hypoKind.IsAuxiliary());
1750   }
1751   else {
1752     hypoKind.And( hypoKind.IsApplicableTo( theShape ));
1753   }
1754
1755   return _father->GetHypothesis( theShape, hypoKind, false );
1756 }
1757
1758 //=======================================================================
1759 //function : CheckConcurentHypothesis
1760 //purpose  : check if there are several applicable hypothesis attached to
1761 //           ansestors
1762 //=======================================================================
1763
1764 SMESH_Hypothesis::Hypothesis_Status
1765   SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
1766 {
1767   MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
1768
1769   // is there local hypothesis on me?
1770   if ( GetSimilarAttached( _subShape, 0, theHypType ) )
1771     return SMESH_Hypothesis::HYP_OK;
1772
1773
1774   TopoDS_Shape aPrevWithHyp;
1775   const SMESH_Hypothesis* aPrevHyp = 0;
1776   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1777   for (; it.More(); it.Next())
1778   {
1779     const TopoDS_Shape& ancestor = it.Value();
1780     const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
1781     if ( hyp )
1782     {
1783       if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
1784       {
1785         aPrevWithHyp = ancestor;
1786         aPrevHyp     = hyp;
1787       }
1788       else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
1789         return SMESH_Hypothesis::HYP_CONCURENT;
1790       else
1791         return SMESH_Hypothesis::HYP_OK;
1792     }
1793   }
1794   return SMESH_Hypothesis::HYP_OK;
1795 }
1796
1797 //================================================================================
1798 /*!
1799  * \brief Sets an event listener and its data to a submesh
1800  * \param listener - the listener to store
1801  * \param data - the listener data to store
1802  * \param where - the submesh to store the listener and it's data
1803  * \param deleteListener - if true then the listener will be deleted as
1804  *        it is removed from where submesh
1805  * 
1806  * It remembers the submesh where it puts the listener in order to delete
1807  * them when HYP_OK algo_state is lost
1808  * After being set, event listener is notified on each event of where submesh.
1809  */
1810 //================================================================================
1811
1812 void SMESH_subMesh::SetEventListener(EventListener*     listener,
1813                                      EventListenerData* data,
1814                                      SMESH_subMesh*     where)
1815 {
1816   if ( listener && where ) {
1817     where->SetEventListener( listener, data );
1818     myOwnListeners.push_back( make_pair( where, listener ));
1819   }
1820 }
1821
1822 //================================================================================
1823 /*!
1824  * \brief Sets an event listener and its data to a submesh
1825  * \param listener - the listener to store
1826  * \param data - the listener data to store
1827  * 
1828  * After being set, event listener is notified on each event of a submesh.
1829  */
1830 //================================================================================
1831
1832 void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data)
1833 {
1834   myEventListeners.insert( make_pair( listener, data ));
1835 }
1836
1837 //================================================================================
1838 /*!
1839  * \brief Return an event listener data
1840  * \param listener - the listener whose data is
1841  * \retval EventListenerData* - found data, maybe NULL
1842  */
1843 //================================================================================
1844
1845 EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
1846 {
1847   map< EventListener*, EventListenerData* >::const_iterator l_d =
1848     myEventListeners.find( listener );
1849   if ( l_d != myEventListeners.end() )
1850     return l_d->second;
1851   return 0;
1852 }
1853
1854 //================================================================================
1855 /*!
1856  * \brief Notify stored event listeners on the occured event
1857  * \param event - algo_event or compute_event itself
1858  * \param eventType - algo_event or compute_event
1859  * \param subMesh - the submesh where the event occures
1860  * \param data - listener data stored in the subMesh
1861  * \param hyp - hypothesis, if eventType is algo_event
1862  */
1863 //================================================================================
1864
1865 void SMESH_subMesh::NotifyListenersOnEvent( const int         event,
1866                                             const event_type  eventType,
1867                                             SMESH_Hypothesis* hyp)
1868 {
1869   map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin();
1870   for ( ; l_d != myEventListeners.end(); ++l_d )
1871     l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp );
1872 }
1873
1874 //================================================================================
1875 /*!
1876  * \brief Unregister the listener and delete listener's data
1877  * \param listener - the event listener
1878  */
1879 //================================================================================
1880
1881 void SMESH_subMesh::DeleteEventListener(EventListener* listener)
1882 {
1883   map< EventListener*, EventListenerData* >::iterator l_d =
1884     myEventListeners.find( listener );
1885   if ( l_d != myEventListeners.end() ) {
1886     delete l_d->first;
1887     delete l_d->second;
1888     myEventListeners.erase( l_d );
1889   }
1890 }
1891
1892 //================================================================================
1893 /*!
1894  * \brief Delete event listeners depending on algo of this submesh
1895  */
1896 //================================================================================
1897
1898 void SMESH_subMesh::DeleteOwnListeners()
1899 {
1900   list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l;
1901   for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l)
1902     sm_l->first->DeleteEventListener( sm_l->second );
1903   myOwnListeners.clear();
1904 }
1905
1906 //================================================================================
1907 /*!
1908  * \brief Do something on a certain event
1909  * \param event - algo_event or compute_event itself
1910  * \param eventType - algo_event or compute_event
1911  * \param subMesh - the submesh where the event occures
1912  * \param data - listener data stored in the subMesh
1913  * \param hyp - hypothesis, if eventType is algo_event
1914  * 
1915  * The base implementation translates CLEAN event to the subMesh
1916  * stored in listener data
1917  */
1918 //================================================================================
1919
1920 void SMESH_subMeshEventListener::ProcessEvent(const int          event,
1921                                               const int          eventType,
1922                                               SMESH_subMesh*     subMesh,
1923                                               EventListenerData* data,
1924                                               SMESH_Hypothesis*  /*hyp*/)
1925 {
1926   if ( event == SMESH_subMesh::CLEAN && eventType == SMESH_subMesh::COMPUTE_EVENT )
1927     if ( data && !data->mySubMeshes.empty() ) {
1928       ASSERT( data->mySubMeshes.front() != subMesh );
1929       data->mySubMeshes.front()->ComputeStateEngine( event );
1930     }
1931 }