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