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