Salome HOME
SMH: Version ported on new OCT6.1.1
[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_SHELL:
486   case TopAbs_SOLID:
487     return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
488 //   case TopAbs_WIRE:
489 //   case TopAbs_COMPSOLID:
490 //   case TopAbs_COMPOUND:
491   default:;
492   }
493   return false;
494 }
495
496 //=============================================================================
497 /*!
498  *
499  */
500 //=============================================================================
501
502 SMESH_Hypothesis::Hypothesis_Status
503   SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
504 {
505   //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
506   //SCRUTE(_algoState);
507   //SCRUTE(event);
508
509   // **** les retour des evenement shape sont significatifs
510   // (add ou remove fait ou non)
511   // le retour des evenement father n'indiquent pas que add ou remove fait
512
513   SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
514
515   int dim = SMESH_Gen::GetShapeDim(_subShape);
516
517   if (dim < 1)
518   {
519     _algoState = HYP_OK;
520     if (event == ADD_HYP || event == ADD_ALGO)
521       return SMESH_Hypothesis::HYP_BAD_DIM; // do not allow to assign any hyp
522     else
523       return SMESH_Hypothesis::HYP_OK;
524   }
525
526   SMESH_Gen* gen =_father->GetGen();
527 //  bool ret = false;
528   int oldAlgoState = _algoState;
529   bool modifiedHyp = false;  // if set to true, force event MODIF_ALGO_STATE
530                              // in ComputeStateEngine
531
532   // ----------------------
533   // check mesh conformity
534   // ----------------------
535   if (event == ADD_ALGO)
536   {
537     if (IsApplicableHypotesis( anHyp ) &&
538         !_father->IsNotConformAllowed() &&
539         !IsConform( static_cast< SMESH_Algo* >( anHyp )))
540       return SMESH_Hypothesis::HYP_NOTCONFORM;
541   }
542
543   // ----------------------------------
544   // add a hypothesis to DS if possible
545   // ----------------------------------
546   if (event == ADD_HYP || event == ADD_ALGO)
547   {
548     if ( ! CanAddHypothesis( anHyp ))
549       return SMESH_Hypothesis::HYP_BAD_DIM;
550
551     if ( /*!anHyp->IsAuxiliary() &&*/ GetSimilarAttached( _subShape, anHyp ) )
552       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
553
554     if ( !_meshDS->AddHypothesis(_subShape, anHyp))
555       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
556
557     // Serve Propagation of 1D hypothesis
558     if (event == ADD_HYP) {
559       bool isPropagationOk = true;
560       bool isPropagationHyp = ( strcmp( "Propagation", anHyp->GetName() ) == 0 );
561
562       if ( isPropagationHyp ) {
563         TopExp_Explorer exp (_subShape, TopAbs_EDGE);
564         TopTools_MapOfShape aMap;
565         for (; exp.More(); exp.Next()) {
566           if (aMap.Add(exp.Current())) {
567             if (!_father->BuildPropagationChain(exp.Current())) {
568               isPropagationOk = false;
569             }
570           }
571         }
572       }
573       else if (anHyp->GetDim() == 1) { // Only 1D hypothesis can be propagated
574         TopExp_Explorer exp (_subShape, TopAbs_EDGE);
575         TopTools_MapOfShape aMap;
576         for (; exp.More(); exp.Next()) {
577           if (aMap.Add(exp.Current())) {
578             TopoDS_Shape aMainEdge;
579             if (_father->IsPropagatedHypothesis(exp.Current(), aMainEdge)) {
580               isPropagationOk = _father->RebuildPropagationChains();
581             } else if (_father->IsPropagationHypothesis(exp.Current())) {
582               isPropagationOk = _father->BuildPropagationChain(exp.Current());
583             } else {
584             }
585           }
586         }
587       } else {
588       }
589
590       if ( isPropagationOk ) {
591         if ( isPropagationHyp )
592           return ret; // nothing more to do for "Propagation" hypothesis
593       }
594       else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
595         ret = SMESH_Hypothesis::HYP_CONCURENT;
596       }
597     } // Serve Propagation of 1D hypothesis
598   }
599
600   // --------------------------
601   // remove a hypothesis from DS
602   // --------------------------
603   if (event == REMOVE_HYP || event == REMOVE_ALGO)
604   {
605     if (!_meshDS->RemoveHypothesis(_subShape, anHyp))
606       return SMESH_Hypothesis::HYP_OK; // nothing changes
607
608     // Serve Propagation of 1D hypothesis
609     if (event == REMOVE_HYP)
610     {
611       bool isPropagationOk = true;
612       SMESH_HypoFilter propagFilter( SMESH_HypoFilter::HasName( "Propagation" ));
613       bool isPropagationHyp = propagFilter.IsOk( anHyp, _subShape );
614
615       if ( isPropagationHyp )
616       {
617         TopExp_Explorer exp (_subShape, TopAbs_EDGE);
618         TopTools_MapOfShape aMap;
619         for (; exp.More(); exp.Next()) {
620           if (aMap.Add(exp.Current()) &&
621               !_father->GetHypothesis( exp.Current(), propagFilter, true )) {
622             // no more Propagation on the current edge
623             if (!_father->RemovePropagationChain(exp.Current())) {
624               return SMESH_Hypothesis::HYP_UNKNOWN_FATAL;
625             }
626           }
627         }
628         // rebuild propagation chains, because removing one
629         // chain can resolve concurention, existing before
630         isPropagationOk = _father->RebuildPropagationChains();
631       }
632       else if (anHyp->GetDim() == 1) // Only 1D hypothesis can be propagated
633       {
634         isPropagationOk = _father->RebuildPropagationChains();
635       }
636
637       if ( isPropagationOk ) {
638         if ( isPropagationHyp )
639           return ret; // nothing more to do for "Propagation" hypothesis
640       }
641       else if ( ret < SMESH_Hypothesis::HYP_CONCURENT) {
642         ret = SMESH_Hypothesis::HYP_CONCURENT;
643       }
644     } // Serve Propagation of 1D hypothesis
645     else // event == REMOVE_ALGO
646     {
647       SMESH_Algo* algo = dynamic_cast<SMESH_Algo*> (anHyp);
648       if (!algo->NeedDescretBoundary())
649       {
650         // clean all mesh in the tree of the current submesh;
651         // we must perform it now because later
652         // we will have no information about the type of the removed algo
653         CleanDependants();
654         ComputeStateEngine( CLEAN );
655         CleanDependsOn();
656       }
657     }
658   }
659
660   // ------------------
661   // analyse algo state
662   // ------------------
663   if (!IsApplicableHypotesis( anHyp ))
664     return ret; // not applicable hypotheses do not change algo state
665
666   switch (_algoState)
667   {
668
669     // ----------------------------------------------------------------------
670
671   case NO_ALGO:
672     switch (event) {
673     case ADD_HYP:
674       break;
675     case ADD_ALGO: {
676       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
677       ASSERT(algo);
678       if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
679         SetAlgoState(HYP_OK);
680       else
681         SetAlgoState(MISSING_HYP);
682       break;
683     }
684     case REMOVE_HYP:
685       break;
686     case REMOVE_ALGO:
687       break;
688     case ADD_FATHER_HYP:
689       break;
690     case ADD_FATHER_ALGO: {    // Algo just added in father
691       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
692       ASSERT(algo);
693       if ( algo == anHyp ) {
694         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
695           SetAlgoState(HYP_OK);
696         else
697           SetAlgoState(MISSING_HYP);
698       }
699       break;
700     }
701     case REMOVE_FATHER_HYP:
702       break;
703     case REMOVE_FATHER_ALGO: {
704       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
705       if (algo)
706       {
707         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
708             SetAlgoState(HYP_OK);
709         else
710           SetAlgoState(MISSING_HYP);
711       }
712       break;
713     }
714     default:
715       ASSERT(0);
716       break;
717     }
718     break;
719
720     // ----------------------------------------------------------------------
721
722   case MISSING_HYP:
723     switch (event)
724     {
725     case ADD_HYP: {
726       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
727       ASSERT(algo);
728       if ( algo->CheckHypothesis((*_father),_subShape, ret ))
729         SetAlgoState(HYP_OK);
730       if (SMESH_Hypothesis::IsStatusFatal( ret ))
731         _meshDS->RemoveHypothesis(_subShape, anHyp);
732       else if (!_father->IsUsedHypothesis( anHyp, this ))
733       {
734         _meshDS->RemoveHypothesis(_subShape, anHyp);
735         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
736       }
737       break;
738     }
739     case ADD_ALGO: {           //already existing algo : on father ?
740       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
741       ASSERT(algo);
742       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
743         SetAlgoState(HYP_OK);
744       else
745         SetAlgoState(MISSING_HYP);
746       break;
747     }
748     case REMOVE_HYP:
749       break;
750     case REMOVE_ALGO: {        // perhaps a father algo applies ?
751       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
752       if (algo == NULL)  // no more algo applying on subShape...
753       {
754         SetAlgoState(NO_ALGO);
755       }
756       else
757       {
758         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
759           SetAlgoState(HYP_OK);
760         else
761           SetAlgoState(MISSING_HYP);
762       }
763       break;
764     }
765     case ADD_FATHER_HYP: {
766       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
767       ASSERT(algo);
768       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
769         SetAlgoState(HYP_OK);
770       else
771         SetAlgoState(MISSING_HYP);
772     }
773       break;
774     case ADD_FATHER_ALGO: { // new father algo
775       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
776       ASSERT( algo );
777       if ( algo == anHyp ) {
778         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
779           SetAlgoState(HYP_OK);
780         else
781           SetAlgoState(MISSING_HYP);
782       }
783       break;
784     }
785     case REMOVE_FATHER_HYP:    // nothing to do
786       break;
787     case REMOVE_FATHER_ALGO: {
788       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
789       if (algo == NULL)  // no more applying algo on father
790       {
791         SetAlgoState(NO_ALGO);
792       }
793       else
794       {
795         if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
796           SetAlgoState(HYP_OK);
797         else
798           SetAlgoState(MISSING_HYP);
799       }
800       break;
801     }
802     default:
803       ASSERT(0);
804       break;
805     }
806     break;
807
808     // ----------------------------------------------------------------------
809
810   case HYP_OK:
811     switch (event)
812     {
813     case ADD_HYP: {
814       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
815       ASSERT(algo);
816       if (!algo->CheckHypothesis((*_father),_subShape, ret ))
817       {
818         if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
819           // ret should be fatal: anHyp was not added
820           ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
821       }
822       else if (!_father->IsUsedHypothesis(  anHyp, this ))
823         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
824
825       if (SMESH_Hypothesis::IsStatusFatal( ret ))
826       {
827         MESSAGE("do not add extra hypothesis");
828         _meshDS->RemoveHypothesis(_subShape, anHyp);
829       }
830       else
831       {
832         modifiedHyp = true;
833       }
834       break;
835     }
836     case ADD_ALGO: {           //already existing algo : on father ?
837       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
838       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
839         // check if algo changes
840         SMESH_HypoFilter f;
841         f.Init(   SMESH_HypoFilter::IsAlgo() );
842         f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
843         f.AndNot( SMESH_HypoFilter::Is( algo ));
844         const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
845         if (prevAlgo && 
846             string(algo->GetName()) != string(prevAlgo->GetName()) )
847           modifiedHyp = true;
848       }
849       else
850         SetAlgoState(MISSING_HYP);
851       break;
852     }
853     case REMOVE_HYP: {
854       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
855       ASSERT(algo);
856       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
857         SetAlgoState(HYP_OK);
858       else
859         SetAlgoState(MISSING_HYP);
860       modifiedHyp = true;
861       break;
862     }
863     case REMOVE_ALGO: {         // perhaps a father algo applies ?
864       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
865       if (algo == NULL)   // no more algo applying on subShape...
866       {
867         SetAlgoState(NO_ALGO);
868       }
869       else
870       {
871         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
872           // check if algo remains
873           if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
874             modifiedHyp = true;
875         }
876         else
877           SetAlgoState(MISSING_HYP);
878       }
879       break;
880     }
881     case ADD_FATHER_HYP: {  // new father hypothesis ?
882       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
883       ASSERT(algo);
884       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
885       {
886         if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
887           modifiedHyp = true;
888       }
889       else
890         SetAlgoState(MISSING_HYP);
891       break;
892     }
893     case ADD_FATHER_ALGO: {
894       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
895       if ( algo == anHyp ) { // a new algo on father
896         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
897           // check if algo changes
898           SMESH_HypoFilter f;
899           f.Init(   SMESH_HypoFilter::IsAlgo() );
900           f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
901           f.AndNot( SMESH_HypoFilter::Is( algo ));
902           const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
903           if (prevAlgo && 
904               string(algo->GetName()) != string(prevAlgo->GetName()) )
905             modifiedHyp = true;
906         }
907         else
908           SetAlgoState(MISSING_HYP);
909       }
910       break;
911     }
912     case REMOVE_FATHER_HYP: {
913       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
914       ASSERT(algo);
915       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
916         // is there the same local hyp or maybe a new father algo applied?
917         if ( !GetSimilarAttached( _subShape, anHyp ) )
918           modifiedHyp = true;
919       }
920       else
921         SetAlgoState(MISSING_HYP);
922       break;
923     }
924     case REMOVE_FATHER_ALGO: {
925       SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
926       if (algo == NULL)  // no more applying algo on father
927       {
928         SetAlgoState(NO_ALGO);
929       }
930       else
931       {
932         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
933           // check if algo changes
934           if ( string(algo->GetName()) != string( anHyp->GetName()) )
935             modifiedHyp = true;
936         }
937         else
938           SetAlgoState(MISSING_HYP);
939       }
940       break;
941     }
942     default:
943       ASSERT(0);
944       break;
945     }
946     break;
947
948     // ----------------------------------------------------------------------
949
950   default:
951     ASSERT(0);
952     break;
953   }
954
955   if ((_algoState != oldAlgoState) || modifiedHyp)
956     ComputeStateEngine(MODIF_ALGO_STATE);
957
958   return ret;
959 }
960
961
962 //=======================================================================
963 //function : IsConform
964 //purpose  : check if a conform mesh will be produced by the Algo
965 //=======================================================================
966
967 bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
968 {
969 //  MESSAGE( "SMESH_subMesh::IsConform" );
970
971   if ( !theAlgo ) return false;
972
973   // check only algo that doesn't NeedDescretBoundary(): because mesh made
974   // on a sub-shape will be ignored by theAlgo
975   if ( theAlgo->NeedDescretBoundary() )
976     return true;
977
978   SMESH_Gen* gen =_father->GetGen();
979
980   // only local algo is to be checked
981   if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
982     return true;
983
984   // check algo attached to adjacent shapes
985
986   // loop on one level down sub-meshes
987   TopoDS_Iterator itsub( _subShape );
988   for (; itsub.More(); itsub.Next())
989   {
990     // loop on adjacent subShapes
991     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
992     for (; it.More(); it.Next())
993     {
994       const TopoDS_Shape& adjacent = it.Value();
995       if ( _subShape.IsSame( adjacent )) continue;
996       if ( adjacent.ShapeType() != _subShape.ShapeType())
997         break;
998
999       // check algo attached to smAdjacent
1000       SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
1001       if (algo &&
1002           //algo != theAlgo &&
1003           !algo->NeedDescretBoundary() /*&&
1004           !gen->IsGlobalHypothesis( algo, *_father )*/)
1005         return false; // NOT CONFORM MESH WILL BE PRODUCED
1006     }
1007   }
1008
1009   return true;
1010 }
1011
1012 //=============================================================================
1013 /*!
1014  *
1015  */
1016 //=============================================================================
1017
1018 void SMESH_subMesh::SetAlgoState(int state)
1019 {
1020   _algoState = state;
1021 }
1022
1023 //=============================================================================
1024 /*!
1025  *
1026  */
1027 //=============================================================================
1028 SMESH_Hypothesis::Hypothesis_Status
1029   SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
1030                                           SMESH_Hypothesis * anHyp)
1031 {
1032   //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
1033   SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
1034   //EAP: a wire (dim==1) should notify edges (dim==1)
1035   //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
1036   if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
1037   {
1038     const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1039
1040     map < int, SMESH_subMesh * >::const_iterator itsub;
1041     for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1042     {
1043       SMESH_subMesh *sm = (*itsub).second;
1044       SMESH_Hypothesis::Hypothesis_Status ret2 =
1045         sm->AlgoStateEngine(event, anHyp);
1046       if ( ret2 > ret )
1047         ret = ret2;
1048     }
1049   }
1050   return ret;
1051 }
1052
1053 //=============================================================================
1054 /*!
1055  *
1056  */
1057 //=============================================================================
1058
1059 void SMESH_subMesh::CleanDependsOn()
1060 {
1061   //MESSAGE("SMESH_subMesh::CleanDependsOn");
1062
1063   const map < int, SMESH_subMesh * >&dependson = DependsOn();
1064   map < int, SMESH_subMesh * >::const_iterator its;
1065   for (its = dependson.begin(); its != dependson.end(); its++)
1066   {
1067     SMESH_subMesh *sm = (*its).second;
1068     sm->ComputeStateEngine(CLEAN);
1069   }
1070 }
1071
1072 //=============================================================================
1073 /*!
1074  *
1075  */
1076 //=============================================================================
1077
1078 void SMESH_subMesh::DumpAlgoState(bool isMain)
1079 {
1080         int dim = SMESH_Gen::GetShapeDim(_subShape);
1081 //   if (dim < 1) return;
1082         if (isMain)
1083         {
1084                 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
1085
1086                 map < int, SMESH_subMesh * >::const_iterator itsub;
1087                 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
1088                 {
1089                         SMESH_subMesh *sm = (*itsub).second;
1090                         sm->DumpAlgoState(false);
1091                 }
1092         }
1093         int type = _subShape.ShapeType();
1094         MESSAGE("dim = " << dim << " type of shape " << type);
1095         switch (_algoState)
1096         {
1097         case NO_ALGO:
1098                 MESSAGE(" AlgoState = NO_ALGO");
1099                 break;
1100         case MISSING_HYP:
1101                 MESSAGE(" AlgoState = MISSING_HYP");
1102                 break;
1103         case HYP_OK:
1104                 MESSAGE(" AlgoState = HYP_OK");
1105                 break;
1106         }
1107         switch (_computeState)
1108         {
1109         case NOT_READY:
1110                 MESSAGE(" ComputeState = NOT_READY");
1111                 break;
1112         case READY_TO_COMPUTE:
1113                 MESSAGE(" ComputeState = READY_TO_COMPUTE");
1114                 break;
1115         case COMPUTE_OK:
1116                 MESSAGE(" ComputeState = COMPUTE_OK");
1117                 break;
1118         case FAILED_TO_COMPUTE:
1119                 MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
1120                 break;
1121         }
1122 }
1123
1124 //================================================================================
1125 /*!
1126  * \brief Remove nodes and elements bound to submesh
1127   * \param subMesh - submesh containing nodes and elements
1128  */
1129 //================================================================================
1130
1131 static void cleanSubMesh( SMESH_subMesh * subMesh )
1132 {
1133   if (subMesh) {
1134     if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
1135       SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
1136       SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
1137       while (ite->more()) {
1138         const SMDS_MeshElement * elt = ite->next();
1139         //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
1140         //meshDS->RemoveElement(elt);
1141         meshDS->RemoveFreeElement(elt, subMeshDS);
1142       }
1143
1144       SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
1145       while (itn->more()) {
1146         const SMDS_MeshNode * node = itn->next();
1147         //MESSAGE( " RM node: "<<node->GetID());
1148         //meshDS->RemoveNode(node);
1149         meshDS->RemoveFreeNode(node, subMeshDS);
1150       }
1151     }
1152   }
1153 }
1154
1155 //=============================================================================
1156 /*!
1157  *
1158  */
1159 //=============================================================================
1160
1161 bool SMESH_subMesh::ComputeStateEngine(int event)
1162 {
1163   //MESSAGE("SMESH_subMesh::ComputeStateEngine");
1164   //SCRUTE(_computeState);
1165   //SCRUTE(event);
1166
1167   int dim = SMESH_Gen::GetShapeDim(_subShape);
1168
1169   if (dim < 1)
1170   {
1171     if ( IsMeshComputed() )
1172       _computeState = COMPUTE_OK;
1173     else
1174       _computeState = READY_TO_COMPUTE;
1175     return true;
1176   }
1177   SMESH_Gen *gen = _father->GetGen();
1178   SMESH_Algo *algo = 0;
1179   bool ret = true;
1180   SMESH_Hypothesis::Hypothesis_Status hyp_status;
1181
1182   switch (_computeState)
1183   {
1184
1185     // ----------------------------------------------------------------------
1186
1187   case NOT_READY:
1188     switch (event)
1189     {
1190     case MODIF_HYP:
1191     case MODIF_ALGO_STATE:
1192       algo = gen->GetAlgo((*_father), _subShape);
1193       if (algo && !algo->NeedDescretBoundary())
1194         CleanDependsOn(); // clean sub-meshes with event CLEAN
1195       if (event == MODIF_ALGO_STATE && _algoState == HYP_OK)
1196       {
1197         _computeState = READY_TO_COMPUTE;
1198       }
1199       break;
1200     case COMPUTE:               // nothing to do
1201       break;
1202     case CLEAN:
1203       CleanDependants();
1204       RemoveSubMeshElementsAndNodes();
1205       break;
1206     case SUBMESH_COMPUTED:      // nothing to do
1207       break;
1208     case SUBMESH_RESTORED:
1209       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1210       break;
1211     case MESH_ENTITY_REMOVED:
1212       break;
1213     case CHECK_COMPUTE_STATE:
1214       if ( IsMeshComputed() )
1215         _computeState = COMPUTE_OK;
1216       break;
1217     default:
1218       ASSERT(0);
1219       break;
1220     }
1221     break;
1222
1223     // ----------------------------------------------------------------------
1224
1225   case READY_TO_COMPUTE:
1226     switch (event)
1227     {
1228     case MODIF_HYP:
1229     case MODIF_ALGO_STATE:
1230       algo = gen->GetAlgo((*_father), _subShape);
1231       if (algo && !algo->NeedDescretBoundary())
1232         CleanDependsOn(); // clean sub-meshes with event CLEAN
1233       if (event == MODIF_HYP)
1234         break;            // nothing else to do when MODIF_HYP
1235       _computeState = NOT_READY;
1236       if (algo)
1237       {
1238         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1239         if (ret)
1240           _computeState = READY_TO_COMPUTE;
1241       }
1242       break;
1243     case COMPUTE:
1244       {
1245         algo = gen->GetAlgo((*_father), _subShape);
1246         ASSERT(algo);
1247         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1248         if (!ret)
1249         {
1250           MESSAGE("***** verify compute state *****");
1251           _computeState = NOT_READY;
1252           break;
1253         }
1254         // check submeshes needed
1255         if (algo->NeedDescretBoundary())
1256           ret = SubMeshesComputed();
1257         if (!ret)
1258         {
1259           MESSAGE("Some SubMeshes not computed");
1260           _computeState = FAILED_TO_COMPUTE;
1261           break;
1262         }
1263         // compute
1264         CleanDependants();
1265         RemoveSubMeshElementsAndNodes();
1266         {
1267           try {
1268             OCC_CATCH_SIGNALS;
1269             if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
1270               ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
1271             else
1272               ret = algo->Compute((*_father), _subShape);
1273           }
1274           catch (Standard_Failure) {
1275             MESSAGE( "Exception in algo->Compute() ");
1276             ret = false;
1277           }
1278         }
1279         if (!ret)
1280         {
1281           MESSAGE("problem in algo execution: failed to compute");
1282           _computeState = FAILED_TO_COMPUTE;
1283           if (!algo->NeedDescretBoundary())
1284             UpdateSubMeshState( FAILED_TO_COMPUTE );
1285
1286 #ifdef _DEBUG_
1287           // Show vertices location of a failed shape
1288           cout << algo->GetName() << " failed on shape with the following vertices:" << endl;
1289           TopTools_IndexedMapOfShape vMap;
1290           TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
1291           for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
1292             gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
1293             cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
1294           }
1295 #endif
1296           break;
1297         }
1298         else
1299         {
1300           _computeState = COMPUTE_OK;
1301           UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
1302           if (!algo->NeedDescretBoundary())
1303             UpdateSubMeshState( COMPUTE_OK );
1304         }
1305       }
1306       break;
1307     case CLEAN:
1308       CleanDependants();
1309       RemoveSubMeshElementsAndNodes();
1310       _computeState = NOT_READY;
1311       algo = gen->GetAlgo((*_father), _subShape);
1312       if (algo)
1313       {
1314         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1315         if (ret)
1316           _computeState = READY_TO_COMPUTE;
1317       }
1318       break;
1319     case SUBMESH_COMPUTED:      // nothing to do
1320       break;
1321     case SUBMESH_RESTORED:
1322       // check if a mesh is already computed that may
1323       // happen after retrieval from a file
1324       ComputeStateEngine( CHECK_COMPUTE_STATE );
1325       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1326       break;
1327     case MESH_ENTITY_REMOVED:
1328       break;
1329     case CHECK_COMPUTE_STATE:
1330       if ( IsMeshComputed() )
1331         _computeState = COMPUTE_OK;
1332       break;
1333     default:
1334       ASSERT(0);
1335       break;
1336     }
1337     break;
1338
1339     // ----------------------------------------------------------------------
1340
1341   case COMPUTE_OK:
1342     switch (event)
1343     {
1344     case MODIF_HYP:
1345     case MODIF_ALGO_STATE:
1346       ComputeStateEngine( CLEAN );
1347       algo = gen->GetAlgo((*_father), _subShape);
1348       if (algo && !algo->NeedDescretBoundary())
1349         CleanDependsOn(); // clean sub-meshes with event CLEAN
1350       break;
1351     case COMPUTE:               // nothing to do
1352       break;
1353     case CLEAN:
1354       CleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
1355       RemoveSubMeshElementsAndNodes();
1356       _computeState = NOT_READY;
1357       algo = gen->GetAlgo((*_father), _subShape);
1358       if (algo)
1359       {
1360         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1361         if (ret)
1362           _computeState = READY_TO_COMPUTE;
1363       }
1364       break;
1365     case SUBMESH_COMPUTED:      // nothing to do
1366       break;
1367     case SUBMESH_RESTORED:
1368       ComputeStateEngine( CHECK_COMPUTE_STATE );
1369       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1370       break;
1371     case MESH_ENTITY_REMOVED:
1372       UpdateDependantsState( CHECK_COMPUTE_STATE );
1373       ComputeStateEngine( CHECK_COMPUTE_STATE );
1374       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1375       break;
1376     case CHECK_COMPUTE_STATE:
1377       if ( !IsMeshComputed() )
1378         if (_algoState == HYP_OK)
1379           _computeState = READY_TO_COMPUTE;
1380         else
1381           _computeState = NOT_READY;
1382       break;
1383     default:
1384       ASSERT(0);
1385       break;
1386     }
1387     break;
1388
1389     // ----------------------------------------------------------------------
1390
1391   case FAILED_TO_COMPUTE:
1392     switch (event)
1393     {
1394     case MODIF_HYP:
1395       if (_algoState == HYP_OK)
1396         _computeState = READY_TO_COMPUTE;
1397       else
1398         _computeState = NOT_READY;
1399       break;
1400     case MODIF_ALGO_STATE:
1401       if (_algoState == HYP_OK)
1402         _computeState = READY_TO_COMPUTE;
1403       else
1404         _computeState = NOT_READY;
1405       break;
1406     case COMPUTE:      // nothing to do
1407       break;
1408     case CLEAN:
1409       CleanDependants(); // submeshes dependent on me should be cleaned as well
1410       RemoveSubMeshElementsAndNodes();
1411       if (_algoState == HYP_OK)
1412         _computeState = READY_TO_COMPUTE;
1413       else
1414         _computeState = NOT_READY;
1415       break;
1416     case SUBMESH_COMPUTED:      // allow retry compute
1417       if (_algoState == HYP_OK)
1418         _computeState = READY_TO_COMPUTE;
1419       else
1420         _computeState = NOT_READY;
1421       break;
1422     case SUBMESH_RESTORED:
1423       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1424       break;
1425     case MESH_ENTITY_REMOVED:
1426       break;
1427     case CHECK_COMPUTE_STATE:
1428       if ( IsMeshComputed() )
1429         _computeState = COMPUTE_OK;
1430       else
1431         if (_algoState == HYP_OK)
1432           _computeState = READY_TO_COMPUTE;
1433         else
1434           _computeState = NOT_READY;
1435       break;
1436     default:
1437       ASSERT(0);
1438       break;
1439     }
1440     break;
1441
1442     // ----------------------------------------------------------------------
1443   default:
1444     ASSERT(0);
1445     break;
1446   }
1447
1448   //SCRUTE(_computeState);
1449   return ret;
1450 }
1451
1452 //=======================================================================
1453 //function : ApplyToCollection
1454 //purpose  : Apply theAlgo to all subshapes in theCollection
1455 //=======================================================================
1456
1457 bool SMESH_subMesh::ApplyToCollection (SMESH_Algo*         theAlgo,
1458                                        const TopoDS_Shape& theCollection)
1459 {
1460   MESSAGE("SMESH_subMesh::ApplyToCollection");
1461   ASSERT ( !theAlgo->NeedDescretBoundary() );
1462
1463   bool ret = false;
1464
1465
1466   ret = theAlgo->Compute( *_father, theCollection );
1467
1468   // set _computeState of subshapes
1469   TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
1470   for ( ; anExplorer.More(); anExplorer.Next() )
1471   {
1472     const TopoDS_Shape& aSubShape = anExplorer.Current();
1473     SMESH_subMesh* subMesh = _father->GetSubMeshContaining( aSubShape );
1474     if ( subMesh )
1475     {
1476       if (ret)
1477       {
1478         subMesh->_computeState = COMPUTE_OK;
1479         subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
1480         subMesh->UpdateSubMeshState( COMPUTE_OK );
1481       }
1482       else
1483       {
1484         subMesh->_computeState = FAILED_TO_COMPUTE;
1485       }
1486     }
1487   }
1488   return ret;
1489 }
1490
1491
1492 //=======================================================================
1493 //function : UpdateSubMeshState
1494 //purpose  :
1495 //=======================================================================
1496
1497 void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
1498 {
1499   const map<int, SMESH_subMesh*>& smMap = DependsOn();
1500   map<int, SMESH_subMesh*>::const_iterator itsub;
1501   for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1502   {
1503     SMESH_subMesh* sm = (*itsub).second;
1504     sm->_computeState = theState;
1505   }
1506 }
1507
1508 //=======================================================================
1509 //function : ComputeSubMeshStateEngine
1510 //purpose  :
1511 //=======================================================================
1512
1513 void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
1514 {
1515   const map<int, SMESH_subMesh*>& smMap = DependsOn();
1516   map<int, SMESH_subMesh*>::const_iterator itsub;
1517   for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1518   {
1519     SMESH_subMesh* sm = (*itsub).second;
1520     sm->ComputeStateEngine(event);
1521   }
1522 }
1523
1524 //=======================================================================
1525 //function : UpdateDependantsState
1526 //purpose  :
1527 //=======================================================================
1528
1529 void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
1530 {
1531   //MESSAGE("SMESH_subMesh::UpdateDependantsState");
1532   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1533   for (; it.More(); it.Next())
1534   {
1535     const TopoDS_Shape& ancestor = it.Value();
1536     SMESH_subMesh *aSubMesh =
1537       _father->GetSubMeshContaining(ancestor);
1538     if (aSubMesh)
1539       aSubMesh->ComputeStateEngine( theEvent );
1540   }
1541 }
1542
1543 //=============================================================================
1544 /*!
1545  *
1546  */
1547 //=============================================================================
1548
1549 void SMESH_subMesh::CleanDependants()
1550 {
1551   int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
1552
1553   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1554   for (; it.More(); it.Next())
1555   {
1556     const TopoDS_Shape& ancestor = it.Value();
1557     if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
1558       // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
1559       // will erase mesh on other shapes in a compound
1560       if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
1561         SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
1562         if (aSubMesh)
1563           aSubMesh->ComputeStateEngine(CLEAN);
1564       }
1565     }
1566   }
1567 }
1568
1569 //=============================================================================
1570 /*!
1571  *
1572  */
1573 //=============================================================================
1574
1575 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
1576 {
1577   //SCRUTE(_subShape.ShapeType());
1578
1579   cleanSubMesh( this );
1580
1581   // algo may bind a submesh not to _subShape, eg 3D algo
1582   // sets nodes on SHELL while _subShape may be SOLID
1583
1584   int dim = SMESH_Gen::GetShapeDim( _subShape );
1585   int type = _subShape.ShapeType() + 1;
1586   for ( ; type <= TopAbs_EDGE; type++) {
1587     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1588     {
1589       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1590       for ( ; exp.More(); exp.Next() )
1591         cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
1592     }
1593     else
1594       break;
1595   }
1596 }
1597
1598 //=======================================================================
1599 //function : IsMeshComputed
1600 //purpose  : check if _subMeshDS contains mesh elements
1601 //=======================================================================
1602
1603 bool SMESH_subMesh::IsMeshComputed() const
1604 {
1605   // algo may bind a submesh not to _subShape, eg 3D algo
1606   // sets nodes on SHELL while _subShape may be SOLID
1607
1608   int dim = SMESH_Gen::GetShapeDim( _subShape );
1609   int type = _subShape.ShapeType();
1610   for ( ; type <= TopAbs_VERTEX; type++) {
1611     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1612     {
1613       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1614       for ( ; exp.More(); exp.Next() )
1615       {
1616         SMESHDS_SubMesh * subMeshDS = _meshDS->MeshElements( exp.Current() );
1617         if ( subMeshDS != NULL &&
1618             (subMeshDS->GetElements()->more() || subMeshDS->GetNodes()->more())) {
1619           return true;
1620         }
1621       }
1622     }
1623     else
1624       break;
1625   }
1626
1627   return false;
1628 }
1629
1630
1631 //=======================================================================
1632 //function : GetCollection
1633 //purpose  : return a shape containing all sub-shapes of the MainShape that can be
1634 //           meshed at once along with _subShape
1635 //=======================================================================
1636
1637 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
1638 {
1639   MESSAGE("SMESH_subMesh::GetCollection");
1640   ASSERT (!theAlgo->NeedDescretBoundary());
1641
1642   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
1643
1644   if ( mainShape.IsSame( _subShape ))
1645     return _subShape;
1646
1647   const bool ignoreAuxiliaryHyps = false;
1648   list<const SMESHDS_Hypothesis*> aUsedHyp =
1649     theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
1650
1651   // put in a compound all shapes with the same hypothesis assigned
1652   // and a good ComputState
1653
1654   TopoDS_Compound aCompound;
1655   BRep_Builder aBuilder;
1656   aBuilder.MakeCompound( aCompound );
1657
1658   TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
1659   for ( ; anExplorer.More(); anExplorer.Next() )
1660   {
1661     const TopoDS_Shape& S = anExplorer.Current();
1662     SMESH_subMesh* subMesh = _father->GetSubMesh( S );
1663     SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
1664
1665     if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
1666         anAlgo == theAlgo &&
1667         anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
1668     {
1669       aBuilder.Add( aCompound, S );
1670     }
1671   }
1672
1673   return aCompound;
1674 }
1675
1676 //=======================================================================
1677 //function : GetSimilarAttached
1678 //purpose  : return a hypothesis attached to theShape.
1679 //           If theHyp is provided, similar but not same hypotheses
1680 //           is returned; else only applicable ones having theHypType
1681 //           is returned
1682 //=======================================================================
1683
1684 const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&      theShape,
1685                                                           const SMESH_Hypothesis * theHyp,
1686                                                           const int                theHypType)
1687 {
1688   SMESH_HypoFilter hypoKind;
1689   hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
1690   if ( theHyp ) {
1691     hypoKind.And   ( hypoKind.HasDim( theHyp->GetDim() ));
1692     hypoKind.AndNot( hypoKind.Is( theHyp ));
1693     if ( theHyp->IsAuxiliary() )
1694       hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
1695     else
1696       hypoKind.AndNot( hypoKind.IsAuxiliary());
1697   }
1698   else {
1699     hypoKind.And( hypoKind.IsApplicableTo( theShape ));
1700   }
1701
1702   return _father->GetHypothesis( theShape, hypoKind, false );
1703 }
1704
1705 //=======================================================================
1706 //function : CheckConcurentHypothesis
1707 //purpose  : check if there are several applicable hypothesis attached to
1708 //           ansestors
1709 //=======================================================================
1710
1711 SMESH_Hypothesis::Hypothesis_Status
1712   SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
1713 {
1714   MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
1715
1716   // is there local hypothesis on me?
1717   if ( GetSimilarAttached( _subShape, 0, theHypType ) )
1718     return SMESH_Hypothesis::HYP_OK;
1719
1720
1721   TopoDS_Shape aPrevWithHyp;
1722   const SMESH_Hypothesis* aPrevHyp = 0;
1723   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1724   for (; it.More(); it.Next())
1725   {
1726     const TopoDS_Shape& ancestor = it.Value();
1727     const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
1728     if ( hyp )
1729     {
1730       if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
1731       {
1732         aPrevWithHyp = ancestor;
1733         aPrevHyp     = hyp;
1734       }
1735       else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
1736         return SMESH_Hypothesis::HYP_CONCURENT;
1737       else
1738         return SMESH_Hypothesis::HYP_OK;
1739     }
1740   }
1741   return SMESH_Hypothesis::HYP_OK;
1742 }