00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
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;
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
00115
00116
00117
00118 namespace {
00119
00120 enum SubMeshState { WAIT_PROPAG_HYP,
00121 HAS_PROPAG_HYP,
00122 IN_CHAIN,
00123 LAST_IN_CHAIN,
00124 MEANINGLESS_LAST };
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
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
00267 TopTools_ListIteratorOfListOfShape itA (mesh->GetAncestors(anE));
00268 for (; itA.More(); itA.Next())
00269 {
00270
00271 if ( itA.Value().ShapeType() != TopAbs_WIRE )
00272 continue;
00273
00274
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
00288 TopoDS_Edge anOppE;
00289 if ( edges.size() < 4 ) {
00290 continue;
00291 }
00292 else if ( edges.size() == 4 ) {
00293 int oppIndex = ( edgeIndex + 2 ) % 4;
00294 anOppE = edges[ oppIndex ];
00295 }
00296 else {
00297
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
00309 if ( anE.IsSame( prevEdge ) || anE.IsSame( edges[ eIndex ])) {
00310 anOppE.Nullify(); break;
00311 }
00312 }
00313 if ( nbSide == 2 ) {
00314 if ( !anOppE.IsNull() ) {
00315
00316 anOppE.Nullify(); break;
00317 }
00318 anOppE = edges[ eIndex ];
00319 }
00320 if ( nbSide == 5 ) {
00321 anOppE.Nullify(); break;
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
00338 if ( oppData->State() == WAIT_PROPAG_HYP )
00339 {
00340 oppData->SetSource( theMainSubMesh );
00341 if ( !getLocal1DHyp( *mesh, 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
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 )
00361 {
00362 DBGMSG( "encounters LAST_IN_CHAIN on " << oppSM->GetId() );
00363 oppData->AddSource( theMainSubMesh );
00364 }
00365 }
00366 }
00367
00368
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 )
00453 {}
00454
00458
00459
00460 void PropagationMgr::Set(SMESH_subMesh * submesh)
00461 {
00462 if ( findData( submesh )) return;
00463 DBGMSG( "PropagationMgr::Set() on " << submesh->GetId() );
00464 EventListenerData* data = new PropagationMgrData();
00465 submesh->SetEventListener( getListener(), data, submesh );
00466
00467 const SMESH_Hypothesis * propagHyp =
00468 getProagationHyp( *submesh->GetFather(), submesh->GetSubShape() );
00469 if ( propagHyp )
00470 getListener()->ProcessEvent( SMESH_subMesh::ADD_HYP,
00471 SMESH_subMesh::ALGO_EVENT,
00472 submesh,
00473 data,
00474 propagHyp);
00475 }
00476
00480
00481
00482 TopoDS_Edge PropagationMgr::GetSource(SMESH_subMesh * submesh)
00483 {
00484 if ( PropagationMgrData* data = findData( submesh )) {
00485 if ( data->State() == IN_CHAIN ) {
00486 if ( SMESH_subMesh* sm = data->GetSource() )
00487 {
00488 TopoDS_Shape edge = sm->GetSubShape();
00489 edge = edge.Oriented( data->myForward ? TopAbs_FORWARD : TopAbs_REVERSED );
00490 DBGMSG( " GetSource() = edge " << sm->GetId() << " REV = " << (!data->myForward));
00491 if ( edge.ShapeType() == TopAbs_EDGE )
00492 return TopoDS::Edge( edge );
00493 }
00494 }
00495 }
00496 return TopoDS_Edge();
00497 }
00498
00502
00503
00504 void PropagationMgr::ProcessEvent(const int event,
00505 const int eventType,
00506 SMESH_subMesh* subMesh,
00507 SMESH_subMeshEventListenerData* listenerData,
00508 const SMESH_Hypothesis* hyp)
00509 {
00510 if ( !listenerData )
00511 return;
00512 if ( !hyp || hyp->GetType() != SMESHDS_Hypothesis::PARAM_ALGO || hyp->GetDim() != 1 )
00513 return;
00514 if ( eventType != SMESH_subMesh::ALGO_EVENT )
00515 return;
00516 DBGMSG( "PropagationMgr::ProcessEvent() on " << subMesh->GetId() );
00517
00518 bool isPropagHyp = ( StdMeshers_Propagation::GetName() == hyp->GetName() );
00519
00520 PropagationMgrData* data = static_cast<PropagationMgrData*>( listenerData );
00521 switch ( data->State() ) {
00522
00523 case WAIT_PROPAG_HYP: {
00524
00525 bool hasPropagHyp = ( isPropagHyp ||
00526 getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) );
00527 if ( !hasPropagHyp )
00528 return;
00529 bool hasLocal1DHyp = getLocal1DHyp( *subMesh->GetFather(), subMesh->GetSubShape());
00530 if ( !hasLocal1DHyp )
00531 return;
00532 if ( event == SMESH_subMesh::ADD_HYP ||
00533 event == SMESH_subMesh::ADD_FATHER_HYP )
00534 {
00535 DBGMSG( "ADD_HYP propagation to WAIT_PROPAG_HYP " << subMesh->GetId() );
00536
00537 buildPropagationChain( subMesh );
00538 }
00539 return;
00540 }
00541 case HAS_PROPAG_HYP: {
00542
00543 switch ( event ) {
00544 case SMESH_subMesh::REMOVE_HYP:
00545 case SMESH_subMesh::REMOVE_FATHER_HYP:
00546 if ( isPropagHyp && !getProagationHyp( *subMesh->GetFather(), subMesh->GetSubShape()) )
00547 {
00548 DBGMSG( "REMOVE_HYP propagation from HAS_PROPAG_HYP " << subMesh->GetId() );
00549
00550 clearPropagationChain( subMesh );
00551 }
00552
00553 default:
00554
00555
00556 DBGMSG( "MODIF_HYP on HAS_PROPAG_HYP " << subMesh->GetId() );
00557 SMESH_subMeshIteratorPtr smIt = data->GetChain();
00558 while ( smIt->more() ) {
00559 SMESH_subMesh* smInChain = smIt->next();
00560 smInChain->AlgoStateEngine( SMESH_subMesh::MODIF_HYP,
00561 (SMESH_Hypothesis*) hyp );
00562 }
00563 return;
00564 }
00565 return;
00566 }
00567 case IN_CHAIN: {
00568
00569 if ( event == SMESH_subMesh::ADD_HYP ) {
00570 if ( isPropagHyp ) {
00571 DBGMSG( "ADD_HYP propagation on IN_CHAIN " << subMesh->GetId() );
00572
00573 }
00574 else {
00575
00576 DBGMSG( "ADD_HYP 1D on IN_CHAIN " << subMesh->GetId() );
00577 SMESH_subMesh* sourceSM = data->GetSource();
00578 clearPropagationChain( sourceSM );
00579 buildPropagationChain( sourceSM );
00580 }
00581 }
00582 return;
00583 }
00584 case LAST_IN_CHAIN: {
00585
00586 if ( event == SMESH_subMesh::REMOVE_HYP ) {
00587
00588 DBGMSG( "REMOVE_HYP 1D from LAST_IN_CHAIN " << subMesh->GetId() );
00589 list<SMESH_subMesh*> sourceSM = data->mySubMeshes;
00590 clearPropagationChain( subMesh );
00591 SMESH_subMeshIteratorPtr smIt = iterate( sourceSM.begin(), sourceSM.end());
00592 while ( smIt->more() )
00593 buildPropagationChain( smIt->next() );
00594 }
00595 return;
00596 }
00597 }
00598 }
00599
00600 }