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