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