X-Git-Url: http://git.salome-platform.org/gitweb/?p=modules%2Fsmesh.git;a=blobdiff_plain;f=src%2FStdMeshersGUI%2FStdMeshersGUI_CartesianParamCreator.cxx;h=2aa6c49f1a7e5c13b82c7d5e8373c0676619721f;hp=937c79066efa46a064d6c65bce302e29f9b0912e;hb=HEAD;hpb=bd8f1aee7c78f7d2eb82bd4fec5e08c9e3d280ce diff --git a/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx b/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx index 937c79066..675f377cc 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_CartesianParamCreator.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2024 CEA, EDF, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -6,7 +6,7 @@ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -25,23 +25,39 @@ // SMESH includes #include "StdMeshersGUI_CartesianParamCreator.h" -#include -#include -#include -#include +#include "SMESHGUI.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_VTKUtils.h" +#include "SMESHGUI_HypothesesUtils.h" +#include "SMESHGUI_SpinBox.h" +#include "SMESHGUI_MeshEditPreview.h" // IDL includes #include CORBA_SERVER_HEADER(SMESH_BasicHypothesis) // SALOME GUI includes -#include -#include +#include #include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include // Qt includes #include #include #include +#include +#include #include #include #include @@ -49,14 +65,14 @@ #include #include #include +#include #include #include #include +#include #include #include #include -#include -#include #define SPACING 6 #define MARGIN 11 @@ -161,8 +177,8 @@ namespace StdMeshersGUI myStepSpin->SetStep( 1. ); myStepSpin->SetValue( myStep = 1. ); - // 3) Coodrinates/Spacing group - QFrame* csFrame = new QFrame( this ); + // 3) Coordinates/Spacing group + QFrame* csFrame = new QFrame( this ); QVBoxLayout* scLay = new QVBoxLayout( csFrame ); scLay->setMargin( 0 ); scLay->setSpacing( SPACING ); @@ -188,8 +204,8 @@ namespace StdMeshersGUI axisTabLayout->setSpacing( SPACING ); axisTabLayout->addWidget( modeBox , 0, 0, 1, 3 ); - axisTabLayout->addWidget( myInsertBtn , 1, 0, 1, 2 ); - axisTabLayout->addWidget( myDeleteBtn , 2, 0, 1, 2 ); + axisTabLayout->addWidget( myInsertBtn, 1, 0, 1, 2 ); + axisTabLayout->addWidget( myDeleteBtn, 2, 0, 1, 2 ); axisTabLayout->addWidget( myStepLabel, 3, 0 ); axisTabLayout->addWidget( myStepSpin , 3, 1 ); axisTabLayout->addWidget( csFrame , 1, 2, 4, 1 ); @@ -200,11 +216,18 @@ namespace StdMeshersGUI connect( myInsertBtn, SIGNAL( clicked() ), SLOT( onInsert() )); connect( myDeleteBtn, SIGNAL( clicked() ), SLOT( onDelete() )); connect( myModeGroup, SIGNAL( buttonClicked ( int )), SLOT( onMode(int))); + connect( myModeGroup, SIGNAL( buttonClicked ( int )), SIGNAL( gridModeChanged(int))); connect( mySpacingTreeWdg, SIGNAL( itemSelectionChanged()), SLOT( updateButtons() )); connect( myCoordList, SIGNAL( itemSelectionChanged()), SLOT( updateButtons() )); connect( myStepSpin, SIGNAL( valueChanged(double)), SLOT( onStepChange() )); } + //================================================================================ + /*! + * \brief SLOT onInsert + */ + //================================================================================ + void GridAxisTab::onInsert() { if ( isGridBySpacing() ) @@ -253,6 +276,12 @@ namespace StdMeshersGUI updateButtons(); } + //================================================================================ + /*! + * \brief SLOT onDelete + */ + //================================================================================ + void GridAxisTab::onDelete() { if ( isGridBySpacing() ) @@ -282,12 +311,18 @@ namespace StdMeshersGUI updateButtons(); } + //================================================================================ + /*! + * \brief SLOT onMode + */ + //================================================================================ + void GridAxisTab::onMode(int isSpacing) { - mySpacingTreeWdg->setShown( isSpacing ); - myCoordList->setShown( !isSpacing ); - myStepSpin->setShown( !isSpacing ); - myStepLabel->setShown( !isSpacing ); + mySpacingTreeWdg->setVisible( isSpacing ); + myCoordList->setVisible( !isSpacing ); + myStepSpin->setVisible( !isSpacing ); + myStepLabel->setVisible( !isSpacing ); if ( isSpacing ) { if ( mySpacingTreeWdg->topLevelItemCount() == 0 ) @@ -312,6 +347,12 @@ namespace StdMeshersGUI updateButtons(); } + //================================================================================ + /*! + * \brief SLOT onStepChange + */ + //================================================================================ + void GridAxisTab::onStepChange() { if ( fabs( myStepSpin->GetValue() ) < 1e-100 ) @@ -322,6 +363,12 @@ namespace StdMeshersGUI myStep = myStepSpin->GetValue(); } + //================================================================================ + /*! + * \brief Enables/disables buttons + */ + //================================================================================ + void GridAxisTab::updateButtons() { bool insertEnable = false, deleteEnable = false; @@ -346,6 +393,12 @@ namespace StdMeshersGUI myDeleteBtn->setEnabled( deleteEnable ); } + //================================================================================ + /*! + * \brief Inserts coordinates into myCoordList + */ + //================================================================================ + void GridAxisTab::setCoordinates( SMESH::double_array_var coords ) { myCoordList->clear(); @@ -356,6 +409,12 @@ namespace StdMeshersGUI onMode( COORD_BUT ); } + //================================================================================ + /*! + * \brief Sets spacing got from hypothesis + */ + //================================================================================ + void GridAxisTab::setSpacing( SMESH::string_array_var funs, SMESH::double_array_var points ) { mySpacingTreeWdg->clear(); @@ -369,11 +428,23 @@ namespace StdMeshersGUI onMode( SPACING_BUT ); } + //================================================================================ + /*! + * \brief Checks grid definition mode + */ + //================================================================================ + bool GridAxisTab::isGridBySpacing() const { return ( myModeGroup->checkedId() == SPACING_BUT ); } + //================================================================================ + /*! + * \brief Returns coordinates to set to a hypothesis + */ + //================================================================================ + SMESH::double_array* GridAxisTab::getCoordinates() { SMESH::double_array_var coords = new SMESH::double_array; @@ -384,6 +455,12 @@ namespace StdMeshersGUI return coords._retn(); } + //================================================================================ + /*! + * \brief Returns spacing to set to a hypothesis + */ + //================================================================================ + void GridAxisTab::getSpacing(SMESH::string_array_out funs, SMESH::double_array_out points) const { @@ -403,6 +480,12 @@ namespace StdMeshersGUI } + //================================================================================ + /*! + * \brief Verifies parameters + */ + //================================================================================ + bool GridAxisTab::checkParams(QString& msg, SMESH::SMESH_Hypothesis_var& hyp) const { if ( isGridBySpacing() ) @@ -431,6 +514,12 @@ namespace StdMeshersGUI return true; } + //================================================================================ + /*! + * \brief LineDelegate constructor + */ + //================================================================================ + LineDelegate::LineDelegate( QWidget* parent ): QItemDelegate( parent ), mySpacingTreeWdg( qobject_cast( parent )), @@ -438,8 +527,14 @@ namespace StdMeshersGUI { } + //================================================================================ + /*! + * \brief Creates an editor depending on a current item + */ + //================================================================================ + QWidget* LineDelegate::createEditor( QWidget* parent, - const QStyleOptionViewItem& opt, + const QStyleOptionViewItem& /*opt*/, const QModelIndex& index) const { QWidget* w = 0; @@ -471,6 +566,12 @@ namespace StdMeshersGUI return w; } + //================================================================================ + /*! + * \brief Limit value range in the spin of a neighbor range + */ + //================================================================================ + void LineDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const { if ( mySpacingTreeWdg && index.column() == 0 ) @@ -493,6 +594,13 @@ namespace StdMeshersGUI QItemDelegate::setEditorData( editor, index ); } } + + //================================================================================ + /*! + * \brief + */ + //================================================================================ + void LineDelegate::setModelData( QWidget* editor, QAbstractItemModel* model, const QModelIndex& index ) const @@ -529,6 +637,69 @@ namespace StdMeshersGUI } // namespace StdMeshersGUI +namespace +{ + const double theAngTol = M_PI / 180.; + + //================================================================================ + /*! + * \brief Set variables to groups of spin boxes + */ + //================================================================================ + + void setText( const QString& vars, SMESHGUI_SpinBox** spins ) + { + QStringList varList = vars.split( ':' ); + for ( int i = 0; i < 3 && i < varList.count(); ++i ) + if ( !varList[i].isEmpty() ) + spins[i]->setText( varList[i] ); + } + + //================================================================================ + /*! + * \brief Computes more 2 axes by one + * \param [in] iOk - index of a given axis + * \param [in,out] dirs - directions of 3 axes + */ + //================================================================================ + + void get3Dirs( int iOk, gp_XYZ dirs[3] ) + { + dirs[ ( iOk+1 ) % 3 ] = dirs[ iOk ]; + + if ( Abs( dirs[ iOk ].Y() ) < 1e-100 && + Abs( dirs[ iOk ].Z() ) < 1e-100 ) + // dirs[ iOk ] || OX + dirs[ ( iOk+1 ) % 3 ].SetY( dirs[ iOk ].Y() + 1. ); + else + dirs[ ( iOk+1 ) % 3 ].SetX( dirs[ iOk ].X() + 1. ); + + dirs[( iOk+2 ) % 3] = dirs[ iOk ] ^ dirs[ ( iOk+1 ) % 3 ]; + dirs[( iOk+1 ) % 3] = dirs[ ( iOk+2 ) % 3 ] ^ dirs[ iOk ]; + } + + //================================================================================ + /*! + * \brief Returns a minimal width of a SpinBox depending on a precision type + */ + //================================================================================ + + int getMinWidth( const char* precisionType ) + { + int nb = SMESHGUI::resourceMgr()->integerValue( "SMESH", precisionType, -3 ); + QString s; + s.fill('0', qAbs(nb)+7 ); + QLineEdit le; + QFontMetrics metrics( le.font() ); + return metrics.width( s ); + } +} + +//================================================================================ +/*! + * \brief StdMeshersGUI_CartesianParamCreator constructor + */ +//================================================================================ StdMeshersGUI_CartesianParamCreator::StdMeshersGUI_CartesianParamCreator(const QString& aHypType) : StdMeshersGUI_StdHypothesisCreator( aHypType ), @@ -537,8 +708,23 @@ StdMeshersGUI_CartesianParamCreator::StdMeshersGUI_CartesianParamCreator(const Q myAxisTabs[0] = 0; myAxisTabs[1] = 0; myAxisTabs[2] = 0; + + myAxesPreview = new SMESHGUI_MeshEditPreview( SMESH::GetViewWindow( SMESHGUI::GetSMESHGUI() )); + myAxesPreview->SetArrowShapeAndNb( /*nbArrows=*/3, + /*headLength=*/0.1, + /*headRadius=*/0.01, + /*start=*/0., + /*labels=*/"XYZ"); + + myDirTic[0] = myDirTic[1] = myDirTic[2] = 0; } +//================================================================================ +/*! + * \brief StdMeshersGUI_CartesianParamCreator destructor + */ +//================================================================================ + StdMeshersGUI_CartesianParamCreator::~StdMeshersGUI_CartesianParamCreator() { if ( myAxisTabs[0] ) delete myAxisTabs[0]; @@ -547,8 +733,16 @@ StdMeshersGUI_CartesianParamCreator::~StdMeshersGUI_CartesianParamCreator() myAxisTabs[0] = 0; myAxisTabs[1] = 0; myAxisTabs[2] = 0; + + delete myAxesPreview; } +//================================================================================ +/*! + * \brief Validate parameters + */ +//================================================================================ + bool StdMeshersGUI_CartesianParamCreator::checkParams( QString& msg ) const { if( !SMESHGUI_GenericHypothesisCreator::checkParams( msg ) ) @@ -567,9 +761,22 @@ bool StdMeshersGUI_CartesianParamCreator::checkParams( QString& msg ) const if ( !myAxisTabs[1]->checkParams( msg, hyp )) return false; if ( !myAxisTabs[2]->checkParams( msg, hyp )) return false; + StdMeshersGUI_CartesianParamCreator* me = (StdMeshersGUI_CartesianParamCreator*) this; + if ( !me->updateAxesPreview() ) + { + msg = tr("INVALID_AXES_DIR"); + return false; + } + return true; } +//================================================================================ +/*! + * \brief Create widgets + */ +//================================================================================ + QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame() { QFrame* fr = new QFrame(); @@ -610,7 +817,32 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame() argGroupLayout->addWidget( myThreshold, row, 1 ); row++; - // 2) Grid definition + // 2) "Implement edges" + myAddEdges = new QCheckBox( tr("ADD_EDGES"), GroupC1 ); + argGroupLayout->addWidget( myAddEdges, row, 0, 1, 2 ); + row++; + myCreateFaces = new QCheckBox( tr("CREATE_FACES"), GroupC1 ); + argGroupLayout->addWidget( myCreateFaces, row, 0, 1, 2 ); + row++; + myConsiderInternalFaces = new QCheckBox( tr("CONSIDER_INTERNAL_FACES"), GroupC1 ); + argGroupLayout->addWidget( myConsiderInternalFaces, row, 0, 1, 2 ); + row++; + myUseThresholdForInternalFaces = new QCheckBox( tr("USE_THRESHOLD_FOR_INTERNAL_FACES"), GroupC1 ); + argGroupLayout->addWidget( myUseThresholdForInternalFaces, row, 0, 1, 2 ); + row++; + mySetQuanta = new QCheckBox( tr("SET_QUANTA"), GroupC1 ); + argGroupLayout->addWidget( mySetQuanta, row, 0, 1, 2 ); + row++; + + argGroupLayout->addWidget( new QLabel( tr("QUANTA_VALUE"), GroupC1 ), row, 0 ); + myQuanta = new SMESHGUI_SpinBox( GroupC1 ); + myQuanta->setAcceptNames( false ); + myQuanta->RangeStepAndValidator( 1e-6, 1, 0.05, "length_precision" ); + myQuanta->setEnabled(false); + argGroupLayout->addWidget( myQuanta, row, 1 ); + row++; + + // 3) Grid definition QTabWidget* tabWdg = new QTabWidget( fr ); myAxisTabs[ 0 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 0 ); myAxisTabs[ 1 ] = new StdMeshersGUI::GridAxisTab( tabWdg, 1 ); @@ -619,10 +851,160 @@ QFrame* StdMeshersGUI_CartesianParamCreator::buildFrame() tabWdg->addTab( myAxisTabs[ 1 ], tr( "AXIS_Y" ) ); tabWdg->addTab( myAxisTabs[ 2 ], tr( "AXIS_Z" ) ); argGroupLayout->addWidget( tabWdg, row, 0, 1, 2 ); + row++; + + QPixmap aPix = SMESHGUI::resourceMgr()->loadPixmap("SMESH", tr("ICON_SELECT")); + + // 4) Fixed point + myFixedPointGrp = new QGroupBox( tr("FIXED_POINT"), fr ); + myFixedPointGrp->setCheckable( true ); + //QPushButton* pointBtn = new QPushButton( QIcon(aPix), "", myFixedPointGrp ); + QLabel* pXLbl = new QLabel( tr("SMESH_X"), myFixedPointGrp ); + QLabel* pYLbl = new QLabel( tr("SMESH_Y"), myFixedPointGrp ); + QLabel* pZLbl = new QLabel( tr("SMESH_Z"), myFixedPointGrp ); + for ( int i = 0; i < 3; ++i ) + { + myPointSpin[i] = new SMESHGUI_SpinBox( myFixedPointGrp ); + myPointSpin[i]->RangeStepAndValidator( -1e20, 1e20, 10 ); + myPointSpin[i]->SetValue( 0. ); + } + QHBoxLayout* aFixedPointLay = new QHBoxLayout( myFixedPointGrp ); + aFixedPointLay->addWidget( pXLbl, 0, Qt::AlignRight ); + aFixedPointLay->addWidget( myPointSpin[0], 1 ); + aFixedPointLay->addWidget( pYLbl, 0, Qt::AlignRight ); + aFixedPointLay->addWidget( myPointSpin[1], 1 ); + aFixedPointLay->addWidget( pZLbl, 0, Qt::AlignRight ); + aFixedPointLay->addWidget( myPointSpin[2], 1 ); + argGroupLayout->addWidget( myFixedPointGrp, row, 0, 1, 2 ); + row++; + + // 5) Axes direction + QGroupBox* axesDirGrp = new QGroupBox( tr("AXES_DIRECTION"), fr ); + QGridLayout* axisDirLay = new QGridLayout( axesDirGrp ); + axisDirLay->setSpacing( SPACING ); + axisDirLay->setMargin( MARGIN ); + axisDirLay->setColumnStretch( 0, 2 ); + // is orthogonal + myOrthogonalChk = new QCheckBox( tr("ORTHOGONAL_AXES"), axesDirGrp ); + axisDirLay->addWidget( myOrthogonalChk, 0, 0, 1, 7 ); + // axes + QLabel* axisLbl[3]; + axisLbl[0] = new QLabel( tr( "AXIS_X"), axesDirGrp ); + axisLbl[1] = new QLabel( tr( "AXIS_Y"), axesDirGrp ); + axisLbl[2] = new QLabel( tr( "AXIS_Z"), axesDirGrp ); + QLabel* dLbl[3]; + myAxisBtnGrp = new QButtonGroup( axesDirGrp ); + // get spin width + const char * const precisionType = "len_tol_precision"; + int minWidth = getMinWidth( precisionType ); + for ( int i = 0; i < 3; ++i ) + { + QPushButton* axisBtn = new QPushButton( QIcon(aPix), "", axesDirGrp ); + axisBtn->setCheckable( true ); + myAxisBtnGrp->addButton( axisBtn, i ); + myXDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp ); + myYDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp ); + myZDirSpin[i] = new SMESHGUI_SpinBox( axesDirGrp ); + myXDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, precisionType ); + myYDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, precisionType ); + myZDirSpin[i]->RangeStepAndValidator( -1, 1, 0.1, precisionType ); + myXDirSpin[i]->setMinimumWidth( minWidth ); + myYDirSpin[i]->setMinimumWidth( minWidth ); + myZDirSpin[i]->setMinimumWidth( minWidth ); + dLbl[0] = new QLabel( tr("SMESH_DX"), axesDirGrp ); + dLbl[1] = new QLabel( tr("SMESH_DY"), axesDirGrp ); + dLbl[2] = new QLabel( tr("SMESH_DZ"), axesDirGrp ); + axisDirLay->addWidget( axisLbl[i], i+1, 0 ); + axisDirLay->addWidget( axisBtn, i+1, 1 ); + axisDirLay->addWidget( dLbl[0], i+1, 2 ); + axisDirLay->addWidget( dLbl[1], i+1, 4 ); + axisDirLay->addWidget( dLbl[2], i+1, 6 ); + axisDirLay->addWidget( myXDirSpin[i], 1, 3+i*2 ); + axisDirLay->addWidget( myYDirSpin[i], 2, 3+i*2 ); + axisDirLay->addWidget( myZDirSpin[i], 3, 3+i*2 ); + } + axisDirLay->setColumnStretch( 3, 10 ); + axisDirLay->setColumnStretch( 5, 10 ); + axisDirLay->setColumnStretch( 7, 10 ); + + // set optimal axes + QPushButton* optimBtn = new QPushButton( tr("OPTIMAL_AXES"), axesDirGrp ); + QPushButton* resetBtn = new QPushButton( tr("RESET_AXES"), axesDirGrp ); + axisDirLay->addWidget( optimBtn, 4, 0, 1, 4 ); + axisDirLay->addWidget( resetBtn, 4, 4, 1, 4 ); + + argGroupLayout->addWidget( axesDirGrp, row, 0, 1, 2 ); + row++; + + // Signals + + LightApp_SelectionMgr* selMgr = SMESH::GetSelectionMgr( SMESHGUI::GetSMESHGUI() ); + + connect( selMgr, SIGNAL( currentSelectionChanged()), SLOT( onSelectionChange())); + connect( myOrthogonalChk, SIGNAL( toggled(bool)), SLOT( onOrthogonalAxes(bool))); + connect( optimBtn, SIGNAL( clicked(bool)), SLOT( onOptimalAxes(bool))); + connect( resetBtn, SIGNAL( clicked(bool)), SLOT( onResetAxes(bool))); + connect( myConsiderInternalFaces, SIGNAL( toggled(bool)), + myUseThresholdForInternalFaces, SLOT( setEnabled(bool))); + connect( mySetQuanta, SIGNAL( clicked(bool)), SLOT( onSetQuanta(bool)) ); + for ( int i = 0; i < 3; ++i ) + { + connect( myXDirSpin[i], SIGNAL(valueChanged (const QString&)), + this, SLOT (onAxisDirChange(const QString&)) ); + connect( myYDirSpin[i], SIGNAL(valueChanged (const QString&)), + this, SLOT (onAxisDirChange(const QString&)) ); + connect( myZDirSpin[i], SIGNAL(valueChanged (const QString&)), + this, SLOT (onAxisDirChange(const QString&)) ); + connect( myAxisTabs[i], SIGNAL(gridModeChanged(int)), + this, SLOT (onGridModeChanged(int))); + } + + // Show axes + myAxesLen = 120; // default trihedron size is 100 + myOrigin[0] = myOrigin[1] = myOrigin[2] = 0.; + TopoDS_Shape shape; + QString shapeEntry = getMainShapeEntry(); + if ( !shapeEntry.isEmpty() ) + { + // find origin + GEOM::GEOM_Object_var geomObj = SMESH::EntryToInterface( shapeEntry ); + if ( GEOMBase::GetShape( geomObj, shape ) && !shape.IsNull()) + { + Bnd_Box box; + BRepBndLib::Add( shape, box ); + double max[3]; + if ( !box.IsVoid() ) + { + box.Get( myOrigin[0], myOrigin[1], myOrigin[2], max[0], max[1], max[2] ); + gp_Pnt o( myOrigin[0], myOrigin[1], myOrigin[2] ); + gp_Pnt x( max[0], max[1], max[2] ); + myAxesLen = o.Distance( x ); + + double step = 1e20; + while ( step > myAxesLen / 5 ) + step /= 10; + myPointSpin[0]->SetStep( step ); + myPointSpin[1]->SetStep( step ); + myPointSpin[2]->SetStep( step ); + } + } + } + myAxisBtnGrp->button(0)->setEnabled( !shape.IsNull() ); + myAxisBtnGrp->button(1)->setEnabled( !shape.IsNull() ); + myAxisBtnGrp->button(2)->setEnabled( !shape.IsNull() ); + optimBtn->setEnabled( !shape.IsNull() ); + + updateAxesPreview(); return fr; } +//================================================================================ +/*! + * \brief Transfer parameters from hypothesis to widgets + */ +//================================================================================ + void StdMeshersGUI_CartesianParamCreator::retrieveParams() const { StdMeshers::StdMeshers_CartesianParameters3D_var h = @@ -637,6 +1019,16 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const else myThreshold->setText( varName ); + myAddEdges->setChecked( h->GetToAddEdges() ); + myCreateFaces->setChecked( h->GetToCreateFaces() ); + myConsiderInternalFaces->setChecked( h->GetToConsiderInternalFaces() ); + myUseThresholdForInternalFaces->setChecked( h->GetToUseThresholdForInternalFaces() ); + mySetQuanta->setChecked( h->GetToUseQuanta() ); + myQuanta->setValue( h->GetQuanta() ); + if (h->GetToUseQuanta()) + myQuanta->setEnabled(true); + + // grid definition for ( int ax = 0; ax < 3; ++ax ) { if ( h->IsGridBySpacing( ax )) @@ -652,10 +1044,62 @@ void StdMeshersGUI_CartesianParamCreator::retrieveParams() const myAxisTabs[ax]->setCoordinates( coords ); } } + + // fixed point + SMESH::PointStruct fp; + StdMeshersGUI_CartesianParamCreator* me = (StdMeshersGUI_CartesianParamCreator*) this; + if ( h->GetFixedPoint( fp )) + { + me->myPointSpin[0]->SetValue( fp.x ); + me->myPointSpin[1]->SetValue( fp.y ); + me->myPointSpin[2]->SetValue( fp.z ); + setText( getVariableName("GetFixedPoint"), &me->myPointSpin[0] ); + myFixedPointGrp->setChecked( true ); + } + else + { + myFixedPointGrp->setChecked( false ); + } + + // axes directions + SMESHGUI_SpinBox** spins[3] = { &me->myXDirSpin[0], &me->myYDirSpin[0], &me->myZDirSpin[0] }; + SMESH::DirStruct axisDir[3]; + h->GetAxesDirs( axisDir[0], + axisDir[1], + axisDir[2]); + QString vars = getVariableName("GetAxesDirs"); + for ( int i = 0; i < 3; ++i ) + { + spins[i][0]->SetValue( axisDir[i].PS.x ); + spins[i][1]->SetValue( axisDir[i].PS.y ); + spins[i][2]->SetValue( axisDir[i].PS.z ); + setText( vars, spins[i] ); + + // cut off 3 used vars + if ( !vars.isEmpty() ) + { + int ind = -1; + for ( int j = 0; j < 3; ++j ) + if (( ind = vars.indexOf(':', ind+1 )) < 0 ) + break; + if ( ind < 0 ) + vars.clear(); + else + vars.remove( 0, ind+1 ); + } + } + if ( dlg() ) - dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), dlg()->minimumSizeHint().height() ); + dlg()->setMinimumSize( dlg()->minimumSizeHint().width(), + dlg()->minimumSizeHint().height() ); } +//================================================================================ +/*! + * \brief Transfer parameters from widgets to hypothesis + */ +//================================================================================ + QString StdMeshersGUI_CartesianParamCreator::storeParams() const { StdMeshers::StdMeshers_CartesianParameters3D_var h = @@ -664,11 +1108,19 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const try { if( isCreation() ) - SMESH::SetName( SMESH::FindSObject( h ), myName->text().toLatin1().constData() ); + SMESH::SetName( SMESH::FindSObject( h ), myName->text().toUtf8().constData() ); + // threshold h->SetVarParameter( myThreshold->text().toLatin1().constData(), "SetSizeThreshold" ); h->SetSizeThreshold( myThreshold->text().toDouble() ); - + h->SetToAddEdges( myAddEdges->isChecked() ); + h->SetToCreateFaces( myCreateFaces->isChecked() ); + h->SetToConsiderInternalFaces( myConsiderInternalFaces->isChecked() ); + h->SetToUseThresholdForInternalFaces( myUseThresholdForInternalFaces->isChecked() ); + h->SetToUseQuanta( mySetQuanta->isChecked() ); + h->SetQuanta( myQuanta->text().toDouble() ); + + // grid for ( int ax = 0; ax < 3; ++ax ) { if ( myAxisTabs[ax]->isGridBySpacing()) @@ -684,6 +1136,40 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const h->SetGrid( coords, ax ); } } + + // fixed point + QStringList params; + params << myPointSpin[0]->text(); + params << myPointSpin[1]->text(); + params << myPointSpin[2]->text(); + h->SetVarParameter( params.join(":").toUtf8().constData(), "SetFixedPoint" ); + params.clear(); + + SMESH::PointStruct ps; + ps.x = myPointSpin[0]->GetValue(); + ps.y = myPointSpin[1]->GetValue(); + ps.z = myPointSpin[2]->GetValue(); + h->SetFixedPoint( ps, !myFixedPointGrp->isEnabled() || !myFixedPointGrp->isChecked() ); + + // axes directions + SMESHGUI_SpinBox* const * spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + for ( int ax = 0; ax < 3; ++ax ) + { + params << spins[ax][0]->text(); + params << spins[ax][1]->text(); + params << spins[ax][2]->text(); + } + h->SetVarParameter( params.join(":").toUtf8().constData(), "SetAxesDirs" ); + + SMESH::DirStruct axDir[3]; + for ( int ax = 0; ax < 3; ++ax ) + { + axDir[ax].PS.x = spins[ax][0]->GetValue(); + axDir[ax].PS.y = spins[ax][1]->GetValue(); + axDir[ax].PS.z = spins[ax][2]->GetValue(); + } + h->SetAxesDirs( axDir[0], axDir[1], axDir[2] ); + } catch(const SALOME::SALOME_Exception& ex) { @@ -692,7 +1178,312 @@ QString StdMeshersGUI_CartesianParamCreator::storeParams() const return ""; } +//================================================================================ +/*! + * \brief Returns a name of help page + */ +//================================================================================ + QString StdMeshersGUI_CartesianParamCreator::helpPage() const { - return "cartesian_algo_page.html#cartesian_hyp_anchor"; + return "cartesian_algo.html#cartesian-hyp-anchor"; +} + +//================================================================================ +/*! + * \brief Show axes if they are OK + */ +//================================================================================ + +bool StdMeshersGUI_CartesianParamCreator::updateAxesPreview() +{ + bool isOk = true; + gp_Ax1 axes[3]; + SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + for ( int i = 0; i < 3 && isOk; ++i ) + { + gp_XYZ dir( spins[i][0]->GetValue(), + spins[i][1]->GetValue(), + spins[i][2]->GetValue()); + if (( isOk = ( dir.Modulus() > 1e-100 ))) + axes[i].SetDirection( gp_Dir( dir )); + + axes[i].SetLocation ( gp_Pnt( myOrigin[0], + myOrigin[1], + myOrigin[2])); + } + gp_Vec norm01 = axes[0].Direction().XYZ() ^ axes[1].Direction().XYZ(); + gp_Vec norm12 = axes[1].Direction().XYZ() ^ axes[2].Direction().XYZ(); + if ( isOk ) + isOk = ( !axes[0].Direction().IsParallel( axes[1].Direction(), theAngTol ) && + !axes[1].Direction().IsParallel( axes[2].Direction(), theAngTol ) && + !axes[2].Direction().IsParallel( axes[0].Direction(), theAngTol ) && + !norm01.IsParallel( norm12, theAngTol ) ); + if ( isOk ) + myAxesPreview->SetArrows( axes, myAxesLen ); + + myAxesPreview->SetVisibility( isOk ); + + return isOk; +} + +//================================================================================ +/*! + * \brief Makes axes orthogonal if necessary + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onOrthogonalAxes(bool isOrtho) +{ + if ( !isOrtho ) + { + updateAxesPreview(); + return; + } + + std::multimap< int, int > ageOfAxis; + gp_XYZ dirs[3]; + SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + int nbOk = 0, isOk; + for ( int iAx = 0; iAx < 3; ++iAx ) + { + dirs[iAx].SetCoord( spins[iAx][0]->GetValue(), + spins[iAx][1]->GetValue(), + spins[iAx][2]->GetValue()); + if (( isOk = ( dirs[iAx].Modulus() > 1e-100 ))) + ageOfAxis.insert( std::make_pair( myDirTic[iAx], iAx )); + else + ageOfAxis.insert( std::make_pair( -1, iAx )); + nbOk += isOk; + } + switch ( nbOk ) + { + case 0: + { + dirs[0].SetCoord( 1, 0, 0 ); + dirs[1].SetCoord( 0, 1, 0 ); + dirs[2].SetCoord( 0, 0, 1 ); + break; + } + case 1: + { + int iOk = ageOfAxis.rbegin()->second; + get3Dirs( iOk, dirs ); + break; + } + default: + std::multimap< int, int >::reverse_iterator ag2ax = ageOfAxis.rbegin(); + int iOk1 = ag2ax->second; + int iOk2 = (++ag2ax)->second; + int iKo = (++ag2ax)->second; + if ( gp_Vec( dirs[ iOk1 ]).IsParallel( gp_Vec( dirs[ iOk2 ]), theAngTol )) + std::swap( iOk2, iKo ); + if ( gp_Vec( dirs[ iOk1 ]).IsParallel( gp_Vec( dirs[ iOk2 ]), theAngTol )) + { + get3Dirs( iOk1, dirs ); + } + else + { + dirs[ iKo ] = dirs[ iOk1 ] ^ dirs[ iOk2 ]; + dirs[ iOk2 ] = dirs[ iKo ] ^ dirs[ iOk1 ]; + if ( ( iOk1+1 ) % 3 != iOk2 ) + dirs[ iKo ].Reverse(); + } + } + + for ( int iAx = 0; iAx < 3; ++iAx ) + { + double size = dirs[iAx].Modulus(); + if ( size > 1e-100 ) + dirs[iAx] /= size; + for (int i = 0; i < 3; ++i ) + { + bool isBlocked = spins[iAx][i]->blockSignals( true ); + spins[iAx][i]->SetValue( dirs[iAx].Coord( i+1 )); + spins[iAx][i]->blockSignals( isBlocked ); + } + } + + updateAxesPreview(); +} + +//================================================================================ +/*! + * \brief Increment myDirTic and update the preview of axes + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onAxisDirChange(const QString&) +{ + QObject* changedSpin = sender(); + SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + for ( int iAx = 0; iAx < 3; ++iAx ) + if ( spins[iAx][0] == changedSpin || + spins[iAx][1] == changedSpin || + spins[iAx][2] == changedSpin ) + { + myDirTic[ iAx ] = 1 + Max( Max( myDirTic[0], myDirTic[1] ), myDirTic[2] ); + break; + } + + onOrthogonalAxes( myOrthogonalChk->isChecked() ); +} + +//================================================================================ +/*! + * \brief Sets axis direction by a selected EDGE + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onSelectionChange() +{ + int iAxis = myAxisBtnGrp->checkedId(); + if ( iAxis < 0 ) + return; + + SALOME_ListIO aList; + SMESHGUI::GetSMESHGUI()->selectionMgr()->selectedObjects(aList); + + TopoDS_Shape edge, shape; + for( SALOME_ListIteratorOfListIO anIt( aList ); anIt.More(); anIt.Next() ) + { + GEOM::GEOM_Object_var go = SMESH::IObjectToInterface( anIt.Value() ); + if ( GEOMBase::GetShape( go, shape ) && shape.ShapeType() == TopAbs_EDGE ) + { + if ( !edge.IsNull() ) + return; // several EDGEs selected + edge = shape; + } + } + if ( edge.IsNull() ) + return; + + TopoDS_Shape vv[2]; + TopoDS_Iterator vIt( edge ); + for ( ; vIt.More() && vv[1].IsNull(); vIt.Next() ) + vv[ !vv[0].IsNull() ] = vIt.Value(); + + gp_Pnt pp[2]; + if ( !GEOMBase::VertexToPoint( vv[0], pp[0] ) || + !GEOMBase::VertexToPoint( vv[1], pp[1] )) + return; + + SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + + gp_Vec newDir( pp[0], pp[1] ); + gp_Vec curDir( spins[iAxis][0]->GetValue(), + spins[iAxis][1]->GetValue(), + spins[iAxis][2]->GetValue()); + if ( newDir * curDir < 0 ) + newDir.Reverse(); + + double size = newDir.Magnitude(); + if ( size < 1e-100 ) + return; + newDir /= size; + + for (int i = 0; i < 3; ++i ) + { + bool isBlocked = spins[iAxis][i]->blockSignals( true ); + spins[iAxis][i]->SetValue( newDir.Coord( i+1 )); + spins[iAxis][i]->blockSignals( isBlocked ); + } + myDirTic[ iAxis ] = 1 + Max( Max( myDirTic[0], myDirTic[1] ), myDirTic[2] ); + + onOrthogonalAxes( myOrthogonalChk->isChecked() ); +} + +//================================================================================ +/*! + * \brief Sets axes at which number of hexahedra is maximal + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onOptimalAxes(bool) +{ + StdMeshers::StdMeshers_CartesianParameters3D_var h = + StdMeshers::StdMeshers_CartesianParameters3D::_narrow( hypothesis() ); + if ( h->_is_nil() ) + return; + + QString shapeEntry = getMainShapeEntry(); + if ( shapeEntry.isEmpty() ) + return; + + GEOM::GEOM_Object_var geomObj = SMESH::EntryToInterface( shapeEntry ); + if ( geomObj->_is_nil() ) + return; + + SMESH::DirStruct axDirs[3]; + h->ComputeOptimalAxesDirs( geomObj, + myOrthogonalChk->isChecked(), + axDirs[0], + axDirs[1], + axDirs[2]); + + SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + for ( int iAx = 0; iAx < 3; ++iAx ) + { + double coords[3] = { axDirs[iAx].PS.x, axDirs[iAx].PS.y, axDirs[iAx].PS.z }; + for (int i = 0; i < 3; ++i ) + { + bool isBlocked = spins[iAx][i]->blockSignals( true ); + spins[iAx][i]->SetValue( coords[ i ]); + spins[iAx][i]->blockSignals( isBlocked ); + } + } + updateAxesPreview(); +} + +//================================================================================ +/*! + * \brief Sets axes || to the axes of global CS + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onResetAxes(bool) +{ + SMESHGUI_SpinBox** spins[3] = { &myXDirSpin[0], &myYDirSpin[0], &myZDirSpin[0] }; + for ( int iAx = 0; iAx < 3; ++iAx ) + { + for (int i = 0; i < 3; ++i ) + { + bool isBlocked = spins[iAx][i]->blockSignals( true ); + spins[iAx][i]->SetValue( iAx == i ? 1. : 0. ); + spins[iAx][i]->blockSignals( isBlocked ); + } + myDirTic[iAx] = 0; + } + updateAxesPreview(); +} + +//================================================================================ +/*! + * \brief SLOT called when the grid definition mode changes + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onGridModeChanged(int) +{ + bool haveSpacing = ( myAxisTabs[0]->isGridBySpacing() || + myAxisTabs[1]->isGridBySpacing() || + myAxisTabs[2]->isGridBySpacing() ); + + myFixedPointGrp->setEnabled( haveSpacing ); +} + +//================================================================================ +/*! + * \brief Enable and disable quanta value combo box + */ +//================================================================================ + +void StdMeshersGUI_CartesianParamCreator::onSetQuanta(bool) +{ + StdMeshers::StdMeshers_CartesianParameters3D_var h = + StdMeshers::StdMeshers_CartesianParameters3D::_narrow( hypothesis() ); + if ( h->_is_nil() ) + return; + + myQuanta->setEnabled( mySetQuanta->isChecked() ); }