Salome HOME
sources v1.2
[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 using namespace std;
31 #include "SMESH_subMesh.hxx"
32 #include "SMESH_Gen.hxx"
33 #include "SMESH_Mesh.hxx"
34 #include "SMESH_Hypothesis.hxx"
35 #include "SMESH_Algo.hxx"
36 #include "utilities.h"
37 #include "OpUtil.hxx"
38
39 #include <TopExp.hxx>
40 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
41 #include <TopTools_ListOfShape.hxx>
42 #include <TopTools_ListIteratorOfListOfShape.hxx>
43 #include <TColStd_ListIteratorOfListOfInteger.hxx>
44
45 //=============================================================================
46 /*!
47  *  default constructor:
48  */
49 //=============================================================================
50
51 SMESH_subMesh::SMESH_subMesh(int Id, 
52                              SMESH_Mesh* father,
53                              const Handle(SMESHDS_Mesh)& meshDS,
54                              const TopoDS_Shape & aSubShape)
55 {
56   //MESSAGE("SMESH_subMesh::SMESH_subMesh");
57   _subShape = aSubShape;
58   _meshDS = meshDS;
59   _subMeshDS =  meshDS->MeshElements(_subShape); // may be null ...
60   _father = father;
61   _Id = Id;
62   _vertexSet = false;        // only for Vertex subMesh
63   _dependenceAnalysed = false;
64   _dependantsFound = false;
65
66   if (_subShape.ShapeType() == TopAbs_VERTEX)
67     {
68       _algoState = HYP_OK;
69       _computeState = READY_TO_COMPUTE;
70     }
71   else
72     {
73       _algoState = NO_ALGO;
74       _computeState = NOT_READY;
75     }
76 }
77
78 //=============================================================================
79 /*!
80  * 
81  */
82 //=============================================================================
83
84 SMESH_subMesh::~SMESH_subMesh()
85 {
86   MESSAGE("SMESH_subMesh::~SMESH_subMesh");
87   // ****
88 }
89
90 //=============================================================================
91 /*!
92  * 
93  */
94 //=============================================================================
95
96 int  SMESH_subMesh::GetId()
97 {
98   //MESSAGE("SMESH_subMesh::GetId");
99   return _Id;
100 }
101
102 //=============================================================================
103 /*!
104  * Given a subShape, find the subMesh is associated to this subShape or
105  * to a collection of shapes containing this subShape. Collection = compsolid,
106  * shell, wire
107  */
108 //=============================================================================
109
110 // bool SMESH_subMesh::Contains(const TopoDS_Shape & aSubShape)
111 //   throw (SALOME_Exception)
112 // {
113 //   //MESSAGE("SMESH_subMesh::Contains");
114 //   bool contains = false;
115 //   int type = _subShape.ShapeType();
116 //   int typesub = aSubShape.ShapeType();
117 //   //SCRUTE(type)
118 //   //SCRUTE(typesub)
119 //   switch (type)
120 //     {
121 // //     case TopAbs_COMPOUND:
122 // //       {
123 // //   //MESSAGE("---");
124 // //   throw SALOME_Exception(LOCALIZED("Compound not yet treated"));
125 // //   break;
126 // //       }
127 //     case TopAbs_COMPSOLID:
128 //       {
129 //      //MESSAGE("---");
130 //      for (TopExp_Explorer exp(aSubShape,TopAbs_SOLID);exp.More();exp.Next())
131 //        {
132 //          contains = _subShape.IsSame(exp.Current());
133 //          if (contains) break;
134 //        }
135 //      break;
136 //       }
137 //     case TopAbs_SHELL:
138 //       {
139 //      //MESSAGE("---");
140 //      for (TopExp_Explorer exp(aSubShape,TopAbs_FACE);exp.More();exp.Next())
141 //        {
142 //          contains = _subShape.IsSame(exp.Current());
143 //          if (contains) break;
144 //        }
145 //      break;
146 //       }
147 //     case TopAbs_WIRE:
148 //       {
149 //      //MESSAGE("---");
150 //      for (TopExp_Explorer exp(aSubShape,TopAbs_EDGE);exp.More();exp.Next())
151 //        {
152 //          contains = _subShape.IsSame(exp.Current());
153 //          if (contains) break;
154 //        }
155 //      break;
156 //       }
157 //     case TopAbs_COMPOUND:
158 //     case TopAbs_SOLID:
159 //     case TopAbs_FACE:
160 //     case TopAbs_EDGE:
161 //     case TopAbs_VERTEX:
162 //       {
163 //      //MESSAGE("---");
164 //      contains = _subShape.IsSame(aSubShape);
165 //      break;
166 //       }
167 //     default:
168 //       {
169 //      break;
170 //       }
171 //     }
172 //   //SCRUTE(contains);
173 //   return contains;
174 // }
175
176 //=============================================================================
177 /*!
178  * 
179  */
180 //=============================================================================
181
182 const Handle(SMESHDS_SubMesh)& SMESH_subMesh::GetSubMeshDS()
183   throw (SALOME_Exception)
184 {
185   //MESSAGE("SMESH_subMesh::GetSubMeshDS");
186   if (_subMeshDS.IsNull())
187     {
188       //MESSAGE("subMesh pointer still null, trying to get it...");
189       _subMeshDS =  _meshDS->MeshElements(_subShape); // may be null ...
190       if (_subMeshDS.IsNull())
191         {
192           MESSAGE("problem... subMesh still empty");
193           //NRI   ASSERT(0);
194           //NRI   throw SALOME_Exception(LOCALIZED(subMesh still empty));
195         }
196     }
197   return _subMeshDS;
198 }
199
200 //=============================================================================
201 /*!
202  * 
203  */
204 //=============================================================================
205
206 SMESH_subMesh* SMESH_subMesh::GetFirstToCompute()
207   throw (SALOME_Exception)
208 {
209   //MESSAGE("SMESH_subMesh::GetFirstToCompute");
210   const map<int, SMESH_subMesh*>& subMeshes = DependsOn();
211   SMESH_subMesh* firstToCompute = 0;
212
213   map<int, SMESH_subMesh*>::const_iterator itsub;
214   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
215     {
216       SMESH_subMesh* sm = (*itsub).second;
217 //       SCRUTE(sm->GetId());
218 //       SCRUTE(sm->GetComputeState());
219       bool readyToCompute = (sm->GetComputeState() == READY_TO_COMPUTE);
220       if (readyToCompute)
221         {
222           firstToCompute = sm; 
223           //SCRUTE(sm->GetId());
224           break;
225         }
226     }
227   if (firstToCompute)
228     {
229       //MESSAGE("--- submesh to compute");
230       return firstToCompute;       // a subMesh of this
231     }
232   if (_computeState == READY_TO_COMPUTE)
233     {
234       //MESSAGE("--- this to compute");
235       return this;  // this
236     }
237   //MESSAGE("--- nothing to compute");
238   return 0;                                            // nothing to compute
239 }
240
241 //=============================================================================
242 /*!
243  * 
244  */
245 //=============================================================================
246
247 bool SMESH_subMesh::SubMeshesComputed()
248   throw (SALOME_Exception)
249 {
250   //MESSAGE("SMESH_subMesh::SubMeshesComputed");
251   const map<int, SMESH_subMesh*>& subMeshes = DependsOn();
252
253   bool subMeshesComputed = true;
254   map<int, SMESH_subMesh*>::const_iterator itsub;
255   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
256     {
257       SMESH_subMesh* sm = (*itsub).second;
258 //       SCRUTE(sm->GetId());
259 //       SCRUTE(sm->GetComputeState());
260       bool computeOk =  (sm->GetComputeState() == COMPUTE_OK);
261       if (! computeOk)
262         {
263           subMeshesComputed = false;
264           SCRUTE(sm->GetId());
265           break;
266         }
267     }
268    return subMeshesComputed; 
269 }
270
271 //=============================================================================
272 /*!
273  * 
274  */
275 //=============================================================================
276
277 bool SMESH_subMesh::SubMeshesReady()
278 {
279   MESSAGE("SMESH_subMesh::SubMeshesReady");
280   const map<int, SMESH_subMesh*>& subMeshes = DependsOn();
281
282   bool subMeshesReady = true;
283   map<int, SMESH_subMesh*>::const_iterator itsub;
284   for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
285     {
286       SMESH_subMesh* sm = (*itsub).second;
287 //       SCRUTE(sm->GetId());
288 //       SCRUTE(sm->GetComputeState());
289       bool computeOk = (    (sm->GetComputeState() == COMPUTE_OK)
290                          || (sm->GetComputeState() == READY_TO_COMPUTE)) ;
291       if (! computeOk)
292         {
293           subMeshesReady = false;
294           SCRUTE(sm->GetId());
295           break;
296         }
297     }
298   return subMeshesReady; 
299 }
300
301 //=============================================================================
302 /*!
303  * Construct dependence on first level subMeshes. complex shapes (compsolid, 
304  * shell, wire) are not analysed the same way as simple shapes (solid, face,
305  * edge). 
306  * For collection shapes (compsolid, shell, wire) prepare a list of submeshes
307  * with possible multiples occurences. Multiples occurences corresponds to
308  * internal frontiers within shapes of the collection and must not be keeped.
309  * See FinalizeDependence.
310  */
311 //=============================================================================
312
313 const map<int, SMESH_subMesh*>& SMESH_subMesh::DependsOn()
314 {
315  if (_dependenceAnalysed) return _mapDepend;
316
317  //MESSAGE("SMESH_subMesh::DependsOn");
318
319   int type = _subShape.ShapeType();
320   //SCRUTE(type);
321   switch (type)
322     {
323     case TopAbs_COMPOUND:
324       {
325         //MESSAGE("compound");
326         list<TopoDS_Shape> shellInSolid;
327         for (TopExp_Explorer exp(_subShape,TopAbs_SOLID);exp.More();exp.Next())
328           {
329             InsertDependence(exp.Current());
330             for (TopExp_Explorer 
331                    exp2(exp.Current(),TopAbs_SHELL);exp2.More();exp2.Next())
332               {
333                 shellInSolid.push_back(exp2.Current()); 
334               }
335           }
336         for (TopExp_Explorer exp(_subShape,TopAbs_SHELL);exp.More();exp.Next())
337           {
338             list<TopoDS_Shape>::iterator it1;
339             bool isInSolid = false;
340             for (it1 = shellInSolid.begin(); it1 != shellInSolid.end(); it1++)
341               {
342                 TopoDS_Shape aShape = (*it1);
343                 if (aShape.IsSame(exp.Current())) 
344                 {
345                   isInSolid = true;
346                   break;
347                 }
348               }
349             if (!isInSolid)
350               InsertDependence(exp.Current()); //only shell not in solid
351           }
352         for (TopExp_Explorer exp(_subShape,TopAbs_FACE);exp.More();exp.Next())
353           {
354             InsertDependence(exp.Current());
355           }
356         for (TopExp_Explorer exp(_subShape,TopAbs_EDGE);exp.More();exp.Next())
357           {
358             InsertDependence(exp.Current());
359           }
360         break;
361       }
362     case TopAbs_COMPSOLID:
363       {
364         //MESSAGE("compsolid");
365         for (TopExp_Explorer exp(_subShape,TopAbs_SOLID);exp.More();exp.Next())
366           {
367             InsertDependence(exp.Current());
368           }
369 //      list<TopoDS_Shape> shapeList;
370 //      for (TopExp_Explorer exp(_subShape,TopAbs_SOLID);exp.More();exp.Next())
371 //        {
372 //          for (TopExp_Explorer 
373 //                 exp2(exp.Current(),TopAbs_FACE);exp2.More();exp2.Next())
374 //            {
375 //              shapeList.push_back(exp2.Current()); 
376 //            }
377 //        }
378 //      FinalizeDependence(shapeList);
379         break;
380       }
381     case TopAbs_SHELL:
382       {
383         //MESSAGE("shell");
384         for (TopExp_Explorer exp(_subShape,TopAbs_FACE);exp.More();exp.Next())
385           {
386             InsertDependence(exp.Current());
387           }
388 //      list<TopoDS_Shape> shapeList;
389 //      for (TopExp_Explorer exp(_subShape,TopAbs_FACE);exp.More();exp.Next())
390 //        {
391 //          for (TopExp_Explorer 
392 //                 exp2(exp.Current(),TopAbs_EDGE);exp2.More();exp2.Next())
393 //            {
394 //              shapeList.push_back(exp2.Current()); 
395 //            }
396 //        }
397 //      FinalizeDependence(shapeList);
398         break;
399       }
400     case TopAbs_WIRE:
401       {
402         //MESSAGE("wire");
403         for (TopExp_Explorer exp(_subShape,TopAbs_EDGE);exp.More();exp.Next())
404           {
405             InsertDependence(exp.Current());
406           }
407 //      list<TopoDS_Shape> shapeList;
408 //      for (TopExp_Explorer exp(_subShape,TopAbs_EDGE);exp.More();exp.Next())
409 //        {
410 //          for (TopExp_Explorer 
411 //                 exp2(exp.Current(),TopAbs_VERTEX);exp2.More();exp2.Next())
412 //            {
413 //              shapeList.push_back(exp2.Current()); 
414 //            }
415 //        }
416 //      FinalizeDependence(shapeList);
417         break;
418       }
419     case TopAbs_SOLID:
420       {
421         //MESSAGE("solid");
422 //      for (TopExp_Explorer exp(_subShape,TopAbs_SHELL);exp.More();exp.Next())
423 //        {
424 //          InsertDependence(exp.Current());
425 //        }
426         for (TopExp_Explorer exp(_subShape,TopAbs_FACE);exp.More();exp.Next())
427           {
428             InsertDependence(exp.Current());
429           }
430         break;
431       }
432     case TopAbs_FACE:
433       {
434         //MESSAGE("face");
435 //      for (TopExp_Explorer exp(_subShape,TopAbs_WIRE);exp.More();exp.Next())
436 //        {
437 //          InsertDependence(exp.Current());
438 //        }
439         for (TopExp_Explorer exp(_subShape,TopAbs_EDGE);exp.More();exp.Next())
440           {
441             InsertDependence(exp.Current());
442           }
443         break;
444       }
445     case TopAbs_EDGE:
446       {
447         //MESSAGE("edge");
448         for (TopExp_Explorer exp(_subShape,TopAbs_VERTEX);exp.More();exp.Next())
449           {
450             InsertDependence(exp.Current());
451           }
452         break;
453       }
454     case TopAbs_VERTEX:
455       {
456         break;
457       }
458     default:
459       {
460         break;
461       }
462     }
463   _dependenceAnalysed = true;
464   return _mapDepend;
465 }
466
467 //=============================================================================
468 /*!
469  * For simple Shapes (solid, face, edge): add subMesh into dependence list.
470  */
471 //=============================================================================
472
473 void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
474 {
475   //MESSAGE("SMESH_subMesh::InsertDependence");
476   //SMESH_subMesh* aSubMesh = _father->GetSubMeshContaining(aSubShape);
477   //SCRUTE(aSubMesh);
478   //if (! aSubMesh) aSubMesh = _father->GetSubMesh(aSubShape);
479
480   SMESH_subMesh* aSubMesh = _father->GetSubMesh(aSubShape);
481   int type = aSubShape.ShapeType();
482   int ordType = 9 - type; // 2 = Vertex, 8 = CompSolid
483   int cle = aSubMesh->GetId();
484   cle += 10000000 * ordType; // sort map by ordType then index
485   if (_mapDepend.find(cle) == _mapDepend.end())
486     {
487       _mapDepend[cle] = aSubMesh;
488       const map<int, SMESH_subMesh*>& subMap = aSubMesh->DependsOn();
489       map<int, SMESH_subMesh*>::const_iterator im;
490       for (im = subMap.begin(); im != subMap.end(); im++)
491         {
492           int clesub = (*im).first;
493           SMESH_subMesh* sm = (*im).second;
494           if (_mapDepend.find(clesub) == _mapDepend.end())
495             _mapDepend[clesub] = sm;
496         }
497     }
498
499 }
500  
501 //=============================================================================
502 /*!
503  * For collection shapes (compsolid, shell, wire).
504  * Add only subMesh figuring only once in multiset to dependence list 
505  */
506 //=============================================================================
507
508 // void SMESH_subMesh::FinalizeDependence(list<TopoDS_Shape>& shapeList)
509 // {
510 //   //MESSAGE("SMESH_subMesh::FinalizeDependence");
511 //   list<TopoDS_Shape>::iterator it1, it2;
512 //   for(it1 = shapeList.begin(); it1 != shapeList.end(); it1++)
513 //     {
514 //       TopoDS_Shape aSubShape = (*it1);
515 //       int count = 0;
516 //       for(it2 = shapeList.begin(); it2 != shapeList.end(); it2++)
517 //      {
518 //        TopoDS_Shape other = (*it2);
519 //        if (other.IsSame(aSubShape)) count++;
520 //      }
521 //       if (count == 1) InsertDependence(aSubShape);
522 //       SCRUTE(count);
523 //     }
524 // }
525
526 //=============================================================================
527 /*!
528  * 
529  */
530 //=============================================================================
531
532  const TopoDS_Shape& SMESH_subMesh::GetSubShape()
533 {
534   //MESSAGE("SMESH_subMesh::GetSubShape");
535   return _subShape;
536 }
537
538 //=============================================================================
539 /*!
540  * 
541  */
542 //=============================================================================
543
544 bool SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis* anHyp)
545   throw (SALOME_Exception)
546 {
547   //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
548   //SCRUTE(_algoState);
549   //SCRUTE(event);
550
551   // **** les retour des evenement shape sont significatifs
552   // (add ou remove fait ou non)
553   // le retour des evenement father n'indiquent pas que add ou remove fait
554   int dim = SMESH_Gen::GetShapeDim(_subShape);
555
556   if (dim < 1)
557     {
558       _algoState = HYP_OK;
559       //SCRUTE(_algoState);
560       return true;
561     }
562
563   SMESH_Gen* gen =_father->GetGen();
564   bool ret;
565   _oldAlgoState = _algoState;
566   bool modifiedHyp = false;  // if set to true, force event MODIF_ALGO_STATE
567                              // in ComputeStateEngine
568
569   switch (_algoState)
570     {
571
572       // ----------------------------------------------------------------------
573
574     case NO_ALGO:
575       switch (event)
576         {
577         case ADD_HYP:
578           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
579           ret = _meshDS->AddHypothesis(_subShape, anHyp);
580           break;
581         case ADD_ALGO:
582           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
583           if (anHyp->GetDim() <= SMESH_Gen::GetShapeDim(_subShape))
584             {
585               ret = _meshDS->AddHypothesis(_subShape, anHyp);
586 //            if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
587 //            if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
588               if (ret &&(anHyp->GetShapeType() & (1<< _subShape.ShapeType())))
589                 {
590                   SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
591                   ASSERT(algo);
592                   ret = algo->CheckHypothesis((*_father),_subShape);
593                   if (ret) SetAlgoState(HYP_OK);
594                   else SetAlgoState(MISSING_HYP);
595                 }
596             }
597           break;
598         case REMOVE_HYP:
599           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
600           ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
601           break;
602         case REMOVE_ALGO:
603           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
604           ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
605           break;
606         case ADD_FATHER_HYP:      // nothing to do
607           break;
608         case ADD_FATHER_ALGO:     // Algo just added in father
609           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
610 //        if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
611 //        if (anHyp->GetShapeType() == _subShape.ShapeType())
612           if (anHyp->GetShapeType() & (1<< _subShape.ShapeType()))
613             {
614               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
615               ASSERT(algo);
616               ret = algo->CheckHypothesis((*_father),_subShape);
617               if (ret) SetAlgoState(HYP_OK);
618               else SetAlgoState(MISSING_HYP);
619             }
620           break;
621         case REMOVE_FATHER_HYP:    // nothing to do
622           break;
623         case REMOVE_FATHER_ALGO:   // nothing to do
624           break;
625         default:
626           ASSERT(0);
627           break;
628         }
629       break;
630
631       // ----------------------------------------------------------------------
632
633     case MISSING_HYP:
634       switch (event)
635         {
636         case ADD_HYP:
637           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
638           ret = _meshDS->AddHypothesis(_subShape, anHyp);
639           if (ret)
640             {
641               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
642               ASSERT(algo);
643               ret = algo->CheckHypothesis((*_father),_subShape);
644               if (ret) SetAlgoState(HYP_OK);
645               else SetAlgoState(MISSING_HYP);
646             }
647           break;
648         case ADD_ALGO:            //already existing algo : on father ?
649           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
650           if (anHyp->GetDim() <= SMESH_Gen::GetShapeDim(_subShape))
651             {
652               ret = _meshDS->AddHypothesis(_subShape, anHyp);
653 //            if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
654 //            if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
655               if (ret &&(anHyp->GetShapeType() & (1<< _subShape.ShapeType())))
656                 {
657                   SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
658                   if (algo == NULL) // two algo on the same subShape...
659                     {
660                       MESSAGE("two algo on the same subshape not allowed");
661                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
662                       ret = false;
663                     }
664                   else
665                     {
666                       ret = algo->CheckHypothesis((*_father),_subShape);
667                       if (ret) SetAlgoState(HYP_OK);
668                       else SetAlgoState(MISSING_HYP);
669                     }
670                 }
671             }
672           break;
673         case REMOVE_HYP:
674           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);  
675           ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
676           break;
677         case REMOVE_ALGO:         // perhaps a father algo applies ?
678           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
679           ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
680 //        if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
681 //        if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
682           if (ret &&(anHyp->GetShapeType() & (1<<_subShape.ShapeType())))
683             {
684               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
685               if (algo == NULL)  // no more algo applying on subShape...
686                 {
687                   SetAlgoState(NO_ALGO);
688                 }
689               else
690                 {
691                   ret = algo->CheckHypothesis((*_father),_subShape);
692                   if (ret) SetAlgoState(HYP_OK);
693                   else SetAlgoState(MISSING_HYP);
694                 }
695             }
696           break;
697         case ADD_FATHER_HYP:
698           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
699           {
700             SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
701             ASSERT(algo);
702             ret = algo->CheckHypothesis((*_father),_subShape);
703             if (ret) SetAlgoState(HYP_OK);
704             else SetAlgoState(MISSING_HYP);
705           }
706           break;
707         case ADD_FATHER_ALGO:     // detect if two algo of same dim on father
708           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
709 //        if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
710 //        if (anHyp->GetShapeType() == _subShape.ShapeType())
711           if (anHyp->GetShapeType() & (1<< _subShape.ShapeType()))
712             {
713               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
714               if (algo == NULL)  // two applying algo on father
715                 {
716                   MESSAGE("two applying algo on fatherShape...");
717                   SetAlgoState(NO_ALGO);
718                 }
719               else
720                 {
721                   ret = algo->CheckHypothesis((*_father),_subShape);
722                   if (ret) SetAlgoState(HYP_OK);
723                   else SetAlgoState(MISSING_HYP);
724                 }
725             }
726           break;
727         case REMOVE_FATHER_HYP:    // nothing to do
728           break;
729         case REMOVE_FATHER_ALGO:
730           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
731 //        if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
732 //        if (anHyp->GetShapeType() == _subShape.ShapeType())
733           if (anHyp->GetShapeType() & (1<< _subShape.ShapeType()))
734             {
735               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
736               if (algo == NULL)  // no more applying algo on father
737                 {
738                   SetAlgoState(NO_ALGO);
739                 }
740               else
741                 {
742                   ret = algo->CheckHypothesis((*_father),_subShape);
743                   if (ret) SetAlgoState(HYP_OK);
744                   else SetAlgoState(MISSING_HYP);
745                 }
746             }
747           break;
748         default:
749           ASSERT(0);
750           break;
751         }
752       break;
753
754       // ----------------------------------------------------------------------
755
756     case HYP_OK:
757       switch (event)
758         {
759         case ADD_HYP:
760           {
761             ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
762             SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
763             ASSERT(algo);
764             list<SMESHDS_Hypothesis*> originalUsedHyps
765               = algo->GetUsedHypothesis((*_father), _subShape); // copy
766             
767             ret = _meshDS->AddHypothesis(_subShape, anHyp);
768             if (ret)
769               {
770                 ret = algo->CheckHypothesis((*_father),_subShape);
771                 if (! ret) 
772                   {
773                     INFOS("two applying algo on the same shape not allowed");
774                     ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
775                     ret = false;
776                   }
777                 else  // compare SMESHDS_Hypothesis* lists (order important)
778                   {
779                     MESSAGE("---");
780                     const list<SMESHDS_Hypothesis*>& newUsedHyps
781                       = algo->GetUsedHypothesis((*_father), _subShape);
782                     modifiedHyp = (originalUsedHyps != newUsedHyps); 
783                   }
784               }
785           }
786           break;
787         case ADD_ALGO:            //already existing algo : on father ?
788           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
789           if (anHyp->GetDim() <= SMESH_Gen::GetShapeDim(_subShape))
790             {
791               ret = _meshDS->AddHypothesis(_subShape, anHyp);
792 //            if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
793 //            if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
794               if (ret &&(anHyp->GetShapeType() & (1<< _subShape.ShapeType())))
795                 {
796                   SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
797                   if (algo == NULL) // two algo on the same subShape...
798                     {
799                       INFOS("two algo on the same subshape not allowed");
800                       ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
801                       ret = false;
802                     }
803                   else
804                     {
805                       ret = algo->CheckHypothesis((*_father),_subShape);
806                       if (ret) SetAlgoState(HYP_OK);
807                       else SetAlgoState(MISSING_HYP);
808                     }
809                 }
810             }
811           break;
812         case REMOVE_HYP:
813           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
814           ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
815           if (ret)
816             {
817               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
818               ASSERT(algo);
819               ret = algo->CheckHypothesis((*_father),_subShape);
820               if (ret) SetAlgoState(HYP_OK);
821               else SetAlgoState(MISSING_HYP);
822               modifiedHyp = true;
823             }
824           break;
825         case REMOVE_ALGO:         // perhaps a father algo applies ?
826           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
827           ret = _meshDS->RemoveHypothesis(_subShape, anHyp);
828 //        if (ret &&(anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape)))
829 //        if (ret &&(anHyp->GetShapeType() == _subShape.ShapeType()))
830           if (ret &&(anHyp->GetShapeType() & (1<< _subShape.ShapeType())))
831             {
832               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
833               if (algo == NULL)   // no more algo applying on subShape...
834                 {
835                   SetAlgoState(NO_ALGO);
836                 }
837               else
838                 {
839                   ret = algo->CheckHypothesis((*_father),_subShape);
840                   if (ret) SetAlgoState(HYP_OK);
841                   else SetAlgoState(MISSING_HYP);
842                 }
843             }
844           break;
845         case ADD_FATHER_HYP:
846           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
847           {
848             SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
849             ASSERT(algo);
850             ret = algo->CheckHypothesis((*_father),_subShape);
851             if (ret) SetAlgoState(HYP_OK);
852             else SetAlgoState(MISSING_HYP);
853           }
854           break;
855         case ADD_FATHER_ALGO:     // detect if two algo of same dim on father
856           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
857 //        if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
858 //        if (anHyp->GetShapeType() == _subShape.ShapeType())
859           if (anHyp->GetShapeType() & (1<< _subShape.ShapeType()))
860             {
861               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
862               if (algo == NULL)  // two applying algo on father
863                 {
864                   MESSAGE("two applying algo on fatherShape...");
865                   SetAlgoState(NO_ALGO);
866                 }
867               else
868                 {
869                   ret = algo->CheckHypothesis((*_father),_subShape);
870                   if (ret) SetAlgoState(HYP_OK);
871                   else SetAlgoState(MISSING_HYP);
872                 }
873             }
874           break;
875         case REMOVE_FATHER_HYP:
876           ASSERT(anHyp->GetType() == SMESHDS_Hypothesis::PARAM_ALGO);
877           {
878             SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
879             ASSERT(algo);
880             ret = algo->CheckHypothesis((*_father),_subShape);
881             if (ret) SetAlgoState(HYP_OK);
882             else SetAlgoState(MISSING_HYP);
883           }
884           break;
885         case REMOVE_FATHER_ALGO:
886           ASSERT(anHyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO);
887 //        if (anHyp->GetDim() == SMESH_Gen::GetShapeDim(_subShape))
888 //        if (anHyp->GetShapeType() == _subShape.ShapeType())
889           if (anHyp->GetShapeType() & (1<< _subShape.ShapeType()))
890             {
891               SMESH_Algo* algo = gen->GetAlgo((*_father), _subShape);
892               if (algo == NULL)  // no more applying algo on father
893                 {
894                   SetAlgoState(NO_ALGO);
895                 }
896               else
897                 {
898                   ret = algo->CheckHypothesis((*_father),_subShape);
899                   if (ret) SetAlgoState(HYP_OK);
900                   else SetAlgoState(MISSING_HYP);
901                 }
902             }
903           break;
904         default:
905           ASSERT(0);
906           break;
907         }
908       break;
909
910       // ----------------------------------------------------------------------
911
912     default:
913       ASSERT(0);
914       break;
915     }
916   //SCRUTE(_algoState);
917   if ((_algoState != _oldAlgoState) || modifiedHyp)
918     int retc = ComputeStateEngine(MODIF_ALGO_STATE);
919   return ret;
920 }
921
922 //=============================================================================
923 /*!
924  * 
925  */
926 //=============================================================================
927
928 void SMESH_subMesh::SetAlgoState(int state)
929 {
930   if (state != _oldAlgoState)
931 //     int retc = ComputeStateEngine(MODIF_ALGO_STATE);
932   _algoState = state;
933 }
934
935 //=============================================================================
936 /*!
937  * 
938  */
939 //=============================================================================
940
941 void SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
942                                              SMESH_Hypothesis* anHyp)
943     throw (SALOME_Exception)
944 {
945   //MESSAGE("SMESH_subMesh::SubMeshesAlgoStateEngine");
946   int dim = SMESH_Gen::GetShapeDim(_subShape);
947   if (dim > 1)
948     {
949       const map<int, SMESH_subMesh*>& subMeshes = DependsOn();
950       
951       map<int, SMESH_subMesh*>::const_iterator itsub;
952       for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
953         {
954           SMESH_subMesh* sm = (*itsub).second;
955           sm->AlgoStateEngine(event, anHyp);
956         }
957     }
958 }
959
960 //=============================================================================
961 /*!
962  * 
963  */
964 //=============================================================================
965
966 void SMESH_subMesh::DumpAlgoState(bool isMain)
967 {
968   int dim = SMESH_Gen::GetShapeDim(_subShape);
969 //   if (dim < 1) return;
970   if (isMain)
971     {
972       const map<int, SMESH_subMesh*>& subMeshes = DependsOn();
973       
974       map<int, SMESH_subMesh*>::const_iterator itsub;
975       for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
976         {
977           SMESH_subMesh* sm = (*itsub).second;
978           sm->DumpAlgoState(false);
979         } 
980     }
981   int type = _subShape.ShapeType();
982   MESSAGE("dim = " << dim << " type of shape " << type);
983   switch(_algoState)
984     {
985     case NO_ALGO: MESSAGE(" AlgoState = NO_ALGO"); break;
986     case MISSING_HYP: MESSAGE(" AlgoState = MISSING_HYP"); break;
987     case HYP_OK: MESSAGE(" AlgoState = HYP_OK"); break;
988     }
989   switch (_computeState)
990     {
991     case NOT_READY: MESSAGE(" ComputeState = NOT_READY"); break;
992     case READY_TO_COMPUTE: MESSAGE(" ComputeState = READY_TO_COMPUTE"); break;
993     case COMPUTE_OK: MESSAGE(" ComputeState = COMPUTE_OK"); break;
994     case FAILED_TO_COMPUTE: MESSAGE(" ComputeState = FAILED_TO_COMPUTE");break;
995     }
996 }
997
998 //=============================================================================
999 /*!
1000  * 
1001  */
1002 //=============================================================================
1003
1004 bool SMESH_subMesh::ComputeStateEngine(int event)
1005   throw (SALOME_Exception)
1006 {
1007   //MESSAGE("SMESH_subMesh::ComputeStateEngine");
1008   //SCRUTE(_computeState);
1009   //SCRUTE(event);
1010
1011   int dim = SMESH_Gen::GetShapeDim(_subShape);
1012
1013   if (dim < 1)
1014     {
1015       if (_vertexSet) _computeState = COMPUTE_OK;
1016       else _computeState = READY_TO_COMPUTE;
1017       //SCRUTE(_computeState);
1018       return true;
1019     }
1020   SMESH_Gen* gen =_father->GetGen();
1021   SMESH_Algo* algo = 0;
1022   bool ret;
1023
1024   switch(_computeState)
1025     {
1026
1027       // ----------------------------------------------------------------------
1028
1029     case NOT_READY:
1030       switch (event)
1031         {
1032         case MODIF_HYP:                // nothing to do
1033           break;
1034         case MODIF_ALGO_STATE:
1035           if (_algoState == HYP_OK)
1036             _computeState = READY_TO_COMPUTE;
1037           break;
1038         case COMPUTE:                  // nothing to do
1039           break;
1040         case CLEAN:                    // nothing to do
1041           break;
1042         case CLEANDEP:                 // nothing to do
1043           RemoveSubMeshElementsAndNodes(); // recursive call...
1044           break;
1045         case SUBMESH_COMPUTED:         // nothing to do
1046           break;
1047         default:
1048           ASSERT(0);
1049           break;
1050         }
1051       break;
1052
1053       // ----------------------------------------------------------------------
1054
1055     case READY_TO_COMPUTE:
1056       switch (event)
1057         {
1058         case MODIF_HYP:                // nothing to do
1059           break;
1060         case MODIF_ALGO_STATE:
1061           _computeState = NOT_READY;
1062           algo = gen->GetAlgo((*_father), _subShape);
1063           if (algo)
1064             {
1065               ret = algo->CheckHypothesis((*_father),_subShape);
1066               if (ret) _computeState = READY_TO_COMPUTE;
1067             }
1068           break;
1069         case COMPUTE:
1070           {
1071             algo = gen->GetAlgo((*_father), _subShape);
1072             ASSERT(algo);
1073             ret = algo->CheckHypothesis((*_father),_subShape);
1074             if (! ret)
1075               {
1076                 MESSAGE("***** verify compute state *****");
1077                 _computeState = NOT_READY;
1078                 break;
1079               }
1080             ret = SubMeshesComputed();
1081             if (!ret)
1082               {
1083                 MESSAGE("Some SubMeshes not computed");
1084                 _computeState = FAILED_TO_COMPUTE;
1085                 break;
1086               }
1087             ret = algo->Compute((*_father),_subShape);
1088             if (!ret)
1089               {
1090                 MESSAGE("problem in algo execution: failed to compute");
1091                 _computeState = FAILED_TO_COMPUTE;
1092                 break;
1093               }
1094             else
1095               {
1096                 _computeState = COMPUTE_OK;
1097                 UpdateDependantsState(); // send event SUBMESH_COMPUTED
1098               }
1099           }
1100           break;
1101         case CLEAN:
1102           _computeState = NOT_READY;
1103           algo = gen->GetAlgo((*_father), _subShape);
1104           if (algo)
1105             {
1106               ret = algo->CheckHypothesis((*_father),_subShape);
1107               if (ret) _computeState = READY_TO_COMPUTE;
1108             }
1109           break;
1110         case CLEANDEP:
1111           RemoveSubMeshElementsAndNodes();
1112           _computeState = NOT_READY;
1113           algo = gen->GetAlgo((*_father), _subShape);
1114           if (algo)
1115             {
1116               ret = algo->CheckHypothesis((*_father),_subShape);
1117               if (ret) _computeState = READY_TO_COMPUTE;
1118             }
1119           break;
1120         case SUBMESH_COMPUTED:         // nothing to do
1121           break;
1122         default:
1123           ASSERT(0);
1124           break;
1125         }
1126       break;
1127
1128       // ----------------------------------------------------------------------
1129
1130     case COMPUTE_OK:
1131       switch (event)
1132         {
1133         case MODIF_HYP:
1134           CleanDependants();           // recursive recall with event CLEANDEP
1135           break;
1136         case MODIF_ALGO_STATE:
1137           CleanDependants();           // recursive recall with event CLEANDEP
1138           break;
1139         case COMPUTE:                  // nothing to do
1140           break;
1141         case CLEAN:
1142           CleanDependants();           // recursive recall with event CLEANDEP
1143           break;
1144         case CLEANDEP:
1145           RemoveSubMeshElementsAndNodes();
1146           _computeState = NOT_READY;
1147           algo = gen->GetAlgo((*_father), _subShape);
1148           if (algo)
1149             {
1150               ret = algo->CheckHypothesis((*_father),_subShape);
1151               if (ret) _computeState = READY_TO_COMPUTE;
1152             }
1153           break;
1154         case SUBMESH_COMPUTED:         // nothing to do
1155           break;
1156         default:
1157           ASSERT(0);
1158           break;
1159         }
1160       break;
1161
1162       // ----------------------------------------------------------------------
1163
1164     case FAILED_TO_COMPUTE:
1165       switch (event)
1166         {
1167         case MODIF_HYP:
1168           if (_algoState == HYP_OK)
1169             _computeState = READY_TO_COMPUTE;
1170           else _computeState = NOT_READY;
1171           break;
1172         case MODIF_ALGO_STATE:
1173           if (_algoState == HYP_OK)
1174             _computeState = READY_TO_COMPUTE;
1175           else _computeState = NOT_READY;
1176           break;
1177         case COMPUTE:                  // nothing to do
1178           break;
1179         case CLEAN:
1180           break;
1181         case CLEANDEP:
1182           RemoveSubMeshElementsAndNodes();
1183           if (_algoState == HYP_OK)
1184             _computeState = READY_TO_COMPUTE;
1185           else _computeState = NOT_READY;
1186           break;
1187         case SUBMESH_COMPUTED:         // allow retry compute
1188           if (_algoState == HYP_OK)
1189             _computeState = READY_TO_COMPUTE;
1190           else _computeState = NOT_READY;
1191           break;
1192         default:
1193           ASSERT(0);
1194           break;
1195         }
1196       break;
1197
1198       // ----------------------------------------------------------------------
1199     default:
1200       ASSERT(0);
1201       break;
1202     }
1203
1204   //SCRUTE(_computeState);
1205   return ret;
1206 }
1207
1208 //=============================================================================
1209 /*!
1210  * 
1211  */
1212 //=============================================================================
1213
1214 void SMESH_subMesh::UpdateDependantsState()
1215 {
1216   //MESSAGE("SMESH_subMesh::UpdateDependantsState");
1217
1218   const map<int, SMESH_subMesh*>& dependants = Dependants();
1219   map<int, SMESH_subMesh*>::const_iterator its;
1220   for (its = dependants.begin(); its != dependants.end(); its++)
1221     {
1222       SMESH_subMesh* sm = (*its).second;
1223       //SCRUTE((*its).first);
1224       sm->ComputeStateEngine(SUBMESH_COMPUTED);
1225     }
1226 }
1227
1228 //=============================================================================
1229 /*!
1230  * 
1231  */
1232 //=============================================================================
1233
1234 void SMESH_subMesh::CleanDependants()
1235 {
1236   MESSAGE("SMESH_subMesh::CleanDependants");
1237   // **** parcourir les ancetres dans l'ordre de dépendance
1238
1239   const map<int, SMESH_subMesh*>& dependants = Dependants();
1240   map<int, SMESH_subMesh*>::const_iterator its;
1241   for (its = dependants.begin(); its != dependants.end(); its++)
1242     {
1243       SMESH_subMesh* sm = (*its).second;
1244       SCRUTE((*its).first);
1245       sm->ComputeStateEngine(CLEANDEP);
1246     }
1247   ComputeStateEngine(CLEANDEP);
1248 }
1249 //=============================================================================
1250 /*!
1251  * 
1252  */
1253 //=============================================================================
1254
1255 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
1256 {
1257   MESSAGE("SMESH_subMesh::RemoveSubMeshElementsAndNodes");
1258   SCRUTE(_subShape.ShapeType());
1259   SCRUTE(_Id);
1260
1261   _subMeshDS =  _meshDS->MeshElements(_subShape);
1262   if (!_subMeshDS.IsNull())
1263     {
1264       const TColStd_ListOfInteger& indElt
1265         = _subMeshDS->GetIDElements();
1266       TColStd_ListIteratorOfListOfInteger ite(indElt);
1267       for (; ite.More(); ite.Next())
1268         {
1269           int eltId = ite.Value();
1270           SCRUTE(eltId);
1271           Handle (SMDS_MeshElement) elt = _meshDS->FindElement(eltId);
1272           _subMeshDS->RemoveElement(elt);
1273           _meshDS->RemoveElement(eltId);
1274         }
1275   
1276       const TColStd_ListOfInteger& indNodes
1277         = _subMeshDS->GetIDNodes();
1278       TColStd_ListIteratorOfListOfInteger itn(indNodes);
1279       for (; itn.More(); itn.Next())
1280         {
1281           int nodeId = itn.Value();
1282           SCRUTE(nodeId);
1283           Handle (SMDS_MeshElement) elt = _meshDS->FindNode(nodeId);
1284           Handle (SMDS_MeshNode) node = _meshDS->GetNode(1, elt);
1285           _subMeshDS->RemoveNode(node);
1286           _meshDS->RemoveNode(nodeId);
1287         }
1288     }
1289 }
1290
1291 //=============================================================================
1292 /*!
1293  * 
1294  */
1295 //=============================================================================
1296
1297 const map<int, SMESH_subMesh*>& SMESH_subMesh::Dependants()
1298 {
1299   if (_dependantsFound) return _mapDependants;
1300
1301   //MESSAGE("SMESH_subMesh::Dependants");
1302
1303   int shapeType = _subShape.ShapeType();
1304   //SCRUTE(shapeType);
1305   TopTools_IndexedDataMapOfShapeListOfShape M;
1306   TopoDS_Shape mainShape = _meshDS->ShapeToMesh();
1307
1308   switch (shapeType)
1309     {
1310     case TopAbs_VERTEX:
1311       break;
1312     case TopAbs_EDGE:
1313     case TopAbs_WIRE:
1314       TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_WIRE, M);
1315       TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_FACE, M);
1316       TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_SHELL, M);
1317       TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_SOLID, M);
1318       TopExp::MapShapesAndAncestors(mainShape, TopAbs_EDGE, TopAbs_COMPSOLID, M);
1319       ExtractDependants(M, TopAbs_EDGE);
1320       break;
1321     case TopAbs_FACE:
1322     case TopAbs_SHELL:
1323       TopExp::MapShapesAndAncestors(mainShape, TopAbs_FACE, TopAbs_SHELL, M);
1324       TopExp::MapShapesAndAncestors(mainShape, TopAbs_FACE, TopAbs_SOLID, M);
1325       TopExp::MapShapesAndAncestors(mainShape, TopAbs_FACE, TopAbs_COMPSOLID, M);
1326       ExtractDependants(M, TopAbs_FACE);
1327       break;
1328     case TopAbs_SOLID:
1329     case TopAbs_COMPSOLID:
1330       TopExp::MapShapesAndAncestors(mainShape, TopAbs_SOLID, TopAbs_COMPSOLID, M);
1331       ExtractDependants(M, TopAbs_SOLID);
1332       break;
1333      case TopAbs_COMPOUND:
1334       break;
1335    }
1336
1337   _dependantsFound = true;
1338   return _mapDependants;
1339 }
1340
1341 //=============================================================================
1342 /*!
1343  * 
1344  */
1345 //=============================================================================
1346
1347 void SMESH_subMesh::ExtractDependants(const TopTools_IndexedDataMapOfShapeListOfShape& M,
1348                                       const TopAbs_ShapeEnum etype)
1349 {
1350   //MESSAGE("SMESH_subMesh::ExtractDependants");
1351
1352   TopoDS_Shape mainShape = _meshDS->ShapeToMesh();
1353   int lg = M.Extent();
1354   //SCRUTE(lg);
1355
1356   int shapeType = _subShape.ShapeType();
1357   switch (shapeType)
1358     {
1359     case TopAbs_VERTEX:
1360       break;
1361     case TopAbs_EDGE:
1362     case TopAbs_FACE:
1363     case TopAbs_SOLID:
1364       {
1365         const TopTools_ListOfShape& ancestors = M.FindFromKey(_subShape);
1366         TopTools_ListIteratorOfListOfShape it(ancestors);
1367         for ( ; it.More();it.Next())
1368           {
1369             TopoDS_Shape ancestor = it.Value();
1370             SMESH_subMesh* aSubMesh = _father->GetSubMeshContaining(ancestor);
1371             //      if (! aSubMesh) aSubMesh = _father->GetSubMesh(ancestor);
1372             if (aSubMesh)
1373               {
1374                 int type = aSubMesh->_subShape.ShapeType();
1375                 int cle = aSubMesh->GetId();
1376                 cle += 10000000 * type; // sort map by ordType then index
1377                 if (_mapDependants.find(cle) == _mapDependants.end())
1378                   {
1379                     _mapDependants[cle] = aSubMesh;
1380                     //SCRUTE(cle);
1381                   }
1382               } 
1383           }
1384       }
1385       break;
1386     case TopAbs_WIRE:
1387     case TopAbs_SHELL:
1388     case TopAbs_COMPSOLID:
1389       for (TopExp_Explorer expE(_subShape, etype); expE.More(); expE.Next())
1390         {
1391           TopoDS_Shape aShape = expE.Current();
1392           const TopTools_ListOfShape& ancestors = M.FindFromKey( aShape);
1393           TopTools_ListIteratorOfListOfShape it(ancestors);
1394           for ( ; it.More();it.Next())
1395             {
1396               MESSAGE("---");
1397               TopoDS_Shape ancestor = it.Value();
1398               SMESH_subMesh* aSubMesh = _father->GetSubMeshContaining(ancestor);
1399               if (! aSubMesh) aSubMesh = _father->GetSubMesh(ancestor);
1400               int type = aSubMesh->_subShape.ShapeType();
1401               int cle = aSubMesh->GetId();
1402               cle += 10000000 * type; // sort map by ordType then index
1403               if (_mapDependants.find(cle) == _mapDependants.end())
1404                 {
1405                   _mapDependants[cle] = aSubMesh;
1406                   SCRUTE(cle);
1407                 }
1408             }   
1409         } 
1410       break;
1411      case TopAbs_COMPOUND:
1412       break;
1413    }
1414 }
1415