diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 7cc93177b..9173c3f86 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -238,6 +238,14 @@ module SMESH in GEOM::GEOM_Object theSubObject ) raises ( SALOME::SALOME_Exception ); + /*! + * Evaluates size of prospective mesh on a shape + */ + long_array Evaluate(in SMESH_Mesh theMesh, + in GEOM::GEOM_Object theSubObject) + //inout long_array theNbElems) + raises ( SALOME::SALOME_Exception ); + /*! * Calculate Mesh as preview till indicated dimension * First, verify list of hypothesis associated with the subShape. diff --git a/src/SMESH/SMESH_Algo.hxx b/src/SMESH/SMESH_Algo.hxx index 1ed9cde25..0cdaf639b 100644 --- a/src/SMESH/SMESH_Algo.hxx +++ b/src/SMESH/SMESH_Algo.hxx @@ -54,6 +54,13 @@ class SMDS_MeshNode; class SMESH_subMesh; class SMESH_MesherHelper; +typedef std::map< SMESH_subMesh*, std::vector > MapShapeNbElems; +// vector must have size 17: +// 0 - node, 1 - edge lin, 2 - edge quad, 3 - triangle lin, 4 - triangle quad +// 5 - quadrangle lin, 6 - quadrangle quad, 7 - polygon, 8 - tetra lin, +// 9 - tetra quad, 10 - pyramid lin, 11 - pyramid quad, 12 - penta lin, +// 13 - penta quad, 14 - hexa lin, 15 - hexa quad, 16 -polyhedra +typedef std::map< SMESH_subMesh*, std::vector >::iterator MapShapeNbElemsItr; class SMESH_EXPORT SMESH_Algo:public SMESH_Hypothesis { @@ -122,6 +129,16 @@ public: */ virtual bool Compute(SMESH_Mesh & aMesh, SMESH_MesherHelper* aHelper); + /*! + * \brief evaluates size of prospective mesh on a shape + * \param aMesh - the mesh + * \param aShape - the shape + * \param aNbElems - prospective number of elements by types + * \retval bool - is a success + */ + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap) = 0; + /*! * \brief Returns a list of compatible hypotheses used to mesh a shape * \param aMesh - the mesh diff --git a/src/SMESH/SMESH_Gen.cxx b/src/SMESH/SMESH_Gen.cxx index 955e1335d..77d3c92ac 100644 --- a/src/SMESH/SMESH_Gen.cxx +++ b/src/SMESH/SMESH_Gen.cxx @@ -287,6 +287,139 @@ bool SMESH_Gen::Compute(SMESH_Mesh & aMesh, return ret; } + +//============================================================================= +/*! + * Evaluate a mesh + */ +//============================================================================= + +bool SMESH_Gen::Evaluate(SMESH_Mesh & aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap, + const bool anUpward, + TSetOfInt* aShapesId) +{ + MESSAGE("SMESH_Gen::Evaluate"); + + bool ret = true; + + SMESH_subMesh *sm = aMesh.GetSubMesh(aShape); + + const bool includeSelf = true; + const bool complexShapeFirst = true; + SMESH_subMeshIteratorPtr smIt; + + if ( anUpward ) { // is called from below code here + // ----------------------------------------------- + // mesh all the subshapes starting from vertices + // ----------------------------------------------- + smIt = sm->getDependsOnIterator(includeSelf, !complexShapeFirst); + while ( smIt->more() ) { + SMESH_subMesh* smToCompute = smIt->next(); + + // do not mesh vertices of a pseudo shape + const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType(); + //if ( !aMesh.HasShapeToMesh() && aShType == TopAbs_VERTEX ) + // continue; + if ( !aMesh.HasShapeToMesh() ) { + if( aShType == TopAbs_VERTEX || aShType == TopAbs_WIRE || + aShType == TopAbs_SHELL ) + continue; + } + + smToCompute->Evaluate(aResMap); + if( aShapesId ) + aShapesId->insert( smToCompute->GetId() ); + } + return ret; + } + else { + // ----------------------------------------------------------------- + // apply algos that DO NOT require descretized boundaries and DO NOT + // support submeshes, starting from the most complex shapes + // and collect submeshes with algos that DO support submeshes + // ----------------------------------------------------------------- + list< SMESH_subMesh* > smWithAlgoSupportingSubmeshes; + smIt = sm->getDependsOnIterator(includeSelf, complexShapeFirst); + while ( smIt->more() ) { + SMESH_subMesh* smToCompute = smIt->next(); + const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); + const int aShapeDim = GetShapeDim( aSubShape ); + if ( aShapeDim < 1 ) break; + + SMESH_Algo* algo = GetAlgo( aMesh, aSubShape ); + if ( algo && !algo->NeedDescretBoundary() ) { + if ( algo->SupportSubmeshes() ) { + smWithAlgoSupportingSubmeshes.push_back( smToCompute ); + } + else { + smToCompute->Evaluate(aResMap); + if ( aShapesId ) + aShapesId->insert( smToCompute->GetId() ); + } + } + } + // ------------------------------------------------------------ + // compute submeshes under shapes with algos that DO NOT require + // descretized boundaries and DO support submeshes + // ------------------------------------------------------------ + list< SMESH_subMesh* >::reverse_iterator subIt, subEnd; + subIt = smWithAlgoSupportingSubmeshes.rbegin(); + subEnd = smWithAlgoSupportingSubmeshes.rend(); + // start from lower shapes + for ( ; subIt != subEnd; ++subIt ) { + sm = *subIt; + + // get a shape the algo is assigned to + TopoDS_Shape algoShape; + if ( !GetAlgo( aMesh, sm->GetSubShape(), & algoShape )) + continue; // strange... + + // look for more local algos + smIt = sm->getDependsOnIterator(!includeSelf, !complexShapeFirst); + while ( smIt->more() ) { + SMESH_subMesh* smToCompute = smIt->next(); + + const TopoDS_Shape& aSubShape = smToCompute->GetSubShape(); + const int aShapeDim = GetShapeDim( aSubShape ); + if ( aShapeDim < 1 ) continue; + + const TopAbs_ShapeEnum aShType = smToCompute->GetSubShape().ShapeType(); + + SMESH_HypoFilter filter( SMESH_HypoFilter::IsAlgo() ); + filter + .And( SMESH_HypoFilter::IsApplicableTo( aSubShape )) + .And( SMESH_HypoFilter::IsMoreLocalThan( algoShape )); + + if ( SMESH_Algo* subAlgo = (SMESH_Algo*) aMesh.GetHypothesis( aSubShape, filter, true )) { + SMESH_Hypothesis::Hypothesis_Status status; + if ( subAlgo->CheckHypothesis( aMesh, aSubShape, status )) + // mesh a lower smToCompute starting from vertices + Evaluate( aMesh, aSubShape, aResMap, /*anUpward=*/true, aShapesId ); + } + } + } + // ---------------------------------------------------------- + // apply the algos that do not require descretized boundaries + // ---------------------------------------------------------- + for ( subIt = smWithAlgoSupportingSubmeshes.rbegin(); subIt != subEnd; ++subIt ) { + sm->Evaluate(aResMap); + if ( aShapesId ) + aShapesId->insert( sm->GetId() ); + } + + // ----------------------------------------------- + // mesh the rest subshapes starting from vertices + // ----------------------------------------------- + ret = Evaluate( aMesh, aShape, aResMap, /*anUpward=*/true, aShapesId ); + } + + MESSAGE( "VSR - SMESH_Gen::Evaluate() finished, OK = " << ret); + return ret; +} + + //======================================================================= //function : checkConformIgnoredAlgos //purpose : diff --git a/src/SMESH/SMESH_Gen.hxx b/src/SMESH/SMESH_Gen.hxx index 46c00dc2c..57a5af6eb 100644 --- a/src/SMESH/SMESH_Gen.hxx +++ b/src/SMESH/SMESH_Gen.hxx @@ -81,6 +81,19 @@ class SMESH_EXPORT SMESH_Gen const ::MeshDimension aDim=::MeshDim_3D, TSetOfInt* aShapesId=0); + /*! + * \brief evaluates size of prospective mesh on a shape + * \param aMesh - the mesh + * \param aShape - the shape + * \param aResMap - map for prospective numbers of elements + * \retval bool - is a success + */ + bool Evaluate(::SMESH_Mesh & aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap, + const bool anUpward=false, + TSetOfInt* aShapesId=0); + bool CheckAlgoState(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); // notify on bad state of attached algos, return false // if Compute() would fail because of some algo bad state diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 5a8f63ebf..efd05b9c1 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1577,6 +1577,47 @@ bool SMESH_subMesh::ComputeStateEngine(int event) return ret; } + +//============================================================================= +/*! + * + */ +//============================================================================= + +bool SMESH_subMesh::Evaluate(MapShapeNbElems& aResMap) +{ + _computeError.reset(); + + bool ret = true; + + if (_subShape.ShapeType() == TopAbs_VERTEX) { + std::vector aVec(17); + aVec[0] = 1; + for(int i=1; i<17; i++) aVec[i] = 0; + aResMap.insert(std::make_pair(this,aVec)); + return ret; + } + + SMESH_Gen *gen = _father->GetGen(); + SMESH_Algo *algo = 0; + SMESH_Hypothesis::Hypothesis_Status hyp_status; + + algo = gen->GetAlgo((*_father), _subShape); + if(algo) { + ret = algo->CheckHypothesis((*_father), _subShape, hyp_status); + if (!ret) return false; + + TopoDS_Shape shape = _subShape; + + _computeError = SMESH_ComputeError::New(COMPERR_OK,"",algo); + + ret = algo->Evaluate((*_father), shape, aResMap); + } + + return ret; +} + + //======================================================================= /*! * \brief Update compute_state by _computeError and send proper events to diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index 83de353db..d4c0468f9 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -34,6 +34,7 @@ #include "SMESHDS_SubMesh.hxx" #include "SMESH_Hypothesis.hxx" #include "SMESH_ComputeError.hxx" +#include "SMESH_Algo.hxx" #include "Utils_SALOME_Exception.hxx" @@ -192,6 +193,8 @@ public: bool ComputeStateEngine(int event); + bool Evaluate(MapShapeNbElems& aResMap); + bool IsConform(const SMESH_Algo* theAlgo); // check if a conform mesh will be produced by the Algo diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index dcbe51e7f..e485f10ff 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -1614,6 +1614,7 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 701: // COMPUTE MESH case 711: // PRECOMPUTE MESH + case 712: // EVALUATE MESH { if (checkLock(aStudy)) break; startOperation( theCommandID ); @@ -2692,6 +2693,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 704, "EDIT_MESHSUBMESH","ICON_DLG_EDIT_MESH" ); createSMESHAction( 710, "BUILD_COMPOUND", "ICON_BUILD_COMPOUND" ); createSMESHAction( 711, "PRECOMPUTE", "ICON_PRECOMPUTE" ); + //createSMESHAction( 712, "EVALUATE", "ICON_EVALUATE" ); + createSMESHAction( 712, "EVALUATE", "ICON_COMPUTE" ); createSMESHAction( 806, "CREATE_GEO_GROUP","ICON_CREATE_GEO_GROUP" ); createSMESHAction( 801, "CREATE_GROUP", "ICON_CREATE_GROUP" ); createSMESHAction( 802, "CONSTRUCT_GROUP", "ICON_CONSTRUCT_GROUP" ); @@ -2836,6 +2839,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( separator(), meshId, -1 ); createMenu( 701, meshId, -1 ); createMenu( 711, meshId, -1 ); + createMenu( 712, meshId, -1 ); createMenu( separator(), meshId, -1 ); createMenu( 801, meshId, -1 ); createMenu( 806, meshId, -1 ); @@ -2937,6 +2941,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( separator(), meshTb ); createTool( 701, meshTb ); createTool( 711, meshTb ); + createTool( 712, meshTb ); createTool( separator(), meshTb ); createTool( 801, meshTb ); createTool( 806, meshTb ); @@ -3052,6 +3057,7 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->insert( separator(), -1, 0 ); createPopupItem( 701, OB, mesh, "&& isComputable" ); // COMPUTE createPopupItem( 711, OB, mesh, "&& isComputable" ); // PRECOMPUTE + createPopupItem( 712, OB, mesh ); // EVALUATE createPopupItem( 214, OB, mesh_group ); // UPDATE createPopupItem( 900, OB, mesh_group ); // ADV_INFO createPopupItem( 902, OB, mesh ); // STD_INFO @@ -3854,6 +3860,9 @@ LightApp_Operation* SMESHGUI::createOperation( const int id ) const case 711: // Precompute mesh op = new SMESHGUI_PrecomputeOp(); break; + case 712: // Evaluate mesh + op = new SMESHGUI_EvaluateOp(); + break; case 806: // Create group on geom op = new SMESHGUI_GroupOnShapeOp(); break; diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx index 8e9400a4c..55e9ad332 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.cxx @@ -789,14 +789,14 @@ void SMESHGUI_MeshInfosBox::SetInfoByMesh(SMESH::SMESH_Mesh_var mesh) */ //======================================================================= -SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg( QWidget* parent ) +SMESHGUI_ComputeDlg::SMESHGUI_ComputeDlg( QWidget* parent, bool ForEval ) : SMESHGUI_Dialog( parent, false, true, Close/* | Help*/ ) { QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame()); aDlgLay->setMargin( 0 ); aDlgLay->setSpacing( SPACING ); - QFrame* aMainFrame = createMainFrame (mainFrame()); + QFrame* aMainFrame = createMainFrame(mainFrame(),ForEval); aDlgLay->addWidget(aMainFrame); @@ -818,7 +818,7 @@ SMESHGUI_ComputeDlg::~SMESHGUI_ComputeDlg() // purpose : Create frame containing dialog's fields //======================================================================= -QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) +QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent, bool ForEval) { QFrame* aFrame = new QFrame(theParent); @@ -827,7 +827,13 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) // constructor - QGroupBox* aPixGrp = new QGroupBox(tr("CONSTRUCTOR"), aFrame); + QGroupBox* aPixGrp; + if(ForEval) { + aPixGrp = new QGroupBox(tr("EVAL_DLG"), aFrame); + } + else { + aPixGrp = new QGroupBox(tr("CONSTRUCTOR"), aFrame); + } QButtonGroup* aBtnGrp = new QButtonGroup(this); QHBoxLayout* aPixGrpLayout = new QHBoxLayout(aPixGrp); aPixGrpLayout->setMargin(MARGIN); aPixGrpLayout->setSpacing(SPACING); @@ -931,8 +937,7 @@ QFrame* SMESHGUI_ComputeDlg::createMainFrame (QWidget* theParent) //================================================================================ SMESHGUI_BaseComputeOp::SMESHGUI_BaseComputeOp() - : SMESHGUI_Operation(), - myCompDlg( 0 ) + : SMESHGUI_Operation(), myCompDlg( 0 ) { myTShapeDisplayer = new SMESH::TShapeDisplayer(); myBadMeshDisplayer = 0; @@ -1420,7 +1425,7 @@ SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::computeDlg() const if ( !myCompDlg ) { SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this; - me->myCompDlg = new SMESHGUI_ComputeDlg( desktop() ); + me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), false ); // connect signals and slots connect(myCompDlg->myShowBtn, SIGNAL (clicked()), SLOT(onPreviewShape())); connect(myCompDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape())); @@ -1908,3 +1913,352 @@ int SMESHGUI_PrecomputeDlg::getPreviewMode() const { return myPreviewMode->currentId(); } + + +//================================================================================ +/*! + * \brief Constructor +*/ +//================================================================================ + +SMESHGUI_EvaluateOp::SMESHGUI_EvaluateOp() + : SMESHGUI_BaseComputeOp() +{ +} + + +//================================================================================ +/*! + * \brief Desctructor +*/ +//================================================================================ + +SMESHGUI_EvaluateOp::~SMESHGUI_EvaluateOp() +{ +} + +//================================================================================ +/*! + * \brief perform it's intention action: compute mesh + */ +//================================================================================ + +void SMESHGUI_EvaluateOp::startOperation() +{ + SMESHGUI_BaseComputeOp::evaluateDlg(); + SMESHGUI_BaseComputeOp::startOperation(); + evaluateMesh(); +} + +//================================================================================ +/*! + * \brief Gets dialog of this operation + * \retval LightApp_Dialog* - pointer to dialog of this operation + */ +//================================================================================ + +LightApp_Dialog* SMESHGUI_EvaluateOp::dlg() const +{ + return evaluateDlg(); +} + +//================================================================================ +/*! + * \brief evaluaateMesh() +*/ +//================================================================================ + +void SMESHGUI_BaseComputeOp::evaluateMesh() +{ + // EVALUATE MESH + + SMESH::MemoryReserve aMemoryReserve; + + SMESH::compute_error_array_var aCompErrors; + QString aHypErrors; + + bool evaluateFailed = true, memoryLack = false; + std::vector aResVec(18); + + _PTR(SObject) aMeshSObj = SMESH::FindSObject(myMesh); + bool hasShape = myMesh->HasShapeToMesh(); + bool shapeOK = myMainShape->_is_nil() ? !hasShape : hasShape; + if ( shapeOK && aMeshSObj ) + { + myCompDlg->myMeshName->setText( aMeshSObj->GetName().c_str() ); + SMESH::SMESH_Gen_var gen = getSMESHGUI()->GetSMESHGen(); + SMESH::algo_error_array_var errors = gen->GetAlgoState(myMesh,myMainShape); + if ( errors->length() > 0 ) { + aHypErrors = SMESH::GetMessageOnAlgoStateErrors( errors.in() ); + } + SUIT_OverrideCursor aWaitCursor; + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + SMESH::long_array_var aVec = gen->Evaluate(myMesh, myMainShape); + for(int i=0; i<17; i++) { + aResVec[i] = aVec[i]; + } + } + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + } + + try { +#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 + OCC_CATCH_SIGNALS; +#endif + aCompErrors = gen->GetComputeErrors( myMesh, myMainShape ); + } + catch(const SALOME::SALOME_Exception & S_ex){ + memoryLack = true; + } + } + + if ( memoryLack ) + aMemoryReserve.release(); + + myCompDlg->setWindowTitle(tr( evaluateFailed ? "SMESH_WRN_COMPUTE_FAILED" : "SMESH_COMPUTE_SUCCEED")); + + // SHOW ERRORS + + bool noCompError = ( !aCompErrors.operator->() || aCompErrors->length() == 0 ); + bool noHypoError = ( aHypErrors.isEmpty() ); + + //SUIT_ResourceMgr* resMgr = SMESH::GetResourceMgr( SMESHGUI::GetSMESHGUI() ); + //int aNotifyMode = resMgr->integerValue( "SMESH", "show_result_notification" ); + + bool isShowResultDlg = true; + //if( noHypoError ) + //switch( aNotifyMode ) { + //case 0: // show the mesh computation result dialog NEVER + //isShowResultDlg = false; + //commit(); + //break; + //case 1: // show the mesh computation result dialog if there are some errors + //if ( memoryLack || !noHypoError ) + // isShowResultDlg = true; + //else + //{ + // isShowResultDlg = false; + // commit(); + //} + //break; + //default: // show the result dialog after each mesh computation + //isShowResultDlg = true; + //} + + // SHOW RESULTS + if ( isShowResultDlg ) + //showComputeResult( memoryLack, noCompError,aCompErrors, noHypoError, aHypErrors ); + showEvaluateResult( aResVec, memoryLack, noCompError, aCompErrors, + noHypoError, aHypErrors); +} + + +void SMESHGUI_BaseComputeOp::showEvaluateResult(std::vector theVec, + const bool theMemoryLack, + const bool theNoCompError, + SMESH::compute_error_array_var& theCompErrors, + const bool theNoHypoError, + const QString& theHypErrors) +{ + bool hasShape = myMesh->HasShapeToMesh(); + SMESHGUI_ComputeDlg* aCompDlg = evaluateDlg(); + aCompDlg->myMemoryLackGroup->hide(); + + if ( theMemoryLack ) + { + aCompDlg->myMemoryLackGroup->show(); + aCompDlg->myFullInfo->hide(); + aCompDlg->myBriefInfo->hide(); + aCompDlg->myHypErrorGroup->hide(); + aCompDlg->myCompErrorGroup->hide(); + } + else if ( theNoCompError && theNoHypoError ) + { + //aCompDlg->myFullInfo->SetInfoByMesh( myMesh ); + aCompDlg->myFullInfo->SetInfoByEval( theVec ); + aCompDlg->myFullInfo->show(); + aCompDlg->myBriefInfo->hide(); + aCompDlg->myHypErrorGroup->hide(); + aCompDlg->myCompErrorGroup->hide(); + } + else + { + QTableWidget* tbl = aCompDlg->myTable; + //aCompDlg->myBriefInfo->SetInfoByMesh( myMesh ); + aCompDlg->myBriefInfo->SetInfoByEval( theVec ); + aCompDlg->myBriefInfo->show(); + aCompDlg->myFullInfo->hide(); + + if ( theNoHypoError ) { + aCompDlg->myHypErrorGroup->hide(); + } + else { + aCompDlg->myHypErrorGroup->show(); + aCompDlg->myHypErrorLabel->setText( theHypErrors ); + } + + if ( theNoCompError ) { + aCompDlg->myCompErrorGroup->hide(); + } + else { + aCompDlg->myCompErrorGroup->show(); + + aCompDlg->myPublishBtn->hide(); + aCompDlg->myShowBtn->hide(); + + // fill table of errors + tbl->setRowCount( theCompErrors->length() ); + if ( !hasShape ) tbl->hideColumn( COL_SHAPE ); + else tbl->showColumn( COL_SHAPE ); + tbl->setColumnWidth( COL_ERROR, 200 ); + + bool hasBadMesh = false; + for ( int row = 0; row < theCompErrors->length(); ++row ) + { + SMESH::ComputeError & err = theCompErrors[ row ]; + + QString text = err.algoName.in(); + if ( !tbl->item( row, COL_ALGO ) ) tbl->setItem( row, COL_ALGO, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ALGO )->setText( text ); + + text = SMESH::errorText( err.code, err.comment.in() ); + if ( !tbl->item( row, COL_ERROR ) ) tbl->setItem( row, COL_ERROR, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_ERROR )->setText( text ); + + text = QString("%1").arg( err.subShapeID ); + if ( !tbl->item( row, COL_SHAPEID ) ) tbl->setItem( row, COL_SHAPEID, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPEID )->setText( text ); + + text = hasShape ? SMESH::shapeText( err.subShapeID, myMainShape ) : QString(""); + if ( !tbl->item( row, COL_SHAPE ) ) tbl->setItem( row, COL_SHAPE, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_SHAPE )->setText( text ); + + text = ( !hasShape || SMESH::getSubShapeSO( err.subShapeID, myMainShape )) ? "PUBLISHED" : ""; + if ( !tbl->item( row, COL_PUBLISHED ) ) tbl->setItem( row, COL_PUBLISHED, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_PUBLISHED )->setText( text ); // if text=="", "PUBLISH" button enabled + + text = err.hasBadMesh ? "hasBadMesh" : ""; + if ( !tbl->item( row, COL_BAD_MESH ) ) tbl->setItem( row, COL_BAD_MESH, new QTableWidgetItem( text ) ); + else tbl->item( row, COL_BAD_MESH )->setText( text ); + if ( err.hasBadMesh ) hasBadMesh = true; + + //tbl->item( row, COL_ERROR )->setWordWrap( true ); // VSR: TODO ??? + tbl->resizeRowToContents( row ); + } + tbl->resizeColumnToContents( COL_ALGO ); + tbl->resizeColumnToContents( COL_SHAPE ); + + if ( hasBadMesh ) + aCompDlg->myBadMeshBtn->show(); + else + aCompDlg->myBadMeshBtn->hide(); + + tbl->setCurrentCell(0,0); + currentCellChanged(); // to update buttons + } + } + // show dialog and wait, becase Compute can be invoked from Preview operation + //aCompDlg->exec(); // this way it becomes modal - impossible to rotate model in the Viewer + aCompDlg->show(); +} + + +// ========================================================================================= +/*! + * \brief Set mesh info + */ +// ========================================================================================= + +void SMESHGUI_MeshInfosBox::SetInfoByEval(std::vector theVec) +{ + // nodes + myNbNode ->setText( QString("%1").arg( theVec[0] )); + + // edges + int nbTot = theVec[1] + theVec[2]; + myNbEdge ->setText( QString("%1").arg( nbTot )); + myNbLinEdge ->setText( QString("%1").arg( theVec[1] )); + myNbQuadEdge ->setText( QString("%1").arg( theVec[2] )); + + // faces + nbTot = 0; + int i = 3; + for(; i<=7; i++) nbTot += theVec[i]; + myNbFace ->setText( QString("%1").arg( nbTot )); + myNbLinFace ->setText( QString("%1").arg( theVec[3] + theVec[5] )); + myNbQuadFace ->setText( QString("%1").arg( theVec[4] + theVec[6] )); + + // volumes + nbTot = 0; + for(i=8; i<=16; i++) nbTot += theVec[i]; + int nbLin = 0, nbQua = 0;; + for(i=0; i<=3; i++) { + nbLin += theVec[8+2*i]; + nbQua += theVec[9+2*i]; + } + myNbVolum ->setText( QString("%1").arg( nbTot )); + myNbLinVolum ->setText( QString("%1").arg( nbLin )); + myNbQuadVolum->setText( QString("%1").arg( nbQua )); + + if ( myFull ) + { + // triangles + myNbTrai ->setText( QString("%1").arg( theVec[3] + theVec[4] )); + myNbLinTrai ->setText( QString("%1").arg( theVec[3] )); + myNbQuadTrai ->setText( QString("%1").arg( theVec[4] )); + // quadrangles + myNbQuad ->setText( QString("%1").arg( theVec[5] + theVec[6] )); + myNbLinQuad ->setText( QString("%1").arg( theVec[5] )); + myNbQuadQuad ->setText( QString("%1").arg( theVec[6] )); + // poligones + myNbPolyg ->setText( QString("%1").arg( theVec[7] )); + + // tetras + myNbTetra ->setText( QString("%1").arg( theVec[8] + theVec[9] )); + myNbLinTetra ->setText( QString("%1").arg( theVec[8] )); + myNbQuadTetra->setText( QString("%1").arg( theVec[9] )); + // hexas + myNbHexa ->setText( QString("%1").arg( theVec[14] + theVec[15] )); + myNbLinHexa ->setText( QString("%1").arg( theVec[14] )); + myNbQuadHexa ->setText( QString("%1").arg( theVec[15] )); + // pyras + myNbPyra ->setText( QString("%1").arg( theVec[10] + theVec[11] )); + myNbLinPyra ->setText( QString("%1").arg( theVec[10] )); + myNbQuadPyra ->setText( QString("%1").arg( theVec[11] )); + // prisms + myNbPrism ->setText( QString("%1").arg( theVec[12] + theVec[13] )); + myNbLinPrism ->setText( QString("%1").arg( theVec[12] )); + myNbQuadPrism->setText( QString("%1").arg( theVec[13] )); + // polyedres + myNbPolyh ->setText( QString("%1").arg( theVec[16] )); + } +} + +//================================================================================ +/*! + * \brief Gets dialog of evaluate operation + * \retval SMESHGUI_ComputeDlg* - pointer to dialog of this operation + */ +//================================================================================ + +SMESHGUI_ComputeDlg* SMESHGUI_BaseComputeOp::evaluateDlg() const +{ + if ( !myCompDlg ) + { + SMESHGUI_BaseComputeOp* me = (SMESHGUI_BaseComputeOp*)this; + me->myCompDlg = new SMESHGUI_ComputeDlg( desktop(), true ); + // connect signals and slots + connect(myCompDlg->myShowBtn, SIGNAL (clicked()), SLOT(onPreviewShape())); + connect(myCompDlg->myPublishBtn, SIGNAL (clicked()), SLOT(onPublishShape())); + connect(myCompDlg->myBadMeshBtn, SIGNAL (clicked()), SLOT(onShowBadMesh())); + QTableWidget* aTable = me->table(); + connect(aTable, SIGNAL(itemSelectionChanged()), SLOT(currentCellChanged())); + connect(aTable, SIGNAL(currentCellChanged(int,int,int,int)), SLOT(currentCellChanged())); + } + return myCompDlg; +} + diff --git a/src/SMESHGUI/SMESHGUI_ComputeDlg.h b/src/SMESHGUI/SMESHGUI_ComputeDlg.h index 9a84f8a1c..c07e86746 100644 --- a/src/SMESHGUI/SMESHGUI_ComputeDlg.h +++ b/src/SMESHGUI/SMESHGUI_ComputeDlg.h @@ -51,6 +51,7 @@ class QLabel; class QtxComboBox; class SMESHGUI_ComputeDlg; class SMESHGUI_PrecomputeDlg; +//class SMESHGUI_EvaluateDlg; class SMESHGUI_MeshEditPreview; class SMESH::compute_error_array; @@ -82,6 +83,15 @@ protected: SMESH::compute_error_array_var&, const bool, const QString& ); + //SMESHGUI_EvaluateDlg* evaluateDlg() const; + SMESHGUI_ComputeDlg* evaluateDlg() const; + void evaluateMesh(); + void showEvaluateResult(std::vector theVec, + const bool, + const bool, + SMESH::compute_error_array_var&, + const bool, + const QString&); protected slots: virtual bool onApply(); @@ -95,6 +105,7 @@ private: private: QPointer myCompDlg; + //QPointer myEvalDlg; protected: SMESH::SMESH_Mesh_var myMesh; @@ -157,6 +168,25 @@ private: SMESHGUI_MeshEditPreview* myPreviewDisplayer; }; +/*! + * \brief Operation to evaluate a mesh and show result + */ +class SMESHGUI_EXPORT SMESHGUI_EvaluateOp: public SMESHGUI_BaseComputeOp +{ + Q_OBJECT + +public: + SMESHGUI_EvaluateOp(); + virtual ~SMESHGUI_EvaluateOp(); + + virtual LightApp_Dialog* dlg() const; + +protected: + virtual void startOperation(); + +protected slots: +}; + /*! * \brief Box showing mesh info */ @@ -170,6 +200,8 @@ public: void SetInfoByMesh( SMESH::SMESH_Mesh_var ); + void SetInfoByEval( std::vector theVec ); + private: bool myFull; QLabel* myNbNode; @@ -213,11 +245,11 @@ class SMESHGUI_EXPORT SMESHGUI_ComputeDlg : public SMESHGUI_Dialog Q_OBJECT public: - SMESHGUI_ComputeDlg( QWidget* ); + SMESHGUI_ComputeDlg( QWidget*, bool ); virtual ~SMESHGUI_ComputeDlg(); protected: - QFrame* createMainFrame( QWidget* ); + QFrame* createMainFrame( QWidget*, bool ); QLabel* myMeshName; QGroupBox* myMemoryLackGroup; @@ -260,4 +292,36 @@ private: }; +/*! + * \brief Dialog to evaluate a mesh and show result + */ +/* +class SMESHGUI_EXPORT SMESHGUI_EvaluateDlg : public SMESHGUI_Dialog +{ + Q_OBJECT + +public: + SMESHGUI_EvaluateDlg( QWidget* ); + virtual ~SMESHGUI_EvaluateDlg(); + +protected: + QFrame* createMainFrame( QWidget* ); + + QLabel* myMeshName; + QGroupBox* myMemoryLackGroup; + QGroupBox* myCompErrorGroup; + QGroupBox* myHypErrorGroup; + QLabel* myHypErrorLabel; + QTableWidget* myTable; + QPushButton* myShowBtn; + QPushButton* myPublishBtn; + QPushButton* myBadMeshBtn; + + SMESHGUI_MeshInfosBox* myBriefInfo; + SMESHGUI_MeshInfosBox* myFullInfo; + + friend class SMESHGUI_BaseComputeOp; +}; +*/ + #endif // SMESHGUI_COMPUTEDLG_H diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 27f0d1453..10a95c873 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -181,6 +181,10 @@ MEN_PRECOMPUTE Preview + + MEN_EVALUATE + Evaluate + MEN_CONNECTION Borders at Multi-Connection @@ -1987,6 +1991,10 @@ Consider saving your work before application crash STB_PRECOMPUTE Preview + + STB_EVALUATE + Evaluate + STB_CONNECTION Borders at Multi-Connection @@ -2469,6 +2477,10 @@ Consider saving your work before application crash TOP_PRECOMPUTE Preview + + TOP_EVALUATE + Evaluate + TOP_CONNECTION Borders at Multi-Connection @@ -3215,6 +3227,10 @@ Please, create VTK viewer and try again CONSTRUCTOR Compute mesh + + EVAL_DLG + Evaluate mesh + ERRORS Errors diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index eb49db1b9..2dcd38c07 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -1607,6 +1607,93 @@ SMESH::MeshPreviewStruct* SMESH_Gen_i::Precompute( SMESH::SMESH_Mesh_ptr theMesh return result._retn(); } + +//============================================================================= +/*! + * SMESH_Gen_i::Evaluate + * + * Evaluate mesh on a shape + */ +//============================================================================= + +//CORBA::Boolean +SMESH::long_array* SMESH_Gen_i::Evaluate(SMESH::SMESH_Mesh_ptr theMesh, + GEOM::GEOM_Object_ptr theShapeObject) +// SMESH::long_array& theNbElems) + throw ( SALOME::SALOME_Exception ) +{ + Unexpect aCatch(SALOME_SalomeException); + if(MYDEBUG) MESSAGE( "SMESH_Gen_i::Evaluate" ); + + if ( CORBA::is_nil( theShapeObject ) && theMesh->HasShapeToMesh()) + THROW_SALOME_CORBA_EXCEPTION( "bad shape object reference", + SALOME::BAD_PARAM ); + + if ( CORBA::is_nil( theMesh ) ) + THROW_SALOME_CORBA_EXCEPTION( "bad Mesh reference", + SALOME::BAD_PARAM ); + + SMESH::long_array_var nbels = new SMESH::long_array; + + // Update Python script + TPythonDump() << "theNbElems = " << this << ".Evaluate( " + << theMesh << ", " << theShapeObject << ")"; + + try { + // get mesh servant + SMESH_Mesh_i* meshServant = dynamic_cast( GetServant( theMesh ).in() ); + ASSERT( meshServant ); + if ( meshServant ) { + // NPAL16168: "geometrical group edition from a submesh don't modifiy mesh computation" + meshServant->CheckGeomGroupModif(); + // get local TopoDS_Shape + TopoDS_Shape myLocShape; + if(theMesh->HasShapeToMesh()) + myLocShape = GeomObjectToShape( theShapeObject ); + else + myLocShape = SMESH_Mesh::PseudoShape(); + // call implementation compute + ::SMESH_Mesh& myLocMesh = meshServant->GetImpl(); + MapShapeNbElems aResMap; + CORBA::Boolean ret = myGen.Evaluate( myLocMesh, myLocShape, aResMap); + MapShapeNbElemsItr anIt = aResMap.begin(); + vector aResVec(17); + int i = 0; + for(; i<17; i++) aResVec[i] = 0; + for(; anIt!=aResMap.end(); anIt++) { + // 0 - node, 1 - edge lin, 2 - edge quad, + // 3 - triangle lin, 4 - triangle quad + // 5 - quadrangle lin, 6 - quadrangle quad + // 7 - polygon, 8 - tetra lin, 9 - tetra quad + // 10 - pyramid lin, 11 - pyramid quad, + // 12 - penta lin, 13 - penta quad, 14 - hexa lin, + // 15 - hexa quad, 16 -polyhedra + vector aVec = (*anIt).second; + for(i=0; i<17; i++) { + aResVec[i] += aVec[i]; + } + } + nbels->length(17); + for(i=0; i<17; i++) { + nbels[i] = aResVec[i]; + } + cout< #include #include +#include #include #include #include @@ -507,6 +508,213 @@ bool StdMeshers_CompositeHexa_3D::Compute(SMESH_Mesh& theMesh, return true; } + +//======================================================================= +//function : GetNb2d +//purpose : auxilary for Evaluate +//======================================================================= +int GetNb2d(_QuadFaceGrid* QFG, SMESH_Mesh& theMesh, + MapShapeNbElems& aResMap) +{ + int nb2d = 0; + _QuadFaceGrid::TChildIterator aCI = QFG->GetChildren(); + while( aCI.more() ) { + const _QuadFaceGrid& currChild = aCI.next(); + SMESH_subMesh *sm = theMesh.GetSubMesh(currChild.GetFace()); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb2d += Max(aVec[5],aVec[6]); + } + } + return nb2d; +} + + +//================================================================================ +/*! + * Evaluate + */ +//================================================================================ + +bool StdMeshers_CompositeHexa_3D::Evaluate(SMESH_Mesh& theMesh, + const TopoDS_Shape& theShape, + MapShapeNbElems& aResMap) +{ + SMESH_MesherHelper aTool(theMesh); + bool _quadraticMesh = aTool.IsQuadraticSubMesh(theShape); + + + // ------------------------- + // Try to find 6 side faces + // ------------------------- + vector< _QuadFaceGrid > boxFaces; boxFaces.reserve( 6 ); + TopExp_Explorer exp; + int iFace, nbFaces = 0; + for ( exp.Init(theShape, TopAbs_FACE); exp.More(); exp.Next(), ++nbFaces ) + { + _QuadFaceGrid f; + if ( !f.Init( TopoDS::Face( exp.Current() ))) + //return error (COMPERR_BAD_SHAPE); + return false; + bool isContinuous = false; + for ( int i=0; i < boxFaces.size() && !isContinuous; ++i ) + isContinuous = boxFaces[ i ].AddContinuousFace( f ); + if ( !isContinuous ) + boxFaces.push_back( f ); + } + // Check what we have + if ( boxFaces.size() != 6 && nbFaces != 6) + //return error + // (COMPERR_BAD_SHAPE, + // SMESH_Comment("Can't find 6 sides of a box. Number of found sides - ")<FindAdjacentForSide( Q_BOTTOM, boxFaces ); + fLeft = fBottom->FindAdjacentForSide( Q_RIGHT, boxFaces ); + fBack = fBottom->FindAdjacentForSide( Q_TOP, boxFaces ); + fRight = fBottom->FindAdjacentForSide( Q_LEFT, boxFaces ); + // check the found + if ( !fFront || !fBack || !fLeft || !fRight ) + //return error(COMPERR_BAD_SHAPE); + return false; + // top face + fTop = 0; + int i = 1; + for(; i < boxFaces.size() && !fTop; ++i ) { + fTop = & boxFaces[ i ]; + if ( fTop==fFront || fTop==fLeft || fTop==fBack || fTop==fRight ) + fTop = 0; + } + // set bottom of the top side + if ( !fTop->SetBottomSide( fFront->GetSide( Q_TOP ) )) { + if ( !fFront->IsComplex() ) + //return error( ERR_LI("Error in StdMeshers_CompositeHexa_3D::Compute()")); + return false; + else { + _QuadFaceGrid::TChildIterator chIt = fFront->GetChildren(); + while ( chIt.more() ) { + const _QuadFaceGrid& frontChild = chIt.next(); + if ( fTop->SetBottomSide( frontChild.GetSide( Q_TOP ))) + break; + } + } + } + if ( !fTop ) + //return error(COMPERR_BAD_SHAPE); + return false; + + + TopTools_SequenceOfShape BottomFaces; + _QuadFaceGrid::TChildIterator aCI = fBottom->GetChildren(); + while( aCI.more() ) { + const _QuadFaceGrid& currChild = aCI.next(); + BottomFaces.Append(currChild.GetFace()); + } + // find boundary edges and internal nodes for bottom face + TopTools_SequenceOfShape BndEdges; + int nb0d_in = 0; + //TopTools_MapOfShape BndEdges; + for(i=1; i<=BottomFaces.Length(); i++) { + for (TopExp_Explorer exp(BottomFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) { + int nb0 = 0; + SMESH_subMesh *sm = theMesh.GetSubMesh(exp.Current()); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb0 = aVec[0]; + } + int j = 1; + for(; j<=BndEdges.Length(); j++) { + if( BndEdges.Value(j) == exp.Current() ) { + // internal edge => remove it + BndEdges.Remove(j); + nb0d_in += nb0; + break; + } + } + if( j > BndEdges.Length() ) { + BndEdges.Append(exp.Current()); + } + //if( BndEdges.Contains(exp.Current()) ) { + //BndEdges.Remove( exp.Current() ); + //} + //else { + //BndEdges.Add( exp.Current() ); + //} + } + } + + // find number of 1d elems for bottom face + int nb1d = 0; + for(i=1; i<=BndEdges.Length(); i++) { + SMESH_subMesh *sm = theMesh.GetSubMesh(BndEdges.Value(i)); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb1d += Max(aVec[1],aVec[2]); + } + } + + // find number of 2d elems on side faces + int nb2d = 0; + nb2d += GetNb2d(fFront, theMesh, aResMap); + nb2d += GetNb2d(fRight, theMesh, aResMap); + nb2d += GetNb2d(fBack, theMesh, aResMap); + nb2d += GetNb2d(fLeft, theMesh, aResMap); + + // find number of 2d elems and nodes on bottom faces + int nb0d=0, nb2d_3=0, nb2d_4=0; + for(i=1; i<=BottomFaces.Length(); i++) { + SMESH_subMesh *sm = theMesh.GetSubMesh(BottomFaces.Value(i)); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb0d += aVec[0]; + nb2d_3 += Max(aVec[3],aVec[4]); + nb2d_4 += Max(aVec[5],aVec[6]); + } + } + nb0d += nb0d_in; + + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + if(_quadraticMesh) { + aResVec[13] = nb2d_3 * ( nb2d/nb1d ); + aResVec[15] = nb2d_4 * ( nb2d/nb1d ); + aResVec[0] = nb0d * ( 2*nb2d/nb1d - 1 ); + } + else { + aResVec[0] = nb0d * ( nb2d/nb1d - 1 ); + aResVec[12] = nb2d_3 * ( nb2d/nb1d ); + aResVec[14] = nb2d_4 * ( nb2d/nb1d ); + } + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aResVec)); + + return true; +} + + //================================================================================ /*! * \brief constructor of non-initialized _QuadFaceGrid diff --git a/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx b/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx index 09b687fc1..8fd14ba06 100644 --- a/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_CompositeHexa_3D.hxx @@ -50,6 +50,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + virtual bool CheckHypothesis(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, Hypothesis_Status& aStatus); diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.cxx b/src/StdMeshers/StdMeshers_Hexa_3D.cxx index 769d996c5..f0738bb89 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.cxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.cxx @@ -48,6 +48,8 @@ #include #include #include +#include +#include #include #include @@ -58,7 +60,11 @@ typedef SMESH_Comment TComm; using namespace std; -static SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &, const TopoDS_Shape &); +static SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh &, + const TopoDS_Shape &); + +static bool EvaluatePentahedralMesh(SMESH_Mesh &, const TopoDS_Shape &, + MapShapeNbElems &); //============================================================================= /*! @@ -736,6 +742,118 @@ bool StdMeshers_Hexa_3D::Compute(SMESH_Mesh & aMesh, return ClearAndReturn( aQuads, true ); } + +//============================================================================= +/*! + * Evaluate + */ +//============================================================================= + +bool StdMeshers_Hexa_3D::Evaluate(SMESH_Mesh & aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap) +{ + vector < SMESH_subMesh * >meshFaces; + TopTools_SequenceOfShape aFaces; + for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { + aFaces.Append(exp.Current()); + SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current()); + ASSERT(aSubMesh); + meshFaces.push_back(aSubMesh); + } + if (meshFaces.size() != 6) { + //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block"); + static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen()); + return compositeHexa.Evaluate(aMesh, aShape, aResMap); + } + + int i = 0; + for(; i<6; i++) { + //TopoDS_Shape aFace = meshFaces[i]->GetSubShape(); + TopoDS_Shape aFace = aFaces.Value(i+1); + SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace); + string algoName = algo->GetName(); + bool isAllQuad = false; + if (algoName == "Quadrangle_2D") { + MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + int nbtri = Max(aVec[3],aVec[4]); + if( nbtri == 0 ) + isAllQuad = true; + } + if ( ! isAllQuad ) { + return EvaluatePentahedralMesh(aMesh, aShape, aResMap); + } + } + + // find number of 1d elems for 1 face + int nb1d = 0; + TopTools_MapOfShape Edges1; + bool IsQuadratic = false; + bool IsFirst = true; + for (TopExp_Explorer exp(aFaces.Value(1), TopAbs_EDGE); exp.More(); exp.Next()) { + Edges1.Add(exp.Current()); + SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current()); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb1d += Max(aVec[1],aVec[2]); + if(IsFirst) { + IsQuadratic = (aVec[2] > aVec[1]); + IsFirst = false; + } + } + } + // find face opposite to 1 face + int OppNum = 0; + for(i=2; i<=6; i++) { + bool IsOpposite = true; + for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) { + if( Edges1.Contains(exp.Current()) ) { + IsOpposite = false; + break; + } + } + if(IsOpposite) { + OppNum = i; + break; + } + } + // find number of 2d elems on side faces + int nb2d = 0; + for(i=2; i<=6; i++) { + if( i == OppNum ) continue; + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] ); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb2d += Max(aVec[5],aVec[6]); + } + + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[0] ); + std::vector aVec = (*anIt).second; + int nb2d_face0 = Max(aVec[5],aVec[6]); + int nb0d_face0 = aVec[0]; + + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + if(IsQuadratic) { + aResVec[15] = nb2d_face0 * ( nb2d/nb1d ); + int nb1d_face0_int = ( nb2d_face0*4 - nb1d ) / 2; + aResVec[0] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d; + } + else { + aResVec[0] = nb0d_face0 * ( nb2d/nb1d - 1 ); + aResVec[14] = nb2d_face0 * ( nb2d/nb1d ); + } + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + + return true; +} + + //============================================================================= /*! * @@ -1056,3 +1174,33 @@ SMESH_ComputeErrorPtr ComputePentahedralMesh(SMESH_Mesh & aMesh, } +//======================================================================= +//function : EvaluatePentahedralMesh +//purpose : +//======================================================================= + +bool EvaluatePentahedralMesh(SMESH_Mesh & aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap) +{ + StdMeshers_Penta_3D anAlgo; + bool bOK = anAlgo.Evaluate(aMesh, aShape, aResMap); + + //err = anAlgo.GetComputeError(); + //if ( !bOK && anAlgo.ErrorStatus() == 5 ) + if( !bOK ) { + static StdMeshers_Prism_3D * aPrism3D = 0; + if ( !aPrism3D ) { + SMESH_Gen* gen = aMesh.GetGen(); + aPrism3D = new StdMeshers_Prism_3D( gen->GetANewId(), 0, gen ); + } + SMESH_Hypothesis::Hypothesis_Status aStatus; + if ( aPrism3D->CheckHypothesis( aMesh, aShape, aStatus ) ) { + return aPrism3D->Evaluate(aMesh, aShape, aResMap); + } + } + + return bOK; +} + + diff --git a/src/StdMeshers/StdMeshers_Hexa_3D.hxx b/src/StdMeshers/StdMeshers_Hexa_3D.hxx index 24927ef5a..d34d812dd 100644 --- a/src/StdMeshers/StdMeshers_Hexa_3D.hxx +++ b/src/StdMeshers/StdMeshers_Hexa_3D.hxx @@ -77,6 +77,9 @@ public: const TopoDS_Shape& aShape) /*throw (SALOME_Exception)*/; + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + static TopoDS_Vertex OppositeVertex(const TopoDS_Vertex& aVertex, const TopTools_IndexedMapOfShape& aQuads0Vertices, FaceQuadStruct* aQuads[6]); diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx index 453398149..f842eb87b 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.cxx @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -63,6 +64,10 @@ #include #include +#include +#include +#include + using namespace std; //============================================================================= @@ -282,6 +287,79 @@ bool StdMeshers_MEFISTO_2D::Compute(SMESH_Mesh & aMesh, const TopoDS_Shape & aSh return isOk; } + +//============================================================================= +/*! + * + */ +//============================================================================= + +bool StdMeshers_MEFISTO_2D::Evaluate(SMESH_Mesh & aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap) +{ + MESSAGE("StdMeshers_MEFISTO_2D::Evaluate"); + + TopoDS_Face F = TopoDS::Face(aShape.Oriented(TopAbs_FORWARD)); + + double aLen = 0.0; + double NbSeg = 0; + bool IsQuadratic = false; + bool IsFirst = true; + TopExp_Explorer exp(F,TopAbs_EDGE); + for(; exp.More(); exp.Next()) { + TopoDS_Edge E = TopoDS::Edge(exp.Current()); + MapShapeNbElemsItr anIt = aResMap.find( aMesh.GetSubMesh(E) ); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + int nbe = Max(aVec[1],aVec[2]); + NbSeg += nbe; + if(IsFirst) { + IsQuadratic = ( aVec[2] > aVec[1] ); + IsFirst = false; + } + double a,b; + TopLoc_Location L; + Handle(Geom_Curve) C = BRep_Tool::Curve(E,L,a,b); + gp_Pnt P1; + C->D0(a,P1); + double dp = (b-a)/nbe; + for(int i=1; i<=nbe; i++) { + gp_Pnt P2; + C->D0(a+i*dp,P2); + aLen += P1.Distance(P2); + P1 = P2; + } + } + aLen = aLen/NbSeg; // middle length + + _edgeLength = DBL_MAX; + double tmpLength = Min( _edgeLength, aLen ); + + GProp_GProps G; + BRepGProp::SurfaceProperties(aShape,G); + double anArea = G.Mass(); + + int nbFaces = (int) anArea/(tmpLength*tmpLength*sqrt(3)/4); + int nbNodes = (int) ( nbFaces*3 - (NbSeg-1)*2 ) / 6; + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + if(IsQuadratic) { + aVec[4] = nbFaces; + aVec[0] = nbNodes + nbFaces*3 - (NbSeg-1); + } + else { + aVec[0] = nbNodes; + aVec[3] = nbFaces; + } + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //======================================================================= //function : fixOverlappedLinkUV //purpose : prevent failure due to overlapped adjacent links diff --git a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx index fba4b2d34..73075dc07 100644 --- a/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx +++ b/src/StdMeshers/StdMeshers_MEFISTO_2D.hxx @@ -57,6 +57,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + typedef boost::shared_ptr< StdMeshers_FaceSide> StdMeshers_FaceSidePtr; typedef std::vector< StdMeshers_FaceSidePtr > TWireVector; diff --git a/src/StdMeshers/StdMeshers_Penta_3D.cxx b/src/StdMeshers/StdMeshers_Penta_3D.cxx index 3ff7db018..5e85ce9e1 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.cxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.cxx @@ -46,6 +46,8 @@ #include #include #include +#include +#include #include #include #include @@ -1882,3 +1884,100 @@ const TopoDS_Shape& StdMeshers_SMESHBlock::Shape(const int theID) } +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= +bool StdMeshers_Penta_3D::Evaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + MapShapeNbElems& aResMap) +{ + MESSAGE("StdMeshers_Penta_3D::Evaluate()"); + + // find face contains only triangles + vector < SMESH_subMesh * >meshFaces; + TopTools_SequenceOfShape aFaces; + int NumBase = 0, i = 0; + for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { + i++; + aFaces.Append(exp.Current()); + SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); + meshFaces.push_back(aSubMesh); + MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]); + std::vector aVec = (*anIt).second; + int nbtri = Max(aVec[3],aVec[4]); + int nbqua = Max(aVec[5],aVec[6]); + if( nbtri>0 && nbqua==0 ) { + NumBase = i; + } + } + + if(NumBase==0) return false; + + // find number of 1d elems for base face + int nb1d = 0; + TopTools_MapOfShape Edges1; + for (TopExp_Explorer exp(aFaces.Value(NumBase), TopAbs_EDGE); exp.More(); exp.Next()) { + Edges1.Add(exp.Current()); + SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current()); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb1d += Max(aVec[1],aVec[2]); + } + } + // find face opposite to base face + int OppNum = 0; + for(i=1; i<=6; i++) { + if(i==NumBase) continue; + bool IsOpposite = true; + for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) { + if( Edges1.Contains(exp.Current()) ) { + IsOpposite = false; + break; + } + } + if(IsOpposite) { + OppNum = i; + break; + } + } + // find number of 2d elems on side faces + int nb2d = 0; + for(i=1; i<=6; i++) { + if( i==OppNum || i==NumBase ) continue; + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] ); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb2d += Max(aVec[5],aVec[6]); + } + + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[NumBase-1] ); + std::vector aVec = (*anIt).second; + int nb2d_face0 = Max(aVec[5],aVec[6]); + int nb0d_face0 = aVec[0]; + + anIt = aResMap.find( meshFaces[OppNum-1] ); + for(i=0; i<17; i++) + (*anIt).second[i] = aVec[i]; + + SMESH_MesherHelper aTool (aMesh); + bool _quadraticMesh = aTool.IsQuadraticSubMesh(aShape); + + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + if(_quadraticMesh) { + aResVec[13] = nb2d_face0 * ( nb2d/nb1d ); + aResVec[0] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ); + } + else { + aResVec[0] = nb0d_face0 * ( nb2d/nb1d - 1 ); + aResVec[12] = nb2d_face0 * ( nb2d/nb1d ); + } + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + + return true; +} + diff --git a/src/StdMeshers/StdMeshers_Penta_3D.hxx b/src/StdMeshers/StdMeshers_Penta_3D.hxx index f061f8144..882c3b4f3 100644 --- a/src/StdMeshers/StdMeshers_Penta_3D.hxx +++ b/src/StdMeshers/StdMeshers_Penta_3D.hxx @@ -45,6 +45,7 @@ #include "SMESH_Block.hxx" #include "SMESH_ComputeError.hxx" #include "SMESH_MesherHelper.hxx" +#include "SMESH_3D_Algo.hxx" typedef std::map< double, std::vector > StdMeshers_IJNodeMap; @@ -204,6 +205,9 @@ class STDMESHERS_EXPORT StdMeshers_Penta_3D { // The key of theIJNodes map is a normalized parameter of each // 0-the node on theBaseEdge. + bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + protected: // methods diff --git a/src/StdMeshers/StdMeshers_Prism_3D.cxx b/src/StdMeshers/StdMeshers_Prism_3D.cxx index 6374868c1..41657596d 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.cxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.cxx @@ -42,6 +42,8 @@ #include #include #include +#include +#include #include using namespace std; @@ -366,6 +368,115 @@ bool StdMeshers_Prism_3D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& theSh return true; } + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_Prism_3D::Evaluate(SMESH_Mesh& theMesh, + const TopoDS_Shape& theShape, + MapShapeNbElems& aResMap) +{ + // find face contains only triangles + vector < SMESH_subMesh * >meshFaces; + TopTools_SequenceOfShape aFaces; + int NumBase = 0, i = 0, NbQFs = 0; + for (TopExp_Explorer exp(theShape, TopAbs_FACE); exp.More(); exp.Next()) { + i++; + aFaces.Append(exp.Current()); + SMESH_subMesh *aSubMesh = theMesh.GetSubMesh(exp.Current()); + meshFaces.push_back(aSubMesh); + MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i-1]); + std::vector aVec = (*anIt).second; + int nbtri = Max(aVec[3],aVec[4]); + int nbqua = Max(aVec[5],aVec[6]); + if( nbtri==0 && nbqua>0 ) { + NbQFs++; + } + if( nbtri>0 ) { + NumBase = i; + } + } + + if(NbQFs<4) { + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aResVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + + if(NumBase==0) NumBase = 1; // only quads => set 1 faces as base + + // find number of 1d elems for base face + int nb1d = 0; + TopTools_MapOfShape Edges1; + for (TopExp_Explorer exp(aFaces.Value(NumBase), TopAbs_EDGE); exp.More(); exp.Next()) { + Edges1.Add(exp.Current()); + SMESH_subMesh *sm = theMesh.GetSubMesh(exp.Current()); + if( sm ) { + MapShapeNbElemsItr anIt = aResMap.find(sm); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb1d += Max(aVec[1],aVec[2]); + } + } + // find face opposite to base face + int OppNum = 0; + for(i=1; i<=6; i++) { + if(i==NumBase) continue; + bool IsOpposite = true; + for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) { + if( Edges1.Contains(exp.Current()) ) { + IsOpposite = false; + break; + } + } + if(IsOpposite) { + OppNum = i; + break; + } + } + // find number of 2d elems on side faces + int nb2d = 0; + for(i=1; i<=6; i++) { + if( i==OppNum || i==NumBase ) continue; + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] ); + if( anIt == aResMap.end() ) continue; + std::vector aVec = (*anIt).second; + nb2d += Max(aVec[5],aVec[6]); + } + + MapShapeNbElemsItr anIt = aResMap.find( meshFaces[NumBase-1] ); + std::vector aVec = (*anIt).second; + bool IsQuadratic = (aVec[4]>aVec[3]) || (aVec[6]>aVec[5]); + int nb2d_face0_3 = Max(aVec[3],aVec[4]); + int nb2d_face0_4 = Max(aVec[5],aVec[6]); + int nb0d_face0 = aVec[0]; + int nb1d_face0_int = ( nb2d_face0_3*3 + nb2d_face0_4*4 - nb1d ) / 2; + + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + if(IsQuadratic) { + aResVec[13] = nb2d_face0_3 * ( nb2d/nb1d ); + aResVec[15] = nb2d_face0_4 * ( nb2d/nb1d ); + aResVec[0] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d; + } + else { + aResVec[0] = nb0d_face0 * ( nb2d/nb1d - 1 ); + aResVec[12] = nb2d_face0_3 * ( nb2d/nb1d ); + aResVec[14] = nb2d_face0_4 * ( nb2d/nb1d ); + } + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aResVec)); + + return true; +} + + //================================================================================ /*! * \brief Create prisms diff --git a/src/StdMeshers/StdMeshers_Prism_3D.hxx b/src/StdMeshers/StdMeshers_Prism_3D.hxx index 5c29f63ec..d258bb432 100644 --- a/src/StdMeshers/StdMeshers_Prism_3D.hxx +++ b/src/StdMeshers/StdMeshers_Prism_3D.hxx @@ -379,6 +379,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + /*! * \brief Enable removal of quadrangles from the bottom face and * triangles creation there by projection from the top diff --git a/src/StdMeshers/StdMeshers_Projection_1D.cxx b/src/StdMeshers/StdMeshers_Projection_1D.cxx index 4fd7c5d8d..1cb6e21f6 100644 --- a/src/StdMeshers/StdMeshers_Projection_1D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_1D.cxx @@ -372,6 +372,97 @@ bool StdMeshers_Projection_1D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& return true; } + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_Projection_1D::Evaluate(SMESH_Mesh& theMesh, + const TopoDS_Shape& theShape, + MapShapeNbElems& aResMap) +{ + if ( !_sourceHypo ) + return false; + + SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); + SMESH_Mesh * tgtMesh = & theMesh; + if ( !srcMesh ) + srcMesh = tgtMesh; + + SMESHDS_Mesh * meshDS = theMesh.GetMeshDS(); + + // --------------------------- + // Make subshapes association + // --------------------------- + + TopoDS_Edge srcEdge, tgtEdge = TopoDS::Edge( theShape.Oriented(TopAbs_FORWARD)); + TopoDS_Shape srcShape = _sourceHypo->GetSourceEdge().Oriented(TopAbs_FORWARD); + + TAssocTool::TShapeShapeMap shape2ShapeMap; + TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtEdge ); + if ( !TAssocTool::FindSubShapeAssociation( tgtEdge, tgtMesh, srcShape, srcMesh, + shape2ShapeMap) || + !shape2ShapeMap.IsBound( tgtEdge )) + return error("Vertices association failed" ); + + srcEdge = TopoDS::Edge( shape2ShapeMap( tgtEdge ).Oriented(TopAbs_FORWARD)); +// cout << " srcEdge #" << srcMesh->GetMeshDS()->ShapeToIndex( srcEdge ) +// << " tgtEdge #" << tgtMesh->GetMeshDS()->ShapeToIndex( tgtEdge ) << endl; + + TopoDS_Vertex tgtV[2], srcV[2]; + TopExp::Vertices( tgtEdge, tgtV[0], tgtV[1] ); + TopExp::Vertices( srcEdge, srcV[0], srcV[1] ); + + // ---------------------------------------------- + // Assure that mesh on a source edge is computed + // ---------------------------------------------- + + SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcEdge ); + //SMESH_subMesh* tgtSubMesh = tgtMesh->GetSubMesh( tgtEdge ); + + if ( tgtMesh == srcMesh ) { + if ( !TAssocTool::MakeComputed( srcSubMesh )) + return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); + } + else { + if ( !srcSubMesh->IsMeshComputed() ) + return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); + } + // ----------------------------------------------- + // Find out nodes distribution on the source edge + // ----------------------------------------------- + + double srcLength = EdgeLength( srcEdge ); + double tgtLength = EdgeLength( tgtEdge ); + + vector< double > params; // sorted parameters of nodes on the source edge + if ( !SMESH_Algo::GetNodeParamOnEdge( srcMesh->GetMeshDS(), srcEdge, params )) + return error(COMPERR_BAD_INPUT_MESH,"Bad node parameters on the source edge"); + + int nbNodes = params.size(); + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + + aVec[0] = nbNodes; + + bool quadratic = false; + SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements(); + if ( elemIt->more() ) + quadratic = elemIt->next()->IsQuadratic(); + if(quadratic) + aVec[2] = (nbNodes-1)/2; + else + aVec[1] = nbNodes - 1; + + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //============================================================================= /*! * \brief Sets a default event listener to submesh of the source edge diff --git a/src/StdMeshers/StdMeshers_Projection_1D.hxx b/src/StdMeshers/StdMeshers_Projection_1D.hxx index 52f76e170..be003ed7b 100644 --- a/src/StdMeshers/StdMeshers_Projection_1D.hxx +++ b/src/StdMeshers/StdMeshers_Projection_1D.hxx @@ -46,6 +46,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + /*! * \brief Sets a default event listener to submesh of the source edge * \param whenSetToSubMesh - submesh where algo is set diff --git a/src/StdMeshers/StdMeshers_Projection_2D.cxx b/src/StdMeshers/StdMeshers_Projection_2D.cxx index 3457197f5..682c16bb5 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.cxx @@ -642,6 +642,83 @@ bool StdMeshers_Projection_2D::Compute(SMESH_Mesh& theMesh, const TopoDS_Shape& return true; } + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_Projection_2D::Evaluate(SMESH_Mesh& theMesh, + const TopoDS_Shape& theShape, + MapShapeNbElems& aResMap) +{ + if ( !_sourceHypo ) + return false; + + SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); + SMESH_Mesh * tgtMesh = & theMesh; + if ( !srcMesh ) + srcMesh = tgtMesh; + + // --------------------------- + // Make subshapes association + // --------------------------- + + TopoDS_Face tgtFace = TopoDS::Face( theShape.Oriented(TopAbs_FORWARD)); + TopoDS_Shape srcShape = _sourceHypo->GetSourceFace().Oriented(TopAbs_FORWARD); + + TAssocTool::TShapeShapeMap shape2ShapeMap; + TAssocTool::InitVertexAssociation( _sourceHypo, shape2ShapeMap, tgtFace ); + if ( !TAssocTool::FindSubShapeAssociation( tgtFace, tgtMesh, srcShape, srcMesh, + shape2ShapeMap) || + !shape2ShapeMap.IsBound( tgtFace )) + return error(COMPERR_BAD_SHAPE,"Topology of source and target faces seems different" ); + + TopoDS_Face srcFace = TopoDS::Face( shape2ShapeMap( tgtFace ).Oriented(TopAbs_FORWARD)); + + // ---------------------------------------------- + // Assure that mesh on a source Face is computed + // ---------------------------------------------- + + SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( srcFace ); + + if ( !srcSubMesh->IsMeshComputed() ) + return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); + + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + + aVec[0] = srcSubMesh->GetSubMeshDS()->NbNodes(); + + //bool quadratic = false; + SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements(); + while ( elemIt->more() ) { + const SMDS_MeshElement* E = elemIt->next(); + if( E->NbNodes()==3 ) { + aVec[3]++; + } + else if( E->NbNodes()==4 ) { + aVec[5]++; + } + else if( E->NbNodes()==6 && E->IsQuadratic() ) { + aVec[4]++; + } + else if( E->NbNodes()==8 && E->IsQuadratic() ) { + aVec[6]++; + } + else { + aVec[7]++; + } + } + + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //============================================================================= /*! * \brief Sets a default event listener to submesh of the source face diff --git a/src/StdMeshers/StdMeshers_Projection_2D.hxx b/src/StdMeshers/StdMeshers_Projection_2D.hxx index 006db8344..26506e81a 100644 --- a/src/StdMeshers/StdMeshers_Projection_2D.hxx +++ b/src/StdMeshers/StdMeshers_Projection_2D.hxx @@ -44,6 +44,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + /*! * \brief Sets a default event listener to submesh of the source face * \param whenSetToSubMesh - submesh where algo is set diff --git a/src/StdMeshers/StdMeshers_Projection_3D.cxx b/src/StdMeshers/StdMeshers_Projection_3D.cxx index 86d6d65d3..628102410 100644 --- a/src/StdMeshers/StdMeshers_Projection_3D.cxx +++ b/src/StdMeshers/StdMeshers_Projection_3D.cxx @@ -420,6 +420,104 @@ bool StdMeshers_Projection_3D::Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aS return true; } + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_Projection_3D::Evaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + MapShapeNbElems& aResMap) +{ + if ( !_sourceHypo ) + return false; + + SMESH_Mesh * srcMesh = _sourceHypo->GetSourceMesh(); + SMESH_Mesh * tgtMesh = & aMesh; + if ( !srcMesh ) + srcMesh = tgtMesh; + + // get shell from shape3D + TopoDS_Shell srcShell, tgtShell; + TopExp_Explorer exp( _sourceHypo->GetSource3DShape(), TopAbs_SHELL ); + int nbShell; + for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell ) + srcShell = TopoDS::Shell( exp.Current() ); + if ( nbShell != 1 ) + return error(COMPERR_BAD_SHAPE, + SMESH_Comment("Source shape must have 1 shell but not ") << nbShell); + + exp.Init( aShape, TopAbs_SHELL ); + for ( nbShell = 0; exp.More(); exp.Next(), ++nbShell ) + tgtShell = TopoDS::Shell( exp.Current() ); + if ( nbShell != 1 ) + return error(COMPERR_BAD_SHAPE, + SMESH_Comment("Target shape must have 1 shell but not ") << nbShell); + + // Check that shapes are blocks + if ( TAssocTool::Count( tgtShell, TopAbs_FACE , 1 ) != 6 || + TAssocTool::Count( tgtShell, TopAbs_EDGE , 1 ) != 12 || + TAssocTool::Count( tgtShell, TopAbs_WIRE , 1 ) != 6 ) + return error(COMPERR_BAD_SHAPE, "Target shape is not a block"); + if ( TAssocTool::Count( srcShell, TopAbs_FACE , 1 ) != 6 || + TAssocTool::Count( srcShell, TopAbs_EDGE , 1 ) != 12 || + TAssocTool::Count( srcShell, TopAbs_WIRE , 1 ) != 6 ) + return error(COMPERR_BAD_SHAPE, "Source shape is not a block"); + + // Assure that mesh on a source shape is computed + + SMESH_subMesh* srcSubMesh = srcMesh->GetSubMesh( _sourceHypo->GetSource3DShape() ); + + if ( !srcSubMesh->IsMeshComputed() ) + return error(COMPERR_BAD_INPUT_MESH,"Source mesh not computed"); + + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + + aVec[0] = srcSubMesh->GetSubMeshDS()->NbNodes(); + + //bool quadratic = false; + SMDS_ElemIteratorPtr elemIt = srcSubMesh->GetSubMeshDS()->GetElements(); + while ( elemIt->more() ) { + const SMDS_MeshElement* E = elemIt->next(); + if( E->NbNodes()==4 ) { + aVec[8]++; + } + else if( E->NbNodes()==5 ) { + aVec[10]++; + } + else if( E->NbNodes()==6 ) { + aVec[12]++; + } + else if( E->NbNodes()==8 ) { + aVec[14]++; + } + else if( E->NbNodes()==10 && E->IsQuadratic() ) { + aVec[9]++; + } + else if( E->NbNodes()==13 && E->IsQuadratic() ) { + aVec[11]++; + } + else if( E->NbNodes()==15 && E->IsQuadratic() ) { + aVec[13]++; + } + else if( E->NbNodes()==20 && E->IsQuadratic() ) { + aVec[15]++; + } + else { + aVec[16]++; + } + } + + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //============================================================================= /*! * \brief Sets a default event listener to submesh of the source shape diff --git a/src/StdMeshers/StdMeshers_Projection_3D.hxx b/src/StdMeshers/StdMeshers_Projection_3D.hxx index 7f4200ef4..8f9554509 100644 --- a/src/StdMeshers/StdMeshers_Projection_3D.hxx +++ b/src/StdMeshers/StdMeshers_Projection_3D.hxx @@ -44,6 +44,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + /*! * \brief Sets a default event listener to submesh of the source shape * \param whenSetToSubMesh - submesh where algo is set diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx index acc873186..0a13e88ea 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.cxx @@ -587,6 +587,90 @@ bool StdMeshers_Quadrangle_2D::Compute (SMESH_Mesh& aMesh, return isOk; } + +//============================================================================= +/*! + * Evaluate + */ +//============================================================================= + +bool StdMeshers_Quadrangle_2D::Evaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + MapShapeNbElems& aResMap) + +{ + aMesh.GetSubMesh(aShape); + + std::vector aNbNodes(4); + bool IsQuadratic = false; + if( !CheckNbEdgesForEvaluate( aMesh, aShape, aResMap, aNbNodes, IsQuadratic ) ) { + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + + if(myQuadranglePreference) { + int n1 = aNbNodes[0]; + int n2 = aNbNodes[1]; + int n3 = aNbNodes[2]; + int n4 = aNbNodes[3]; + int nfull = n1+n2+n3+n4; + int ntmp = nfull/2; + ntmp = ntmp*2; + if( nfull==ntmp && ( (n1!=n3) || (n2!=n4) ) ) { + // special path for using only quandrangle faces + return EvaluateQuadPref(aMesh, aShape, aNbNodes, aResMap, IsQuadratic); + //return true; + } + } + + int nbdown = aNbNodes[0]; + int nbup = aNbNodes[2]; + + int nbright = aNbNodes[1]; + int nbleft = aNbNodes[3]; + + int nbhoriz = Min(nbdown, nbup); + int nbvertic = Min(nbright, nbleft); + + int dh = Max(nbdown, nbup) - nbhoriz; + int dv = Max(nbright, nbleft) - nbvertic; + + int kdh = 0; + if(dh>0) kdh = 1; + int kdv = 0; + if(dv>0) kdv = 1; + + int nbNodes = (nbhoriz-2)*(nbvertic-2); + int nbFaces3 = dh + dv + kdh*(nbvertic-1)*2 + kdv*(nbhoriz-1)*2; + if( kdh==1 && kdv==1 ) nbFaces3 -= 2; + int nbFaces4 = (nbhoriz-1-kdh)*(nbvertic-1-kdv); + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + if(IsQuadratic) { + aVec[4] = nbFaces3; + aVec[6] = nbFaces4; + int nbbndedges = nbdown + nbup + nbright + nbleft -4; + int nbintedges = ( nbFaces4*4 + nbFaces3*3 - nbbndedges ) / 2; + aVec[0] = nbNodes + nbintedges; + } + else { + aVec[0] = nbNodes; + aVec[3] = nbFaces3; + aVec[5] = nbFaces4; + } + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //================================================================================ /*! * \brief Return true if only two given edges meat at their common vertex @@ -721,6 +805,146 @@ FaceQuadStruct* StdMeshers_Quadrangle_2D::CheckNbEdges(SMESH_Mesh & aMes return quad; } + +//============================================================================= +/*! + * + */ +//============================================================================= + +bool StdMeshers_Quadrangle_2D::CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap, + std::vector& aNbNodes, + bool& IsQuadratic) + +{ + const TopoDS_Face & F = TopoDS::Face(aShape); + + // verify 1 wire only, with 4 edges + TopoDS_Vertex V; + list< TopoDS_Edge > edges; + list< int > nbEdgesInWire; + int nbWire = SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire); + if (nbWire != 1) { + return false; + } + + aNbNodes.resize(4); + + int nbSides = 0; + list< TopoDS_Edge >::iterator edgeIt = edges.begin(); + SMESH_subMesh * sm = aMesh.GetSubMesh( *edgeIt ); + MapShapeNbElemsItr anIt = aResMap.find(sm); + if(anIt==aResMap.end()) { + return false; + } + std::vector aVec = (*anIt).second; + IsQuadratic = (aVec[2] > aVec[1]); + if ( nbEdgesInWire.front() == 4 ) { // exactly 4 edges + for(; edgeIt != edges.end(); edgeIt++) { + SMESH_subMesh * sm = aMesh.GetSubMesh( *edgeIt ); + MapShapeNbElemsItr anIt = aResMap.find(sm); + if(anIt==aResMap.end()) { + return false; + } + std::vector aVec = (*anIt).second; + if(IsQuadratic) + aNbNodes[nbSides] = (aVec[0]-1)/2 + 2; + else + aNbNodes[nbSides] = aVec[0] + 2; + nbSides++; + } + } + else if ( nbEdgesInWire.front() > 4 ) { // more than 4 edges - try to unite some + list< TopoDS_Edge > sideEdges; + while ( !edges.empty()) { + sideEdges.clear(); + sideEdges.splice( sideEdges.end(), edges, edges.begin()); // edges.front() -> sideEdges.end() + bool sameSide = true; + while ( !edges.empty() && sameSide ) { + sameSide = SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ); + if ( sameSide ) + sideEdges.splice( sideEdges.end(), edges, edges.begin()); + } + if ( nbSides == 0 ) { // go backward from the first edge + sameSide = true; + while ( !edges.empty() && sameSide ) { + sameSide = SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ); + if ( sameSide ) + sideEdges.splice( sideEdges.begin(), edges, --edges.end()); + } + } + list::iterator ite = sideEdges.begin(); + aNbNodes[nbSides] = 1; + for(; ite!=sideEdges.end(); ite++) { + SMESH_subMesh * sm = aMesh.GetSubMesh( *ite ); + MapShapeNbElemsItr anIt = aResMap.find(sm); + if(anIt==aResMap.end()) { + return false; + } + std::vector aVec = (*anIt).second; + if(IsQuadratic) + aNbNodes[nbSides] += (aVec[0]-1)/2 + 1; + else + aNbNodes[nbSides] += aVec[0] + 1; + } + ++nbSides; + } + // issue 20222. Try to unite only edges shared by two same faces + if (nbSides < 4) { + nbSides = 0; + SMESH_Block::GetOrderedEdges (F, V, edges, nbEdgesInWire); + while ( !edges.empty()) { + sideEdges.clear(); + sideEdges.splice( sideEdges.end(), edges, edges.begin()); + bool sameSide = true; + while ( !edges.empty() && sameSide ) { + sameSide = + SMESH_Algo::IsContinuous( sideEdges.back(), edges.front() ) && + twoEdgesMeatAtVertex( sideEdges.back(), edges.front(), aMesh ); + if ( sameSide ) + sideEdges.splice( sideEdges.end(), edges, edges.begin()); + } + if ( nbSides == 0 ) { // go backward from the first edge + sameSide = true; + while ( !edges.empty() && sameSide ) { + sameSide = + SMESH_Algo::IsContinuous( sideEdges.front(), edges.back() ) && + twoEdgesMeatAtVertex( sideEdges.front(), edges.back(), aMesh ); + if ( sameSide ) + sideEdges.splice( sideEdges.begin(), edges, --edges.end()); + } + } + list::iterator ite = sideEdges.begin(); + aNbNodes[nbSides] = 1; + for(; ite!=sideEdges.end(); ite++) { + SMESH_subMesh * sm = aMesh.GetSubMesh( *ite ); + MapShapeNbElemsItr anIt = aResMap.find(sm); + if(anIt==aResMap.end()) { + return false; + } + std::vector aVec = (*anIt).second; + if(IsQuadratic) + aNbNodes[nbSides] += (aVec[0]-1)/2 + 1; + else + aNbNodes[nbSides] += aVec[0] + 1; + } + ++nbSides; + } + } + } + if (nbSides != 4) { + if ( !nbSides ) + nbSides = nbEdgesInWire.front(); + error(COMPERR_BAD_SHAPE, TComm("Face must have 4 sides but not ") << nbSides); + return false; + } + + return true; +} + + //============================================================================= /*! * CheckAnd2Dcompute @@ -1397,8 +1621,10 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, } } + int nbf=0; for(j=1; jAddFace(NodesBRD.Value(i,j), NodesBRD.Value(i+1,j), @@ -1413,7 +1639,6 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, } } } - int drl = abs(nr-nl); // create faces for region C StdMeshers_Array2OfNode NodesC(1,nb,1,drl+1+addv); @@ -1512,6 +1737,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, // create faces for(j=1; j<=drl+addv; j++) { for(i=1; iAddFace(NodesC.Value(i,j), NodesC.Value(i+1,j), @@ -1545,6 +1771,7 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, NodesLast.SetValue(nnn,1,NodesC.Value(nb,i)); } for(i=1; iAddFace(NodesLast.Value(i,1), NodesLast.Value(i+1,1), @@ -1566,6 +1793,132 @@ bool StdMeshers_Quadrangle_2D::ComputeQuadPref (SMESH_Mesh & aMesh, return isOk; } + +//======================================================================= +/*! + * Evaluate only quandrangle faces + */ +//======================================================================= + +bool StdMeshers_Quadrangle_2D::EvaluateQuadPref(SMESH_Mesh & aMesh, + const TopoDS_Shape& aShape, + std::vector& aNbNodes, + MapShapeNbElems& aResMap, + bool IsQuadratic) +{ + // Auxilary key in order to keep old variant + // of meshing after implementation new variant + // for bug 0016220 from Mantis. + bool OldVersion = false; + + const TopoDS_Face& F = TopoDS::Face(aShape); + Handle(Geom_Surface) S = BRep_Tool::Surface(F); + + int nb = aNbNodes[0]; + int nr = aNbNodes[1]; + int nt = aNbNodes[2]; + int nl = aNbNodes[3]; + int dh = abs(nb-nt); + int dv = abs(nr-nl); + + if( dh>=dv ) { + if( nt>nb ) { + // it is a base case => not shift + } + else { + // we have to shift on 2 + nb = aNbNodes[2]; + nr = aNbNodes[3]; + nt = aNbNodes[0]; + nl = aNbNodes[1]; + } + } + else { + if( nr>nl ) { + // we have to shift quad on 1 + nb = aNbNodes[3]; + nr = aNbNodes[0]; + nt = aNbNodes[1]; + nl = aNbNodes[2]; + } + else { + // we have to shift quad on 3 + nb = aNbNodes[1]; + nr = aNbNodes[2]; + nt = aNbNodes[3]; + nl = aNbNodes[0]; + } + } + + dh = abs(nb-nt); + dv = abs(nr-nl); + int nbh = Max(nb,nt); + int nbv = Max(nr,nl); + int addh = 0; + int addv = 0; + + if(dh>dv) { + addv = (dh-dv)/2; + nbv = nbv + addv; + } + else { // dv>=dh + addh = (dv-dh)/2; + nbh = nbh + addh; + } + + int dl,dr; + if(OldVersion) { + // add some params to right and left after the first param + // insert to right + dr = nbv - nr; + // insert to left + dl = nbv - nl; + } + + int nnn = Min(nr,nl); + + int nbNodes = 0; + int nbFaces = 0; + if(OldVersion) { + // step1: create faces for left domain + if(dl>0) { + nbNodes += dl*(nl-1); + nbFaces += dl*(nl-1); + } + // step2: create faces for right domain + if(dr>0) { + nbNodes += dr*(nr-1); + nbFaces += dr*(nr-1); + } + // step3: create faces for central domain + nbNodes += (nb-2)*(nnn-1) + (nbv-nnn-1)*(nb-2); + nbFaces += (nb-1)*(nbv-1); + } + else { // New version (!OldVersion) + nbNodes += (nnn-2)*(nb-2); + nbFaces += (nnn-2)*(nb-1); + int drl = abs(nr-nl); + nbNodes += drl*(nb-1) + addv*nb; + nbFaces += (drl+addv)*(nb-1) + (nt-1); + } // end new version implementation + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + if(IsQuadratic) { + aVec[6] = nbFaces; + aVec[0] = nbNodes + nbFaces*4; + } + else { + aVec[0] = nbNodes; + aVec[5] = nbFaces; + } + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //============================================================================= /*! Split quadrangle in to 2 triangles by smallest diagonal * diff --git a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx index 18c1daeca..6c26fde4a 100644 --- a/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx +++ b/src/StdMeshers/StdMeshers_Quadrangle_2D.hxx @@ -65,6 +65,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + FaceQuadStruct* CheckAnd2Dcompute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, const bool CreateQuadratic); @@ -74,6 +77,12 @@ protected: FaceQuadStruct* CheckNbEdges(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + bool CheckNbEdgesForEvaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap, + std::vector& aNbNodes, + bool& IsQuadratic); + bool SetNormalizedGrid(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape, FaceQuadStruct*& quad); @@ -89,10 +98,15 @@ protected: * Special function for creation only quandrangle faces */ bool ComputeQuadPref(SMESH_Mesh& aMesh, - const TopoDS_Shape& aShape, FaceQuadStruct* quad); + bool EvaluateQuadPref(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + std::vector& aNbNodes, + MapShapeNbElems& aResMap, + bool IsQuadratic); + UVPtStruct* LoadEdgePoints2(SMESH_Mesh& aMesh, const TopoDS_Face& F, const TopoDS_Edge& E, bool IsReverse); diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx index 133b68160..182798c94 100644 --- a/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx +++ b/src/StdMeshers/StdMeshers_RadialPrism_3D.cxx @@ -45,10 +45,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include @@ -386,3 +388,171 @@ bool StdMeshers_RadialPrism_3D::computeLayerPositions(const gp_Pnt& pIn, } RETURN_BAD_RESULT("Bad hypothesis"); } + + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_RadialPrism_3D::Evaluate(SMESH_Mesh& aMesh, + const TopoDS_Shape& aShape, + MapShapeNbElems& aResMap) +{ + // get 2 shells + TopoDS_Solid solid = TopoDS::Solid( aShape ); + TopoDS_Shell outerShell = BRepTools::OuterShell( solid ); + TopoDS_Shape innerShell; + int nbShells = 0; + for ( TopoDS_Iterator It (solid); It.More(); It.Next(), ++nbShells ) + if ( !outerShell.IsSame( It.Value() )) + innerShell = It.Value(); + if ( nbShells != 2 ) { + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + + // Associate subshapes of the shells + TAssocTool::TShapeShapeMap shape2ShapeMap; + if ( !TAssocTool::FindSubShapeAssociation( outerShell, &aMesh, + innerShell, &aMesh, + shape2ShapeMap) ) { + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + + // get info for outer shell + int nb0d_Out=0, nb2d_3_Out=0, nb2d_4_Out=0; + //TopTools_SequenceOfShape FacesOut; + for (TopExp_Explorer exp(outerShell, TopAbs_FACE); exp.More(); exp.Next()) { + //FacesOut.Append(exp.Current()); + SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); + MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); + std::vector aVec = (*anIt).second; + nb0d_Out += aVec[0]; + nb2d_3_Out += Max(aVec[3],aVec[4]); + nb2d_4_Out += Max(aVec[5],aVec[6]); + } + int nb1d_Out = 0; + TopTools_MapOfShape tmpMap; + for (TopExp_Explorer exp(outerShell, TopAbs_EDGE); exp.More(); exp.Next()) { + if( tmpMap.Contains( exp.Current() ) ) + continue; + tmpMap.Add( exp.Current() ); + SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); + MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); + std::vector aVec = (*anIt).second; + nb0d_Out += aVec[0]; + nb1d_Out += Max(aVec[1],aVec[2]); + } + tmpMap.Clear(); + for (TopExp_Explorer exp(outerShell, TopAbs_VERTEX); exp.More(); exp.Next()) { + if( tmpMap.Contains( exp.Current() ) ) + continue; + tmpMap.Add( exp.Current() ); + nb0d_Out++; + } + + // get info for inner shell + int nb0d_In=0, nb2d_3_In=0, nb2d_4_In=0; + //TopTools_SequenceOfShape FacesIn; + for (TopExp_Explorer exp(innerShell, TopAbs_FACE); exp.More(); exp.Next()) { + //FacesIn.Append(exp.Current()); + SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); + MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); + std::vector aVec = (*anIt).second; + nb0d_In += aVec[0]; + nb2d_3_In += Max(aVec[3],aVec[4]); + nb2d_4_In += Max(aVec[5],aVec[6]); + } + int nb1d_In = 0; + tmpMap.Clear(); + bool IsQuadratic = false; + bool IsFirst = true; + for (TopExp_Explorer exp(innerShell, TopAbs_EDGE); exp.More(); exp.Next()) { + if( tmpMap.Contains( exp.Current() ) ) + continue; + tmpMap.Add( exp.Current() ); + SMESH_subMesh *aSubMesh = aMesh.GetSubMesh(exp.Current()); + MapShapeNbElemsItr anIt = aResMap.find(aSubMesh); + std::vector aVec = (*anIt).second; + nb0d_In += aVec[0]; + nb1d_In += Max(aVec[1],aVec[2]); + if(IsFirst) { + IsQuadratic = (aVec[2] > aVec[1]); + IsFirst = false; + } + } + tmpMap.Clear(); + for (TopExp_Explorer exp(innerShell, TopAbs_VERTEX); exp.More(); exp.Next()) { + if( tmpMap.Contains( exp.Current() ) ) + continue; + tmpMap.Add( exp.Current() ); + nb0d_In++; + } + + bool IsOK = (nb0d_Out==nb0d_In) && (nb1d_Out==nb1d_In) && + (nb2d_3_Out==nb2d_3_In) && (nb2d_4_Out==nb2d_4_In); + if(!IsOK) { + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + + int nbLayers = 0; + if( myNbLayerHypo ) { + nbLayers = myNbLayerHypo->GetNumberOfLayers(); + } + if ( myDistributionHypo ) { + if ( !myDistributionHypo->GetLayerDistribution() ) { + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + TopExp_Explorer exp(outerShell, TopAbs_VERTEX); + TopoDS_Vertex Vout = TopoDS::Vertex(exp.Current()); + TopoDS_Vertex Vin = TopoDS::Vertex( shape2ShapeMap(Vout) ); + if ( myLayerPositions.empty() ) { + gp_Pnt pIn = BRep_Tool::Pnt(Vin); + gp_Pnt pOut = BRep_Tool::Pnt(Vout); + computeLayerPositions( pIn, pOut ); + } + nbLayers = myLayerPositions.size() + 1; + } + + std::vector aResVec(17); + for(int i=0; i<17; i++) aResVec[i] = 0; + if(IsQuadratic) { + aResVec[13] = nb2d_3_Out * nbLayers; + aResVec[15] = nb2d_4_Out * nbLayers; + int nb1d = ( nb2d_3_Out*3 + nb2d_4_Out*4 ) / 2; + aResVec[0] = nb0d_Out * ( 2*nbLayers - 1 ) - nb1d * nbLayers; + } + else { + aResVec[0] = nb0d_Out * ( nbLayers - 1 ); + aResVec[12] = nb2d_3_Out * nbLayers; + aResVec[14] = nb2d_4_Out * nbLayers; + } + SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); + aResMap.insert(std::make_pair(sm,aResVec)); + + return true; +} diff --git a/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx b/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx index d0c783522..21d8f8362 100644 --- a/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx +++ b/src/StdMeshers/StdMeshers_RadialPrism_3D.hxx @@ -51,6 +51,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + protected: typedef std::vector TNodeColumn; diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index ee4aa86e7..6edeeb036 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -930,6 +930,85 @@ bool StdMeshers_Regular_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & t return true; } + +//============================================================================= +/*! + * + */ +//============================================================================= + +bool StdMeshers_Regular_1D::Evaluate(SMESH_Mesh & theMesh, + const TopoDS_Shape & theShape, + MapShapeNbElems& aResMap) +{ + if ( _hypType == NONE ) + return false; + + SMESHDS_Mesh * meshDS = theMesh.GetMeshDS(); + + const TopoDS_Edge & EE = TopoDS::Edge(theShape); + TopoDS_Edge E = TopoDS::Edge(EE.Oriented(TopAbs_FORWARD)); + int shapeID = meshDS->ShapeToIndex( E ); + + double f, l; + Handle(Geom_Curve) Curve = BRep_Tool::Curve(E, f, l); + + TopoDS_Vertex VFirst, VLast; + TopExp::Vertices(E, VFirst, VLast); // Vfirst corresponds to f and Vlast to l + + ASSERT(!VFirst.IsNull()); + ASSERT(!VLast.IsNull()); + + std::vector aVec(17); + for(int i=0; i<17; i++) aVec[i] = 0; + + if (!Curve.IsNull()) { + list< double > params; + bool reversed = false; + if ( !_mainEdge.IsNull() ) + reversed = ( _mainEdge.Orientation() == TopAbs_REVERSED ); + + BRepAdaptor_Curve C3d( E ); + double length = EdgeLength( E ); + if ( ! computeInternalParameters( theMesh, C3d, length, f, l, params, reversed, true )) { + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aVec)); + SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); + smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); + return false; + } + redistributeNearVertices( theMesh, C3d, length, params, VFirst, VLast ); + + if(_quadraticMesh) { + aVec[0] = 2*params.size() + 1; + aVec[2] = params.size() + 1; + } + else { + aVec[0] = params.size(); + aVec[1] = params.size() + 1; + } + + } + else { + //MESSAGE("************* Degenerated edge! *****************"); + // Edge is a degenerated Edge : We put n = 5 points on the edge. + if(_quadraticMesh) { + aVec[0] = 11; + aVec[2] = 6; + } + else { + aVec[0] = 5; + aVec[1] = 6; + } + } + + SMESH_subMesh * sm = theMesh.GetSubMesh(theShape); + aResMap.insert(std::make_pair(sm,aVec)); + + return true; +} + + //============================================================================= /*! * See comments in SMESH_Algo.cxx diff --git a/src/StdMeshers/StdMeshers_Regular_1D.hxx b/src/StdMeshers/StdMeshers_Regular_1D.hxx index 7df8e4533..244ebe6a1 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.hxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.hxx @@ -49,6 +49,9 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); + virtual const std::list & GetUsedHypothesis(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, const bool=true); diff --git a/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.cxx b/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.cxx index 60ba2518d..204909320 100644 --- a/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.cxx +++ b/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.cxx @@ -92,3 +92,18 @@ bool StdMeshers_SegmentAroundVertex_0D::Compute(SMESH_Mesh&, const TopoDS_Shape& // StdMeshers_SegmentLengthAroundVertex hypothesis return true; } + + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_SegmentAroundVertex_0D::Evaluate(SMESH_Mesh&, + const TopoDS_Shape&, + MapShapeNbElems&) +{ + // This algorithm exists in order just to enable assignation of + // StdMeshers_SegmentLengthAroundVertex hypothesis + return false; +} diff --git a/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx b/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx index 4054a715d..a2f1bd579 100644 --- a/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx +++ b/src/StdMeshers/StdMeshers_SegmentAroundVertex_0D.hxx @@ -46,6 +46,8 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); }; #endif diff --git a/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx b/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx index e44345af4..3638498e1 100644 --- a/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_UseExisting_1D2D.cxx @@ -60,10 +60,27 @@ bool StdMeshers_UseExisting_1D::CheckHypothesis(SMESH_Mesh& , bool StdMeshers_UseExisting_1D::Compute(SMESH_Mesh&, const TopoDS_Shape&) { - // This algorithm exists to allow mesh generation by mesh edition functions in TUI mode + // This algorithm exists to allow mesh generation by mesh + // edition functions in TUI mode return true; } + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_UseExisting_1D::Evaluate(SMESH_Mesh&, + const TopoDS_Shape&, + MapShapeNbElems&) +{ + // This algorithm exists to allow mesh generation by mesh + // edition functions in TUI mode + return false; +} + + //======================================================================= //function : StdMeshers_UseExisting_2D //purpose : @@ -97,6 +114,22 @@ bool StdMeshers_UseExisting_2D::CheckHypothesis(SMESH_Mesh& , bool StdMeshers_UseExisting_2D::Compute(SMESH_Mesh&, const TopoDS_Shape&) { - // This algorithm exists to allow mesh generation by mesh edition functions in TUI mode + // This algorithm exists to allow mesh generation by mesh edition + // functions in TUI mode return true; } + + +//======================================================================= +//function : Evaluate +//purpose : +//======================================================================= + +bool StdMeshers_UseExisting_2D::Evaluate(SMESH_Mesh&, + const TopoDS_Shape&, + MapShapeNbElems&) +{ + // This algorithm exists to allow mesh generation by mesh edition + // functions in TUI mode + return false; +} diff --git a/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx b/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx index 6d5a5e495..961fb4ba9 100644 --- a/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx +++ b/src/StdMeshers/StdMeshers_UseExisting_1D2D.hxx @@ -46,6 +46,8 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); }; class STDMESHERS_EXPORT StdMeshers_UseExisting_1D: public SMESH_1D_Algo @@ -59,6 +61,8 @@ public: virtual bool Compute(SMESH_Mesh& aMesh, const TopoDS_Shape& aShape); + virtual bool Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, + MapShapeNbElems& aResMap); }; #endif