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