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