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