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