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