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