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