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