Back to index

salome-smesh  6.5.0
StdMeshers_Propagation.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   : StdMeshers_Propagation.cxx
00025 //  Module : SMESH
00026 //
00027 #include "StdMeshers_Propagation.hxx"
00028 
00029 #include "utilities.h"
00030 
00031 #include "SMDS_SetIterator.hxx"
00032 #include "SMESH_Algo.hxx"
00033 #include "SMESH_Gen.hxx"
00034 #include "SMESH_HypoFilter.hxx"
00035 #include "SMESH_Mesh.hxx"
00036 #include "SMESH_subMesh.hxx"
00037 
00038 #include <BRepTools_WireExplorer.hxx>
00039 #include <TopTools_ListIteratorOfListOfShape.hxx>
00040 #include <TopTools_MapOfShape.hxx>
00041 #include <TopoDS.hxx>
00042 
00043 #define DBGMSG(txt) \
00044   //  cout << txt << endl;
00045 
00046 using namespace std;
00047 
00048 namespace {
00049 
00050   // =======================================================================
00054   // =======================================================================
00055 
00056   class PropagationMgr: public SMESH_subMeshEventListener
00057   {
00058   public:
00059     static PropagationMgr* GetListener();
00063     static void Set(SMESH_subMesh * submesh);
00067     static TopoDS_Edge GetSource(SMESH_subMesh * submesh);
00071     void ProcessEvent(const int          event,
00072                       const int          eventType,
00073                       SMESH_subMesh*     subMesh,
00074                       SMESH_subMeshEventListenerData* data,
00075                       const SMESH_Hypothesis*         hyp = 0);
00076   private:
00077     PropagationMgr();
00078   };
00079 }
00080 
00081 //=============================================================================
00085 //=============================================================================
00086 
00087 StdMeshers_Propagation::StdMeshers_Propagation (int hypId, int studyId, SMESH_Gen * gen)
00088   : SMESH_Hypothesis(hypId, studyId, gen)
00089 {
00090   _name = GetName();
00091   _param_algo_dim = -1; // 1D auxiliary
00092 }
00093 StdMeshers_Propagation::~StdMeshers_Propagation()                      {}
00094 string StdMeshers_Propagation::GetName ()                              { return "Propagation"; }
00095 ostream & StdMeshers_Propagation::SaveTo (ostream & save)              { return save; }
00096 istream & StdMeshers_Propagation::LoadFrom (istream & load)            { return load; }
00097 ostream & operator << (ostream & save, StdMeshers_Propagation & hyp)   { return hyp.SaveTo(save); }
00098 istream & operator >> (istream & load, StdMeshers_Propagation & hyp)   { return hyp.LoadFrom(load); }
00099 bool StdMeshers_Propagation::SetParametersByMesh(const SMESH_Mesh*,
00100                                                  const TopoDS_Shape& ) { return false; }
00101 bool StdMeshers_Propagation::SetParametersByDefaults(const TDefaults&,const SMESH_Mesh*) { return false; }
00102 void StdMeshers_Propagation::SetPropagationMgr(SMESH_subMesh* subMesh) { PropagationMgr::Set( subMesh ); }
00106 TopoDS_Edge StdMeshers_Propagation::GetPropagationSource(SMESH_Mesh& theMesh,
00107                                                          const TopoDS_Shape& theEdge)
00108 {
00109   return PropagationMgr::GetSource(theMesh.GetSubMeshContaining( theEdge ));
00110 }
00111 
00112 //=============================================================================
00113 //=============================================================================
00114 // PROPAGATION MANAGEMENT
00115 //=============================================================================
00116 //=============================================================================
00117 
00118 namespace {
00119 
00120   enum SubMeshState { WAIT_PROPAG_HYP, // propagation hyp or local 1D hyp is missing
00121                       HAS_PROPAG_HYP,  // propag hyp on this submesh
00122                       IN_CHAIN,        // submesh is in propagation chain
00123                       LAST_IN_CHAIN,   // submesh with local 1D hyp breaking a chain
00124                       MEANINGLESS_LAST };          // meaningless
00125 
00126   struct PropagationMgrData : public EventListenerData
00127   {
00128     bool myForward; 
00129     PropagationMgrData( SubMeshState state=WAIT_PROPAG_HYP ): EventListenerData(true) {
00130       myType = state; myForward = true;
00131     }
00132     void Init() {
00133       myType = WAIT_PROPAG_HYP;  mySubMeshes.clear(); myForward = true;
00134     }
00135     SubMeshState State() const {
00136       return (SubMeshState) myType;
00137     }
00138     void SetState(SubMeshState state) {
00139       myType = state;
00140     }
00141     void SetSource(SMESH_subMesh* sm ) {
00142       mySubMeshes.clear(); if ( sm ) mySubMeshes.push_back( sm );
00143     }
00144     void AddSource(SMESH_subMesh* sm ) {
00145       if ( sm ) mySubMeshes.push_back( sm );
00146     }
00147     void SetChain(list< SMESH_subMesh* >& chain ) {
00148       mySubMeshes.clear(); mySubMeshes.splice( mySubMeshes.end(), chain );
00149     }
00150     SMESH_subMeshIteratorPtr GetChain() const;
00151     SMESH_subMesh* GetSource() const;
00152   };
00153 
00154   //=============================================================================
00158   PropagationMgr* PropagationMgr::GetListener()
00159   {
00160     static PropagationMgr theListener;
00161     return &theListener;
00162   }
00163   PropagationMgr* getListener()
00164   {
00165     return PropagationMgr::GetListener();
00166   }
00167   //=============================================================================
00171   PropagationMgrData* findData(SMESH_subMesh* sm)
00172   {
00173     if ( sm )
00174       return static_cast< PropagationMgrData* >( sm->GetEventListenerData( getListener() ));
00175     return 0;
00176   }
00177   //=============================================================================
00181   PropagationMgrData* findData(SMESH_Mesh& theMesh, const TopoDS_Shape& theEdge)
00182   {
00183     if ( theEdge.ShapeType() == TopAbs_EDGE )
00184       return findData( theMesh.GetSubMeshContaining( theEdge ) );
00185     return 0;
00186   }
00187   //=============================================================================
00191   PropagationMgrData* getData(SMESH_subMesh* sm)
00192   {
00193     PropagationMgrData* data = findData( sm );
00194     if ( !data && sm ) {
00195       data = new PropagationMgrData();
00196       sm->SetEventListener( getListener(), data, sm );
00197     }
00198     return data;
00199   }
00200   //=============================================================================
00204   const SMESH_Hypothesis* getLocal1DHyp (SMESH_Mesh&         theMesh,
00205                                          const TopoDS_Shape& theEdge)
00206   {
00207     static SMESH_HypoFilter hypo;
00208     hypo.Init( hypo.HasDim( 1 )).
00209       AndNot ( hypo.IsAlgo() ).
00210       AndNot ( hypo.IsAssignedTo( theMesh.GetMeshDS()->ShapeToMesh() ));
00211     return theMesh.GetHypothesis( theEdge, hypo, true );
00212   }
00213   //=============================================================================
00217   const SMESH_Hypothesis* getProagationHyp (SMESH_Mesh&         theMesh,
00218                                             const TopoDS_Shape& theEdge)
00219   {
00220     static SMESH_HypoFilter propagHypFilter
00221       ( SMESH_HypoFilter::HasName( StdMeshers_Propagation::GetName ()));
00222     return theMesh.GetHypothesis( theEdge, propagHypFilter, true );
00223   }
00224   //================================================================================
00228   SMESH_subMeshIteratorPtr iterate( list<SMESH_subMesh*>::const_iterator from,
00229                                     list<SMESH_subMesh*>::const_iterator to)
00230   {
00231     typedef SMESH_subMesh* TsubMesh;
00232     typedef SMDS_SetIterator< TsubMesh, list< TsubMesh >::const_iterator > TIterator;
00233     return SMESH_subMeshIteratorPtr ( new TIterator( from, to ));
00234   }
00235   //================================================================================
00240   bool buildPropagationChain ( SMESH_subMesh* theMainSubMesh )
00241   {
00242     DBGMSG( "buildPropagationChain from " << theMainSubMesh->GetId() );
00243     const TopoDS_Shape& theMainEdge = theMainSubMesh->GetSubShape();
00244     if (theMainEdge.ShapeType() != TopAbs_EDGE) return true;
00245 
00246     SMESH_Mesh* mesh = theMainSubMesh->GetFather();
00247 
00248     PropagationMgrData* chainData = getData( theMainSubMesh );
00249     chainData->SetState( HAS_PROPAG_HYP );
00250 
00251     // Edge submeshes, to which the 1D hypothesis will be propagated from theMainEdge
00252     list<SMESH_subMesh*> & chain = chainData->mySubMeshes;
00253     chain.clear();
00254     chain.push_back( theMainSubMesh );
00255 
00256     TopTools_MapOfShape checkedShapes;
00257     checkedShapes.Add( theMainEdge );
00258 
00259     list<SMESH_subMesh*>::iterator smIt = chain.begin();
00260     for ( ; smIt != chain.end(); ++smIt )
00261     {
00262       const TopoDS_Edge& anE = TopoDS::Edge( (*smIt)->GetSubShape() );
00263       PropagationMgrData* data = findData( *smIt );
00264       if ( !data ) continue;
00265 
00266       // Iterate on faces, having edge <anE>
00267       TopTools_ListIteratorOfListOfShape itA (mesh->GetAncestors(anE));
00268       for (; itA.More(); itA.Next())
00269       {
00270         // there are objects of different type among the ancestors of edge
00271         if ( itA.Value().ShapeType() != TopAbs_WIRE /*|| !checkedShapes.Add( itA.Value() )*/)
00272           continue;
00273 
00274         // Get ordered edges and find index of anE in a sequence
00275         BRepTools_WireExplorer aWE (TopoDS::Wire(itA.Value()));
00276         vector<TopoDS_Edge> edges;
00277         edges.reserve(4);
00278         int edgeIndex = 0;
00279         for (; aWE.More(); aWE.Next()) {
00280           TopoDS_Edge edge = aWE.Current();
00281           edge.Orientation( aWE.Orientation() );
00282           if ( edge.IsSame( anE ))
00283             edgeIndex = edges.size();
00284           edges.push_back( edge );
00285         }
00286 
00287         // Find an edge opposite to anE
00288         TopoDS_Edge anOppE;
00289         if ( edges.size() < 4 ) {
00290           continue; // too few edges
00291         }
00292         else if ( edges.size() == 4 ) {
00293           int oppIndex = ( edgeIndex + 2 ) % 4;
00294           anOppE = edges[ oppIndex ];
00295         }
00296         else {
00297           // count nb sides
00298           TopoDS_Edge prevEdge = anE;
00299           int nbSide = 0, eIndex = edgeIndex + 1;
00300           for ( int i = 0; i < edges.size(); ++i, ++eIndex )
00301           {
00302             if ( eIndex == edges.size() )
00303               eIndex = 0;
00304             if ( !SMESH_Algo::IsContinuous( prevEdge, edges[ eIndex ])) {
00305               nbSide++;
00306             }
00307             else {
00308               // check that anE is not a part of a composite side
00309               if ( anE.IsSame( prevEdge ) || anE.IsSame( edges[ eIndex ])) {
00310                 anOppE.Nullify(); break;
00311               }
00312             }
00313             if ( nbSide == 2 ) { // opposite side
00314               if ( !anOppE.IsNull() ) {
00315                 // composite opposite side -> stop propagation
00316                 anOppE.Nullify(); break;
00317               }
00318               anOppE = edges[ eIndex ];
00319             }
00320             if ( nbSide == 5 ) {
00321               anOppE.Nullify(); break; // too many sides
00322             }
00323             prevEdge = edges[ eIndex ];
00324           }
00325           if ( anOppE.IsNull() )
00326             continue;
00327           if ( nbSide != 4 ) {
00328             DBGMSG( nbSide << " sides in wire #" << mesh->GetMeshDS()->ShapeToIndex( itA.Value() ) << " - SKIP" );
00329             continue;
00330           }
00331         }
00332         if ( anOppE.IsNull() || !checkedShapes.Add( anOppE ))
00333           continue;
00334         SMESH_subMesh* oppSM = mesh->GetSubMesh( anOppE );
00335         PropagationMgrData* oppData = getData( oppSM );
00336 
00337         // Add anOppE to aChain if ...
00338         if ( oppData->State() == WAIT_PROPAG_HYP ) // ... anOppE is not in any chain
00339         {
00340           oppData->SetSource( theMainSubMesh );
00341           if ( !getLocal1DHyp( *mesh, anOppE )) // ... no 1d hyp on anOppE
00342           {
00343             oppData->myForward = data->myForward;
00344             if ( edges[ edgeIndex ].Orientation() == anOppE.Orientation() )
00345               oppData->myForward = !oppData->myForward;
00346             chain.push_back( oppSM );
00347             oppSM->ComputeStateEngine( SMESH_subMesh::CLEAN );
00348             oppData->SetState( IN_CHAIN );
00349             DBGMSG( "set IN_CHAIN on " << oppSM->GetId() );
00350             if ( oppSM->GetAlgoState() != SMESH_subMesh::HYP_OK )
00351               // make oppSM check algo state
00352               if ( SMESH_Algo* algo = mesh->GetGen()->GetAlgo( *mesh, anOppE ))
00353                 oppSM->AlgoStateEngine(SMESH_subMesh::ADD_FATHER_ALGO,algo);
00354           }
00355           else {
00356             oppData->SetState( LAST_IN_CHAIN );
00357             DBGMSG( "set LAST_IN_CHAIN on " << oppSM->GetId() );
00358           }
00359         }
00360         else if ( oppData->State() == LAST_IN_CHAIN ) // anOppE breaks other chain
00361         {
00362           DBGMSG( "encounters LAST_IN_CHAIN on " << oppSM->GetId() );
00363           oppData->AddSource( theMainSubMesh );
00364         }
00365       } // loop on face ancestors
00366     } // loop on the chain
00367 
00368     // theMainSubMesh must not be in a chain
00369     chain.pop_front();
00370 
00371     return true;
00372   }
00373   //================================================================================
00377   bool clearPropagationChain( SMESH_subMesh* subMesh )
00378   {
00379     DBGMSG( "clearPropagationChain from " << subMesh->GetId() );
00380     if ( PropagationMgrData* data = findData( subMesh ))
00381     {
00382       switch ( data->State() ) {
00383       case IN_CHAIN:
00384         return clearPropagationChain( data->GetSource() );
00385 
00386       case HAS_PROPAG_HYP: {
00387         SMESH_subMeshIteratorPtr smIt = data->GetChain();
00388         while ( smIt->more() ) {
00389           SMESH_subMesh* sm = smIt->next();
00390           getData( sm )->Init();
00391           sm->ComputeStateEngine( SMESH_subMesh::CLEAN );
00392         }
00393         data->Init();
00394         break;
00395       }
00396       case LAST_IN_CHAIN: {
00397         SMESH_subMeshIteratorPtr smIt = iterate( data->mySubMeshes.begin(),
00398                                                  data->mySubMeshes.end());
00399         while ( smIt->more() )
00400           clearPropagationChain( smIt->next() );
00401         data->Init();
00402         break;
00403       }
00404       default:;
00405       }
00406       return true;
00407     }
00408     return false;
00409   }
00410 
00411 
00412   //================================================================================
00416   //================================================================================
00417 
00418   SMESH_subMeshIteratorPtr PropagationMgrData::GetChain() const
00419   {
00420     switch ( State() ) {
00421     case HAS_PROPAG_HYP:
00422       return iterate( mySubMeshes.begin(), mySubMeshes.end() );
00423     case IN_CHAIN:
00424       if ( mySubMeshes.empty() ) break;
00425       return getData( mySubMeshes.front() )->GetChain();
00426     default:;
00427     }
00428     return iterate( mySubMeshes.end(), mySubMeshes.end() );
00429   }
00430   //================================================================================
00434   //================================================================================
00435 
00436   SMESH_subMesh* PropagationMgrData::GetSource() const
00437   {
00438     if ( myType == IN_CHAIN )
00439       if ( !mySubMeshes.empty() ) 
00440         return mySubMeshes.front();
00441     return 0;
00442   }
00443 
00444 
00445   //================================================================================
00449   //================================================================================
00450 
00451   PropagationMgr::PropagationMgr()
00452     : SMESH_subMeshEventListener( false, // won't be deleted by submesh
00453                                   "StdMeshers_Propagation::PropagationMgr")
00454   {}
00455   //================================================================================
00459   //================================================================================
00460 
00461   void PropagationMgr::Set(SMESH_subMesh * submesh)
00462   {
00463     if ( findData( submesh )) return;
00464     DBGMSG( "PropagationMgr::Set() on  " << submesh->GetId() );
00465     EventListenerData* data = new PropagationMgrData();
00466     submesh->SetEventListener( getListener(), data, submesh );
00467 
00468     const SMESH_Hypothesis * propagHyp =
00469       getProagationHyp( *submesh->GetFather(), submesh->GetSubShape() );
00470     if ( propagHyp )
00471       getListener()->ProcessEvent( SMESH_subMesh::ADD_HYP,
00472                                    SMESH_subMesh::ALGO_EVENT,
00473                                    submesh,
00474                                    data,
00475                                    propagHyp);
00476   }
00477   //================================================================================
00481   //================================================================================
00482 
00483   TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh)
00484   {
00485     if ( PropagationMgrData* data = findData( submesh )) {
00486       if ( data->State() == IN_CHAIN ) {
00487         if ( SMESH_subMesh* sm = data->GetSource() )
00488         {
00489           TopoDS_Shape edge = sm->GetSubShape();
00490           edge = edge.Oriented( data->myForward ? TopAbs_FORWARD : TopAbs_REVERSED );
00491           DBGMSG( " GetSource() = edge " << sm->GetId() << " REV = " << (!data->myForward));
00492           if ( edge.ShapeType() == TopAbs_EDGE )
00493             return TopoDS::Edge( edge );
00494         }
00495       }
00496     }
00497     return TopoDS_Edge();
00498   }
00499   //================================================================================
00503   //================================================================================
00504 
00505   void PropagationMgr::ProcessEvent(const int          event,
00506                                     const int          eventType,
00507                                     SMESH_subMesh*     subMesh,
00508                                     SMESH_subMeshEventListenerData* listenerData,
00509                                     const SMESH_Hypothesis*         hyp)
00510   {
00511     if ( !listenerData )
00512       return;
00513     if ( !hyp || hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO || hyp->GetDim() != 1 )
00514       return;
00515     if ( eventType != SMESH_subMesh::ALGO_EVENT )
00516       return;
00517     DBGMSG( "PropagationMgr::ProcessEvent() on  " << subMesh->GetId() );
00518 
00519     bool isPropagHyp = ( StdMeshers_Propagation::GetName() == hyp->GetName() );
00520 
00521     PropagationMgrData* data = static_cast<PropagationMgrData*>( listenerData );
00522     switch ( data->State() ) {
00523 
00524     case WAIT_PROPAG_HYP: { // propagation hyp or local 1D hyp is missing
00525       // --------------------------------------------------------
00526       bool hasPropagHyp = ( isPropagHyp ||
00527                             getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) );
00528       if ( !hasPropagHyp )
00529         return;
00530       bool hasLocal1DHyp =  getLocal1DHyp( *subMesh->GetFather(), subMesh->GetSubShape());
00531       if ( !hasLocal1DHyp )
00532         return;
00533       if ( event == SMESH_subMesh::ADD_HYP ||
00534            event == SMESH_subMesh::ADD_FATHER_HYP ) // add local or propagation hyp
00535       {
00536         DBGMSG( "ADD_HYP propagation to WAIT_PROPAG_HYP " << subMesh->GetId() );
00537         // build propagation chain
00538         buildPropagationChain( subMesh );
00539       }
00540       return;
00541     }
00542     case HAS_PROPAG_HYP: {  // propag hyp on this submesh
00543       // --------------------------------------------------------
00544       switch ( event ) {
00545       case SMESH_subMesh::REMOVE_HYP:
00546       case SMESH_subMesh::REMOVE_FATHER_HYP: // remove propagation hyp
00547         if ( isPropagHyp && !getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) )
00548         {
00549           DBGMSG( "REMOVE_HYP propagation from HAS_PROPAG_HYP " << subMesh->GetId() );
00550           // clear propagation chain
00551           clearPropagationChain( subMesh );
00552         }
00553         // return; -- hyp is modified any way
00554       default:
00555         //case SMESH_subMesh::MODIF_HYP: // hyp modif
00556         // clear mesh in a chain
00557         DBGMSG( "MODIF_HYP on HAS_PROPAG_HYP " << subMesh->GetId() );
00558         SMESH_subMeshIteratorPtr smIt = data->GetChain();
00559         while ( smIt->more() ) {
00560           SMESH_subMesh* smInChain = smIt->next();
00561           smInChain->AlgoStateEngine( SMESH_subMesh::MODIF_HYP,
00562                                       (SMESH_Hypothesis*) hyp );
00563         }
00564         return;
00565       }
00566       return;
00567     }
00568     case IN_CHAIN: {       // submesh is in propagation chain
00569       // --------------------------------------------------------
00570       if ( event == SMESH_subMesh::ADD_HYP ) { // add local hypothesis
00571         if ( isPropagHyp ) { // propagation hyp added
00572           DBGMSG( "ADD_HYP propagation on IN_CHAIN " << subMesh->GetId() );
00573           // collision - do nothing
00574         }
00575         else { // 1D hyp added
00576           // rebuild propagation chain
00577           DBGMSG( "ADD_HYP 1D on IN_CHAIN " << subMesh->GetId() );
00578           SMESH_subMesh* sourceSM = data->GetSource();
00579           clearPropagationChain( sourceSM );
00580           buildPropagationChain( sourceSM );
00581         }
00582       }
00583       return;
00584     }
00585     case LAST_IN_CHAIN: { // submesh with local 1D hyp, breaking a chain
00586       // --------------------------------------------------------
00587       if ( event == SMESH_subMesh::REMOVE_HYP ) { // remove local hyp
00588         // rebuild propagation chain
00589         DBGMSG( "REMOVE_HYP 1D from LAST_IN_CHAIN " << subMesh->GetId() );
00590         list<SMESH_subMesh*> sourceSM = data->mySubMeshes;
00591         clearPropagationChain( subMesh );
00592         SMESH_subMeshIteratorPtr smIt = iterate( sourceSM.begin(), sourceSM.end());
00593         while ( smIt->more() )
00594           buildPropagationChain( smIt->next() );
00595       }
00596       return;
00597     }
00598     } // switch by SubMeshState
00599   }
00600 
00601 } // namespace