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