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