Salome HOME
Join modifications from branch BR_DEBUG_3_2_0b1
[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             if (!algo->NeedDescretBoundary() && !algo->OnlyUnaryInput())
1269               ret = ApplyToCollection( algo, GetCollection( gen, algo ) );
1270             else
1271               ret = algo->Compute((*_father), _subShape);
1272           }
1273           catch (Standard_Failure) {
1274             MESSAGE( "Exception in algo->Compute() ");
1275             ret = false;
1276           }
1277         }
1278         if (!ret)
1279         {
1280           MESSAGE("problem in algo execution: failed to compute");
1281           _computeState = FAILED_TO_COMPUTE;
1282           if (!algo->NeedDescretBoundary())
1283             UpdateSubMeshState( FAILED_TO_COMPUTE );
1284
1285 #ifdef _DEBUG_
1286           // Show vertices location of a failed shape
1287           cout << algo->GetName() << " failed on shape with the following vertices:" << endl;
1288           TopTools_IndexedMapOfShape vMap;
1289           TopExp::MapShapes( _subShape, TopAbs_VERTEX, vMap );
1290           for ( int iv = 1; iv <= vMap.Extent(); ++iv ) {
1291             gp_Pnt P( BRep_Tool::Pnt( TopoDS::Vertex( vMap( iv ) )));
1292             cout << P.X() << " " << P.Y() << " " << P.Z() << " " << endl;
1293           }
1294 #endif
1295           break;
1296         }
1297         else
1298         {
1299           _computeState = COMPUTE_OK;
1300           UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
1301           if (!algo->NeedDescretBoundary())
1302             UpdateSubMeshState( COMPUTE_OK );
1303         }
1304       }
1305       break;
1306     case CLEAN:
1307       CleanDependants();
1308       RemoveSubMeshElementsAndNodes();
1309       _computeState = NOT_READY;
1310       algo = gen->GetAlgo((*_father), _subShape);
1311       if (algo)
1312       {
1313         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1314         if (ret)
1315           _computeState = READY_TO_COMPUTE;
1316       }
1317       break;
1318     case SUBMESH_COMPUTED:      // nothing to do
1319       break;
1320     case SUBMESH_RESTORED:
1321       // check if a mesh is already computed that may
1322       // happen after retrieval from a file
1323       ComputeStateEngine( CHECK_COMPUTE_STATE );
1324       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1325       break;
1326     case MESH_ENTITY_REMOVED:
1327       break;
1328     case CHECK_COMPUTE_STATE:
1329       if ( IsMeshComputed() )
1330         _computeState = COMPUTE_OK;
1331       break;
1332     default:
1333       ASSERT(0);
1334       break;
1335     }
1336     break;
1337
1338     // ----------------------------------------------------------------------
1339
1340   case COMPUTE_OK:
1341     switch (event)
1342     {
1343     case MODIF_HYP:
1344     case MODIF_ALGO_STATE:
1345       ComputeStateEngine( CLEAN );
1346       algo = gen->GetAlgo((*_father), _subShape);
1347       if (algo && !algo->NeedDescretBoundary())
1348         CleanDependsOn(); // clean sub-meshes with event CLEAN
1349       break;
1350     case COMPUTE:               // nothing to do
1351       break;
1352     case CLEAN:
1353       CleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
1354       RemoveSubMeshElementsAndNodes();
1355       _computeState = NOT_READY;
1356       algo = gen->GetAlgo((*_father), _subShape);
1357       if (algo)
1358       {
1359         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
1360         if (ret)
1361           _computeState = READY_TO_COMPUTE;
1362       }
1363       break;
1364     case SUBMESH_COMPUTED:      // nothing to do
1365       break;
1366     case SUBMESH_RESTORED:
1367       ComputeStateEngine( CHECK_COMPUTE_STATE );
1368       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1369       break;
1370     case MESH_ENTITY_REMOVED:
1371       UpdateDependantsState( CHECK_COMPUTE_STATE );
1372       ComputeStateEngine( CHECK_COMPUTE_STATE );
1373       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1374       break;
1375     case CHECK_COMPUTE_STATE:
1376       if ( !IsMeshComputed() )
1377         if (_algoState == HYP_OK)
1378           _computeState = READY_TO_COMPUTE;
1379         else
1380           _computeState = NOT_READY;
1381       break;
1382     default:
1383       ASSERT(0);
1384       break;
1385     }
1386     break;
1387
1388     // ----------------------------------------------------------------------
1389
1390   case FAILED_TO_COMPUTE:
1391     switch (event)
1392     {
1393     case MODIF_HYP:
1394       if (_algoState == HYP_OK)
1395         _computeState = READY_TO_COMPUTE;
1396       else
1397         _computeState = NOT_READY;
1398       break;
1399     case MODIF_ALGO_STATE:
1400       if (_algoState == HYP_OK)
1401         _computeState = READY_TO_COMPUTE;
1402       else
1403         _computeState = NOT_READY;
1404       break;
1405     case COMPUTE:      // nothing to do
1406       break;
1407     case CLEAN:
1408       CleanDependants(); // submeshes dependent on me should be cleaned as well
1409       RemoveSubMeshElementsAndNodes();
1410       if (_algoState == HYP_OK)
1411         _computeState = READY_TO_COMPUTE;
1412       else
1413         _computeState = NOT_READY;
1414       break;
1415     case SUBMESH_COMPUTED:      // allow retry compute
1416       if (_algoState == HYP_OK)
1417         _computeState = READY_TO_COMPUTE;
1418       else
1419         _computeState = NOT_READY;
1420       break;
1421     case SUBMESH_RESTORED:
1422       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
1423       break;
1424     case MESH_ENTITY_REMOVED:
1425       break;
1426     case CHECK_COMPUTE_STATE:
1427       if ( IsMeshComputed() )
1428         _computeState = COMPUTE_OK;
1429       else
1430         if (_algoState == HYP_OK)
1431           _computeState = READY_TO_COMPUTE;
1432         else
1433           _computeState = NOT_READY;
1434       break;
1435     default:
1436       ASSERT(0);
1437       break;
1438     }
1439     break;
1440
1441     // ----------------------------------------------------------------------
1442   default:
1443     ASSERT(0);
1444     break;
1445   }
1446
1447   //SCRUTE(_computeState);
1448   return ret;
1449 }
1450
1451 //=======================================================================
1452 //function : ApplyToCollection
1453 //purpose  : Apply theAlgo to all subshapes in theCollection
1454 //=======================================================================
1455
1456 bool SMESH_subMesh::ApplyToCollection (SMESH_Algo*         theAlgo,
1457                                        const TopoDS_Shape& theCollection)
1458 {
1459   MESSAGE("SMESH_subMesh::ApplyToCollection");
1460   ASSERT ( !theAlgo->NeedDescretBoundary() );
1461
1462   bool ret = false;
1463
1464
1465   ret = theAlgo->Compute( *_father, theCollection );
1466
1467   // set _computeState of subshapes
1468   TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
1469   for ( ; anExplorer.More(); anExplorer.Next() )
1470   {
1471     const TopoDS_Shape& aSubShape = anExplorer.Current();
1472     SMESH_subMesh* subMesh = _father->GetSubMeshContaining( aSubShape );
1473     if ( subMesh )
1474     {
1475       if (ret)
1476       {
1477         subMesh->_computeState = COMPUTE_OK;
1478         subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
1479         subMesh->UpdateSubMeshState( COMPUTE_OK );
1480       }
1481       else
1482       {
1483         subMesh->_computeState = FAILED_TO_COMPUTE;
1484       }
1485     }
1486   }
1487   return ret;
1488 }
1489
1490
1491 //=======================================================================
1492 //function : UpdateSubMeshState
1493 //purpose  :
1494 //=======================================================================
1495
1496 void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
1497 {
1498   const map<int, SMESH_subMesh*>& smMap = DependsOn();
1499   map<int, SMESH_subMesh*>::const_iterator itsub;
1500   for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1501   {
1502     SMESH_subMesh* sm = (*itsub).second;
1503     sm->_computeState = theState;
1504   }
1505 }
1506
1507 //=======================================================================
1508 //function : ComputeSubMeshStateEngine
1509 //purpose  :
1510 //=======================================================================
1511
1512 void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
1513 {
1514   const map<int, SMESH_subMesh*>& smMap = DependsOn();
1515   map<int, SMESH_subMesh*>::const_iterator itsub;
1516   for (itsub = smMap.begin(); itsub != smMap.end(); itsub++)
1517   {
1518     SMESH_subMesh* sm = (*itsub).second;
1519     sm->ComputeStateEngine(event);
1520   }
1521 }
1522
1523 //=======================================================================
1524 //function : UpdateDependantsState
1525 //purpose  :
1526 //=======================================================================
1527
1528 void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
1529 {
1530   //MESSAGE("SMESH_subMesh::UpdateDependantsState");
1531   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1532   for (; it.More(); it.Next())
1533   {
1534     const TopoDS_Shape& ancestor = it.Value();
1535     SMESH_subMesh *aSubMesh =
1536       _father->GetSubMeshContaining(ancestor);
1537     if (aSubMesh)
1538       aSubMesh->ComputeStateEngine( theEvent );
1539   }
1540 }
1541
1542 //=============================================================================
1543 /*!
1544  *
1545  */
1546 //=============================================================================
1547
1548 void SMESH_subMesh::CleanDependants()
1549 {
1550   int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
1551
1552   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1553   for (; it.More(); it.Next())
1554   {
1555     const TopoDS_Shape& ancestor = it.Value();
1556     if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
1557       // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
1558       // will erase mesh on other shapes in a compound
1559       if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
1560         SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
1561         if (aSubMesh)
1562           aSubMesh->ComputeStateEngine(CLEAN);
1563       }
1564     }
1565   }
1566 }
1567
1568 //=============================================================================
1569 /*!
1570  *
1571  */
1572 //=============================================================================
1573
1574 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
1575 {
1576   //SCRUTE(_subShape.ShapeType());
1577
1578   cleanSubMesh( this );
1579
1580   // algo may bind a submesh not to _subShape, eg 3D algo
1581   // sets nodes on SHELL while _subShape may be SOLID
1582
1583   int dim = SMESH_Gen::GetShapeDim( _subShape );
1584   int type = _subShape.ShapeType() + 1;
1585   for ( ; type <= TopAbs_EDGE; type++) {
1586     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1587     {
1588       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1589       for ( ; exp.More(); exp.Next() )
1590         cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
1591     }
1592     else
1593       break;
1594   }
1595 }
1596
1597 //=======================================================================
1598 //function : IsMeshComputed
1599 //purpose  : check if _subMeshDS contains mesh elements
1600 //=======================================================================
1601
1602 bool SMESH_subMesh::IsMeshComputed() const
1603 {
1604   // algo may bind a submesh not to _subShape, eg 3D algo
1605   // sets nodes on SHELL while _subShape may be SOLID
1606
1607   int dim = SMESH_Gen::GetShapeDim( _subShape );
1608   int type = _subShape.ShapeType();
1609   for ( ; type <= TopAbs_VERTEX; type++) {
1610     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
1611     {
1612       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
1613       for ( ; exp.More(); exp.Next() )
1614       {
1615         SMESHDS_SubMesh * subMeshDS = _meshDS->MeshElements( exp.Current() );
1616         if ( subMeshDS != NULL &&
1617             (subMeshDS->GetElements()->more() || subMeshDS->GetNodes()->more())) {
1618           return true;
1619         }
1620       }
1621     }
1622     else
1623       break;
1624   }
1625
1626   return false;
1627 }
1628
1629
1630 //=======================================================================
1631 //function : GetCollection
1632 //purpose  : return a shape containing all sub-shapes of the MainShape that can be
1633 //           meshed at once along with _subShape
1634 //=======================================================================
1635
1636 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen, SMESH_Algo* theAlgo)
1637 {
1638   MESSAGE("SMESH_subMesh::GetCollection");
1639   ASSERT (!theAlgo->NeedDescretBoundary());
1640
1641   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
1642
1643   if ( mainShape.IsSame( _subShape ))
1644     return _subShape;
1645
1646   const bool ignoreAuxiliaryHyps = false;
1647   list<const SMESHDS_Hypothesis*> aUsedHyp =
1648     theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
1649
1650   // put in a compound all shapes with the same hypothesis assigned
1651   // and a good ComputState
1652
1653   TopoDS_Compound aCompound;
1654   BRep_Builder aBuilder;
1655   aBuilder.MakeCompound( aCompound );
1656
1657   TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
1658   for ( ; anExplorer.More(); anExplorer.Next() )
1659   {
1660     const TopoDS_Shape& S = anExplorer.Current();
1661     SMESH_subMesh* subMesh = _father->GetSubMesh( S );
1662     SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
1663
1664     if (subMesh->GetComputeState() == READY_TO_COMPUTE &&
1665         anAlgo == theAlgo &&
1666         anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp)
1667     {
1668       aBuilder.Add( aCompound, S );
1669     }
1670   }
1671
1672   return aCompound;
1673 }
1674
1675 //=======================================================================
1676 //function : GetSimilarAttached
1677 //purpose  : return a hypothesis attached to theShape.
1678 //           If theHyp is provided, similar but not same hypotheses
1679 //           is returned; else only applicable ones having theHypType
1680 //           is returned
1681 //=======================================================================
1682
1683 const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&      theShape,
1684                                                           const SMESH_Hypothesis * theHyp,
1685                                                           const int                theHypType)
1686 {
1687   SMESH_HypoFilter hypoKind;
1688   hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
1689   if ( theHyp ) {
1690     hypoKind.And   ( hypoKind.HasDim( theHyp->GetDim() ));
1691     hypoKind.AndNot( hypoKind.Is( theHyp ));
1692     if ( theHyp->IsAuxiliary() )
1693       hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
1694     else
1695       hypoKind.AndNot( hypoKind.IsAuxiliary());
1696   }
1697   else {
1698     hypoKind.And( hypoKind.IsApplicableTo( theShape ));
1699   }
1700
1701   return _father->GetHypothesis( theShape, hypoKind, false );
1702 }
1703
1704 //=======================================================================
1705 //function : CheckConcurentHypothesis
1706 //purpose  : check if there are several applicable hypothesis attached to
1707 //           ansestors
1708 //=======================================================================
1709
1710 SMESH_Hypothesis::Hypothesis_Status
1711   SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
1712 {
1713   MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
1714
1715   // is there local hypothesis on me?
1716   if ( GetSimilarAttached( _subShape, 0, theHypType ) )
1717     return SMESH_Hypothesis::HYP_OK;
1718
1719
1720   TopoDS_Shape aPrevWithHyp;
1721   const SMESH_Hypothesis* aPrevHyp = 0;
1722   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
1723   for (; it.More(); it.Next())
1724   {
1725     const TopoDS_Shape& ancestor = it.Value();
1726     const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
1727     if ( hyp )
1728     {
1729       if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
1730       {
1731         aPrevWithHyp = ancestor;
1732         aPrevHyp     = hyp;
1733       }
1734       else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
1735         return SMESH_Hypothesis::HYP_CONCURENT;
1736       else
1737         return SMESH_Hypothesis::HYP_OK;
1738     }
1739   }
1740   return SMESH_Hypothesis::HYP_OK;
1741 }