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