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