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