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