Version: 6.3.1

src/SMESH/SMESH_subMesh.cxx

Go to the documentation of this file.
00001 // Copyright (C) 2007-2011  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 //  SMESH SMESH : implementaion of SMESH idl descriptions
00024 //  File   : SMESH_subMesh.cxx
00025 //  Author : Paul RASCLE, EDF
00026 //  Module : SMESH
00027 //
00028 #include "SMESH_subMesh.hxx"
00029 
00030 #include "SMESH_Algo.hxx"
00031 #include "SMESH_Gen.hxx"
00032 #include "SMESH_HypoFilter.hxx"
00033 #include "SMESH_Hypothesis.hxx"
00034 #include "SMESH_Mesh.hxx"
00035 #include "SMESH_MesherHelper.hxx"
00036 #include "SMESH_subMeshEventListener.hxx"
00037 #include "SMESH_Comment.hxx"
00038 #include "SMDS_SetIterator.hxx"
00039 #include "SMDSAbs_ElementType.hxx"
00040 
00041 #include "utilities.h"
00042 #include "OpUtil.hxx"
00043 #include "Basics_Utils.hxx"
00044 
00045 #include <BRep_Builder.hxx>
00046 #include <BRep_Tool.hxx>
00047 #include <TopExp.hxx>
00048 #include <TopTools_IndexedMapOfShape.hxx>
00049 #include <TopTools_ListIteratorOfListOfShape.hxx>
00050 #include <TopoDS.hxx>
00051 #include <TopoDS_Compound.hxx>
00052 #include <gp_Pnt.hxx>
00053 #include <TopExp_Explorer.hxx>
00054 #include <TopoDS_Iterator.hxx>
00055 
00056 #include <Standard_OutOfMemory.hxx>
00057 #include <Standard_ErrorHandler.hxx>
00058 
00059 #include <numeric>
00060 
00061 using namespace std;
00062 
00063 //=============================================================================
00069 //=============================================================================
00070 
00071 struct MemoryReserve
00072 {
00073   char* myBuf;
00074   MemoryReserve(): myBuf( new char[1024*1024*2] ){}
00075   ~MemoryReserve() { delete [] myBuf; }
00076 };
00077 
00078 //=============================================================================
00082 //=============================================================================
00083 
00084 SMESH_subMesh::SMESH_subMesh(int                  Id,
00085                              SMESH_Mesh *         father,
00086                              SMESHDS_Mesh *       meshDS,
00087                              const TopoDS_Shape & aSubShape)
00088 {
00089         _subShape = aSubShape;
00090         _subMeshDS = meshDS->MeshElements(_subShape);   // may be null ...
00091         _father = father;
00092         _Id = Id;
00093         _dependenceAnalysed = _alwaysComputed = false;
00094 
00095         if (_subShape.ShapeType() == TopAbs_VERTEX)
00096         {
00097                 _algoState = HYP_OK;
00098                 _computeState = READY_TO_COMPUTE;
00099         }
00100         else
00101         {
00102           _algoState = NO_ALGO;
00103           _computeState = NOT_READY;
00104         }
00105 }
00106 
00107 //=============================================================================
00111 //=============================================================================
00112 
00113 SMESH_subMesh::~SMESH_subMesh()
00114 {
00115   MESSAGE("SMESH_subMesh::~SMESH_subMesh");
00116   // ****
00117   DeleteOwnListeners();
00118 }
00119 
00120 //=============================================================================
00124 //=============================================================================
00125 
00126 int SMESH_subMesh::GetId() const
00127 {
00128   //MESSAGE("SMESH_subMesh::GetId");
00129   return _Id;
00130 }
00131 
00132 //=============================================================================
00136 //=============================================================================
00137 
00138 SMESHDS_SubMesh * SMESH_subMesh::GetSubMeshDS()
00139 {
00140   // submesh appears in DS only when a mesher set nodes and elements on a shape
00141   return _subMeshDS ? _subMeshDS : _subMeshDS = _father->GetMeshDS()->MeshElements(_subShape); // may be null
00142 }
00143 
00144 //=============================================================================
00148 //=============================================================================
00149 
00150 SMESHDS_SubMesh* SMESH_subMesh::CreateSubMeshDS()
00151 {
00152   if ( !GetSubMeshDS() ) {
00153     SMESHDS_Mesh* meshDS = _father->GetMeshDS();
00154     meshDS->NewSubMesh( meshDS->ShapeToIndex( _subShape ) );
00155   }
00156   return GetSubMeshDS();
00157 }
00158 
00159 //=============================================================================
00163 //=============================================================================
00164 
00165 SMESH_subMesh *SMESH_subMesh::GetFirstToCompute()
00166 {
00167   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(true,false);
00168   while ( smIt->more() ) {
00169     SMESH_subMesh *sm = smIt->next();
00170     if ( sm->GetComputeState() == READY_TO_COMPUTE )
00171       return sm;
00172   }
00173   return 0;                     // nothing to compute
00174 }
00175 
00176 //================================================================================
00181 //================================================================================
00182 
00183 void SMESH_subMesh::SetIsAlwaysComputed(bool isAlCo)
00184 {
00185   _alwaysComputed = isAlCo;
00186   if ( _alwaysComputed )
00187     _computeState = COMPUTE_OK;
00188   else
00189     ComputeStateEngine( CHECK_COMPUTE_STATE );
00190 }
00191 
00192 //=======================================================================
00196 //=======================================================================
00197 
00198 bool SMESH_subMesh::IsEmpty() const
00199 {
00200   if (SMESHDS_SubMesh * subMeshDS = ((SMESH_subMesh*)this)->GetSubMeshDS())
00201     return (!subMeshDS->NbElements() && !subMeshDS->NbNodes());
00202   return true;
00203 }
00204 
00205 //=======================================================================
00206 //function : IsMeshComputed
00207 //purpose  : check if _subMeshDS contains mesh elements
00208 //=======================================================================
00209 
00210 bool SMESH_subMesh::IsMeshComputed() const
00211 {
00212   if ( _alwaysComputed )
00213     return true;
00214   // algo may bind a submesh not to _subShape, eg 3D algo
00215   // sets nodes on SHELL while _subShape may be SOLID
00216 
00217   SMESHDS_Mesh* meshDS = _father->GetMeshDS();
00218   int dim = SMESH_Gen::GetShapeDim( _subShape );
00219   int type = _subShape.ShapeType();
00220   for ( ; type <= TopAbs_VERTEX; type++) {
00221     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
00222     {
00223       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
00224       for ( ; exp.More(); exp.Next() )
00225       {
00226         if ( SMESHDS_SubMesh * smDS = meshDS->MeshElements( exp.Current() ))
00227         {
00228           bool computed = (dim > 0) ? smDS->NbElements() : smDS->NbNodes();
00229           if ( computed )
00230             return true;
00231         }
00232       }
00233     }
00234     else
00235       break;
00236   }
00237 
00238   return false;
00239 }
00240 
00241 //=============================================================================
00245 //=============================================================================
00246 
00247 bool SMESH_subMesh::SubMeshesComputed()
00248 {
00249   int myDim = SMESH_Gen::GetShapeDim( _subShape );
00250   int dimToCheck = myDim - 1;
00251   bool subMeshesComputed = true;
00252   // check subMeshes with upper dimension => reverse iteration
00253   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
00254   while ( smIt->more() )
00255   {
00256     SMESH_subMesh *sm = smIt->next();
00257     if ( sm->_alwaysComputed )
00258       continue;
00259     const TopoDS_Shape & ss = sm->GetSubShape();
00260     // MSV 07.04.2006: restrict checking to myDim-1 only. Ex., there is no sense
00261     // in checking of existence of edges if the algo needs only faces. Moreover,
00262     // degenerated edges may have no submesh, as after computing NETGEN_2D.
00263     int dim = SMESH_Gen::GetShapeDim( ss );
00264     if (dim < dimToCheck)
00265       break; // the rest subMeshes are all of less dimension
00266     SMESHDS_SubMesh * ds = sm->GetSubMeshDS();
00267     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
00268                       (ds && ( dimToCheck ? ds->NbElements() : ds->NbNodes()  )));
00269     if (!computeOk)
00270     {
00271       int type = ss.ShapeType();
00272 
00273       subMeshesComputed = false;
00274 
00275       switch (type)
00276       {
00277       case TopAbs_COMPOUND:
00278         {
00279           MESSAGE("The not computed sub mesh is a COMPOUND");
00280           break;
00281         }
00282       case TopAbs_COMPSOLID:
00283         {
00284           MESSAGE("The not computed sub mesh is a COMPSOLID");
00285           break;
00286         }
00287       case TopAbs_SHELL:
00288         {
00289           MESSAGE("The not computed sub mesh is a SHEL");
00290           break;
00291         }
00292       case TopAbs_WIRE:
00293         {
00294           MESSAGE("The not computed sub mesh is a WIRE");
00295           break;
00296         }
00297       case TopAbs_SOLID:
00298         {
00299           MESSAGE("The not computed sub mesh is a SOLID");
00300           break;
00301         }
00302       case TopAbs_FACE:
00303         {
00304           MESSAGE("The not computed sub mesh is a FACE");
00305           break;
00306         }
00307       case TopAbs_EDGE:
00308         {
00309           MESSAGE("The not computed sub mesh is a EDGE");
00310           break;
00311         }
00312       default:
00313         {
00314           MESSAGE("The not computed sub mesh is of unknown type");
00315           break;
00316         }
00317       }
00318 
00319       break;
00320     }
00321   }
00322   return subMeshesComputed;
00323 }
00324 
00325 //=============================================================================
00329 //=============================================================================
00330 
00331 bool SMESH_subMesh::SubMeshesReady()
00332 {
00333   bool subMeshesReady = true;
00334   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,true);
00335   while ( smIt->more() ) {
00336     SMESH_subMesh *sm = smIt->next();
00337     bool computeOk = (sm->GetComputeState() == COMPUTE_OK ||
00338                       sm->GetComputeState() == READY_TO_COMPUTE);
00339     if (!computeOk)
00340     {
00341       subMeshesReady = false;
00342       SCRUTE(sm->GetId());
00343       break;
00344     }
00345   }
00346   return subMeshesReady;
00347 }
00348 
00349 //=============================================================================
00359 //=============================================================================
00360 
00361 const map < int, SMESH_subMesh * >& SMESH_subMesh::DependsOn()
00362 {
00363   if (_dependenceAnalysed)
00364     return _mapDepend;
00365 
00366   //MESSAGE("SMESH_subMesh::DependsOn");
00367 
00368   int type = _subShape.ShapeType();
00369   //SCRUTE(type);
00370   switch (type)
00371   {
00372   case TopAbs_COMPOUND:
00373     {
00374       //MESSAGE("compound");
00375       for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More();exp.Next())
00376       {
00377         InsertDependence(exp.Current());
00378       }
00379       for (TopExp_Explorer exp(_subShape, TopAbs_SHELL, TopAbs_SOLID); exp.More(); exp.Next())
00380       {
00381         if ( BRep_Tool::IsClosed(exp.Current() ))
00382           InsertDependence(exp.Current());      //only shell not in solid
00383         else
00384           for (TopExp_Explorer expF(exp.Current(), TopAbs_FACE); expF.More();expF.Next())
00385             InsertDependence(expF.Current());    // issue 0020959: HEXA_3D fails on shell
00386 
00387       }
00388       for (TopExp_Explorer exp(_subShape, TopAbs_FACE, TopAbs_SHELL); exp.More();exp.Next())
00389       {
00390         InsertDependence(exp.Current());
00391       }
00392       for (TopExp_Explorer exp(_subShape, TopAbs_EDGE, TopAbs_FACE); exp.More();exp.Next())
00393       {
00394         InsertDependence(exp.Current());
00395       }
00396       break;
00397     }
00398   case TopAbs_COMPSOLID:
00399     {
00400       //MESSAGE("compsolid");
00401       for (TopExp_Explorer exp(_subShape, TopAbs_SOLID); exp.More(); exp.Next())
00402       {
00403         InsertDependence(exp.Current());
00404       }
00405       break;
00406     }
00407   case TopAbs_SHELL:
00408     {
00409       //MESSAGE("shell");
00410       for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More(); exp.Next())
00411       {
00412         InsertDependence(exp.Current());
00413       }
00414       break;
00415     }
00416   case TopAbs_WIRE:
00417     {
00418       //MESSAGE("wire");
00419       for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More(); exp.Next())
00420       {
00421         InsertDependence(exp.Current());
00422       }
00423       break;
00424     }
00425   case TopAbs_SOLID:
00426     {
00427       //MESSAGE("solid");
00428       if(_father->HasShapeToMesh()) {
00429         for (TopExp_Explorer exp(_subShape, TopAbs_FACE); exp.More();exp.Next())
00430         {
00431           InsertDependence(exp.Current());
00432         }
00433       }
00434       break;
00435     }
00436   case TopAbs_FACE:
00437     {
00438       //MESSAGE("face");
00439       for (TopExp_Explorer exp(_subShape, TopAbs_EDGE); exp.More();exp.Next())
00440       {
00441         InsertDependence(exp.Current());
00442       }
00443       break;
00444     }
00445   case TopAbs_EDGE:
00446     {
00447       //MESSAGE("edge");
00448       for (TopExp_Explorer exp(_subShape, TopAbs_VERTEX); exp.More(); exp.Next())
00449       {
00450         InsertDependence(exp.Current());
00451       }
00452       break;
00453     }
00454   case TopAbs_VERTEX:
00455     {
00456       break;
00457     }
00458   default:
00459     {
00460       break;
00461     }
00462   }
00463   _dependenceAnalysed = true;
00464   return _mapDepend;
00465 }
00466 
00467 //=============================================================================
00471 //=============================================================================
00472 
00473 void SMESH_subMesh::InsertDependence(const TopoDS_Shape aSubShape)
00474 {
00475   //MESSAGE("SMESH_subMesh::InsertDependence");
00476   SMESH_subMesh *aSubMesh = _father->GetSubMesh(aSubShape);
00477   int type = aSubShape.ShapeType();
00478   int ordType = 9 - type;               // 2 = Vertex, 8 = CompSolid
00479   int cle = aSubMesh->GetId();
00480   cle += 10000000 * ordType;    // sort map by ordType then index
00481   if ( _mapDepend.find( cle ) == _mapDepend.end())
00482   {
00483     _mapDepend[cle] = aSubMesh;
00484     const map < int, SMESH_subMesh * > & subMap = aSubMesh->DependsOn();
00485     _mapDepend.insert( subMap.begin(), subMap.end() );
00486   }
00487 }
00488 
00489 //=============================================================================
00493 //=============================================================================
00494 
00495 const TopoDS_Shape & SMESH_subMesh::GetSubShape() const
00496 {
00497         //MESSAGE("SMESH_subMesh::GetSubShape");
00498         return _subShape;
00499 }
00500 
00501 
00502 //=======================================================================
00503 //function : CanAddHypothesis
00504 //purpose  : return true if theHypothesis can be attached to me:
00505 //           its dimention is checked
00506 //=======================================================================
00507 
00508 bool SMESH_subMesh::CanAddHypothesis(const SMESH_Hypothesis* theHypothesis) const
00509 {
00510   int aHypDim   = theHypothesis->GetDim();
00511   int aShapeDim = SMESH_Gen::GetShapeDim(_subShape);
00512   if (aHypDim == 3 && aShapeDim == 3) {
00513     // check case of open shell
00514     //if (_subShape.ShapeType() == TopAbs_SHELL && !_subShape.Closed())
00515     if (_subShape.ShapeType() == TopAbs_SHELL && !BRep_Tool::IsClosed(_subShape))
00516       return false;
00517   }
00518   if ( aHypDim <= aShapeDim )
00519     return true;
00520 
00521   return false;
00522 }
00523 
00524 //=======================================================================
00525 //function : IsApplicableHypotesis
00526 //purpose  :
00527 //=======================================================================
00528 
00529 bool SMESH_subMesh::IsApplicableHypotesis(const SMESH_Hypothesis* theHypothesis,
00530                                           const TopAbs_ShapeEnum  theShapeType)
00531 {
00532   if ( theHypothesis->GetType() > SMESHDS_Hypothesis::PARAM_ALGO)
00533     // algorithm
00534     return ( theHypothesis->GetShapeType() & (1<< theShapeType));
00535 
00536   // hypothesis
00537   switch ( theShapeType ) {
00538   case TopAbs_VERTEX:
00539   case TopAbs_EDGE:
00540   case TopAbs_FACE:
00541   case TopAbs_SOLID:
00542     return SMESH_Gen::GetShapeDim( theShapeType ) == theHypothesis->GetDim();
00543 
00544   case TopAbs_SHELL:
00545     // Special case for algorithms, building 2D mesh on a whole shell.
00546     // Before this fix there was a problem after restoring from study,
00547     // because in that case algorithm is assigned before hypothesis
00548     // (on shell in problem case) and hypothesis is checked on faces
00549     // (because it is 2D), where we have NO_ALGO state.
00550     // Now 2D hypothesis is also applicable to shells.
00551     return (theHypothesis->GetDim() == 2 || theHypothesis->GetDim() == 3);
00552 
00553 //   case TopAbs_WIRE:
00554 //   case TopAbs_COMPSOLID:
00555 //   case TopAbs_COMPOUND:
00556   default:;
00557   }
00558   return false;
00559 }
00560 
00561 //=============================================================================
00565 //=============================================================================
00566 
00567 SMESH_Hypothesis::Hypothesis_Status
00568   SMESH_subMesh::AlgoStateEngine(int event, SMESH_Hypothesis * anHyp)
00569 {
00570   //  MESSAGE("SMESH_subMesh::AlgoStateEngine");
00571   //SCRUTE(_algoState);
00572   //SCRUTE(event);
00573 
00574   // **** les retour des evenement shape sont significatifs
00575   // (add ou remove fait ou non)
00576   // le retour des evenement father n'indiquent pas que add ou remove fait
00577 
00578   SMESH_Hypothesis::Hypothesis_Status aux_ret, ret = SMESH_Hypothesis::HYP_OK;
00579 
00580   SMESHDS_Mesh* meshDS =_father->GetMeshDS();
00581   SMESH_Gen*    gen    =_father->GetGen();
00582   SMESH_Algo*   algo   = 0;
00583 
00584   if (_subShape.ShapeType() == TopAbs_VERTEX )
00585   {
00586     if ( anHyp->GetDim() != 0) {
00587       if (event == ADD_HYP || event == ADD_ALGO)
00588         return SMESH_Hypothesis::HYP_BAD_DIM;
00589       else
00590         return SMESH_Hypothesis::HYP_OK;
00591     }
00592     // 0D hypothesis
00593     else if ( _algoState == HYP_OK ) {
00594       // update default _algoState
00595       if ( event != REMOVE_FATHER_ALGO )
00596       {
00597         _algoState = NO_ALGO;
00598         algo = gen->GetAlgo(*_father, _subShape);
00599         if ( algo ) {
00600           _algoState = MISSING_HYP;
00601           if ( event == REMOVE_FATHER_HYP ||
00602                algo->CheckHypothesis(*_father,_subShape, aux_ret))
00603             _algoState = HYP_OK;
00604         }
00605       }
00606     }
00607   }
00608 
00609   int oldAlgoState = _algoState;
00610   bool modifiedHyp = (event == MODIF_HYP);  // if set to true, force event MODIF_ALGO_STATE
00611   bool needFullClean = false;
00612 
00613   bool isApplicableHyp = IsApplicableHypotesis( anHyp );
00614 
00615   if (event == ADD_ALGO || event == ADD_FATHER_ALGO)
00616   {
00617     // -------------------------------------------
00618     // check if a shape needed by algo is present
00619     // -------------------------------------------
00620     algo = static_cast< SMESH_Algo* >( anHyp );
00621     if ( !_father->HasShapeToMesh() && algo->NeedShape() )
00622       return SMESH_Hypothesis::HYP_NEED_SHAPE;
00623     // ----------------------
00624     // check mesh conformity
00625     // ----------------------
00626     if (isApplicableHyp && !_father->IsNotConformAllowed() && !IsConform( algo ))
00627       return SMESH_Hypothesis::HYP_NOTCONFORM;
00628 
00629     // check if all-dimensional algo is hidden by other local one
00630     if ( event == ADD_ALGO ) {
00631       SMESH_HypoFilter filter( SMESH_HypoFilter::HasType( algo->GetType() ));
00632       filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+1 ));
00633       filter.Or( SMESH_HypoFilter::HasType( algo->GetType()+2 ));
00634       if ( SMESH_Algo * curAlgo = (SMESH_Algo*) _father->GetHypothesis( _subShape, filter, true ))
00635         needFullClean = ( !curAlgo->NeedDescretBoundary() );
00636     }
00637   }
00638 
00639   // ----------------------------------
00640   // add a hypothesis to DS if possible
00641   // ----------------------------------
00642   if (event == ADD_HYP || event == ADD_ALGO)
00643   {
00644     if ( ! CanAddHypothesis( anHyp )) // check dimension
00645       return SMESH_Hypothesis::HYP_BAD_DIM;
00646 
00647     if (  GetSimilarAttached( _subShape, anHyp ) )
00648       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
00649 
00650     if ( !meshDS->AddHypothesis(_subShape, anHyp))
00651       return SMESH_Hypothesis::HYP_ALREADY_EXIST;
00652   }
00653 
00654   // --------------------------
00655   // remove a hypothesis from DS
00656   // --------------------------
00657   if (event == REMOVE_HYP || event == REMOVE_ALGO)
00658   {
00659     if (!meshDS->RemoveHypothesis(_subShape, anHyp))
00660       return SMESH_Hypothesis::HYP_OK; // nothing changes
00661 
00662     if (event == REMOVE_ALGO)
00663     {
00664       algo = dynamic_cast<SMESH_Algo*> (anHyp);
00665       if (!algo->NeedDescretBoundary())
00666       {
00667         // clean all mesh in the tree of the current submesh;
00668         // we must perform it now because later
00669         // we will have no information about the type of the removed algo
00670         needFullClean = true;
00671       }
00672     }
00673   }
00674 
00675   // ------------------
00676   // analyse algo state
00677   // ------------------
00678   if (!isApplicableHyp)
00679     return ret; // not applicable hypotheses do not change algo state
00680 
00681   switch (_algoState)
00682   {
00683 
00684     // ----------------------------------------------------------------------
00685 
00686   case NO_ALGO:
00687     switch (event) {
00688     case ADD_HYP:
00689       break;
00690     case ADD_ALGO: {
00691       algo = gen->GetAlgo((*_father), _subShape);
00692       ASSERT(algo);
00693       if (algo->CheckHypothesis((*_father),_subShape, aux_ret))
00694         SetAlgoState(HYP_OK);
00695       else if ( algo->IsStatusFatal( aux_ret )) {
00696         meshDS->RemoveHypothesis(_subShape, anHyp);
00697         ret = aux_ret;
00698       }
00699       else
00700         SetAlgoState(MISSING_HYP);
00701       break;
00702     }
00703     case REMOVE_HYP:
00704     case REMOVE_ALGO:
00705     case ADD_FATHER_HYP:
00706       break;
00707     case ADD_FATHER_ALGO: {    // Algo just added in father
00708       algo = gen->GetAlgo((*_father), _subShape);
00709       ASSERT(algo);
00710       if ( algo == anHyp ) {
00711         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret))
00712           SetAlgoState(HYP_OK);
00713         else
00714           SetAlgoState(MISSING_HYP);
00715       }
00716       break;
00717     }
00718     case REMOVE_FATHER_HYP:
00719       break;
00720     case REMOVE_FATHER_ALGO: {
00721       algo = gen->GetAlgo((*_father), _subShape);
00722       if (algo)
00723       {
00724         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
00725             SetAlgoState(HYP_OK);
00726         else
00727           SetAlgoState(MISSING_HYP);
00728       }
00729       break;
00730     }
00731     case MODIF_HYP: break;
00732     default:
00733       ASSERT(0);
00734       break;
00735     }
00736     break;
00737 
00738     // ----------------------------------------------------------------------
00739 
00740   case MISSING_HYP:
00741     switch (event)
00742     {
00743     case ADD_HYP: {
00744       algo = gen->GetAlgo((*_father), _subShape);
00745       ASSERT(algo);
00746       if ( algo->CheckHypothesis((*_father),_subShape, ret ))
00747         SetAlgoState(HYP_OK);
00748       if (SMESH_Hypothesis::IsStatusFatal( ret ))
00749         meshDS->RemoveHypothesis(_subShape, anHyp);
00750       else if (!_father->IsUsedHypothesis( anHyp, this ))
00751       {
00752         meshDS->RemoveHypothesis(_subShape, anHyp);
00753         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00754       }
00755       break;
00756     }
00757     case ADD_ALGO: {           //already existing algo : on father ?
00758       algo = gen->GetAlgo((*_father), _subShape);
00759       ASSERT(algo);
00760       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))// ignore hyp status
00761         SetAlgoState(HYP_OK);
00762       else if ( algo->IsStatusFatal( aux_ret )) {
00763         meshDS->RemoveHypothesis(_subShape, anHyp);
00764         ret = aux_ret;
00765       }
00766       else
00767         SetAlgoState(MISSING_HYP);
00768       break;
00769     }
00770     case REMOVE_HYP:
00771       break;
00772     case REMOVE_ALGO: {        // perhaps a father algo applies ?
00773       algo = gen->GetAlgo((*_father), _subShape);
00774       if (algo == NULL)  // no more algo applying on subShape...
00775       {
00776         SetAlgoState(NO_ALGO);
00777       }
00778       else
00779       {
00780         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
00781           SetAlgoState(HYP_OK);
00782         else
00783           SetAlgoState(MISSING_HYP);
00784       }
00785       break;
00786     }
00787     case MODIF_HYP: // assigned hypothesis value may become good
00788     case ADD_FATHER_HYP: {
00789       algo = gen->GetAlgo((*_father), _subShape);
00790       ASSERT(algo);
00791       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
00792         SetAlgoState(HYP_OK);
00793       else
00794         SetAlgoState(MISSING_HYP);
00795       break;
00796     }
00797     case ADD_FATHER_ALGO: { // new father algo
00798       algo = gen->GetAlgo((*_father), _subShape);
00799       ASSERT( algo );
00800       if ( algo == anHyp ) {
00801         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
00802           SetAlgoState(HYP_OK);
00803         else
00804           SetAlgoState(MISSING_HYP);
00805       }
00806       break;
00807     }
00808     case REMOVE_FATHER_HYP:    // nothing to do
00809       break;
00810     case REMOVE_FATHER_ALGO: {
00811       algo = gen->GetAlgo((*_father), _subShape);
00812       if (algo == NULL)  // no more applying algo on father
00813       {
00814         SetAlgoState(NO_ALGO);
00815       }
00816       else
00817       {
00818         if ( algo->CheckHypothesis((*_father),_subShape , aux_ret ))
00819           SetAlgoState(HYP_OK);
00820         else
00821           SetAlgoState(MISSING_HYP);
00822       }
00823       break;
00824     }
00825     default:
00826       ASSERT(0);
00827       break;
00828     }
00829     break;
00830 
00831     // ----------------------------------------------------------------------
00832 
00833   case HYP_OK:
00834     switch (event)
00835     {
00836     case ADD_HYP: {
00837       algo = gen->GetAlgo((*_father), _subShape);
00838       ASSERT(algo);
00839       if (!algo->CheckHypothesis((*_father),_subShape, ret ))
00840       {
00841         if ( !SMESH_Hypothesis::IsStatusFatal( ret ))
00842           // ret should be fatal: anHyp was not added
00843           ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00844       }
00845       else if (!_father->IsUsedHypothesis(  anHyp, this ))
00846         ret = SMESH_Hypothesis::HYP_INCOMPATIBLE;
00847 
00848       if (SMESH_Hypothesis::IsStatusFatal( ret ))
00849       {
00850         MESSAGE("do not add extra hypothesis");
00851         meshDS->RemoveHypothesis(_subShape, anHyp);
00852       }
00853       else
00854       {
00855         modifiedHyp = true;
00856       }
00857       break;
00858     }
00859     case ADD_ALGO: {           //already existing algo : on father ?
00860       algo = gen->GetAlgo((*_father), _subShape);
00861       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
00862         // check if algo changes
00863         SMESH_HypoFilter f;
00864         f.Init(   SMESH_HypoFilter::IsAlgo() );
00865         f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
00866         f.AndNot( SMESH_HypoFilter::Is( algo ));
00867         const SMESH_Hypothesis * prevAlgo = _father->GetHypothesis( _subShape, f, true );
00868         if (prevAlgo &&
00869             string(algo->GetName()) != string(prevAlgo->GetName()) )
00870           modifiedHyp = true;
00871       }
00872       else
00873         SetAlgoState(MISSING_HYP);
00874       break;
00875     }
00876     case REMOVE_HYP: {
00877       algo = gen->GetAlgo((*_father), _subShape);
00878       ASSERT(algo);
00879       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
00880         SetAlgoState(HYP_OK);
00881       else
00882         SetAlgoState(MISSING_HYP);
00883       modifiedHyp = true;
00884       break;
00885     }
00886     case REMOVE_ALGO: {         // perhaps a father algo applies ?
00887       algo = gen->GetAlgo((*_father), _subShape);
00888       if (algo == NULL)   // no more algo applying on subShape...
00889       {
00890         SetAlgoState(NO_ALGO);
00891       }
00892       else
00893       {
00894         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
00895           // check if algo remains
00896           if ( anHyp != algo && strcmp( anHyp->GetName(), algo->GetName()) )
00897             modifiedHyp = true;
00898         }
00899         else
00900           SetAlgoState(MISSING_HYP);
00901       }
00902       break;
00903     }
00904     case MODIF_HYP: // hypothesis value may become bad
00905     case ADD_FATHER_HYP: {  // new father hypothesis ?
00906       algo = gen->GetAlgo((*_father), _subShape);
00907       ASSERT(algo);
00908       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret ))
00909       {
00910         if (_father->IsUsedHypothesis( anHyp, this )) // new Hyp
00911           modifiedHyp = true;
00912       }
00913       else
00914         SetAlgoState(MISSING_HYP);
00915       break;
00916     }
00917     case ADD_FATHER_ALGO: {
00918       algo = gen->GetAlgo((*_father), _subShape);
00919       if ( algo == anHyp ) { // a new algo on father
00920         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
00921           // check if algo changes
00922           SMESH_HypoFilter f;
00923           f.Init(   SMESH_HypoFilter::IsAlgo() );
00924           f.And(    SMESH_HypoFilter::IsApplicableTo( _subShape ));
00925           f.AndNot( SMESH_HypoFilter::Is( algo ));
00926           const SMESH_Hypothesis* prevAlgo = _father->GetHypothesis( _subShape, f, true );
00927           if (prevAlgo &&
00928               string(algo->GetName()) != string(prevAlgo->GetName()) )
00929             modifiedHyp = true;
00930         }
00931         else
00932           SetAlgoState(MISSING_HYP);
00933       }
00934       break;
00935     }
00936     case REMOVE_FATHER_HYP: {
00937       algo = gen->GetAlgo((*_father), _subShape);
00938       ASSERT(algo);
00939       if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
00940         // is there the same local hyp or maybe a new father algo applied?
00941         if ( !GetSimilarAttached( _subShape, anHyp ) )
00942           modifiedHyp = true;
00943       }
00944       else
00945         SetAlgoState(MISSING_HYP);
00946       break;
00947     }
00948     case REMOVE_FATHER_ALGO: {
00949       // IPAL21346. Edges not removed when Netgen 1d-2d is removed from a SOLID.
00950       // CLEAN was not called at event REMOVE_ALGO because the algo is not applicable to SOLID.
00951       algo = dynamic_cast<SMESH_Algo*> (anHyp);
00952       if (!algo->NeedDescretBoundary())
00953         needFullClean = true;
00954 
00955       algo = gen->GetAlgo((*_father), _subShape);
00956       if (algo == NULL)  // no more applying algo on father
00957       {
00958         SetAlgoState(NO_ALGO);
00959       }
00960       else
00961       {
00962         if ( algo->CheckHypothesis((*_father),_subShape, aux_ret )) {
00963           // check if algo changes
00964           if ( string(algo->GetName()) != string( anHyp->GetName()) )
00965             modifiedHyp = true;
00966         }
00967         else
00968           SetAlgoState(MISSING_HYP);
00969       }
00970       break;
00971     }
00972     default:
00973       ASSERT(0);
00974       break;
00975     }
00976     break;
00977 
00978     // ----------------------------------------------------------------------
00979 
00980   default:
00981     ASSERT(0);
00982     break;
00983   }
00984 
00985   // detect algorithm hiding
00986   //
00987   if ( ret == SMESH_Hypothesis::HYP_OK &&
00988        ( event == ADD_ALGO || event == ADD_FATHER_ALGO ) &&
00989        algo->GetName() == anHyp->GetName() )
00990   {
00991     // is algo hidden?
00992     SMESH_Gen* gen = _father->GetGen();
00993     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
00994     for ( ; ( ret == SMESH_Hypothesis::HYP_OK && it.More()); it.Next() ) {
00995       if ( SMESH_Algo* upperAlgo = gen->GetAlgo( *_father, it.Value() ))
00996         if ( !upperAlgo->NeedDescretBoundary() && !upperAlgo->SupportSubmeshes())
00997           ret = SMESH_Hypothesis::HYP_HIDDEN_ALGO;
00998     }
00999     // is algo hiding?
01000     if ( ret == SMESH_Hypothesis::HYP_OK &&
01001          !algo->NeedDescretBoundary()    &&
01002          !algo->SupportSubmeshes()) {
01003       TopoDS_Shape algoAssignedTo, otherAssignedTo;
01004       gen->GetAlgo( *_father, _subShape, &algoAssignedTo );
01005       map<int, SMESH_subMesh*>::reverse_iterator i_sm = _mapDepend.rbegin();
01006       for ( ; ( ret == SMESH_Hypothesis::HYP_OK && i_sm != _mapDepend.rend()) ; ++i_sm )
01007         if ( gen->GetAlgo( *_father, i_sm->second->_subShape, &otherAssignedTo ) &&
01008              SMESH_MesherHelper::IsSubShape( /*sub=*/otherAssignedTo, /*main=*/algoAssignedTo ))
01009           ret = SMESH_Hypothesis::HYP_HIDING_ALGO;
01010     }
01011   }
01012 
01013   bool stateChange = ( _algoState != oldAlgoState );
01014 
01015   if ( stateChange && _algoState == HYP_OK ) // hyp becomes OK
01016     algo->SetEventListener( this );
01017 
01018   NotifyListenersOnEvent( event, ALGO_EVENT, anHyp );
01019 
01020   if ( stateChange && oldAlgoState == HYP_OK ) { // hyp becomes KO
01021     DeleteOwnListeners();
01022     SetIsAlwaysComputed( false );
01023     if (_subShape.ShapeType() == TopAbs_VERTEX ) {
01024       // restore default states
01025       _algoState = HYP_OK;
01026       _computeState = READY_TO_COMPUTE;
01027     }
01028   }
01029 
01030   if ( needFullClean ) {
01031     // added or removed algo is all-dimensional
01032     ComputeStateEngine( CLEAN );
01033     CleanDependsOn();
01034     ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
01035   }
01036 
01037   if (stateChange || modifiedHyp)
01038     ComputeStateEngine(MODIF_ALGO_STATE);
01039 
01040   return ret;
01041 }
01042 
01043 //=======================================================================
01044 //function : IsConform
01045 //purpose  : check if a conform mesh will be produced by the Algo
01046 //=======================================================================
01047 
01048 bool SMESH_subMesh::IsConform(const SMESH_Algo* theAlgo)
01049 {
01050 //  MESSAGE( "SMESH_subMesh::IsConform" );
01051   if ( !theAlgo ) return false;
01052 
01053   // Suppose that theAlgo is applicable to _subShape, do not check it here
01054   //if ( !IsApplicableHypotesis( theAlgo )) return false;
01055 
01056   // check only algo that doesn't NeedDescretBoundary(): because mesh made
01057   // on a sub-shape will be ignored by theAlgo
01058   if ( theAlgo->NeedDescretBoundary() ||
01059        !theAlgo->OnlyUnaryInput() ) // all adjacent shapes will be meshed by this algo?
01060     return true;
01061 
01062   SMESH_Gen* gen =_father->GetGen();
01063 
01064   // only local algo is to be checked
01065   //if ( gen->IsGlobalHypothesis( theAlgo, *_father ))
01066   if ( _subShape.ShapeType() == _father->GetMeshDS()->ShapeToMesh().ShapeType() )
01067     return true;
01068 
01069   // check algo attached to adjacent shapes
01070 
01071   // loop on one level down sub-meshes
01072   TopoDS_Iterator itsub( _subShape );
01073   for (; itsub.More(); itsub.Next())
01074   {
01075     // loop on adjacent subShapes
01076     TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( itsub.Value() ));
01077     for (; it.More(); it.Next())
01078     {
01079       const TopoDS_Shape& adjacent = it.Value();
01080       if ( _subShape.IsSame( adjacent )) continue;
01081       if ( adjacent.ShapeType() != _subShape.ShapeType())
01082         break;
01083 
01084       // check algo attached to smAdjacent
01085       SMESH_Algo * algo = gen->GetAlgo((*_father), adjacent);
01086       if (algo &&
01087           !algo->NeedDescretBoundary() &&
01088           algo->OnlyUnaryInput())
01089         return false; // NOT CONFORM MESH WILL BE PRODUCED
01090     }
01091   }
01092 
01093   return true;
01094 }
01095 
01096 //=============================================================================
01100 //=============================================================================
01101 
01102 void SMESH_subMesh::SetAlgoState(int state)
01103 {
01104   _algoState = state;
01105 }
01106 
01107 //=============================================================================
01111 //=============================================================================
01112 SMESH_Hypothesis::Hypothesis_Status
01113   SMESH_subMesh::SubMeshesAlgoStateEngine(int event,
01114                                           SMESH_Hypothesis * anHyp)
01115 {
01116   SMESH_Hypothesis::Hypothesis_Status ret = SMESH_Hypothesis::HYP_OK;
01117   //EAP: a wire (dim==1) should notify edges (dim==1)
01118   //EAP: int dim = SMESH_Gen::GetShapeDim(_subShape);
01119   //if (_subShape.ShapeType() < TopAbs_EDGE ) // wire,face etc
01120   {
01121     SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
01122     while ( smIt->more() ) {
01123       SMESH_Hypothesis::Hypothesis_Status ret2 =
01124         smIt->next()->AlgoStateEngine(event, anHyp);
01125       if ( ret2 > ret )
01126         ret = ret2;
01127     }
01128   }
01129   return ret;
01130 }
01131 
01132 //=============================================================================
01136 //=============================================================================
01137 
01138 void SMESH_subMesh::CleanDependsOn()
01139 {
01140   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
01141   while ( smIt->more() )
01142     smIt->next()->ComputeStateEngine(CLEAN);
01143 }
01144 
01145 //=============================================================================
01149 //=============================================================================
01150 
01151 void SMESH_subMesh::DumpAlgoState(bool isMain)
01152 {
01153         int dim = SMESH_Gen::GetShapeDim(_subShape);
01154 //   if (dim < 1) return;
01155         if (isMain)
01156         {
01157                 const map < int, SMESH_subMesh * >&subMeshes = DependsOn();
01158 
01159                 map < int, SMESH_subMesh * >::const_iterator itsub;
01160                 for (itsub = subMeshes.begin(); itsub != subMeshes.end(); itsub++)
01161                 {
01162                         SMESH_subMesh *sm = (*itsub).second;
01163                         sm->DumpAlgoState(false);
01164                 }
01165         }
01166         int type = _subShape.ShapeType();
01167         MESSAGE("dim = " << dim << " type of shape " << type);
01168         switch (_algoState)
01169         {
01170         case NO_ALGO:
01171                 MESSAGE(" AlgoState = NO_ALGO");
01172                 break;
01173         case MISSING_HYP:
01174                 MESSAGE(" AlgoState = MISSING_HYP");
01175                 break;
01176         case HYP_OK:
01177                 MESSAGE(" AlgoState = HYP_OK");
01178                 break;
01179         }
01180         switch (_computeState)
01181         {
01182         case NOT_READY:
01183                 MESSAGE(" ComputeState = NOT_READY");
01184                 break;
01185         case READY_TO_COMPUTE:
01186                 MESSAGE(" ComputeState = READY_TO_COMPUTE");
01187                 break;
01188         case COMPUTE_OK:
01189                 MESSAGE(" ComputeState = COMPUTE_OK");
01190                 break;
01191         case FAILED_TO_COMPUTE:
01192                 MESSAGE(" ComputeState = FAILED_TO_COMPUTE");
01193                 break;
01194         }
01195 }
01196 
01197 //================================================================================
01202 //================================================================================
01203 
01204 static void cleanSubMesh( SMESH_subMesh * subMesh )
01205 {
01206   if (subMesh) {
01207     if (SMESHDS_SubMesh * subMeshDS = subMesh->GetSubMeshDS()) {
01208       SMESHDS_Mesh * meshDS = subMesh->GetFather()->GetMeshDS();
01209       SMDS_ElemIteratorPtr ite = subMeshDS->GetElements();
01210       while (ite->more()) {
01211         const SMDS_MeshElement * elt = ite->next();
01212         //MESSAGE( " RM elt: "<<elt->GetID()<<" ( "<<elt->NbNodes()<<" )" );
01213         //meshDS->RemoveElement(elt);
01214         meshDS->RemoveFreeElement(elt, subMeshDS);
01215       }
01216 
01217       SMDS_NodeIteratorPtr itn = subMeshDS->GetNodes();
01218       while (itn->more()) {
01219         const SMDS_MeshNode * node = itn->next();
01220         //MESSAGE( " RM node: "<<node->GetID());
01221         if ( node->NbInverseElements() == 0 )
01222           meshDS->RemoveFreeNode(node, subMeshDS);
01223         else // for StdMeshers_CompositeSegment_1D: node in one submesh, edge in another
01224           meshDS->RemoveNode(node);
01225       }
01226     }
01227   }
01228 }
01229 
01230 //=============================================================================
01234 //=============================================================================
01235 
01236 bool SMESH_subMesh::ComputeStateEngine(int event)
01237 {
01238   _computeError.reset();
01239 
01240   //MESSAGE("SMESH_subMesh::ComputeStateEngine");
01241   //SCRUTE(_computeState);
01242   //SCRUTE(event);
01243 
01244   if (_subShape.ShapeType() == TopAbs_VERTEX)
01245   {
01246     _computeState = READY_TO_COMPUTE;
01247     SMESHDS_SubMesh* smDS = GetSubMeshDS();
01248     if ( smDS && smDS->NbNodes() ) {
01249       if ( event == CLEAN ) {
01250         CleanDependants();
01251         cleanSubMesh( this );
01252       }
01253       else
01254         _computeState = COMPUTE_OK;
01255     }
01256     else if ( event == COMPUTE && !_alwaysComputed ) {
01257       const TopoDS_Vertex & V = TopoDS::Vertex( _subShape );
01258       gp_Pnt P = BRep_Tool::Pnt(V);
01259       if ( SMDS_MeshNode * n = _father->GetMeshDS()->AddNode(P.X(), P.Y(), P.Z()) ) {
01260         _father->GetMeshDS()->SetNodeOnVertex(n,_Id);
01261         _computeState = COMPUTE_OK;
01262       }
01263     }
01264     if ( event == MODIF_ALGO_STATE )
01265       CleanDependants();
01266     return true;
01267   }
01268   SMESH_Gen *gen = _father->GetGen();
01269   SMESH_Algo *algo = 0;
01270   bool ret = true;
01271   SMESH_Hypothesis::Hypothesis_Status hyp_status;
01272   //algo_state oldAlgoState = (algo_state) GetAlgoState();
01273 
01274   switch (_computeState)
01275   {
01276 
01277     // ----------------------------------------------------------------------
01278 
01279   case NOT_READY:
01280     switch (event)
01281     {
01282     case MODIF_ALGO_STATE:
01283       algo = gen->GetAlgo((*_father), _subShape);
01284       if (algo && !algo->NeedDescretBoundary())
01285         CleanDependsOn(); // clean sub-meshes with event CLEAN
01286       if ( _algoState == HYP_OK )
01287         _computeState = READY_TO_COMPUTE;
01288       break;
01289     case COMPUTE:               // nothing to do
01290       break;
01291 #ifdef WITH_SMESH_CANCEL_COMPUTE
01292     case COMPUTE_CANCELED:               // nothing to do
01293       break;
01294 #endif
01295     case CLEAN:
01296       CleanDependants();
01297       RemoveSubMeshElementsAndNodes();
01298       break;
01299     case SUBMESH_COMPUTED:      // nothing to do
01300       break;
01301     case SUBMESH_RESTORED:
01302       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
01303       break;
01304     case MESH_ENTITY_REMOVED:
01305       break;
01306     case CHECK_COMPUTE_STATE:
01307       if ( IsMeshComputed() )
01308         _computeState = COMPUTE_OK;
01309       break;
01310     default:
01311       ASSERT(0);
01312       break;
01313     }
01314     break;
01315 
01316     // ----------------------------------------------------------------------
01317 
01318   case READY_TO_COMPUTE:
01319     switch (event)
01320     {
01321     case MODIF_ALGO_STATE:
01322       _computeState = NOT_READY;
01323       algo = gen->GetAlgo((*_father), _subShape);
01324       if (algo)
01325       {
01326         if (!algo->NeedDescretBoundary())
01327           CleanDependsOn(); // clean sub-meshes with event CLEAN
01328         if ( _algoState == HYP_OK )
01329           _computeState = READY_TO_COMPUTE;
01330       }
01331       break;
01332     case COMPUTE:
01333       {
01334         algo = gen->GetAlgo((*_father), _subShape);
01335         ASSERT(algo);
01336         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
01337         if (!ret)
01338         {
01339           MESSAGE("***** verify compute state *****");
01340           _computeState = NOT_READY;
01341           SetAlgoState(MISSING_HYP);
01342           break;
01343         }
01344         TopoDS_Shape shape = _subShape;
01345         // check submeshes needed
01346         if (_father->HasShapeToMesh() ) {
01347           bool subComputed = false;
01348           if (!algo->OnlyUnaryInput())
01349             shape = GetCollection( gen, algo, subComputed );
01350           else
01351             subComputed = SubMeshesComputed();
01352           ret = ( algo->NeedDescretBoundary() ? subComputed :
01353                   algo->SupportSubmeshes() ? true :
01354                   ( !subComputed || _father->IsNotConformAllowed() ));
01355           if (!ret) {
01356             _computeState = FAILED_TO_COMPUTE;
01357             if ( !algo->NeedDescretBoundary() )
01358               _computeError =
01359                 SMESH_ComputeError::New(COMPERR_BAD_INPUT_MESH,
01360                                         "Unexpected computed submesh",algo);
01361             break;
01362           }
01363         }
01364         // compute
01365 //         CleanDependants(); for "UseExisting_*D" algos
01366 //         RemoveSubMeshElementsAndNodes();
01367         ret = false;
01368         _computeState = FAILED_TO_COMPUTE;
01369         _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
01370         try {
01371 #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
01372           OCC_CATCH_SIGNALS;
01373 #endif
01374           algo->InitComputeError();
01375           MemoryReserve aMemoryReserve;
01376           SMDS_Mesh::CheckMemory();
01377           Kernel_Utils::Localizer loc;
01378           if ( !_father->HasShapeToMesh() ) // no shape
01379           {
01380             SMESH_MesherHelper helper( *_father );
01381             helper.SetSubShape( shape );
01382             helper.SetElementsOnShape( true );
01383             ret = algo->Compute(*_father, &helper );
01384           }
01385           else
01386           {
01387             ret = algo->Compute((*_father), shape);
01388           }
01389           if ( !_computeError || ( !ret && _computeError->IsOK() ) ) // algo can set _computeError of submesh
01390             _computeError = algo->GetComputeError();
01391         }
01392         catch ( std::bad_alloc& exc ) {
01393           MESSAGE("std::bad_alloc thrown inside algo->Compute()");
01394           if ( _computeError ) {
01395             _computeError->myName = COMPERR_MEMORY_PB;
01396             //_computeError->myComment = exc.what();
01397           }
01398           cleanSubMesh( this );
01399           throw exc;
01400         }
01401         catch ( Standard_OutOfMemory& exc ) {
01402           MESSAGE("Standard_OutOfMemory thrown inside algo->Compute()");
01403           if ( _computeError ) {
01404             _computeError->myName = COMPERR_MEMORY_PB;
01405             //_computeError->myComment = exc.what();
01406           }
01407           cleanSubMesh( this );
01408           throw std::bad_alloc();
01409         }
01410         catch (Standard_Failure& ex) {
01411           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
01412           _computeError->myName    = COMPERR_OCC_EXCEPTION;
01413           _computeError->myComment += ex.DynamicType()->Name();
01414           if ( ex.GetMessageString() && strlen( ex.GetMessageString() )) {
01415             _computeError->myComment += ": ";
01416             _computeError->myComment += ex.GetMessageString();
01417           }
01418         }
01419         catch ( SALOME_Exception& S_ex ) {
01420           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
01421           _computeError->myName    = COMPERR_SLM_EXCEPTION;
01422           _computeError->myComment = S_ex.what();
01423         }
01424         catch ( std::exception& exc ) {
01425           if ( !_computeError ) _computeError = SMESH_ComputeError::New();
01426           _computeError->myName    = COMPERR_STD_EXCEPTION;
01427           _computeError->myComment = exc.what();
01428         }
01429         catch ( ... ) {
01430           if ( _computeError )
01431             _computeError->myName = COMPERR_EXCEPTION;
01432           else
01433             ret = false;
01434         }
01435         TopExp_Explorer subS(shape, _subShape.ShapeType());
01436         if (ret) // check if anything was built
01437         {
01438           for (; ret && subS.More(); subS.Next())
01439             ret = _father->GetSubMesh( subS.Current() )->IsMeshComputed();
01440         }
01441         bool isComputeErrorSet = !CheckComputeError( algo, shape );
01442         if (!ret && !isComputeErrorSet)
01443         {
01444           // Set _computeError
01445           for (subS.ReInit(); subS.More(); subS.Next())
01446           {
01447             SMESH_subMesh* sm = _father->GetSubMesh( subS.Current() );
01448             if ( !sm->IsMeshComputed() )
01449             {
01450               if ( !sm->_computeError )
01451                 sm->_computeError = SMESH_ComputeError::New();
01452               if ( sm->_computeError->IsOK() )
01453                 sm->_computeError->myName = COMPERR_ALGO_FAILED;
01454               sm->_computeState = FAILED_TO_COMPUTE;
01455               sm->_computeError->myAlgo = algo;
01456             }
01457           }
01458         }
01459         if (ret)
01460         {
01461           _computeError.reset();
01462         }
01463         UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
01464       }
01465       break;
01466 #ifdef WITH_SMESH_CANCEL_COMPUTE
01467     case COMPUTE_CANCELED:               // nothing to do
01468       break;
01469 #endif
01470     case CLEAN:
01471       CleanDependants();
01472       RemoveSubMeshElementsAndNodes();
01473       _computeState = NOT_READY;
01474       algo = gen->GetAlgo((*_father), _subShape);
01475       if (algo)
01476       {
01477         ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
01478         if (ret)
01479           _computeState = READY_TO_COMPUTE;
01480         else
01481           SetAlgoState(MISSING_HYP);
01482       }
01483       break;
01484     case SUBMESH_COMPUTED:      // nothing to do
01485       break;
01486     case SUBMESH_RESTORED:
01487       // check if a mesh is already computed that may
01488       // happen after retrieval from a file
01489       ComputeStateEngine( CHECK_COMPUTE_STATE );
01490       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
01491       algo = gen->GetAlgo(*_father, _subShape);
01492       if (algo) algo->SubmeshRestored( this );
01493       break;
01494     case MESH_ENTITY_REMOVED:
01495       break;
01496     case CHECK_COMPUTE_STATE:
01497       if ( IsMeshComputed() )
01498         _computeState = COMPUTE_OK;
01499       break;
01500     default:
01501       ASSERT(0);
01502       break;
01503     }
01504     break;
01505 
01506     // ----------------------------------------------------------------------
01507 
01508   case COMPUTE_OK:
01509     switch (event)
01510     {
01511     case MODIF_ALGO_STATE:
01512       ComputeStateEngine( CLEAN );
01513       algo = gen->GetAlgo((*_father), _subShape);
01514       if (algo && !algo->NeedDescretBoundary())
01515         CleanDependsOn(); // clean sub-meshes with event CLEAN
01516       break;
01517     case COMPUTE:               // nothing to do
01518       break;
01519 #ifdef WITH_SMESH_CANCEL_COMPUTE
01520     case COMPUTE_CANCELED:               // nothing to do
01521       break;
01522 #endif
01523     case CLEAN:
01524       CleanDependants();  // clean sub-meshes, dependant on this one, with event CLEAN
01525       RemoveSubMeshElementsAndNodes();
01526       _computeState = NOT_READY;
01527       if ( _algoState == HYP_OK )
01528         _computeState = READY_TO_COMPUTE;
01529       break;
01530     case SUBMESH_COMPUTED:      // nothing to do
01531       break;
01532     case SUBMESH_RESTORED:
01533       ComputeStateEngine( CHECK_COMPUTE_STATE );
01534       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
01535       algo = gen->GetAlgo(*_father, _subShape);
01536       if (algo) algo->SubmeshRestored( this );
01537       break;
01538     case MESH_ENTITY_REMOVED:
01539       UpdateDependantsState( CHECK_COMPUTE_STATE );
01540       ComputeStateEngine( CHECK_COMPUTE_STATE );
01541       ComputeSubMeshStateEngine( CHECK_COMPUTE_STATE );
01542       break;
01543     case CHECK_COMPUTE_STATE:
01544       if ( !IsMeshComputed() ) {
01545         if (_algoState == HYP_OK)
01546           _computeState = READY_TO_COMPUTE;
01547         else
01548           _computeState = NOT_READY;
01549       }
01550       break;
01551     default:
01552       ASSERT(0);
01553       break;
01554     }
01555     break;
01556 
01557     // ----------------------------------------------------------------------
01558 
01559   case FAILED_TO_COMPUTE:
01560     switch (event)
01561     {
01562     case MODIF_ALGO_STATE:
01563       if ( !IsEmpty() )
01564         ComputeStateEngine( CLEAN );
01565       algo = gen->GetAlgo((*_father), _subShape);
01566       if (algo && !algo->NeedDescretBoundary())
01567         CleanDependsOn(); // clean sub-meshes with event CLEAN
01568       if (_algoState == HYP_OK)
01569         _computeState = READY_TO_COMPUTE;
01570       else
01571         _computeState = NOT_READY;
01572       break;
01573     case COMPUTE:      // nothing to do
01574       break;
01575 #ifdef WITH_SMESH_CANCEL_COMPUTE
01576     case COMPUTE_CANCELED:
01577       {
01578         algo = gen->GetAlgo((*_father), _subShape);
01579         algo->CancelCompute();
01580       }
01581       break;
01582 #endif
01583     case CLEAN:
01584       CleanDependants(); // submeshes dependent on me should be cleaned as well
01585       RemoveSubMeshElementsAndNodes();
01586       break;
01587     case SUBMESH_COMPUTED:      // allow retry compute
01588       if (_algoState == HYP_OK)
01589         _computeState = READY_TO_COMPUTE;
01590       else
01591         _computeState = NOT_READY;
01592       break;
01593     case SUBMESH_RESTORED:
01594       ComputeSubMeshStateEngine( SUBMESH_RESTORED );
01595       break;
01596     case MESH_ENTITY_REMOVED:
01597       break;
01598     case CHECK_COMPUTE_STATE:
01599       if ( IsMeshComputed() )
01600         _computeState = COMPUTE_OK;
01601       else
01602         if (_algoState == HYP_OK)
01603           _computeState = READY_TO_COMPUTE;
01604         else
01605           _computeState = NOT_READY;
01606       break;
01607     default:
01608       ASSERT(0);
01609       break;
01610     }
01611     break;
01612 
01613     // ----------------------------------------------------------------------
01614   default:
01615     ASSERT(0);
01616     break;
01617   }
01618 
01619   NotifyListenersOnEvent( event, COMPUTE_EVENT );
01620 
01621   return ret;
01622 }
01623 
01624 
01625 //=============================================================================
01629 //=============================================================================
01630 
01631 bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap)
01632 {
01633   _computeError.reset();
01634 
01635   bool ret = true;
01636 
01637   if (_subShape.ShapeType() == TopAbs_VERTEX) {
01638     vector<int> aVec(SMDSEntity_Last,0);
01639     aVec[SMDSEntity_Node] = 1;
01640     aResMap.insert(make_pair(this,aVec));
01641     return ret;
01642   }
01643 
01644   SMESH_Gen *gen = _father->GetGen();
01645   SMESH_Algo *algo = 0;
01646   SMESH_Hypothesis::Hypothesis_Status hyp_status;
01647 
01648   algo = gen->GetAlgo((*_father), _subShape);
01649   if(algo && !aResMap.count(this) )
01650   {
01651     ret = algo->CheckHypothesis((*_father), _subShape, hyp_status);
01652     if (!ret) return false;
01653 
01654     if (_father->HasShapeToMesh() && algo->NeedDescretBoundary())
01655     {
01656       // check submeshes needed
01657       bool subMeshEvaluated = true;
01658       int dimToCheck = SMESH_Gen::GetShapeDim( _subShape ) - 1;
01659       SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,/*complexShapeFirst=*/true);
01660       while ( smIt->more() && subMeshEvaluated )
01661       {
01662         SMESH_subMesh* sm = smIt->next();
01663         int dim = SMESH_Gen::GetShapeDim( sm->GetSubShape() );
01664         if (dim < dimToCheck) break; // the rest subMeshes are all of less dimension
01665         const vector<int> & nbs = aResMap[ sm ];
01666         subMeshEvaluated = (std::accumulate( nbs.begin(), nbs.end(), 0 ) > 0 );
01667       }
01668       if ( !subMeshEvaluated )
01669         return false;
01670     }
01671     _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo);
01672     ret = algo->Evaluate((*_father), _subShape, aResMap);
01673 
01674     aResMap.insert( make_pair( this,vector<int>(0)));
01675   }
01676 
01677   return ret;
01678 }
01679 
01680 
01681 //=======================================================================
01687 //=======================================================================
01688 
01689 bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& theShape)
01690 {
01691   bool noErrors = true;
01692 
01693   if ( !theShape.IsNull() )
01694   {
01695     // Check state of submeshes
01696     if ( !theAlgo->NeedDescretBoundary())
01697     {
01698       SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
01699       while ( smIt->more() )
01700         if ( !smIt->next()->CheckComputeError( theAlgo ))
01701           noErrors = false;
01702     }
01703 
01704     // Check state of neighbours
01705     if ( !theAlgo->OnlyUnaryInput() &&
01706          theShape.ShapeType() == TopAbs_COMPOUND &&
01707          !theShape.IsSame( _subShape ))
01708     {
01709       for (TopoDS_Iterator subIt( theShape ); subIt.More(); subIt.Next()) {
01710         SMESH_subMesh* sm = _father->GetSubMesh( subIt.Value() );
01711         if ( sm != this ) {
01712           if ( !sm->CheckComputeError( theAlgo, sm->GetSubShape() ))
01713             noErrors = false;
01714           UpdateDependantsState( SUBMESH_COMPUTED ); // send event SUBMESH_COMPUTED
01715         }
01716       }
01717     }
01718   }
01719   {
01720     // Check my state
01721     if ( !_computeError || _computeError->IsOK() )
01722     {
01723       _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE;
01724     }
01725     else
01726     {
01727       if ( !_computeError->myAlgo )
01728         _computeError->myAlgo = theAlgo;
01729 
01730       // Show error
01731       SMESH_Comment text;
01732       text << theAlgo->GetName() << " failed on subshape #" << _Id << " with error ";
01733       if (_computeError->IsCommon() )
01734         text << _computeError->CommonName();
01735       else
01736         text << _computeError->myName;
01737       if ( _computeError->myComment.size() > 0 )
01738         text << " \"" << _computeError->myComment << "\"";
01739 
01740       INFOS( text );
01741 
01742       _computeState = FAILED_TO_COMPUTE;
01743       noErrors = false;
01744     }
01745   }
01746   return noErrors;
01747 }
01748 
01749 //=======================================================================
01750 //function : ApplyToCollection
01751 //purpose  : Apply theAlgo to all subshapes in theCollection
01752 //=======================================================================
01753 
01754 bool SMESH_subMesh::ApplyToCollection (SMESH_Algo*         theAlgo,
01755                                        const TopoDS_Shape& theCollection)
01756 {
01757   MESSAGE("SMESH_subMesh::ApplyToCollection");
01758   ASSERT ( !theAlgo->NeedDescretBoundary() );
01759 
01760   if ( _computeError )
01761     _computeError->myName = COMPERR_OK;
01762 
01763   bool ok = theAlgo->Compute( *_father, theCollection );
01764 
01765   // set _computeState of subshapes
01766   TopExp_Explorer anExplorer( theCollection, _subShape.ShapeType() );
01767   for ( ; anExplorer.More(); anExplorer.Next() )
01768   {
01769     if ( SMESH_subMesh* subMesh = _father->GetSubMeshContaining( anExplorer.Current() ))
01770     {
01771       bool localOK = subMesh->CheckComputeError( theAlgo );
01772       if ( !ok && localOK && !subMesh->IsMeshComputed() )
01773       {
01774         subMesh->_computeError = theAlgo->GetComputeError();
01775         if ( subMesh->_computeError->IsOK() )
01776           _computeError = SMESH_ComputeError::New(COMPERR_ALGO_FAILED);
01777         localOK = CheckComputeError( theAlgo );
01778       }
01779       if ( localOK )
01780         subMesh->UpdateDependantsState( SUBMESH_COMPUTED );
01781       subMesh->UpdateSubMeshState( localOK ? COMPUTE_OK : FAILED_TO_COMPUTE );
01782     }
01783   }
01784 
01785   return true;
01786 }
01787 
01788 
01789 //=======================================================================
01790 //function : UpdateSubMeshState
01791 //purpose  :
01792 //=======================================================================
01793 
01794 void SMESH_subMesh::UpdateSubMeshState(const compute_state theState)
01795 {
01796   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
01797   while ( smIt->more() )
01798     smIt->next()->_computeState = theState;
01799 }
01800 
01801 //=======================================================================
01802 //function : ComputeSubMeshStateEngine
01803 //purpose  :
01804 //=======================================================================
01805 
01806 void SMESH_subMesh::ComputeSubMeshStateEngine(int event)
01807 {
01808   SMESH_subMeshIteratorPtr smIt = getDependsOnIterator(false,false);
01809   while ( smIt->more() )
01810     smIt->next()->ComputeStateEngine(event);
01811 }
01812 
01813 //=======================================================================
01814 //function : UpdateDependantsState
01815 //purpose  :
01816 //=======================================================================
01817 
01818 void SMESH_subMesh::UpdateDependantsState(const compute_event theEvent)
01819 {
01820   //MESSAGE("SMESH_subMesh::UpdateDependantsState");
01821   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
01822   for (; it.More(); it.Next())
01823   {
01824     const TopoDS_Shape& ancestor = it.Value();
01825     SMESH_subMesh *aSubMesh =
01826       _father->GetSubMeshContaining(ancestor);
01827     if (aSubMesh)
01828       aSubMesh->ComputeStateEngine( theEvent );
01829   }
01830 }
01831 
01832 //=============================================================================
01836 //=============================================================================
01837 
01838 void SMESH_subMesh::CleanDependants()
01839 {
01840   int dimToClean = SMESH_Gen::GetShapeDim( _subShape ) + 1;
01841 
01842   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
01843   for (; it.More(); it.Next())
01844   {
01845     const TopoDS_Shape& ancestor = it.Value();
01846     if ( SMESH_Gen::GetShapeDim( ancestor ) == dimToClean ) {
01847       // PAL8021. do not go upper than SOLID, else ComputeStateEngine(CLEAN)
01848       // will erase mesh on other shapes in a compound
01849       if ( ancestor.ShapeType() >= TopAbs_SOLID ) {
01850         SMESH_subMesh *aSubMesh = _father->GetSubMeshContaining(ancestor);
01851         if (aSubMesh)
01852           aSubMesh->ComputeStateEngine(CLEAN);
01853       }
01854     }
01855   }
01856 }
01857 
01858 //=============================================================================
01862 //=============================================================================
01863 
01864 void SMESH_subMesh::RemoveSubMeshElementsAndNodes()
01865 {
01866   //SCRUTE(_subShape.ShapeType());
01867 
01868   cleanSubMesh( this );
01869 
01870   // algo may bind a submesh not to _subShape, eg 3D algo
01871   // sets nodes on SHELL while _subShape may be SOLID
01872 
01873   int dim = SMESH_Gen::GetShapeDim( _subShape );
01874   int type = _subShape.ShapeType() + 1;
01875   for ( ; type <= TopAbs_EDGE; type++) {
01876     if ( dim == SMESH_Gen::GetShapeDim( (TopAbs_ShapeEnum) type ))
01877     {
01878       TopExp_Explorer exp( _subShape, (TopAbs_ShapeEnum) type );
01879       for ( ; exp.More(); exp.Next() )
01880         cleanSubMesh( _father->GetSubMeshContaining( exp.Current() ));
01881     }
01882     else
01883       break;
01884   }
01885 }
01886 
01887 //=======================================================================
01888 //function : GetCollection
01889 //purpose  : return a shape containing all sub-shapes of the MainShape that can be
01890 //           meshed at once along with _subShape
01891 //=======================================================================
01892 
01893 TopoDS_Shape SMESH_subMesh::GetCollection(SMESH_Gen * theGen,
01894                                           SMESH_Algo* theAlgo,
01895                                           bool &      theSubComputed)
01896 {
01897   MESSAGE("SMESH_subMesh::GetCollection");
01898 
01899   theSubComputed = SubMeshesComputed();
01900 
01901   TopoDS_Shape mainShape = _father->GetMeshDS()->ShapeToMesh();
01902 
01903   if ( mainShape.IsSame( _subShape ))
01904     return _subShape;
01905 
01906   const bool ignoreAuxiliaryHyps = false;
01907   list<const SMESHDS_Hypothesis*> aUsedHyp =
01908     theAlgo->GetUsedHypothesis( *_father, _subShape, ignoreAuxiliaryHyps ); // copy
01909 
01910   // put in a compound all shapes with the same hypothesis assigned
01911   // and a good ComputState
01912 
01913   TopoDS_Compound aCompound;
01914   BRep_Builder aBuilder;
01915   aBuilder.MakeCompound( aCompound );
01916 
01917   TopExp_Explorer anExplorer( mainShape, _subShape.ShapeType() );
01918   for ( ; anExplorer.More(); anExplorer.Next() )
01919   {
01920     const TopoDS_Shape& S = anExplorer.Current();
01921     SMESH_subMesh* subMesh = _father->GetSubMesh( S );
01922     if ( subMesh == this )
01923     {
01924       aBuilder.Add( aCompound, S );
01925     }
01926     else if ( subMesh->GetComputeState() == READY_TO_COMPUTE )
01927     {
01928       SMESH_Algo* anAlgo = theGen->GetAlgo( *_father, S );
01929       if (strcmp( anAlgo->GetName(), theAlgo->GetName()) == 0 && // same algo
01930           anAlgo->GetUsedHypothesis( *_father, S, ignoreAuxiliaryHyps ) == aUsedHyp) // same hyps
01931         aBuilder.Add( aCompound, S );
01932       if ( !subMesh->SubMeshesComputed() )
01933         theSubComputed = false;
01934     }
01935   }
01936 
01937   return aCompound;
01938 }
01939 
01940 //=======================================================================
01941 //function : GetSimilarAttached
01942 //purpose  : return a hypothesis attached to theShape.
01943 //           If theHyp is provided, similar but not same hypotheses
01944 //           is returned; else only applicable ones having theHypType
01945 //           is returned
01946 //=======================================================================
01947 
01948 const SMESH_Hypothesis* SMESH_subMesh::GetSimilarAttached(const TopoDS_Shape&      theShape,
01949                                                           const SMESH_Hypothesis * theHyp,
01950                                                           const int                theHypType)
01951 {
01952   SMESH_HypoFilter hypoKind;
01953   hypoKind.Init( hypoKind.HasType( theHyp ? theHyp->GetType() : theHypType ));
01954   if ( theHyp ) {
01955     hypoKind.And   ( hypoKind.HasDim( theHyp->GetDim() ));
01956     hypoKind.AndNot( hypoKind.Is( theHyp ));
01957     if ( theHyp->IsAuxiliary() )
01958       hypoKind.And( hypoKind.HasName( theHyp->GetName() ));
01959     else
01960       hypoKind.AndNot( hypoKind.IsAuxiliary());
01961   }
01962   else {
01963     hypoKind.And( hypoKind.IsApplicableTo( theShape ));
01964   }
01965 
01966   return _father->GetHypothesis( theShape, hypoKind, false );
01967 }
01968 
01969 //=======================================================================
01970 //function : CheckConcurentHypothesis
01971 //purpose  : check if there are several applicable hypothesis attached to
01972 //           ancestors
01973 //=======================================================================
01974 
01975 SMESH_Hypothesis::Hypothesis_Status
01976   SMESH_subMesh::CheckConcurentHypothesis (const int theHypType)
01977 {
01978   MESSAGE ("SMESH_subMesh::CheckConcurentHypothesis");
01979 
01980   // is there local hypothesis on me?
01981   if ( GetSimilarAttached( _subShape, 0, theHypType ) )
01982     return SMESH_Hypothesis::HYP_OK;
01983 
01984 
01985   TopoDS_Shape aPrevWithHyp;
01986   const SMESH_Hypothesis* aPrevHyp = 0;
01987   TopTools_ListIteratorOfListOfShape it( _father->GetAncestors( _subShape ));
01988   for (; it.More(); it.Next())
01989   {
01990     const TopoDS_Shape& ancestor = it.Value();
01991     const SMESH_Hypothesis* hyp = GetSimilarAttached( ancestor, 0, theHypType );
01992     if ( hyp )
01993     {
01994       if ( aPrevWithHyp.IsNull() || aPrevWithHyp.IsSame( ancestor ))
01995       {
01996         aPrevWithHyp = ancestor;
01997         aPrevHyp     = hyp;
01998       }
01999       else if ( aPrevWithHyp.ShapeType() == ancestor.ShapeType() && aPrevHyp != hyp )
02000         return SMESH_Hypothesis::HYP_CONCURENT;
02001       else
02002         return SMESH_Hypothesis::HYP_OK;
02003     }
02004   }
02005   return SMESH_Hypothesis::HYP_OK;
02006 }
02007 
02008 //================================================================================
02021 //================================================================================
02022 
02023 void SMESH_subMesh::SetEventListener(EventListener*     listener,
02024                                      EventListenerData* data,
02025                                      SMESH_subMesh*     where)
02026 {
02027   if ( listener && where ) {
02028     where->SetEventListener( listener, data );
02029     myOwnListeners.push_back( make_pair( where, listener ));
02030   }
02031 }
02032 
02033 //================================================================================
02041 //================================================================================
02042 
02043 void SMESH_subMesh::SetEventListener(EventListener* listener, EventListenerData* data)
02044 {
02045   map< EventListener*, EventListenerData* >::iterator l_d =
02046     myEventListeners.find( listener );
02047   if ( l_d != myEventListeners.end() ) {
02048     EventListenerData* curData = l_d->second;
02049     if ( curData && curData != data && curData->IsDeletable() )
02050       delete curData;
02051     l_d->second = data;
02052   }
02053   else 
02054     myEventListeners.insert( make_pair( listener, data ));
02055 }
02056 
02057 //================================================================================
02063 //================================================================================
02064 
02065 EventListenerData* SMESH_subMesh::GetEventListenerData(EventListener* listener) const
02066 {
02067   map< EventListener*, EventListenerData* >::const_iterator l_d =
02068     myEventListeners.find( listener );
02069   if ( l_d != myEventListeners.end() )
02070     return l_d->second;
02071   return 0;
02072 }
02073 
02074 //================================================================================
02081 //================================================================================
02082 
02083 void SMESH_subMesh::NotifyListenersOnEvent( const int         event,
02084                                             const event_type  eventType,
02085                                             SMESH_Hypothesis* hyp)
02086 {
02087   map< EventListener*, EventListenerData* >::iterator l_d = myEventListeners.begin();
02088   for ( ; l_d != myEventListeners.end(); ++l_d )
02089     if ( (*l_d).first->myBusySM.insert( this ).second )
02090     {
02091       l_d->first->ProcessEvent( event, eventType, this, l_d->second, hyp );
02092       l_d->first->myBusySM.erase( this );
02093     }
02094 }
02095 
02096 //================================================================================
02101 //================================================================================
02102 
02103 void SMESH_subMesh::DeleteEventListener(EventListener* listener)
02104 {
02105   map< EventListener*, EventListenerData* >::iterator l_d =
02106     myEventListeners.find( listener );
02107   if ( l_d != myEventListeners.end() ) {
02108     if ( l_d->first  && l_d->first->IsDeletable() )  delete l_d->first;
02109     if ( l_d->second && l_d->second->IsDeletable() ) delete l_d->second;
02110     myEventListeners.erase( l_d );
02111   }
02112 }
02113 
02114 //================================================================================
02118 //================================================================================
02119 
02120 void SMESH_subMesh::DeleteOwnListeners()
02121 {
02122   list< pair< SMESH_subMesh*, EventListener* > >::iterator sm_l;
02123   for ( sm_l = myOwnListeners.begin(); sm_l != myOwnListeners.end(); ++sm_l)
02124     sm_l->first->DeleteEventListener( sm_l->second );
02125   myOwnListeners.clear();
02126 }
02127 
02128 //================================================================================
02141 //================================================================================
02142 
02143 void SMESH_subMeshEventListener::ProcessEvent(const int          event,
02144                                               const int          eventType,
02145                                               SMESH_subMesh*     subMesh,
02146                                               EventListenerData* data,
02147                                               const SMESH_Hypothesis*  /*hyp*/)
02148 {
02149   if ( data && !data->mySubMeshes.empty() &&
02150        eventType == SMESH_subMesh::COMPUTE_EVENT)
02151   {
02152     ASSERT( data->mySubMeshes.front() != subMesh );
02153     list<SMESH_subMesh*>::iterator smIt = data->mySubMeshes.begin();
02154     list<SMESH_subMesh*>::iterator smEnd = data->mySubMeshes.end();
02155     switch ( event ) {
02156     case SMESH_subMesh::CLEAN:
02157       for ( ; smIt != smEnd; ++ smIt)
02158         (*smIt)->ComputeStateEngine( event );
02159       break;
02160     case SMESH_subMesh::COMPUTE:
02161       if ( subMesh->GetComputeState() == SMESH_subMesh::COMPUTE_OK )
02162         for ( ; smIt != smEnd; ++ smIt)
02163           (*smIt)->ComputeStateEngine( SMESH_subMesh::SUBMESH_COMPUTED );
02164       break;
02165     default:;
02166     }
02167   }
02168 }
02169 
02170 namespace {
02171 
02172   //================================================================================
02176   //================================================================================
02177 
02178   struct _Iterator : public SMDS_Iterator<SMESH_subMesh*>
02179   {
02180     _Iterator(SMDS_Iterator<SMESH_subMesh*>* subIt,
02181               SMESH_subMesh*                 prepend,
02182               SMESH_subMesh*                 append): myIt(subIt),myAppend(append)
02183     {
02184       myCur = prepend ? prepend : myIt->more() ? myIt->next() : append;
02185       if ( myCur == append ) append = 0;
02186     }
02188     virtual bool more()
02189     {
02190       return myCur;
02191     }
02193     virtual SMESH_subMesh* next()
02194     {
02195       SMESH_subMesh* res = myCur;
02196       if ( myIt->more() ) { myCur = myIt->next(); }
02197       else                { myCur = myAppend; myAppend = 0; }
02198       return res;
02199     }
02201     ~_Iterator()
02202     { delete myIt; }
02204     SMESH_subMesh                 *myAppend, *myCur;
02205     SMDS_Iterator<SMESH_subMesh*> *myIt;
02206   };
02207 }
02208 
02209 //================================================================================
02215 //================================================================================
02216 
02217 SMESH_subMeshIteratorPtr SMESH_subMesh::getDependsOnIterator(const bool includeSelf,
02218                                                              const bool reverse)
02219 {
02220   SMESH_subMesh *prepend=0, *append=0;
02221   if ( includeSelf ) {
02222     if ( reverse ) prepend = this;
02223     else            append = this;
02224   }
02225   typedef map < int, SMESH_subMesh * > TMap;
02226   if ( reverse )
02227   {
02228     return SMESH_subMeshIteratorPtr
02229       ( new _Iterator( new SMDS_mapReverseIterator<TMap>( DependsOn() ), prepend, append ));
02230   }
02231   {
02232     return SMESH_subMeshIteratorPtr
02233       ( new _Iterator( new SMDS_mapIterator<TMap>( DependsOn() ), prepend, append ));
02234   }
02235 }
02236 
02237 //================================================================================
02243 //================================================================================
02244 
02245 bool SMESH_subMesh::FindIntersection(const SMESH_subMesh* theOther,
02246                                      std::set<const SMESH_subMesh*>& theSetOfCommon ) const
02247 {
02248   int oldNb = theSetOfCommon.size();
02249   // check main submeshes
02250   const map <int, SMESH_subMesh*>::const_iterator otherEnd = theOther->_mapDepend.end();
02251   if ( theOther->_mapDepend.find(this->GetId()) != otherEnd )
02252     theSetOfCommon.insert( this );
02253   if ( _mapDepend.find(theOther->GetId()) != _mapDepend.end() )
02254     theSetOfCommon.insert( theOther );
02255   // check common submeshes
02256   map <int, SMESH_subMesh*>::const_iterator mapIt = _mapDepend.begin();
02257   for( ; mapIt != _mapDepend.end(); mapIt++ )
02258     if ( theOther->_mapDepend.find((*mapIt).first) != otherEnd )
02259       theSetOfCommon.insert( (*mapIt).second );
02260   return oldNb < theSetOfCommon.size();
02261 }
Copyright © 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
Copyright © 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS