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