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