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