Back to index

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