]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH/SMESH_subMesh.cxx
Salome HOME
017107a340c69e3b0eecf077a1f4e25c8c538341
[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   if(_father->HasShapeToMesh()) {
501     int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
502     if ( aHypDim <= aShapeDim )
503       return true;
504   }
505   else
506     //Only 3D hypothesis may be assigned to the mesh w/o geometry
507     return aHypDim == 3;
508 //   if ( aHypDim < aShapeDim )
509 //     return ( _father->IsMainShape( _subShape ));
510
511   return false;
512 }
513
514 //=======================================================================
515 //function : IsApplicableHypotesis
516 //purpose  :
517 //=======================================================================
518
519 bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
520                                           const TopAbs_ShapeEnum  theShapeType)
521 {
522   if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
523     // algorithm
524     return ( theHypothesis->GetShapeType() & (1<< theShapeType));
525
526   // hypothesis
527   switch ( theShapeType ) {
528   case TopAbs_VERTEX:
529   case TopAbs_EDGE:
530   case TopAbs_FACE:
531   case TopAbs_SOLID:
532     return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
533
534   case TopAbs_SHELL:
535     // Special case for algorithms, building 2D mesh on a whole shell.
536     // Before this fix there was a problem after restoring from study,
537     // because in that case algorithm is assigned before hypothesis
538     // (on shell in problem case) and hypothesis is checked on faces
539     // (because it is 2D), where we have NO_ALGO state.
540     // Now 2D hypothesis is also applicable to shells.
541     return (theHypothesis->GetDim() == 2 || theHypothesis->GetDim() == 3);
542
543 //   case TopAbs_WIRE:
544 //   case TopAbs_COMPSOLID:
545 //   case TopAbs_COMPOUND:
546   default:;
547   }
548   return false;
549 }
550
551 //=============================================================================
552 /*!
553  *
554  */
555 //=============================================================================
556
557 SMESH_Hypothesis::Hypothesis_Status
558   SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
559 {
560   //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
561   //SCRUTE(_algoState);
562   //SCRUTE(event);
563
564   // **** les retour des evenement shape sont significatifs
565   // (add ou remove fait ou non)
566   // le retour des evenement father n'indiquent pas que add ou remove fait
567
568   SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
569
570   SMESHDS_Mesh* meshDS =_father->GetMeshDS();
571   SMESH_Gen*    gen    =_father->GetGen();
572   SMESH_Algo*   algo   = 0;
573
574   if (_subShape.ShapeType() == TopAbs_VERTEX )
575   {
576     if ( anHyp->GetDim() != 0) {
577       if (event == ADD_HYP || event == ADD_ALGO)
578         return SMESH_Hypothesis::HYP_BAD_DIM;
579       else
580         return SMESH_Hypothesis::HYP_OK;
581     }
582     // 0D hypothesis
583     else if ( _algoState == HYP_OK ) {
584       // update default _algoState
585       if ( event != REMOVE_FATHER_ALGO )
586       {
587         _algoState = NO_ALGO;
588         algo = gen->GetAlgo(*_father, _subShape);
589         if ( algo ) {
590           _algoState = MISSING_HYP;
591           if ( event == REMOVE_FATHER_HYP ||
592                algo->CheckHypothesis(*_father,_subShape, aux_ret))
593             _algoState = HYP_OK;
594         }
595       }
596     }
597   }
598
599   int oldAlgoState = _algoState;
600   bool modifiedHyp = (event == MODIF_HYP);  // if set to true, force event MODIF_ALGO_STATE
601
602   bool isApplicableHyp = IsApplicableHypotesis( anHyp );
603
604   if (event == ADD_ALGO || event == ADD_FATHER_ALGO)
605   {
606     // -------------------------------------------
607     // check if a shape needed by algo is present
608     // -------------------------------------------
609     algo = static_cast< SMESH_Algo* >( anHyp );
610     if(_father->GetShapeToMesh() != SMESH_Mesh::PseudoShape())
611       if ( !_father->HasShapeToMesh() && algo->NeedShape() )
612         return SMESH_Hypothesis::HYP_BAD_GEOMETRY;
613     // ----------------------
614     // check mesh conformity
615     // ----------------------
616     if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
617       return SMESH_Hypothesis::HYP_NOTCONFORM;
618   }
619
620   // ----------------------------------
621   // add a hypothesis to DS if possible
622   // ----------------------------------
623   if (event == ADD_HYP || event == ADD_ALGO)
624   {
625     if ( ! CanAddHypothesis( anHyp )) // check dimension
626       return SMESH_Hypothesis::HYP_BAD_DIM;
627
628     // EAP: __NOT__ Only NETGEN_3D and GHS3D_3D can be assigned to the Mesh w/o geometryy,
629     // but any algo which !NeedShape()
630 //     if(anHyp->GetDim() == 3 && !_father->HasShapeToMesh()
631 //        && event == ADD_ALGO) {
632 //       //Only NETGEN_3D and GHS3D_3D can be assigned to the Mesh w/o geometryy
633 //       bool isNetgen3D = (strcmp( "NETGEN_3D", anHyp->GetName()) == 0);
634 //       bool  isGhs3d = (strcmp( "GHS3D_3D", anHyp->GetName()) == 0);
635 //       if( !isNetgen3D && !isGhs3d)
636 //         return SMESH_Hypothesis::HYP_BAD_DIM;
637 //     }
638     
639     if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
640       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
641
642     if ( !meshDS->AddHypothesis(_subShape, anHyp))
643       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
644   }
645
646   // --------------------------
647   // remove a hypothesis from DS
648   // --------------------------
649   if (event == REMOVE_HYP || event == REMOVE_ALGO)
650   {
651     if (!meshDS->RemoveHypothesis(_subShape, anHyp))
652       return SMESH_Hypothesis::HYP_OK; // nothing changes
653
654     if (event == REMOVE_ALGO)
655     {
656       algo = dynamic_cast<SMESH_Algo*> (anHyp);
657       if (!algo->NeedDescretBoundary())
658       {
659         // clean all mesh in the tree of the current submesh;
660         // we must perform it now because later
661         // we will have no information about the type of the removed algo
662         CleanDependants();
663         ComputeStateEngine( CLEAN );
664         CleanDependsOn();
665         ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
666       }
667     }
668   }
669
670   // ------------------
671   // analyse algo state
672   // ------------------
673   if (!isApplicableHyp)
674     return ret; // not applicable hypotheses do not change algo state
675
676   switch (_algoState)
677   {
678
679     // ----------------------------------------------------------------------
680
681   case NO_ALGO:
682     switch (event) {
683     case ADD_HYP:
684       break;
685     case ADD_ALGO: {
686       algo = gen->GetAlgo((*_father), _subShape);
687       ASSERT(algo);
688       if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
689         SetAlgoState(HYP_OK);
690       else if ( algo->IsStatusFatal( aux_ret )) {
691         meshDS->RemoveHypothesis(_subShape, anHyp);
692         ret = aux_ret;
693       }
694       else
695         SetAlgoState(MISSING_HYP);
696       break;
697     }
698     case REMOVE_HYP:
699     case REMOVE_ALGO:
700     case ADD_FATHER_HYP:
701       break;
702     case ADD_FATHER_ALGO: {    // Algo just added in father
703       algo = gen->GetAlgo((*_father), _subShape);
704       ASSERT(algo);
705       if ( algo == anHyp ) {
706         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
707           SetAlgoState(HYP_OK);
708         else
709           SetAlgoState(MISSING_HYP);
710       }
711       break;
712     }
713     case REMOVE_FATHER_HYP:
714       break;
715     case REMOVE_FATHER_ALGO: {
716       algo = gen->GetAlgo((*_father), _subShape);
717       if (algo)
718       {
719         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
720             SetAlgoState(HYP_OK);
721         else
722           SetAlgoState(MISSING_HYP);
723       }
724       break;
725     }
726     case MODIF_HYP: break;
727     default:
728       ASSERT(0);
729       break;
730     }
731     break;
732
733     // ----------------------------------------------------------------------
734
735   case MISSING_HYP:
736     switch (event)
737     {
738     case ADD_HYP: {
739       algo = gen->GetAlgo((*_father), _subShape);
740       ASSERT(algo);
741       if ( algo->CheckHypothesis((*_father),_subShape, ret ))
742         SetAlgoState(HYP_OK);
743       if (SMESH_Hypothesis::IsStatusFatal( ret ))
744         meshDS->RemoveHypothesis(_subShape, anHyp);
745       else if (!_father->IsUsedHypothesis( anHyp, this ))
746       {
747         meshDS->RemoveHypothesis(_subShape, anHyp);
748         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
749       }
750       break;
751     }
752     case ADD_ALGO: {           //already existing algo : on father ?
753       algo = gen->GetAlgo((*_father), _subShape);
754       ASSERT(algo);
755       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
756         SetAlgoState(HYP_OK);
757       else if ( algo->IsStatusFatal( aux_ret )) {
758         meshDS->RemoveHypothesis(_subShape, anHyp);
759         ret = aux_ret;
760       }
761       else
762         SetAlgoState(MISSING_HYP);
763       break;
764     }
765     case REMOVE_HYP:
766       break;
767     case REMOVE_ALGO: {        // perhaps a father algo applies ?
768       algo = gen->GetAlgo((*_father), _subShape);
769       if (algo == NULL)  // no more algo applying on subShape...
770       {
771         SetAlgoState(NO_ALGO);
772       }
773       else
774       {
775         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
776           SetAlgoState(HYP_OK);
777         else
778           SetAlgoState(MISSING_HYP);
779       }
780       break;
781     }
782     case MODIF_HYP: // assigned hypothesis value may become good
783     case ADD_FATHER_HYP: {
784       algo = gen->GetAlgo((*_father), _subShape);
785       ASSERT(algo);
786       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
787         SetAlgoState(HYP_OK);
788       else
789         SetAlgoState(MISSING_HYP);
790       break;
791     }
792     case ADD_FATHER_ALGO: { // new father algo
793       algo = gen->GetAlgo((*_father), _subShape);
794       ASSERT( algo );
795       if ( algo == anHyp ) {
796         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
797           SetAlgoState(HYP_OK);
798         else
799           SetAlgoState(MISSING_HYP);
800       }
801       break;
802     }
803     case REMOVE_FATHER_HYP:    // nothing to do
804       break;
805     case REMOVE_FATHER_ALGO: {
806       algo = gen->GetAlgo((*_father), _subShape);
807       if (algo == NULL)  // no more applying algo on father
808       {
809         SetAlgoState(NO_ALGO);
810       }
811       else
812       {
813         if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
814           SetAlgoState(HYP_OK);
815         else
816           SetAlgoState(MISSING_HYP);
817       }
818       break;
819     }
820     default:
821       ASSERT(0);
822       break;
823     }
824     break;
825
826     // ----------------------------------------------------------------------
827
828   case HYP_OK:
829     switch (event)
830     {
831     case ADD_HYP: {
832       algo = gen->GetAlgo((*_father), _subShape);
833       ASSERT(algo);
834       if (!algo->CheckHypothesis((*_father),_subShape, ret ))
835       {
836         if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
837           // ret should be fatal: anHyp was not added
838           ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
839       }
840       else if (!_father->IsUsedHypothesis(  anHyp, this ))
841         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
842
843       if (SMESH_Hypothesis::IsStatusFatal( ret ))
844       {
845         MESSAGE("do not add extra hypothesis");
846         meshDS->RemoveHypothesis(_subShape, anHyp);
847       }
848       else
849       {
850         modifiedHyp = true;
851       }
852       break;
853     }
854     case ADD_ALGO: {           //already existing algo : on father ?
855       algo = gen->GetAlgo((*_father), _subShape);
856       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
857         // check if algo changes
858         SMESH_HypoFilter f;
859         f.Init(   SMESH_HypoFilter::IsAlgo() );
860         f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
861         f.AndNot( SMESH_HypoFilter::Is( algo ));
862         const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
863         if (prevAlgo &&
864             string(algo->GetName()) != string(prevAlgo->GetName()) )
865           modifiedHyp = true;
866       }
867       else
868         SetAlgoState(MISSING_HYP);
869       break;
870     }
871     case REMOVE_HYP: {
872       algo = gen->GetAlgo((*_father), _subShape);
873       ASSERT(algo);
874       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
875         SetAlgoState(HYP_OK);
876       else
877         SetAlgoState(MISSING_HYP);
878       modifiedHyp = true;
879       break;
880     }
881     case REMOVE_ALGO: {         // perhaps a father algo applies ?
882       algo = gen->GetAlgo((*_father), _subShape);
883       if (algo == NULL)   // no more algo applying on subShape...
884       {
885         SetAlgoState(NO_ALGO);
886       }
887       else
888       {
889         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
890           // check if algo remains
891           if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
892             modifiedHyp = true;
893         }
894         else
895           SetAlgoState(MISSING_HYP);
896       }
897       break;
898     }
899     case MODIF_HYP: // hypothesis value may become bad
900     case ADD_FATHER_HYP: {  // new father hypothesis ?
901       algo = gen->GetAlgo((*_father), _subShape);
902       ASSERT(algo);
903       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
904       {
905         if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
906           modifiedHyp = true;
907       }
908       else
909         SetAlgoState(MISSING_HYP);
910       break;
911     }
912     case ADD_FATHER_ALGO: {
913       algo = gen->GetAlgo((*_father), _subShape);
914       if ( algo == anHyp ) { // a new algo on father
915         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
916           // check if algo changes
917           SMESH_HypoFilter f;
918           f.Init(   SMESH_HypoFilter::IsAlgo() );
919           f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
920           f.AndNot( SMESH_HypoFilter::Is( algo ));
921           const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
922           if (prevAlgo &&
923               string(algo->GetName()) != string(prevAlgo->GetName()) )
924             modifiedHyp = true;
925         }
926         else
927           SetAlgoState(MISSING_HYP);
928       }
929       break;
930     }
931     case REMOVE_FATHER_HYP: {
932       algo = gen->GetAlgo((*_father), _subShape);
933       ASSERT(algo);
934       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
935         // is there the same local hyp or maybe a new father algo applied?
936         if ( !GetSimilarAttached( _subShape, anHyp ) )
937           modifiedHyp = true;
938       }
939       else
940         SetAlgoState(MISSING_HYP);
941       break;
942     }
943     case REMOVE_FATHER_ALGO: {
944       algo = gen->GetAlgo((*_father), _subShape);
945       if (algo == NULL)  // no more applying algo on father
946       {
947         SetAlgoState(NO_ALGO);
948       }
949       else
950       {
951         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
952           // check if algo changes
953           if ( string(algo->GetName()) != string( anHyp->GetName()) )
954             modifiedHyp = true;
955         }
956         else
957           SetAlgoState(MISSING_HYP);
958       }
959       break;
960     }
961     default:
962       ASSERT(0);
963       break;
964     }
965     break;
966
967     // ----------------------------------------------------------------------
968
969   default:
970     ASSERT(0);
971     break;
972   }
973
974   // detect algorithm hiding
975   //
976   if ( ret == SMESH_Hypothesis::HYP_OK &&
977        ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
978        algo->GetName() == anHyp->GetName() )
979   {
980     // is algo hidden?
981     SMESH_Gen* gen = _father->GetGen();
982     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
983     for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
984       if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
985         if ( !upperAlgo->NeedDescretBoundary() )
986           ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
987     }
988     // is algo hiding?
989     if ( ret == SMESH_Hypothesis::HYP_OK && !algo->NeedDescretBoundary() ) {
990       map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
991       for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
992         if ( gen->GetAlgo( *_father, i_sm->second->_subShape ))
993           ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
994     }
995   }
996
997   bool stateChange = ( _algoState != oldAlgoState );
998
999   if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
1000     algo->SetEventListener( this );
1001
1002   NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
1003
1004   if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
1005     DeleteOwnListeners();
1006     SetIsAlwaysComputed( false );
1007     if (_subShape.ShapeType() == TopAbs_VERTEX ) {
1008       // restore default states
1009       _algoState = HYP_OK;
1010       _computeState = READY_TO_COMPUTE;
1011     }
1012   }
1013
1014   if (stateChange || modifiedHyp)
1015     ComputeStateEngine(MODIF_ALGO_STATE);
1016
1017   return ret;
1018 }
1019
1020 //=======================================================================
1021 //function : IsConform
1022 //purpose  : check if a conform mesh will be produced by the Algo
1023 //=======================================================================
1024
1025 bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
1026 {
1027 //  MESSAGE( "SMESH_subMesh::IsConform" );
1028   if ( !theAlgo ) return false;
1029
1030   // Suppose that theAlgo is applicable to _subShape, do not check it here
1031   //if ( !IsApplicableHypotesis( theAlgo )) return false;
1032
1033   // check only algo that doesn't NeedDescretBoundary(): because mesh made
1034   // on a sub-shape will be ignored by theAlgo
1035   if ( theAlgo->NeedDescretBoundary() ||
1036        !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
1037     return true;
1038
1039   SMESH_Gen* gen =_father->GetGen();
1040
1041   // only local algo is to be checked
1042   //if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
1043   if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
1044     return true;
1045
1046   // check algo attached to adjacent shapes
1047
1048   // loop on one level down sub-meshes
1049   TopoDS_Iterator itsub( _subShape );
1050   for (; itsub.More(); itsub.Next())
1051   {
1052     // loop on adjacent subShapes
1053     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
1054     for (; it.More(); it.Next())
1055     {
1056       const TopoDS_Shape& adjacent = it.Value();
1057       if ( _subShape.IsSame( adjacent )) continue;
1058       if ( adjacent.ShapeType() != _subShape.ShapeType())
1059         break;
1060
1061       // check algo attached to smAdjacent
1062       SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
1063       if (algo &&
1064           !algo->NeedDescretBoundary() &&
1065           algo->OnlyUnaryInput())
1066         return false; // NOT CONFORM MESH WILL BE PRODUCED
1067     }
1068   }
1069
1070   return true;
1071 }
1072
1073 //=============================================================================
1074 /*!
1075  *
1076  */
1077 //=============================================================================
1078
1079 void SMESH_subMesh::SetAlgoState(int state)
1080 {
1081   _algoState = state;
1082 }
1083
1084 //=============================================================================
1085 /*!
1086  *
1087  */
1088 //=============================================================================
1089 SMESH_Hypothesis::Hypothesis_Status
1090   SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
1091                                           SMESH_Hypothesis * anHyp)
1092 {
1093   SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
1094   //EAP: a wire (dim==1) should notify edges (dim==1)
1095   //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
1096   //if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
1097   {
1098     SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
1099     while ( smIt->more() ) {
1100       SMESH_Hypothesis::Hypothesis_Status ret2 =
1101         smIt->next()->AlgoStateEngine(event, anHyp);
1102       if ( ret2 > ret )
1103         ret = ret2;
1104     }
1105   }
1106   return ret;
1107 }
1108
1109 //=============================================================================
1110 /*!
1111  *
1112  */
1113 //=============================================================================
1114
1115 void SMESH_subMesh::CleanDependsOn()
1116 {
1117   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
1118   while ( smIt->more() )
1119     smIt->next()->ComputeStateEngine(CLEAN);
1120 }
1121
1122 //=============================================================================
1123 /*!
1124  *
1125  */
1126 //=============================================================================
1127
1128 void SMESH_subMesh::DumpAlgoState(bool isMain)
1129 {
1130         int dim = SMESH_Gen::GetShapeDim(_subShape);
1131 //   if (dim < 1) return;
1132         if (isMain)
1133         {
1134                 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1135
1136                 map < int, SMESH_subMesh * >::const_iterator itsub;
1137                 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1138                 {
1139                         SMESH_subMesh *sm = (*itsub).second;
1140                         sm->DumpAlgoState(false);
1141                 }
1142         }
1143         int type = _subShape.ShapeType();
1144         MESSAGE("dim = " << dim << " type of shape " << type);
1145         switch (_algoState)
1146         {
1147         case NO_ALGO:
1148                 MESSAGE(" AlgoState = NO_ALGO");
1149                 break;
1150         case MISSING_HYP:
1151                 MESSAGE(" AlgoState = MISSING_HYP");
1152                 break;
1153         case HYP_OK:
1154                 MESSAGE(" AlgoState = HYP_OK");
1155                 break;
1156         }
1157         switch (_computeState)
1158         {
1159         case NOT_READY:
1160                 MESSAGE(" ComputeState = NOT_READY");
1161                 break;
1162         case READY_TO_COMPUTE:
1163                 MESSAGE(" ComputeState = READY_TO_COMPUTE");
1164                 break;
1165         case COMPUTE_OK:
1166                 MESSAGE(" ComputeState = COMPUTE_OK");
1167                 break;
1168         case FAILED_TO_COMPUTE:
1169                 MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
1170                 break;
1171         }
1172 }
1173
1174 //================================================================================
1175 /*!
1176  * \brief Remove nodes and elements bound to submesh
1177   * \param subMesh - submesh containing nodes and elements
1178  */
1179 //================================================================================
1180
1181 static void cleanSubMesh( SMESH_subMesh * subMesh )
1182 {
1183   if (subMesh) {
1184     if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
1185       SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
1186       SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
1187       while (ite->more()) {
1188         const SMDS_MeshElement * elt = ite->next();
1189         //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
1190         //meshDS->RemoveElement(elt);
1191         meshDS->RemoveFreeElement(elt, subMeshDS);
1192       }
1193
1194       SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
1195       while (itn->more()) {
1196         const SMDS_MeshNode * node = itn->next();
1197         //MESSAGE( " RM node: "<<node->GetID());
1198         if ( node->NbInverseElements() == 0 )
1199           meshDS->RemoveFreeNode(node, subMeshDS);
1200         else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
1201           meshDS->RemoveNode(node);
1202       }
1203     }
1204   }
1205 }
1206
1207 //=============================================================================
1208 /*!
1209  *
1210  */
1211 //=============================================================================
1212
1213 bool SMESH_subMesh::ComputeStateEngine(int event)
1214 {
1215   _computeError.reset();
1216
1217   //MESSAGE("SMESH_subMesh::ComputeStateEngine");
1218   //SCRUTE(_computeState);
1219   //SCRUTE(event);
1220
1221   if (_subShape.ShapeType() == TopAbs_VERTEX)
1222   {
1223     _computeState = READY_TO_COMPUTE;
1224     SMESHDS_SubMesh* smDS = GetSubMeshDS();
1225     if ( smDS && smDS->NbNodes() ) {
1226       if ( event == CLEAN ) {
1227         CleanDependants();
1228         cleanSubMesh( this );
1229       }
1230       else
1231         _computeState = COMPUTE_OK;
1232     }
1233     else if ( event == COMPUTE && !_alwaysComputed ) {
1234       const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
1235       gp_Pnt P = BRep_Tool::Pnt(V);
1236       if ( SMDS_MeshNode * n = _father->GetMeshDS()->AddNode(P.X(), P.Y(), P.Z()) ) {
1237         _father->GetMeshDS()->SetNodeOnVertex(n,_Id);
1238         _computeState = COMPUTE_OK;
1239       }
1240     }
1241     if ( event == MODIF_ALGO_STATE )
1242       CleanDependants();
1243     return true;
1244   }
1245   SMESH_Gen *gen = _father->GetGen();
1246   SMESH_Algo *algo = 0;
1247   bool ret = true;
1248   SMESH_Hypothesis::Hypothesis_Status hyp_status;
1249   //algo_state oldAlgoState = (algo_state) GetAlgoState();
1250
1251   switch (_computeState)
1252   {
1253
1254     // ----------------------------------------------------------------------
1255
1256   case NOT_READY:
1257     switch (event)
1258     {
1259     case MODIF_ALGO_STATE:
1260       algo = gen->GetAlgo((*_father), _subShape);
1261       if (algo && !algo->NeedDescretBoundary())
1262         CleanDependsOn(); // clean sub-meshes with event CLEAN
1263       if ( _algoState == HYP_OK )
1264         _computeState = READY_TO_COMPUTE;
1265       break;
1266     case COMPUTE:               // nothing to do
1267       break;
1268     case CLEAN:
1269       CleanDependants();
1270       RemoveSubMeshElementsAndNodes();
1271       break;
1272     case SUBMESH_COMPUTED:      // nothing to do
1273       break;
1274     case SUBMESH_RESTORED:
1275       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1276       break;
1277     case MESH_ENTITY_REMOVED:
1278       break;
1279     case CHECK_COMPUTE_STATE:
1280       if ( IsMeshComputed() )
1281         _computeState = COMPUTE_OK;
1282       break;
1283     default:
1284       ASSERT(0);
1285       break;
1286     }
1287     break;
1288
1289     // ----------------------------------------------------------------------
1290
1291   case READY_TO_COMPUTE:
1292     switch (event)
1293     {
1294     case MODIF_ALGO_STATE:
1295       _computeState = NOT_READY;
1296       algo = gen->GetAlgo((*_father), _subShape);
1297       if (algo)
1298       {
1299         if (!algo->NeedDescretBoundary())
1300           CleanDependsOn(); // clean sub-meshes with event CLEAN
1301         if ( _algoState == HYP_OK )
1302           _computeState = READY_TO_COMPUTE;
1303       }
1304       break;
1305     case COMPUTE:
1306       {
1307         algo = gen->GetAlgo((*_father), _subShape);
1308         ASSERT(algo);
1309         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1310         if (!ret)
1311         {
1312           MESSAGE("***** verify compute state *****");
1313           _computeState = NOT_READY;
1314           SetAlgoState(MISSING_HYP);
1315           break;
1316         }
1317         TopoDS_Shape shape = _subShape;
1318         // check submeshes needed
1319         if (_father->HasShapeToMesh() ) {
1320           bool subComputed = false;
1321           if (!algo->OnlyUnaryInput())
1322             shape = GetCollection( gen, algo, subComputed );
1323           else
1324             subComputed = SubMeshesComputed();
1325           ret = ( algo->NeedDescretBoundary() ? subComputed :
1326                   ( !subComputed || _father->IsNotConformAllowed() ));
1327           if (!ret) {
1328             _computeState = FAILED_TO_COMPUTE;
1329             if ( !algo->NeedDescretBoundary() )
1330               _computeError =
1331                 SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
1332                                         "Unexpected computed submesh",algo);
1333             break;
1334           }
1335         }
1336         // compute
1337 //         CleanDependants(); for "UseExisting_*D" algos
1338 //         RemoveSubMeshElementsAndNodes();
1339         ret = false;
1340         _computeState = FAILED_TO_COMPUTE;
1341         _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
1342         try {
1343 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
1344           OCC_CATCH_SIGNALS;
1345 #endif
1346           algo->InitComputeError();
1347           MemoryReserve aMemoryReserve;
1348           SMDS_Mesh::CheckMemory();
1349           if ( !_father->HasShapeToMesh() ) // no shape
1350           {
1351             SMESH_MesherHelper helper( *_father );
1352             helper.SetSubShape( shape );
1353             helper.SetElementsOnShape( true );
1354             ret = algo->Compute(*_father, &helper );
1355           }
1356           else
1357           {
1358             ret = algo->Compute((*_father), shape);
1359           }
1360           if ( !ret )
1361             _computeError = algo->GetComputeError();
1362         }
1363         catch ( std::bad_alloc& exc ) {
1364           printf("std::bad_alloc thrown inside algo->Compute()\n");
1365           if ( _computeError ) {
1366             _computeError->myName = COMPERR_MEMORY_PB;
1367             //_computeError->myComment = exc.what();
1368           }
1369           cleanSubMesh( this );
1370           throw exc;
1371         }
1372         catch ( Standard_OutOfMemory& exc ) {
1373           printf("Standard_OutOfMemory thrown inside algo->Compute()\n");
1374           if ( _computeError ) {
1375             _computeError->myName = COMPERR_MEMORY_PB;
1376             //_computeError->myComment = exc.what();
1377           }
1378           cleanSubMesh( this );
1379           throw std::bad_alloc();
1380         }
1381         catch (Standard_Failure& ex) {
1382           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
1383           _computeError->myName    = COMPERR_OCC_EXCEPTION;
1384           _computeError->myComment += ex.DynamicType()->Name();
1385           if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
1386             _computeError->myComment += ": ";
1387             _computeError->myComment += ex.GetMessageString();
1388           }
1389         }
1390         catch ( SALOME_Exception& S_ex ) {
1391           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
1392           _computeError->myName    = COMPERR_SLM_EXCEPTION;
1393           _computeError->myComment = S_ex.what();
1394         }
1395         catch ( std::exception& exc ) {
1396           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
1397           _computeError->myName    = COMPERR_STD_EXCEPTION;
1398           _computeError->myComment = exc.what();
1399         }
1400         catch ( ... ) {
1401           if ( _computeError )
1402             _computeError->myName = COMPERR_EXCEPTION;
1403           else
1404             ret = false;
1405         }
1406         if (ret && !_alwaysComputed) { // check if anything was built
1407           ret = ( GetSubMeshDS() && ( GetSubMeshDS()->NbElements() || GetSubMeshDS()->NbNodes() ));
1408         }
1409         bool isComputeErrorSet = !CheckComputeError( algo, shape );
1410         if (!ret && !isComputeErrorSet)
1411         {
1412           // Set _computeError
1413           if ( !_computeError )
1414             _computeError = SMESH_ComputeError::New();
1415           if ( _computeError->IsOK() )
1416             _computeError->myName = COMPERR_ALGO_FAILED;
1417           _computeState = FAILED_TO_COMPUTE;
1418         }
1419         if (ret)
1420         {
1421           _computeError.reset();
1422         }
1423         UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
1424       }
1425       break;
1426     case CLEAN:
1427       CleanDependants();
1428       RemoveSubMeshElementsAndNodes();
1429       _computeState = NOT_READY;
1430       algo = gen->GetAlgo((*_father), _subShape);
1431       if (algo)
1432       {
1433         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1434         if (ret)
1435           _computeState = READY_TO_COMPUTE;
1436         else
1437           SetAlgoState(MISSING_HYP);
1438       }
1439       break;
1440     case SUBMESH_COMPUTED:      // nothing to do
1441       break;
1442     case SUBMESH_RESTORED:
1443       // check if a mesh is already computed that may
1444       // happen after retrieval from a file
1445       ComputeStateEngine( CHECK_COMPUTE_STATE );
1446       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1447       algo = gen->GetAlgo(*_father, _subShape);
1448       if (algo) algo->SubmeshRestored( this );
1449       break;
1450     case MESH_ENTITY_REMOVED:
1451       break;
1452     case CHECK_COMPUTE_STATE:
1453       if ( IsMeshComputed() )
1454         _computeState = COMPUTE_OK;
1455       break;
1456     default:
1457       ASSERT(0);
1458       break;
1459     }
1460     break;
1461
1462     // ----------------------------------------------------------------------
1463
1464   case COMPUTE_OK:
1465     switch (event)
1466     {
1467     case MODIF_ALGO_STATE:
1468       ComputeStateEngine( CLEAN );
1469       algo = gen->GetAlgo((*_father), _subShape);
1470       if (algo && !algo->NeedDescretBoundary())
1471         CleanDependsOn(); // clean sub-meshes with event CLEAN
1472       break;
1473     case COMPUTE:               // nothing to do
1474       break;
1475     case CLEAN:
1476       CleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
1477       RemoveSubMeshElementsAndNodes();
1478       _computeState = NOT_READY;
1479       if ( _algoState == HYP_OK )
1480         _computeState = READY_TO_COMPUTE;
1481       break;
1482     case SUBMESH_COMPUTED:      // nothing to do
1483       break;
1484     case SUBMESH_RESTORED:
1485       ComputeStateEngine( CHECK_COMPUTE_STATE );
1486       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1487       algo = gen->GetAlgo(*_father, _subShape);
1488       if (algo) algo->SubmeshRestored( this );
1489       break;
1490     case MESH_ENTITY_REMOVED:
1491       UpdateDependantsState( CHECK_COMPUTE_STATE );
1492       ComputeStateEngine( CHECK_COMPUTE_STATE );
1493       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1494       break;
1495     case CHECK_COMPUTE_STATE:
1496       if ( !IsMeshComputed() )
1497         if (_algoState == HYP_OK)
1498           _computeState = READY_TO_COMPUTE;
1499         else
1500           _computeState = NOT_READY;
1501       break;
1502     default:
1503       ASSERT(0);
1504       break;
1505     }
1506     break;
1507
1508     // ----------------------------------------------------------------------
1509
1510   case FAILED_TO_COMPUTE:
1511     switch (event)
1512     {
1513     case MODIF_ALGO_STATE:
1514       algo = gen->GetAlgo((*_father), _subShape);
1515       if (algo && !algo->NeedDescretBoundary())
1516         CleanDependsOn(); // clean sub-meshes with event CLEAN
1517       if (_algoState == HYP_OK)
1518         _computeState = READY_TO_COMPUTE;
1519       else
1520         _computeState = NOT_READY;
1521       break;
1522     case COMPUTE:      // nothing to do
1523       break;
1524     case CLEAN:
1525       CleanDependants(); // submeshes dependent on me should be cleaned as well
1526       RemoveSubMeshElementsAndNodes();
1527       break;
1528     case SUBMESH_COMPUTED:      // allow retry compute
1529       if (_algoState == HYP_OK)
1530         _computeState = READY_TO_COMPUTE;
1531       else
1532         _computeState = NOT_READY;
1533       break;
1534     case SUBMESH_RESTORED:
1535       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
1536       break;
1537     case MESH_ENTITY_REMOVED:
1538       break;
1539     case CHECK_COMPUTE_STATE:
1540       if ( IsMeshComputed() )
1541         _computeState = COMPUTE_OK;
1542       else
1543         if (_algoState == HYP_OK)
1544           _computeState = READY_TO_COMPUTE;
1545         else
1546           _computeState = NOT_READY;
1547       break;
1548     default:
1549       ASSERT(0);
1550       break;
1551     }
1552     break;
1553
1554     // ----------------------------------------------------------------------
1555   default:
1556     ASSERT(0);
1557     break;
1558   }
1559
1560   NotifyListenersOnEvent( event, COMPUTE_EVENT );
1561
1562   return ret;
1563 }
1564
1565 //=======================================================================
1566 /*!
1567  * \brief Update compute_state by _computeError and send proper events to
1568  * dependent submeshes
1569   * \retval bool - true if _computeError is NOT set
1570  */
1571 //=======================================================================
1572
1573 bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape)
1574 {
1575   bool noErrors = true;
1576
1577   if ( !theShape.IsNull() )
1578   {
1579     // Check state of submeshes
1580     if ( !theAlgo->NeedDescretBoundary())
1581     {
1582       SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
1583       while ( smIt->more() )
1584         if ( !smIt->next()->CheckComputeError( theAlgo ))
1585           noErrors = false;
1586     }
1587
1588     // Check state of neighbours
1589     if ( !theAlgo->OnlyUnaryInput() &&
1590          theShape.ShapeType() == TopAbs_COMPOUND &&
1591          !theShape.IsSame( _subShape ))
1592     {
1593       for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) {
1594         SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() );
1595         if ( sm != this ) {
1596           if ( !sm->CheckComputeError( theAlgo ))
1597             noErrors = false;
1598           UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
1599         }
1600       }
1601     }
1602   }
1603   {
1604     // Check my state
1605     if ( !_computeError || _computeError->IsOK() )
1606     {
1607       _computeState = COMPUTE_OK;
1608     }
1609     else
1610     {
1611       if ( !_computeError->myAlgo )
1612         _computeError->myAlgo = theAlgo;
1613
1614       // Show error
1615       SMESH_Comment text;
1616       text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error ";
1617       if (_computeError->IsCommon() )
1618         text << _computeError->CommonName();
1619       else
1620         text << _computeError->myName;
1621       if ( _computeError->myComment.size() > 0 )
1622         text << " \"" << _computeError->myComment << "\"";
1623
1624 #ifdef _DEBUG_
1625       cout << text << endl;
1626       // Show vertices location of a failed shape
1627       TopTools_IndexedMapOfShape vMap;
1628       TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
1629       cout << "Subshape vertices " << ( vMap.Extent()>10 ? "(first 10):" : ":") << endl;
1630       for ( int iv = 1; iv <= vMap.Extent() && iv < 11; ++iv ) {
1631         gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
1632         cout << "#" << _father->GetMeshDS()->ShapeToIndex( vMap( iv )) << " ";
1633         cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
1634       }
1635 #else
1636       INFOS( text );
1637 #endif
1638       _computeState = FAILED_TO_COMPUTE;
1639       noErrors = false;
1640     }
1641   }
1642   return noErrors;
1643 }
1644
1645 //=======================================================================
1646 //function : ApplyToCollection
1647 //purpose  : Apply theAlgo to all subshapes in theCollection
1648 //=======================================================================
1649
1650 bool SMESH_subMesh::ApplyToCollection (SMESH_Algo*         theAlgo,
1651                                        const TopoDS_Shape& theCollection)
1652 {
1653   MESSAGE("SMESH_subMesh::ApplyToCollection");
1654   ASSERT ( !theAlgo->NeedDescretBoundary() );
1655
1656   if ( _computeError )
1657     _computeError->myName = COMPERR_OK;
1658
1659   bool ok = theAlgo->Compute( *_father, theCollection );
1660
1661   // set _computeState of subshapes
1662   TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
1663   for ( ; anExplorer.More(); anExplorer.Next() )
1664   {
1665     if ( SMESH_subMesh* subMesh = _father->GetSubMeshContaining( anExplorer.Current() ))
1666     {
1667       bool localOK = subMesh->CheckComputeError( theAlgo );
1668       if ( !ok && localOK && !subMesh->IsMeshComputed() )
1669       {
1670         subMesh->_computeError = theAlgo->GetComputeError();
1671         if ( subMesh->_computeError->IsOK() )
1672           _computeError = SMESH_ComputeError::New(COMPERR_ALGO_FAILED);
1673         localOK = CheckComputeError( theAlgo );
1674       }
1675       if ( localOK )
1676         subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
1677       subMesh->UpdateSubMeshState( localOK ? COMPUTE_OK : FAILED_TO_COMPUTE );
1678     }
1679   }
1680
1681   return true;
1682 }
1683
1684
1685 //=======================================================================
1686 //function : UpdateSubMeshState
1687 //purpose  :
1688 //=======================================================================
1689
1690 void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
1691 {
1692   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
1693   while ( smIt->more() )
1694     smIt->next()->_computeState = theState;
1695 }
1696
1697 //=======================================================================
1698 //function : ComputeSubMeshStateEngine
1699 //purpose  :
1700 //=======================================================================
1701
1702 void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
1703 {
1704   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
1705   while ( smIt->more() )
1706     smIt->next()->ComputeStateEngine(event);
1707 }
1708
1709 //=======================================================================
1710 //function : UpdateDependantsState
1711 //purpose  :
1712 //=======================================================================
1713
1714 void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
1715 {
1716   //MESSAGE("SMESH_subMesh::UpdateDependantsState");
1717   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1718   for (; it.More(); it.Next())
1719   {
1720     const TopoDS_Shape& ancestor = it.Value();
1721     SMESH_subMesh *aSubMesh =
1722       _father->GetSubMeshContaining(ancestor);
1723     if (aSubMesh)
1724       aSubMesh->ComputeStateEngine( theEvent );
1725   }
1726 }
1727
1728 //=============================================================================
1729 /*!
1730  *
1731  */
1732 //=============================================================================
1733
1734 void SMESH_subMesh::CleanDependants()
1735 {
1736   int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
1737
1738   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1739   for (; it.More(); it.Next())
1740   {
1741     const TopoDS_Shape& ancestor = it.Value();
1742     if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
1743       // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
1744       // will erase mesh on other shapes in a compound
1745       if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
1746         SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
1747         if (aSubMesh)
1748           aSubMesh->ComputeStateEngine(CLEAN);
1749       }
1750     }
1751   }
1752 }
1753
1754 //=============================================================================
1755 /*!
1756  *
1757  */
1758 //=============================================================================
1759
1760 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
1761 {
1762   //SCRUTE(_subShape.ShapeType());
1763
1764   cleanSubMesh( this );
1765
1766   // algo may bind a submesh not to _subShape, eg 3D algo
1767   // sets nodes on SHELL while _subShape may be SOLID
1768
1769   int dim = SMESH_Gen::GetShapeDim( _subShape );
1770   int type = _subShape.ShapeType() + 1;
1771   for ( ; type <= TopAbs_EDGE; type++) {
1772     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1773     {
1774       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1775       for ( ; exp.More(); exp.Next() )
1776         cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
1777     }
1778     else
1779       break;
1780   }
1781 }
1782
1783 //=======================================================================
1784 //function : GetCollection
1785 //purpose  : return a shape containing all sub-shapes of the MainShape that can be
1786 //           meshed at once along with _subShape
1787 //=======================================================================
1788
1789 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen,
1790                                           SMESH_Algo* theAlgo,
1791                                           bool &      theSubComputed)
1792 {
1793   MESSAGE("SMESH_subMesh::GetCollection");
1794
1795   theSubComputed = SubMeshesComputed();
1796
1797   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
1798
1799   if ( mainShape.IsSame( _subShape ))
1800     return _subShape;
1801
1802   const bool ignoreAuxiliaryHyps = false;
1803   list<const SMESHDS_Hypothesis*> aUsedHyp =
1804     theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
1805
1806   // put in a compound all shapes with the same hypothesis assigned
1807   // and a good ComputState
1808
1809   TopoDS_Compound aCompound;
1810   BRep_Builder aBuilder;
1811   aBuilder.MakeCompound( aCompound );
1812
1813   TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
1814   for ( ; anExplorer.More(); anExplorer.Next() )
1815   {
1816     const TopoDS_Shape& S = anExplorer.Current();
1817     SMESH_subMesh* subMesh = _father->GetSubMesh( S );
1818     if ( subMesh == this )
1819     {
1820       aBuilder.Add( aCompound, S );
1821     }
1822     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
1823     {
1824       SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
1825       if (anAlgo == theAlgo &&
1826           anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
1827         aBuilder.Add( aCompound, S );
1828       if ( !subMesh->SubMeshesComputed() )
1829         theSubComputed = false;
1830     }
1831   }
1832
1833   return aCompound;
1834 }
1835
1836 //=======================================================================
1837 //function : GetSimilarAttached
1838 //purpose  : return a hypothesis attached to theShape.
1839 //           If theHyp is provided, similar but not same hypotheses
1840 //           is returned; else only applicable ones having theHypType
1841 //           is returned
1842 //=======================================================================
1843
1844 const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&      theShape,
1845                                                           const SMESH_Hypothesis * theHyp,
1846                                                           const int                theHypType)
1847 {
1848   SMESH_HypoFilter hypoKind;
1849   hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
1850   if ( theHyp ) {
1851     hypoKind.And   ( hypoKind.HasDim( theHyp->GetDim() ));
1852     hypoKind.AndNot( hypoKind.Is( theHyp ));
1853     if ( theHyp->IsAuxiliary() )
1854       hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
1855     else
1856       hypoKind.AndNot( hypoKind.IsAuxiliary());
1857   }
1858   else {
1859     hypoKind.And( hypoKind.IsApplicableTo( theShape ));
1860   }
1861
1862   return _father->GetHypothesis( theShape, hypoKind, false );
1863 }
1864
1865 //=======================================================================
1866 //function : CheckConcurentHypothesis
1867 //purpose  : check if there are several applicable hypothesis attached to
1868 //           ancestors
1869 //=======================================================================
1870
1871 SMESH_Hypothesis::Hypothesis_Status
1872   SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
1873 {
1874   MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
1875
1876   // is there local hypothesis on me?
1877   if ( GetSimilarAttached( _subShape, 0, theHypType ) )
1878     return SMESH_Hypothesis::HYP_OK;
1879
1880
1881   TopoDS_Shape aPrevWithHyp;
1882   const SMESH_Hypothesis* aPrevHyp = 0;
1883   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1884   for (; it.More(); it.Next())
1885   {
1886     const TopoDS_Shape& ancestor = it.Value();
1887     const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
1888     if ( hyp )
1889     {
1890       if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
1891       {
1892         aPrevWithHyp = ancestor;
1893         aPrevHyp     = hyp;
1894       }
1895       else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
1896         return SMESH_Hypothesis::HYP_CONCURENT;
1897       else
1898         return SMESH_Hypothesis::HYP_OK;
1899     }
1900   }
1901   return SMESH_Hypothesis::HYP_OK;
1902 }
1903
1904 //================================================================================
1905 /*!
1906  * \brief Sets an event listener and its data to a submesh
1907  * \param listener - the listener to store
1908  * \param data - the listener data to store
1909  * \param where - the submesh to store the listener and it's data
1910  * \param deleteListener - if true then the listener will be deleted as
1911  *        it is removed from where submesh
1912  * 
1913  * It remembers the submesh where it puts the listener in order to delete
1914  * them when HYP_OK algo_state is lost
1915  * After being set, event listener is notified on each event of where submesh.
1916  */
1917 //================================================================================
1918
1919 void SMESH_subMesh::SetEventListener(EventListener*     listener,
1920                                      EventListenerData* data,
1921                                      SMESH_subMesh*     where)
1922 {
1923   if ( listener && where ) {
1924     where->SetEventListener( listener, data );
1925     myOwnListeners.push_back( make_pair( where, listener ));
1926   }
1927 }
1928
1929 //================================================================================
1930 /*!
1931  * \brief Sets an event listener and its data to a submesh
1932  * \param listener - the listener to store
1933  * \param data - the listener data to store
1934  * 
1935  * After being set, event listener is notified on each event of a submesh.
1936  */
1937 //================================================================================
1938
1939 void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data)
1940 {
1941   map< EventListener*, EventListenerData* >::iterator l_d =
1942     myEventListeners.find( listener );
1943   if ( l_d != myEventListeners.end() ) {
1944     EventListenerData* curData = l_d->second;
1945     if ( curData && curData != data && curData->IsDeletable() )
1946       delete curData;
1947     l_d->second = data;
1948   }
1949   else 
1950     myEventListeners.insert( make_pair( listener, data ));
1951 }
1952
1953 //================================================================================
1954 /*!
1955  * \brief Return an event listener data
1956  * \param listener - the listener whose data is
1957  * \retval EventListenerData* - found data, maybe NULL
1958  */
1959 //================================================================================
1960
1961 EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
1962 {
1963   map< EventListener*, EventListenerData* >::const_iterator l_d =
1964     myEventListeners.find( listener );
1965   if ( l_d != myEventListeners.end() )
1966     return l_d->second;
1967   return 0;
1968 }
1969
1970 //================================================================================
1971 /*!
1972  * \brief Notify stored event listeners on the occured event
1973  * \param event - algo_event or compute_event itself
1974  * \param eventType - algo_event or compute_event
1975  * \param subMesh - the submesh where the event occures
1976  * \param data - listener data stored in the subMesh
1977  * \param hyp - hypothesis, if eventType is algo_event
1978  */
1979 //================================================================================
1980
1981 void SMESH_subMesh::NotifyListenersOnEvent( const int         event,
1982                                             const event_type  eventType,
1983                                             SMESH_Hypothesis* hyp)
1984 {
1985   map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin();
1986   for ( ; l_d != myEventListeners.end(); ++l_d )
1987     l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp );
1988 }
1989
1990 //================================================================================
1991 /*!
1992  * \brief Unregister the listener and delete listener's data
1993  * \param listener - the event listener
1994  */
1995 //================================================================================
1996
1997 void SMESH_subMesh::DeleteEventListener(EventListener* listener)
1998 {
1999   map< EventListener*, EventListenerData* >::iterator l_d =
2000     myEventListeners.find( listener );
2001   if ( l_d != myEventListeners.end() ) {
2002     if ( l_d->first  && l_d->first->IsDeletable() )  delete l_d->first;
2003     if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second;
2004     myEventListeners.erase( l_d );
2005   }
2006 }
2007
2008 //================================================================================
2009 /*!
2010  * \brief Delete event listeners depending on algo of this submesh
2011  */
2012 //================================================================================
2013
2014 void SMESH_subMesh::DeleteOwnListeners()
2015 {
2016   list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l;
2017   for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l)
2018     sm_l->first->DeleteEventListener( sm_l->second );
2019   myOwnListeners.clear();
2020 }
2021
2022 //================================================================================
2023 /*!
2024  * \brief Do something on a certain event
2025  * \param event - algo_event or compute_event itself
2026  * \param eventType - algo_event or compute_event
2027  * \param subMesh - the submesh where the event occures
2028  * \param data - listener data stored in the subMesh
2029  * \param hyp - hypothesis, if eventType is algo_event
2030  * 
2031  * The base implementation translates CLEAN event to the subMesh
2032  * stored in listener data. Also it sends SUBMESH_COMPUTED event in case of
2033  * successful COMPUTE event.
2034  */
2035 //================================================================================
2036
2037 void SMESH_subMeshEventListener::ProcessEvent(const int          event,
2038                                               const int          eventType,
2039                                               SMESH_subMesh*     subMesh,
2040                                               EventListenerData* data,
2041                                               const SMESH_Hypothesis*  /*hyp*/)
2042 {
2043   if ( data && !data->mySubMeshes.empty() &&
2044        eventType == SMESH_subMesh::COMPUTE_EVENT)
2045   {
2046     ASSERT( data->mySubMeshes.front() != subMesh );
2047     list<SMESH_subMesh*>::iterator smIt = data->mySubMeshes.begin();
2048     list<SMESH_subMesh*>::iterator smEnd = data->mySubMeshes.end();
2049     switch ( event ) {
2050     case SMESH_subMesh::CLEAN:
2051       for ( ; smIt != smEnd; ++ smIt)
2052         (*smIt)->ComputeStateEngine( event );
2053       break;
2054     case SMESH_subMesh::COMPUTE:
2055       if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
2056         for ( ; smIt != smEnd; ++ smIt)
2057           (*smIt)->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
2058       break;
2059     default:;
2060     }
2061   }
2062 }
2063
2064 namespace {
2065
2066   //================================================================================
2067   /*!
2068    * \brief Iterator over submeshes and optionally prepended or appended one
2069    */
2070   //================================================================================
2071
2072   struct _Iterator : public SMDS_Iterator<SMESH_subMesh*>
2073   {
2074     _Iterator(SMDS_Iterator<SMESH_subMesh*>* subIt,
2075               SMESH_subMesh*                 prepend,
2076               SMESH_subMesh*                 append): myIt(subIt),myAppend(append)
2077     {
2078       myCur = prepend ? prepend : myIt->more() ? myIt->next() : 0;
2079     }
2080     /// Return true if and only if there are other object in this iterator
2081     virtual bool more()
2082     {
2083       return myCur;
2084     }
2085     /// Return the current object and step to the next one
2086     virtual SMESH_subMesh* next()
2087     {
2088       SMESH_subMesh* res = myCur;
2089       if ( myIt->more() ) { myCur = myIt->next(); }
2090       else                { myCur = myAppend; myAppend = 0; }
2091       return res;
2092     }
2093     /// ~
2094     ~_Iterator()
2095     { delete myIt; }
2096     ///
2097     SMESH_subMesh                 *myAppend, *myCur;
2098     SMDS_Iterator<SMESH_subMesh*> *myIt;
2099   };
2100 }
2101
2102 //================================================================================
2103 /*!
2104  * \brief  Return iterator on the submeshes this one depends on
2105   * \param includeSelf - this submesh to be returned also
2106   * \param reverse - if true, complex shape submeshes go first
2107  */
2108 //================================================================================
2109
2110 SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeSelf,
2111                                                              const bool reverse)
2112 {
2113   SMESH_subMesh *prepend=0, *append=0;
2114   if ( includeSelf ) {
2115     if ( reverse ) prepend = this;
2116     else            append = this;
2117   }
2118   typedef map < int, SMESH_subMesh * > TMap;
2119   if ( reverse )
2120   {
2121     return SMESH_subMeshIteratorPtr
2122       ( new _Iterator( new SMDS_mapReverseIterator<TMap>( DependsOn() ), prepend, append ));
2123   }
2124   {
2125     return SMESH_subMeshIteratorPtr
2126       ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
2127   }
2128 }