From 2ad752b10cb247a162b27593121a7ae13173258d Mon Sep 17 00:00:00 2001 From: asl Date: Wed, 23 Nov 2005 09:07:44 +0000 Subject: [PATCH] PAL8238 - Hypothesis for non-regular 1D meshing --- src/SMESHGUI/Makefile.in | 19 +- src/SMESHGUI/SMESHGUI_FunctionPreview.cxx | 252 ++++++++++ src/SMESHGUI/SMESHGUI_FunctionPreview.h | 54 +++ src/SMESHGUI/SMESHGUI_aParameter.cxx | 323 ++++++++++--- src/SMESHGUI/SMESHGUI_aParameter.h | 50 +- src/SMESHGUI/SMESHGUI_aParameterDlg.cxx | 59 ++- src/SMESHGUI/SMESHGUI_aParameterDlg.h | 5 + src/StdMeshers/Makefile.in | 3 +- .../StdMeshers_NumberOfSegments.cxx | 137 ++++-- .../StdMeshers_NumberOfSegments.hxx | 2 +- src/StdMeshers/StdMeshers_Regular_1D.cxx | 456 +++++++++++------- src/StdMeshersGUI/Makefile.in | 3 +- .../StdMeshersGUI_CreateHypothesisDlg.cxx | 43 +- .../StdMeshersGUI_CreateHypothesisDlg.h | 2 + .../StdMeshersGUI_Parameters.cxx | 12 +- 15 files changed, 1092 insertions(+), 328 deletions(-) create mode 100644 src/SMESHGUI/SMESHGUI_FunctionPreview.cxx create mode 100644 src/SMESHGUI/SMESHGUI_FunctionPreview.h diff --git a/src/SMESHGUI/Makefile.in b/src/SMESHGUI/Makefile.in index 565329b66..07a3a7211 100644 --- a/src/SMESHGUI/Makefile.in +++ b/src/SMESHGUI/Makefile.in @@ -44,7 +44,8 @@ EXPORT_HEADERS= SMESHGUI_Swig.hxx \ SMESHGUI_SpinBox.h \ SMESHGUI_aParameter.h \ SMESHGUI_aParameterDlg.h \ - SMESHGUI_Selection.h + SMESHGUI_Selection.h \ + SMESHGUI_FunctionPreview.h # .po files to transform in .qm PO_FILES = \ @@ -111,7 +112,8 @@ LIB_SRC = SMESHGUI.cxx \ SMESHGUI_Dialog.cxx \ SMESHGUI_MeshDlg.cxx \ SMESHGUI_MeshOp.cxx \ - SMESHGUI_Displayer.cxx + SMESHGUI_Displayer.cxx \ + SMESHGUI_FunctionPreview.cxx LIB_MOC = \ SMESHGUI.h \ @@ -159,7 +161,8 @@ LIB_MOC = \ SMESHGUI_SelectionOp.h \ SMESHGUI_Dialog.h \ SMESHGUI_MeshDlg.h \ - SMESHGUI_MeshOp.h + SMESHGUI_MeshOp.h \ + SMESHGUI_FunctionPreview.h LIB_CLIENT_IDL = SALOME_Exception.idl \ @@ -186,13 +189,17 @@ LIB_SERVER_IDL = CPPFLAGS += $(QT_INCLUDES) $(VTK_INCLUDES) $(OGL_INCLUDES) $(OCC_INCLUDES) $(PYTHON_INCLUDES) \ -I${KERNEL_ROOT_DIR}/include/salome -I${GUI_ROOT_DIR}/include/salome \ - -I${GEOM_ROOT_DIR}/include/salome $(BOOST_CPPFLAGS) + -I${GEOM_ROOT_DIR}/include/salome $(BOOST_CPPFLAGS) -I${QWTHOME}/include CXXFLAGS += -I${KERNEL_ROOT_DIR}/include/salome -I${GUI_ROOT_DIR}/include/salome \ - -I${GEOM_ROOT_DIR}/include/salome + -I${GEOM_ROOT_DIR}/include/salome -I${QWTHOME}/include -LDFLAGS += -lSMESHObject -lSMESHFiltersSelection -lSMDS -lSMESHControls -lDlgRef $(OCC_KERNEL_LIBS) -lTKBO -L${KERNEL_ROOT_DIR}/lib/salome -L${GUI_ROOT_DIR}/lib/salome -lVTKViewer -lSalomeApp -lSalomePrs -lSalomeNS -lSalomeLifeCycleCORBA -lOpUtil -lSalomeObject -lEvent -lSALOMELocalTrace -lSVTK -lOCCViewer -L${GEOM_ROOT_DIR}/lib/salome -lGEOM -lGEOMClient -lGEOMBase -lGEOMObject -lGEOMFiltersSelection +LDFLAGS += -lSMESHObject -lSMESHFiltersSelection -lSMDS -lSMESHControls -lDlgRef \ + $(OCC_KERNEL_LIBS) -lTKBO -lTKAdvTools -L${KERNEL_ROOT_DIR}/lib/salome -L${GUI_ROOT_DIR}/lib/salome \ + -lVTKViewer -lSalomeApp -lSalomePrs -lSalomeNS -lSalomeLifeCycleCORBA -lOpUtil -lSalomeObject \ + -lEvent -lSALOMELocalTrace -lSVTK -lOCCViewer -L${GEOM_ROOT_DIR}/lib/salome -lGEOM -lGEOMClient \ + -lGEOMBase -lGEOMObject -lGEOMFiltersSelection LDFLAGSFORBIN += $(LDFLAGS) diff --git a/src/SMESHGUI/SMESHGUI_FunctionPreview.cxx b/src/SMESHGUI/SMESHGUI_FunctionPreview.cxx new file mode 100644 index 000000000..2add30176 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_FunctionPreview.cxx @@ -0,0 +1,252 @@ + +#include "SMESHGUI_FunctionPreview.h" +#include +#include +#include +#include +#include +#include + +SMESHGUI_FunctionPreview::SMESHGUI_FunctionPreview( QWidget* p ) +: QwtPlot( p ), + myXmin( 0.0 ), + myXmax( 1.0 ), + myPoints( 50 ), + myIsTable( false ), + myVars( 1, 1 ), + myValues( 1, 1 ), + myIsExp( false ), + myIsDone( true ) +{ + myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" ); + myCurve = insertCurve( QString() ); + setCurvePen( myCurve, QPen( Qt::red, 1 ) ); +} + +SMESHGUI_FunctionPreview::~SMESHGUI_FunctionPreview() +{ +} + +bool SMESHGUI_FunctionPreview::isTableFunc() const +{ + return myIsTable; +} + +void SMESHGUI_FunctionPreview::tableFunc( SMESH::double_array& f ) const +{ + f = myTableFunc; +} + +QString SMESHGUI_FunctionPreview::function() const +{ + return myFunction; +} + +void SMESHGUI_FunctionPreview::interval( double& xmin, double& xmax ) const +{ + xmin = myXmin; + xmax = myXmax; +} + +int SMESHGUI_FunctionPreview::pointsCount() const +{ + return myPoints; +} + +void SMESHGUI_FunctionPreview::setIsExp( const bool exp, const bool update ) +{ + myIsExp = exp; + if( update ) + repaint(); +} + +bool SMESHGUI_FunctionPreview::setParams( const QString& func, + const double xmin, const double xmax, + const int points, const bool update ) +{ + myIsTable = false; + myTableFunc = SMESH::double_array(); + myFunction = func.isEmpty() ? "0" : func; + myXmin = xmin; + myXmax = xmax0 ? points : 2; + bool res = init( func ); + if( update ) + repaint(); + return res; +} + +bool SMESHGUI_FunctionPreview::setParams( const SMESH::double_array& f, const double xmin, const double xmax, + const bool update ) +{ + myIsTable = true; + myTableFunc = f; + if( myTableFunc.length()%2==1 ) + myTableFunc.length( myTableFunc.length()-1 ); + + myFunction = "0"; + myXmin = xmin; + myXmax = xmax0; +} + +bool SMESHGUI_FunctionPreview::createTable( SMESH::double_array& func ) +{ + if( myExpr.IsNull() ) + { + func.length( 0 ); + return false; + } + + double d = (myXmax-myXmin)/double(myPoints-1); + func.length( 2*myPoints ); + int err = 0; + for( int i=0, j=0; imax_y ) + max_y = y[i]; + if( i==0 || x[i]max_x ) + max_x = x[i]; + } + + setAxisScale( curveXAxis( myCurve ), min_x, max_x ); + setAxisScale( curveYAxis( myCurve ), min_y, max_y ); + setCurveData( myCurve, x, y, size ); + delete[] x; + delete[] y; + + replot(); + QwtPlot::drawContents( p ); +} + +bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr ) +{ + Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr ); + if( !sub.IsNull() ) + return sub->GetName()=="t"; + + bool res = true; + for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ ) + { + Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i ); + Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub ); + if( !name.IsNull() ) + { + if( name->GetName()!="t" ) + res = false; + } + else + res = isCorrectArg( sub ); + } + return res; +} + +bool SMESHGUI_FunctionPreview::init( const QString& str ) +{ + myExpr = ExprIntrp_GenExp::Create(); + myExpr->Process( ( Standard_CString ) str.latin1() ); + + bool syntax = false, args = false; + if( myExpr->IsDone() ) + { + syntax = true; + args = isCorrectArg( myExpr->Expression() ); + } + + bool res = syntax && args; + if( !res ) + myExpr.Nullify(); + return res; +} + +double SMESHGUI_FunctionPreview::funcValue( const double t, bool& ok ) +{ + if( myExpr.IsNull() ) + return 0; + + myValues.ChangeValue( 1 ) = t; + + ok = true; + double res = calc( ok ); + + return res; +} + +double SMESHGUI_FunctionPreview::calc( bool& ok ) +{ + OSD::SetSignal( true ); + double res = 0.0; + + CASCatch_CatchSignals aCatchSignals; + aCatchSignals.Activate(); + + ok = true; + CASCatch_TRY { + res = myExpr->Expression()->Evaluate( myVars, myValues ); + } + CASCatch_CATCH(CASCatch_Failure) { + aCatchSignals.Deactivate(); + Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught(); + ok = false; + res = 0.0; + } + aCatchSignals.Deactivate(); + return res; +} + +bool SMESHGUI_FunctionPreview::isDone() const +{ + return myIsDone; +} diff --git a/src/SMESHGUI/SMESHGUI_FunctionPreview.h b/src/SMESHGUI/SMESHGUI_FunctionPreview.h new file mode 100644 index 000000000..d77126e4c --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_FunctionPreview.h @@ -0,0 +1,54 @@ + +#ifndef SMESHGUI_FUNCTION_PREVIEW_HEADER +#define SMESHGUI_FUNCTION_PREVIEW_HEADER + +#include "qwt_plot.h" +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) +#include +#include +#include + +class SMESHGUI_FunctionPreview : public QwtPlot +{ + Q_OBJECT + +public: + SMESHGUI_FunctionPreview( QWidget* ); + virtual ~SMESHGUI_FunctionPreview(); + + QString function() const; + bool isTableFunc() const; + void tableFunc( SMESH::double_array& ) const; + void interval( double&, double& ) const; + int pointsCount() const; + bool isDone() const; + + bool setParams( const QString&, const double = 0.0, const double = 1.0, const int = 50, const bool = true ); + bool setParams( const SMESH::double_array&, const double = 0.0, const double = 1.0, const bool = true ); + void setIsExp( const bool, const bool = true ); + +protected: + virtual bool init( const QString& ); + virtual double funcValue( const double, bool& ); + virtual bool createTable( SMESH::double_array& ); + virtual void drawContents( QPainter* ); + +private: + double calc( bool& ); + +private: + QString myFunction; + double myXmin, myXmax; + int myPoints; + bool myIsTable; + bool myIsExp; + SMESH::double_array myTableFunc; + long myCurve; + Handle(ExprIntrp_GenExp) myExpr; + Expr_Array1OfNamedUnknown myVars; + TColStd_Array1OfReal myValues; + bool myIsDone; +}; + +#endif diff --git a/src/SMESHGUI/SMESHGUI_aParameter.cxx b/src/SMESHGUI/SMESHGUI_aParameter.cxx index 3e513f04b..65b07e75b 100644 --- a/src/SMESHGUI/SMESHGUI_aParameter.cxx +++ b/src/SMESHGUI/SMESHGUI_aParameter.cxx @@ -40,7 +40,25 @@ #include -SMESHGUI_aParameter::~SMESHGUI_aParameter() {} +SMESHGUI_aParameter::SMESHGUI_aParameter( const QString& label, const bool preview ) +: _needPreview( preview ), + _label(label) +{ +} + +SMESHGUI_aParameter::~SMESHGUI_aParameter() +{ +} + +bool SMESHGUI_aParameter::needPreview() const +{ + return _needPreview; +} + +QString& SMESHGUI_aParameter::Label() +{ + return _label; +} QString SMESHGUI_aParameter::sigValueChanged() const { @@ -54,8 +72,9 @@ QString SMESHGUI_aParameter::sigValueChanged() const SMESHGUI_intParameter::SMESHGUI_intParameter (const int theInitValue, const QString& theLabel, const int theBottom, - const int theTop) - :SMESHGUI_aParameter(theLabel), + const int theTop, + const bool preview ) + :SMESHGUI_aParameter(theLabel, preview), _top(theTop), _bottom(theBottom), _initValue(theInitValue), _newValue( theInitValue ) { @@ -113,8 +132,9 @@ SMESHGUI_doubleParameter::SMESHGUI_doubleParameter (const double theInitValue, const double theBottom, const double theTop, const double theStep, - const int theDecimals) - :SMESHGUI_aParameter(theLabel), + const int theDecimals, + const bool preview ) + :SMESHGUI_aParameter(theLabel, preview), _top(theTop), _bottom(theBottom), _step(theStep), _initValue(theInitValue), _decimals(theDecimals) { @@ -172,8 +192,9 @@ QString SMESHGUI_doubleParameter::sigValueChanged() const // purpose : //================================================================================= SMESHGUI_strParameter::SMESHGUI_strParameter (const QString& theInitValue, - const QString& theLabel) - :SMESHGUI_aParameter(theLabel), + const QString& theLabel, + const bool preview ) + :SMESHGUI_aParameter(theLabel, preview), _initValue(theInitValue) { } @@ -181,6 +202,7 @@ SMESHGUI_aParameter::Type SMESHGUI_strParameter::GetType() const { return SMESHGUI_aParameter::STRING; } + bool SMESHGUI_strParameter::GetNewInt (int & theValue) const { return false; @@ -225,8 +247,8 @@ QString SMESHGUI_strParameter::sigValueChanged() const // class : SMESHGUI_dependParameter // purpose : //================================================================================= -SMESHGUI_dependParameter::SMESHGUI_dependParameter( const QString& label ) -: SMESHGUI_aParameter( label ) +SMESHGUI_dependParameter::SMESHGUI_dependParameter( const QString& label, const bool preview ) +: SMESHGUI_aParameter( label, preview ) { } @@ -250,8 +272,9 @@ SMESHGUI_dependParameter::ShownMap& SMESHGUI_dependParameter::shownMap() //================================================================================= SMESHGUI_enumParameter::SMESHGUI_enumParameter( const QStringList& values, const int initValue, - const QString& label ) -: SMESHGUI_dependParameter( label ), + const QString& label, + const bool preview ) +: SMESHGUI_dependParameter( label, preview ), myInitValue( initValue ), myValue( initValue ), myValues( values ) @@ -329,8 +352,9 @@ QString SMESHGUI_enumParameter::sigValueChanged() const // purpose : //================================================================================= SMESHGUI_boolParameter::SMESHGUI_boolParameter( const bool initValue, - const QString& label ) -: SMESHGUI_dependParameter( label ), + const QString& label, + const bool preview ) +: SMESHGUI_dependParameter( label, preview ), myInitValue( initValue ), myValue( myInitValue ) { @@ -453,8 +477,10 @@ QWidget* SMESHGUI_doubleItem::createEditor() const // class : SMESHGUI_Table // purpose : //================================================================================= -SMESHGUI_Table::SMESHGUI_Table( int numRows, int numCols, QWidget* parent, const char* name ) -: QTable( numRows, numCols, parent, name ) +SMESHGUI_Table::SMESHGUI_Table( const SMESHGUI_tableParameter* tab, int numRows, int numCols, + QWidget* parent, const char* name ) +: QTable( numRows, numCols, parent, name ), + myParam( ( SMESHGUI_tableParameter* )tab ) { } @@ -509,18 +535,99 @@ void SMESHGUI_Table::setValidator( const double minV, const double maxV, const i } } +bool SMESHGUI_Table::eventFilter( QObject* o, QEvent* e ) +{ + if( o && e && e->type()==QEvent::KeyPress ) + { + QKeyEvent* ke = ( QKeyEvent* )e; + if( ke->key()==Qt::Key_Tab || ke->key()==Qt::Key_Backtab || ke->key()==Qt::Key_Return ) + { + keyPressEvent( ke ); + return true; + } + } + + return QTable::eventFilter( o, e ); +} + +void SMESHGUI_Table::keyPressEvent( QKeyEvent* e ) +{ + if( e ) + { + bool shift = ( e->state() & Qt::ShiftButton ); + int col = currentColumn(), row = currentRow(); + if( e->key()==Qt::Key_Tab || e->key()==Qt::Key_Backtab ) + { + if( e->key()==Qt::Key_Tab ) + col++; + else + col--; + if( col<0 ) + { + col = numCols()-1; + row--; + if( row<0 ) + { + col = 0; + row = 0; + } + } + if( col>=numCols() ) + { + col = 0; + row++; + if( row>=numRows() ) + row = numRows()-1; + } + e->accept(); + } + else if( e->key()==Qt::Key_Return ) + { + col = 0; + if( shift ) + row--; + else + row++; + if( row<0 ) + row = 0; + else if( row>=numRows() ) + { + //add row + myParam->onEdit( this, SMESHGUI_TableFrame::ADD_ROW, 1 ); + } + e->accept(); + } + if( e->isAccepted() ) + { + clearSelection(); + setCurrentCell( row, col ); + } + else + QTable::keyPressEvent( e ); + } +} + +QWidget* SMESHGUI_Table::createEditor( int r, int c, bool init ) const +{ + QWidget* w = QTable::createEditor( r, c, init ); + if( w ) + w->installEventFilter( this ); + return w; +} + //================================================================================= // class : SMESHGUI_TableFrame // purpose : //================================================================================= -SMESHGUI_TableFrame::SMESHGUI_TableFrame( QWidget* parent ) +SMESHGUI_TableFrame::SMESHGUI_TableFrame( const SMESHGUI_tableParameter* param, QWidget* parent ) : QFrame( parent ) { QVBoxLayout* main = new QVBoxLayout( this, 0, 0 ); - myTable = new SMESHGUI_Table( 1, 1, this ); + myTable = new SMESHGUI_Table( param, 1, 1, this ); + connect( myTable, SIGNAL( valueChanged( int, int ) ), this, SIGNAL( valueChanged( int, int ) ) ); QFrame* aButFrame = new QFrame( this ); QHBoxLayout* butLay = new QHBoxLayout( aButFrame, 5, 5 ); @@ -616,8 +723,9 @@ void SMESHGUI_TableFrame::onButtonClicked() // purpose : //================================================================================= SMESHGUI_tableParameter::SMESHGUI_tableParameter( const double init, - const QString& label ) -: SMESHGUI_aParameter( label ), + const QString& label, + const bool preview ) +: SMESHGUI_aParameter( label, preview ), myInitValue( init ), myColsInt( 1 ), myRowsInt( 1 ), @@ -630,6 +738,54 @@ SMESHGUI_tableParameter::~SMESHGUI_tableParameter() { } +bool operator<( const QPair& p1, const QPair& p2 ) +{ + return p1.first < p2.first; +} + +void SMESHGUI_tableParameter::sortData( SMESH::double_array& arr ) +{ + QValueList< QPair > aData; + if( arr.length()%2==1 ) + arr.length( arr.length()-1 ); + + int aLen = arr.length(); + for( int i=0; i( arr[2*i], arr[2*i+1] ) ); + + qHeapSort( aData ); + + QValueList< QPair >::const_iterator anIt = aData.begin(), aLast = aData.end(); + QValueList unique_values; + double prev; int i=0; + if( (*anIt).first>0.0 ) + { + unique_values.append( 0.0 ); + unique_values.append( 0.0 ); + i++; prev = 0.0; + } + for( ; anIt!=aLast; anIt++ ) + { + if( i==0 || (*anIt).first>prev ) + { + unique_values.append( (*anIt).first ); + unique_values.append( (*anIt).second ); + i++; + } + prev = (*anIt).first; + } + if( prev<1.0 ) + { + unique_values.append( 1.0 ); + unique_values.append( 0.0 ); + } + + arr.length( unique_values.count() ); + QValueList::const_iterator anIt1 = unique_values.begin(), aLast1 = unique_values.end(); + for( int j=0; anIt1!=aLast1; anIt1++, j++ ) + arr[j] = *anIt1; +} + SMESHGUI_aParameter::Type SMESHGUI_tableParameter::GetType() const { return TABLE; @@ -652,7 +808,7 @@ bool SMESHGUI_tableParameter::GetNewText( QString& ) const QWidget* SMESHGUI_tableParameter::CreateWidget( QWidget* par ) const { - SMESHGUI_TableFrame* t = new SMESHGUI_TableFrame( par ); + SMESHGUI_TableFrame* t = new SMESHGUI_TableFrame( this, par ); connect( t, SIGNAL( toEdit( SMESHGUI_TableFrame::Button, int ) ), this, SLOT ( onEdit( SMESHGUI_TableFrame::Button, int ) ) ); @@ -705,7 +861,7 @@ void SMESHGUI_tableParameter::InitializeWidget( QWidget* w ) const for( int i=0, m=row; iitem( i, j )->setText( QString( "%1" ).arg( myData[row*j+i] ) ); + tab->item( i, j )->setText( QString( "%1" ).arg( myData[col*i+j] ) ); } } @@ -728,11 +884,13 @@ void SMESHGUI_tableParameter::TakeValue( QWidget* w ) void SMESHGUI_tableParameter::data( SMESH::double_array& v ) const { v = myData; + sortData( v ); } void SMESHGUI_tableParameter::setData( const SMESH::double_array& d ) { myData = d; + sortData( myData ); } void SMESHGUI_tableParameter::update( QWidget* w ) const @@ -874,68 +1032,77 @@ void SMESHGUI_tableParameter::onEdit( SMESHGUI_TableFrame::Button b, int n ) { SMESHGUI_TableFrame* fr = ( SMESHGUI_TableFrame* )sender(); SMESHGUI_Table* tab = fr->table(); + onEdit( tab, b, n ); + } +} - switch( b ) - { - case SMESHGUI_TableFrame::ADD_COLUMN: - { - if( !myEditCols || myCols.get() ) - return; - - myColsInt++; update( fr ); - if( n>=0 ) - for( int i=0; i=n; j-- ) - if( j==n ) - tab->setText( i, j, QString( "%1" ).arg( myInitValue ) ); - else - tab->setText( i, j, tab->text( i, j-1 ) ); - break; - } - - case SMESHGUI_TableFrame::REMOVE_COLUMN: - { - if( !myEditCols || myCols.get() || myColsInt<=1 ) - return; +void SMESHGUI_tableParameter::onEdit( SMESHGUI_Table* tab, SMESHGUI_TableFrame::Button b, int n ) +{ + if( !tab ) + return; - if( n>=0 ) - for( int i=0; isetText( i, j, tab->text( i, j+1 ) ); - myColsInt--; update( fr ); + SMESHGUI_TableFrame* fr = dynamic_cast( tab->parent() ); - break; - } + switch( b ) + { + case SMESHGUI_TableFrame::ADD_COLUMN: + { + if( !myEditCols || myCols.get() ) + return; + + myColsInt++; update( fr ); + if( n>=0 ) + for( int i=0; i=n; j-- ) + if( j==n ) + tab->setText( i, j, QString( "%1" ).arg( myInitValue ) ); + else + tab->setText( i, j, tab->text( i, j-1 ) ); + break; + } + + case SMESHGUI_TableFrame::REMOVE_COLUMN: + { + if( !myEditCols || myCols.get() || myColsInt<=1 ) + return; + + if( n>=0 ) + for( int i=0; isetText( i, j, tab->text( i, j+1 ) ); + myColsInt--; update( fr ); - case SMESHGUI_TableFrame::ADD_ROW: - { - if( !myEditRows || myRows.get() ) - return; - - myRowsInt++; update( fr ); - if( n>=0 ) - for( int i=myRowsInt-1; i>=n; i-- ) - for( int j=0; jsetText( i, j, QString( "%1" ).arg( myInitValue ) ); - else - tab->setText( i, j, tab->text( i-1, j ) ); - break; - } + break; + } - case SMESHGUI_TableFrame::REMOVE_ROW: - { - if( !myEditRows || myRows.get() || myRowsInt<=1 ) - return; - - if( n>=0 ) - for( int i=n; isetText( i, j, tab->text( i+1, j ) ); - myRowsInt--; update( fr ); - - break; - } + case SMESHGUI_TableFrame::ADD_ROW: + { + if( !myEditRows || myRows.get() ) + return; + + myRowsInt++; update( fr ); + if( n>=0 ) + for( int i=myRowsInt-1; i>=n; i-- ) + for( int j=0; jsetText( i, j, QString( "%1" ).arg( myInitValue ) ); + else + tab->setText( i, j, tab->text( i-1, j ) ); + break; + } + + case SMESHGUI_TableFrame::REMOVE_ROW: + { + if( !myEditRows || myRows.get() || myRowsInt<=1 ) + return; + + if( n>=0 ) + for( int i=n; isetText( i, j, tab->text( i+1, j ) ); + myRowsInt--; update( fr ); + + break; } } } diff --git a/src/SMESHGUI/SMESHGUI_aParameter.h b/src/SMESHGUI/SMESHGUI_aParameter.h index 8613b50dd..dcd8c7177 100644 --- a/src/SMESHGUI/SMESHGUI_aParameter.h +++ b/src/SMESHGUI/SMESHGUI_aParameter.h @@ -47,7 +47,9 @@ typedef boost::shared_ptr SMESHGUI_aParameterPtr; class SMESHGUI_aParameter { public: - SMESHGUI_aParameter(const QString& label):_label(label) {} + typedef bool (*VALIDATION_FUNC)( SMESHGUI_aParameter* ); + + SMESHGUI_aParameter(const QString& label, const bool = false ); virtual ~SMESHGUI_aParameter(); enum Type { INT, DOUBLE, STRING, ENUM, BOOL, TABLE }; @@ -59,15 +61,18 @@ public: virtual QWidget* CreateWidget( QWidget* ) const = 0; virtual void InitializeWidget( QWidget* ) const = 0; + bool needPreview() const; + /*! * \brief Returns string representation of signal emitted when value in corrsponding widget is changed */ virtual QString sigValueChanged() const; - QString & Label() { return _label; } + QString & Label(); private: QString _label; + bool _needPreview; }; /*! @@ -79,7 +84,8 @@ public: SMESHGUI_intParameter(const int initValue = 0, const QString& label = QString::null, const int bottom = 0, - const int top = 1000); + const int top = 1000, + const bool = false ); int & InitValue() { return _initValue; } int & Top() { return _top; } int & Bottom() { return _bottom; } @@ -109,7 +115,8 @@ public: const double bottom = -1E6, const double top = +1E6, const double step = 1.0, - const int decimals = 3); + const int decimals = 3, + const bool = false); double & InitValue() { return _initValue; } double & Top() { return _top; } double & Bottom() { return _bottom; } @@ -138,7 +145,8 @@ class SMESHGUI_strParameter: public SMESHGUI_aParameter { public: SMESHGUI_strParameter( const QString& initValue = "", - const QString& label = QString::null); + const QString& label = QString::null, + const bool = false ); QString& InitValue() { return _initValue; } virtual Type GetType() const; virtual bool GetNewInt( int & Value ) const; @@ -171,7 +179,7 @@ public: typedef QMap< int, IntList > ShownMap; public: - SMESHGUI_dependParameter( const QString& = QString::null ); + SMESHGUI_dependParameter( const QString& = QString::null, const bool = false ); const ShownMap& shownMap() const; ShownMap& shownMap(); @@ -192,7 +200,8 @@ public: */ SMESHGUI_enumParameter( const QStringList& values, const int init = 0, - const QString& label = QString::null ); + const QString& label = QString::null, + const bool = false ); virtual ~SMESHGUI_enumParameter(); /*! @@ -224,7 +233,8 @@ class SMESHGUI_boolParameter: public SMESHGUI_dependParameter { public: SMESHGUI_boolParameter( const bool = false, - const QString& = QString::null ); + const QString& = QString::null, + const bool = false ); virtual ~SMESHGUI_boolParameter(); bool& InitValue() { return myInitValue; } @@ -244,6 +254,8 @@ private: class QButton; +class SMESHGUI_tableParameter; + /*! * \brief This class represents custom table. It has only double values and @@ -254,7 +266,7 @@ class SMESHGUI_Table : public QTable Q_OBJECT public: - SMESHGUI_Table( int numRows, int numCols, QWidget* = 0, const char* = 0 ); + SMESHGUI_Table( const SMESHGUI_tableParameter*, int numRows, int numCols, QWidget* = 0, const char* = 0 ); virtual ~SMESHGUI_Table(); /*! @@ -278,6 +290,14 @@ public: void setValidator( const double, const double, const int, const int rmin = -1, const int rmax = -1, const int cmin = -1, const int cmax = -1 ); + +protected: + virtual void keyPressEvent( QKeyEvent* ); + virtual bool eventFilter( QObject*, QEvent* ); + virtual QWidget* createEditor( int, int, bool ) const; + +private: + SMESHGUI_tableParameter* myParam; }; @@ -295,7 +315,7 @@ public: typedef enum { ADD_COLUMN, REMOVE_COLUMN, ADD_ROW, REMOVE_ROW } Button; public: - SMESHGUI_TableFrame( QWidget* ); + SMESHGUI_TableFrame( const SMESHGUI_tableParameter*, QWidget* ); ~SMESHGUI_TableFrame(); SMESHGUI_Table* table() const; @@ -324,6 +344,7 @@ signals: * this object resize table ( returned by table() ) automatically */ void toEdit( SMESHGUI_TableFrame::Button, int ); + void valueChanged( int, int ); private: QButton *myAddColumn, *myRemoveColumn, *myAddRow, *myRemoveRow; @@ -345,7 +366,8 @@ public: * and if new column or row is added then it is filled with default value */ SMESHGUI_tableParameter( const double init = 0.0, - const QString& label = QString::null ); + const QString& label = QString::null, + const bool preview = false ); virtual ~SMESHGUI_tableParameter(); virtual Type GetType() const; @@ -356,6 +378,8 @@ public: virtual void InitializeWidget( QWidget* ) const; virtual void TakeValue( QWidget* ); + static void sortData( SMESH::double_array& ); + /*! * \brief Updates look of widget in accordance with all parameters of this object */ @@ -416,6 +440,7 @@ public: private slots: void onEdit( SMESHGUI_TableFrame::Button, int ); + void onEdit( SMESHGUI_Table*, SMESHGUI_TableFrame::Button, int ); private: void setItems( QWidget*, int = -1, int = -1, int = -1, int = -1 ) const; @@ -437,6 +462,9 @@ private: ValidatorsMap myValidators; bool myEditCols, myEditRows; QMap< int, QString > myColNames; + + friend class SMESHGUI_Table; }; #endif // SMESHGUI_aParameter.h + diff --git a/src/SMESHGUI/SMESHGUI_aParameterDlg.cxx b/src/SMESHGUI/SMESHGUI_aParameterDlg.cxx index 7e824a7b9..b9c9f1d3b 100644 --- a/src/SMESHGUI/SMESHGUI_aParameterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_aParameterDlg.cxx @@ -31,6 +31,7 @@ #include "SMESHGUI.h" #include "SMESHGUI_SpinBox.h" #include "SMESHGUI_Utils.h" +#include "SMESHGUI_FunctionPreview.h" #include "SUIT_Tools.h" #include "SUIT_Desktop.h" @@ -94,7 +95,8 @@ void SMESHGUI_aParameterDlg::init() GroupC1Layout->setMargin(11); /* Spin boxes with labels */ list::iterator paramIt = myParamList.begin(); - for (int row = 0; paramIt != myParamList.end(); paramIt++ , row++) + int row; + for( row = 0; paramIt != myParamList.end(); paramIt++ , row++) { SMESHGUI_aParameterPtr param = (*paramIt); QLabel * label = new QLabel(GroupC1, "TextLabel"); @@ -107,7 +109,7 @@ void SMESHGUI_aParameterDlg::init() aSpinWidget->setMinimumSize(150, 0); QString sig = param->sigValueChanged(); - if( !sig.isEmpty() && param->GetType()!=SMESHGUI_aParameter::TABLE ) + if( !sig.isEmpty() /*&& param->GetType()!=SMESHGUI_aParameter::TABLE*/ ) connect( aSpinWidget, sig.latin1(), this, SLOT( onValueChanged() ) ); param->InitializeWidget(aSpinWidget); @@ -116,11 +118,17 @@ void SMESHGUI_aParameterDlg::init() } } + myPreview = new SMESHGUI_FunctionPreview( GroupC1 ); + GroupC1Layout->addWidget( myPreview, row, 1 ); + paramIt = myParamList.begin(); std::list::const_iterator anIt = mySpinList.begin(); for( ; paramIt!=myParamList.end(); paramIt++, anIt++ ) + { + (*paramIt)->TakeValue( *anIt ); UpdateShown( *paramIt, *anIt ); - + FunctionPreview( *paramIt, *anIt ); + } /***************************************************************/ QGroupBox* GroupButtons = new QGroupBox(this, "GroupButtons"); @@ -196,6 +204,38 @@ bool SMESHGUI_aParameterDlg::Parameters( SMESHGUI* theModule, return false; } +//======================================================================= +// function : FunctionPreview +// purpose : +//======================================================================= +void SMESHGUI_aParameterDlg::FunctionPreview( const SMESHGUI_aParameterPtr p, QWidget* w ) +{ + if( !w || !w->isShown() ) + return; + + SMESHGUI_strParameter* str_param = dynamic_cast( p.operator->() ); + SMESHGUI_tableParameter* tab_param = dynamic_cast( p.operator->() ); + SMESHGUI_boolParameter* bool_param = dynamic_cast( p.operator->() ); + if( str_param && str_param->needPreview() ) + { + QString val; str_param->GetNewText( val ); + if( !val.isNull() ) + myPreview->setParams( val ); + } + else if( tab_param && tab_param->needPreview() ) + { + SMESH::double_array d; + tab_param->data( d ); + myPreview->setParams( d ); + } + else if( bool_param && bool_param->needPreview() ) + { + int exp=0; + bool_param->GetNewInt( exp ); + myPreview->setIsExp( exp ); + } +} + //======================================================================= // function : onValueChanged // purpose : @@ -206,7 +246,6 @@ void SMESHGUI_aParameterDlg::onValueChanged() { QWidget* w = ( QWidget* )sender(); - SMESHGUI_aParameterPtr param; std::list::const_iterator anIt = mySpinList.begin(), aLast = mySpinList.end(); @@ -216,6 +255,7 @@ void SMESHGUI_aParameterDlg::onValueChanged() { (*aPIt)->TakeValue( w ); UpdateShown( *aPIt, w ); + FunctionPreview( *aPIt, w ); break; } } @@ -246,10 +286,19 @@ void SMESHGUI_aParameterDlg::UpdateShown( const SMESHGUI_aParameterPtr param, QW std::list::const_iterator anIt = mySpinList.begin(), aLast = mySpinList.end(), aLIt = myLabelList.begin(); - for( int i=0; anIt!=aLast; anIt++, aLIt++, i++ ) + std::list::iterator aPIt = myParamList.begin(); + bool preview = false; + for( int i=0; anIt!=aLast; anIt++, aLIt++, i++, aPIt++ ) { bool shown = hasValue && map[ val ].contains( i ); (*anIt)->setShown( shown ); (*aLIt)->setShown( shown ); + if( shown ) + { + SMESHGUI_strParameter* str_param = dynamic_cast( (*aPIt).operator->() ); + SMESHGUI_tableParameter* tab_param = dynamic_cast( (*aPIt).operator->() ); + preview = preview || ( str_param && str_param->needPreview() ) || ( tab_param && tab_param->needPreview() ); + } } + myPreview->setShown( preview ); } diff --git a/src/SMESHGUI/SMESHGUI_aParameterDlg.h b/src/SMESHGUI/SMESHGUI_aParameterDlg.h index 7fd28a96f..f749aeedd 100644 --- a/src/SMESHGUI/SMESHGUI_aParameterDlg.h +++ b/src/SMESHGUI/SMESHGUI_aParameterDlg.h @@ -39,6 +39,7 @@ class QLabel; class QPushButton; class SMESHGUI; class QWidget; +class SMESHGUI_FunctionPreview; //================================================================================= // class : SMESHGUI_aParameterDlg @@ -69,6 +70,9 @@ private slots: void ClickOnOk(); void UpdateShown( const SMESHGUI_aParameterPtr, QWidget* ); +private: + void FunctionPreview( const SMESHGUI_aParameterPtr, QWidget* ); + private: SMESHGUI* mySMESHGUI; @@ -77,6 +81,7 @@ private: std::list mySpinList, myLabelList; std::list myParamList; + SMESHGUI_FunctionPreview* myPreview; }; #endif // SMESHGUI_aParameterDlg.h diff --git a/src/StdMeshers/Makefile.in b/src/StdMeshers/Makefile.in index 385d643a5..9b2f65b61 100644 --- a/src/StdMeshers/Makefile.in +++ b/src/StdMeshers/Makefile.in @@ -87,6 +87,7 @@ BIN_SRC = CPPFLAGS+= $(OCC_INCLUDES) -I${KERNEL_ROOT_DIR}/include/salome $(BOOST_CPPFLAGS) CXXFLAGS+= $(OCC_CXXFLAGS) -I${KERNEL_ROOT_DIR}/include/salome -I${GEOM_ROOT_DIR}/include/salome -LDFLAGS+= -lSMESHimpl -lMEFISTO2D $(OCC_LDPATH) -lTKAdvTools -L${KERNEL_ROOT_DIR}/lib/salome -L${GEOM_ROOT_DIR}/lib/salome +LDFLAGS+= -lSMESHimpl -lMEFISTO2D $(OCC_LDPATH) -lTKAdvTools -L${KERNEL_ROOT_DIR}/lib/salome -L${GEOM_ROOT_DIR}/lib/salome \ + -lCASCatch @CONCLUDE@ diff --git a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx index 44ac15909..ecceafd14 100644 --- a/src/StdMeshers/StdMeshers_NumberOfSegments.cxx +++ b/src/StdMeshers/StdMeshers_NumberOfSegments.cxx @@ -33,6 +33,13 @@ using namespace std; #include #include #include +#include +#include +#include +#include +#include +#include + const double PRECISION = 1e-7; @@ -51,7 +58,7 @@ StdMeshers_NumberOfSegments::StdMeshers_NumberOfSegments(int hypId, int studyId, _expMode(false) { _name = "NumberOfSegments"; - _param_algo_dim = 1; + _param_algo_dim = 1; } //============================================================================= @@ -179,6 +186,7 @@ void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector& ta double prev = -PRECISION; bool isSame = table.size() == _table.size(); + bool pos = false; for (i=0; i < table.size()/2; i++) { double par = table[i*2]; double val = table[i*2+1]; @@ -186,8 +194,10 @@ void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector& ta throw SALOME_Exception(LOCALIZED("parameter of table function is out of range [0,1]")); if ( fabs(par-prev)PRECISION ) + pos = true; if (isSame) { double oldpar = _table[i*2]; @@ -198,7 +208,10 @@ void StdMeshers_NumberOfSegments::SetTableFunction(const std::vector& ta prev = par; } - if (!isSame) + if( !pos ) + throw SALOME_Exception(LOCALIZED("value of table function is not positive")); + + if( pos && !isSame ) { _table = table; NotifySubMeshesHypothesisModification(); @@ -223,23 +236,24 @@ const std::vector& StdMeshers_NumberOfSegments::GetTableFunction() const /*! check if only 't' is unknown variable in expression */ //================================================================================ -bool isCorrect( const Handle( Expr_GeneralExpression )& expr ) +bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr ) { - if( expr.IsNull() ) - return true; - + Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr ); + if( !sub.IsNull() ) + return sub->GetName()=="t"; + bool res = true; for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ ) { - Handle( Expr_GeneralExpression ) subexpr = expr->SubExpression( i ); - Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( subexpr ); + Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i ); + Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub ); if( !name.IsNull() ) { if( name->GetName()!="t" ) - res = false; + res = false; } else - res = isCorrect( subexpr ); + res = isCorrectArg( sub ); } return res; } @@ -249,25 +263,66 @@ bool isCorrect( const Handle( Expr_GeneralExpression )& expr ) * ( result in 'syntax' ) and if only 't' is unknown variable in expression ( result in 'args' ) */ //================================================================================ -void casProcess( const TCollection_AsciiString& str, bool& syntax, bool& args ) +bool process( const TCollection_AsciiString& str, + bool& syntax, bool& args, + bool& non_neg, bool& non_zero, + bool& singulars, double& sing_point ) { - // check validity of expression - syntax = false; - args = false; - try + Handle( ExprIntrp_GenExp ) myExpr = ExprIntrp_GenExp::Create(); + myExpr->Process( str.ToCString() ); + + if( myExpr->IsDone() ) { - Handle( ExprIntrp_GenExp ) gen = ExprIntrp_GenExp::Create(); - gen->Process( str ); - - if( gen->IsDone() ) - { - syntax = true; - args = isCorrect( gen->Expression() ); - } + syntax = true; + args = isCorrectArg( myExpr->Expression() ); } - catch (Standard_Failure) + + bool res = syntax && args; + if( !res ) + myExpr.Nullify(); + + non_neg = true; + singulars = false; + non_zero = false; + + if( res ) { + OSD::SetSignal( true ); + CASCatch_CatchSignals aCatchSignals; + aCatchSignals.Activate(); + double res; + Expr_Array1OfNamedUnknown myVars( 1, 1 ); + TColStd_Array1OfReal myValues( 1, 1 ); + myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" ); + + const int max = 500; + for( int i=0; i<=max; i++ ) + { + double t = double(i)/double(max); + myValues.ChangeValue( 1 ) = t; + CASCatch_TRY + { + res = myExpr->Expression()->Evaluate( myVars, myValues ); + } + CASCatch_CATCH(CASCatch_Failure) + { + aCatchSignals.Deactivate(); + Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught(); + sing_point = t; + singulars = true; + break; + } + if( res<0 ) + { + non_neg = false; + break; + } + if( res>PRECISION ) + non_zero = true; + } + aCatchSignals.Deactivate(); } + return res && non_neg && ( !singulars ); } //================================================================================ @@ -289,15 +344,31 @@ void StdMeshers_NumberOfSegments::SetExpressionFunction(const char* expr) str.RemoveAll('\r'); str.RemoveAll('\n'); - bool syntax, args; - casProcess( str, syntax, args ); - if( !syntax ) - throw SALOME_Exception(LOCALIZED("invalid expression syntax")); - if( !args ) - throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument")); + bool syntax, args, non_neg, singulars, non_zero; + double sing_point; + bool res = true;//process( str, syntax, args, non_neg, non_zero, singulars, sing_point ); + if( !res ) + { + if( !syntax ) + throw SALOME_Exception(LOCALIZED("invalid expression syntax")); + if( !args ) + throw SALOME_Exception(LOCALIZED("only 't' may be used as function argument")); + if( !non_neg ) + throw SALOME_Exception(LOCALIZED("only non-negative function can be used as density")); + if( singulars ) + { + char buf[1024]; + sprintf( buf, "Function has singular point in %.3f", sing_point ); + throw SALOME_Exception( buf ); + } + if( !non_zero ) + throw SALOME_Exception(LOCALIZED("f(t)=0 cannot be used as density")); - string func(str.ToCString()); - if (_func != func) + return; + } + + std::string func = expr; + if( _func != func ) { _func = func; NotifySubMeshesHypothesisModification(); diff --git a/src/StdMeshers/StdMeshers_NumberOfSegments.hxx b/src/StdMeshers/StdMeshers_NumberOfSegments.hxx index 2f559fb04..a384752ba 100644 --- a/src/StdMeshers/StdMeshers_NumberOfSegments.hxx +++ b/src/StdMeshers/StdMeshers_NumberOfSegments.hxx @@ -126,7 +126,7 @@ public: * * Throws SALOME_Exception if distribution type is not DT_ExprFunc */ - void SetExpressionFunction(const char* expr) + void SetExpressionFunction( const char* expr) throw (SALOME_Exception); /*! diff --git a/src/StdMeshers/StdMeshers_Regular_1D.cxx b/src/StdMeshers/StdMeshers_Regular_1D.cxx index c9765f039..51df8669d 100644 --- a/src/StdMeshers/StdMeshers_Regular_1D.cxx +++ b/src/StdMeshers/StdMeshers_Regular_1D.cxx @@ -64,6 +64,12 @@ using namespace std; #include #include +#include +#include +#include +#include +#include + #include #include @@ -260,247 +266,333 @@ static void compensateError(double a1, double an, } } -/*! - * \brief This class provides interface for a density function - */ -class Function +class Function { public: - Function(bool expMode) : _expMode(expMode) {} - double operator() (double t) const; - virtual bool IsReady() const = 0; -protected: - virtual double compute(double t) const = 0; + Function( const bool exp ) + : myExp( exp ) + { + } + + virtual ~Function() + { + } + + virtual bool value( const double, double& f ) + { + if( myExp ) + f = pow( 10, f ); + return true; + } + virtual double integral( const double, const double ) = 0; + private: - bool _expMode; + bool myExp; }; -/*! - * \brief This class provides computation of density function given by a table - */ -class TabFunction: public Function +class FunctionIntegral : public Function { public: - TabFunction(const vector& table, bool expMode); - virtual bool IsReady() const; -protected: - virtual double compute(double t) const; + FunctionIntegral( Function*, const double ); + virtual ~FunctionIntegral(); + virtual bool value( const double, double& ); + virtual double integral( const double, const double ); + private: - const vector& _table; + Function* myFunc; + double myStart; }; -/*! - * \brief This class provides computation of density function given by an expression - */ -class ExprFunction: public Function +FunctionIntegral::FunctionIntegral( Function* f, const double st ) +: Function( false ) +{ + myFunc = f; + myStart = st; +} + +FunctionIntegral::~FunctionIntegral() +{ +} + +bool FunctionIntegral::value( const double t, double& f ) +{ + f = myFunc ? myFunc->integral( myStart, t ) : 0; + return myFunc!=0 && Function::value( t, f ); +} + +double FunctionIntegral::integral( const double, const double ) +{ + return 0; +} + +class FunctionTable : public Function { public: - ExprFunction(const char* expr, bool expMode); - virtual bool IsReady() const; -protected: - virtual double compute(double t) const; + FunctionTable( const std::vector&, const bool ); + virtual ~FunctionTable(); + virtual bool value( const double, double& ); + virtual double integral( const double, const double ); + private: - Handle(Expr_GeneralExpression) _expression; - Expr_Array1OfNamedUnknown _var; - mutable TColStd_Array1OfReal _val; + bool findBounds( const double, int&, int& ) const; + + //integral from x[i] to x[i+1] + double integral( const int i ); + + //integral from x[i] to x[i]+d + //warning: function is presented as linear on interaval from x[i] to x[i]+d, + // for correct result d must be >=0 and <=x[i+1]-x[i] + double integral( const int i, const double d ); + +private: + std::vector myData; }; -double Function::operator() (double t) const +FunctionTable::FunctionTable( const std::vector& data, const bool exp ) +: Function( exp ) { - double res = compute(t); - if (_expMode) - res = pow(10, res); - return res; + myData = data; } -TabFunction::TabFunction(const vector& table, bool expMode) - : Function(expMode), - _table(table) +FunctionTable::~FunctionTable() { } -bool TabFunction::IsReady() const +bool FunctionTable::value( const double t, double& f ) { + int i1, i2; + if( !findBounds( t, i1, i2 ) ) + return false; + + double + x1 = myData[2*i1], y1 = myData[2*i1+1], + x2 = myData[2*i2], y2 = myData[2*i2+1]; + + Function::value( x1, y1 ); + Function::value( x2, y2 ); + + f = y1 + ( y2-y1 ) * ( t-x1 ) / ( x2-x1 ); return true; } -double TabFunction::compute (double t) const +double FunctionTable::integral( const int i ) { - //find place of in table - int i; - for (i=0; i < _table.size()/2; i++) - if (_table[i*2] > t) - break; - if (i >= _table.size()/2) - i = _table.size()/2 - 1; - - if (i == 0) - return _table[1]; - - // interpolate function value on found interval - // (t - x[i-1]) / (x[i] - x[i-1]) = (y - f[i-1]) / (f[i] - f[i-1]) - // => y = f[i-1] + (f[i] - f[i-1]) * (t - x[i-1]) / (x[i] - x[i-1]) - double x1 = _table[(i-1)*2]; - double x2 = _table[i*2]; - double y1 = _table[(i-1)*2+1]; - double y2 = _table[i*2+1]; - if (x2 - x1 < Precision::Confusion()) - throw SALOME_Exception("TabFunction::compute : confused points"); - return y1 + (y2 - y1) * ((t - x1) / (x2 - x1)); + if( i>=0 && iProcess(TCollection_AsciiString((char*)expr)); - if (gen->IsDone()) - { - _expression = gen->Expression(); - _var(1) = new Expr_NamedUnknown("t"); - } + double f, res = 0.0; + if( value( myData[2*i]+d, f ) ) + res = ( myData[2*i] + f ) / 2.0 * d; + + return res; } -bool ExprFunction::IsReady() const +double FunctionTable::integral( const double a, const double b ) { - return !_expression.IsNull(); + int x1s, x1f, x2s, x2f; + findBounds( a, x1s, x1f ); + findBounds( b, x2s, x2f ); + double J = 0; + for( int i=x1s; iEvaluate(_var, _val); + int n = myData.size(); + if( n==0 || x (s-sm1) * func(sm2) = (sm1-sm2) * func(sm1) - * => s = sm1 + (sm1-sm2) * func(sm1) / func(sm2) - */ -//================================================================================ -static double nextAbscissa(double sm2, double sm1, const Function& func, int reverse) + +class FunctionExpr : public Function, public math_Function { - if (reverse) - { - sm1 = 1.0 - sm1; - sm2 = 1.0 - sm2; - } - return sm1 + (sm1-sm2) * func(sm1) / func(sm2); +public: + FunctionExpr( const char*, const bool ); + virtual ~FunctionExpr(); + virtual Standard_Boolean Value( Standard_Real, Standard_Real& ); + virtual bool value( const double, double& ); //inherited from Function + virtual double integral( const double, const double ); + +private: + Handle(ExprIntrp_GenExp) myExpr; + Expr_Array1OfNamedUnknown myVars; + TColStd_Array1OfReal myValues; +}; + +FunctionExpr::FunctionExpr( const char* str, const bool exp ) +: Function( exp ), + myVars( 1, 1 ), + myValues( 1, 1 ) +{ + myExpr = ExprIntrp_GenExp::Create(); + myExpr->Process( ( Standard_CString )str ); + if( !myExpr->IsDone() ) + myExpr.Nullify(); + + myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" ); } -//================================================================================ -/*! - * \brief Compute distribution of points on a curve following the law of a function - * \param C3d - the curve to discretize - * \param first - the first parameter on the curve - * \param last - the last parameter on the curve - * \param theReverse - flag indicating that the curve must be reversed - * \param nbSeg - number of output segments - * \param func - the function f(t) - * \param theParams - output points - * \retval bool - true if success - */ -//================================================================================ +FunctionExpr::~FunctionExpr() +{ +} -static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last, - double length, bool theReverse, - int nbSeg, const Function& func, - list& theParams) +Standard_Boolean FunctionExpr::Value( Standard_Real T, Standard_Real& F ) +{ + double f; + Standard_Boolean res = value( T, f ); + F = f; + return res; +} + +bool FunctionExpr::value( const double t, double& f ) { - if (!func.IsReady()) + if( myExpr.IsNull() ) return false; - // ########## TMP until pb division by zero when func(0.0)==0 is fixed ######### - if (::Abs(func(0.0)) <= ::RealSmall() ) return false; - // ########## TMP until pb division by zero when func(0.0)==0 is fixed ######### + CASCatch_CatchSignals aCatchSignals; + aCatchSignals.Activate(); - vector xxx[2]; - int nbPnt = 1 + nbSeg; - int rev, i; - for (rev=0; rev < 2; rev++) + myValues.ChangeValue( 1 ) = t; + bool ok = true; + CASCatch_TRY { + f = myExpr->Expression()->Evaluate( myVars, myValues ); + } + CASCatch_CATCH(CASCatch_Failure) { + aCatchSignals.Deactivate(); + Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught(); + f = 0.0; + } + + aCatchSignals.Deactivate(); + ok = Function::value( t, f ) && ok; + return ok; +} + +double FunctionExpr::integral( const double a, const double b ) +{ + double res = 0.0; + CASCatch_TRY { - // curv abscisses initialisation - vector x(nbPnt, 0.); - // the first abscissa is 0.0 + math_GaussSingleIntegration _int( *this, a, b, 20 ); + if( _int.IsDone() ) + res = _int.Value(); + } + CASCatch_CATCH(CASCatch_Failure) + { + res = 0.0; + MESSAGE( "Exception in integral calculating" ); + } + return res; +} - // The aim of the algorithm is to find a second abscisse x[1] such as the last - // one x[nbSeg] is very close to 1.0 with the epsilon precision - double x1_too_small = 0.0; - double x1_too_large = RealLast(); - double x1 = 1.0/nbSeg; - while (1) - { - x[1] = x1; - // Check if the abscissa of the point 2 to N-1 - // are in the segment ... - bool ok = true; - for (i=2; i <= nbSeg; i++) - { - x[i] = nextAbscissa(x[i-2], x[i-1], func, rev); - if (x[i] - 1.0 > Precision::Confusion()) - { - x[nbSeg] = x[i]; - ok = false; - break; - } - } - if (!ok) - { - // The segments are to large - // Decrease x1 ... - x1_too_large = x1; - x1 = (x1_too_small+x1_too_large)/2; - if ( x1 <= ::RealSmall() ) - return false; // break infinite loop - continue; - } - // Look at the abscissa of the point N - // which is to be close to 1.0 - // break condition --> algo converged !! - if (1.0 - x[nbSeg] < Precision::Confusion()) - break; +double dihotomySolve( Function& f, const double val, const double _start, const double _fin, const double eps, bool& ok ) +{ + double start = _start, fin = _fin, start_val, fin_val; bool ok1, ok2; + ok1 = f.value( start, start_val ); + ok2 = f.value( fin, fin_val ); - // not ok ... + if( !ok1 || !ok2 ) + { + ok = false; + return 0.0; + } - x1_too_small = x1; + bool start_pos = start_val>=val, fin_pos = fin_val>=val; + ok = true; + + while( fin-start>eps ) + { + double mid = ( start+fin )/2.0, mid_val; + ok = f.value( mid, mid_val ); + if( !ok ) + return 0.0; - // Modify x1 value +// char buf[1024]; +// sprintf( buf, "start=%f\nfin=%f\nmid_val=%f\n", float( start ), float( fin ), float( mid_val ) ); +// MESSAGE( buf ); - if (x1_too_large > 1e100) - x1 = 2*x1; - else - x1 = (x1_too_small+x1_too_large)/2; + bool mid_pos = mid_val>=val; + if( start_pos!=mid_pos ) + { + fin_pos = mid_pos; + fin = mid; } - xxx[rev] = x; + else if( fin_pos!=mid_pos ) + { + start_pos = mid_pos; + start = mid; + } + else + break; } + return (start+fin)/2.0; +} + +static bool computeParamByFunc(Adaptor3d_Curve& C3d, double first, double last, + double length, bool theReverse, + int nbSeg, Function& func, + list& theParams) +{ + OSD::SetSignal( true ); + if( nbSeg<=0 ) + return false; - // average + MESSAGE( "computeParamByFunc" ); + + int nbPnt = 1 + nbSeg; vector x(nbPnt, 0.); - for (i=0; i < nbPnt; i++) - x[i] = (xxx[0][i] + (1.0 - xxx[1][nbPnt-i])) / 2; + + x[0] = 0.0; + double J = func.integral( 0.0, 1.0 ) / nbSeg; + bool ok; + for( int i=1; i::iterator paramIt = aParamList.begin(); - for ( int row = 1; paramIt != aParamList.end(); paramIt++ , row++ ) + int row; + for ( row = 1; paramIt != aParamList.end(); paramIt++ , row++ ) { SMESHGUI_aParameterPtr param = (*paramIt); QLabel * label = new QLabel( GroupC1, "TextLabel" ); @@ -147,7 +149,7 @@ void StdMeshersGUI_CreateHypothesisDlg::CreateDlgLayout(const QString & theCapti aWidget->setMinimumSize( 150, 0 ); QString sig = param->sigValueChanged(); - if( !sig.isEmpty() && param->GetType()!=SMESHGUI_aParameter::TABLE ) + if( !sig.isEmpty() /* && param->GetType()!=SMESHGUI_aParameter::TABLE*/ ) connect( aWidget, sig.latin1(), this, SLOT( onValueChanged() ) ); param->InitializeWidget( aWidget ); @@ -160,6 +162,8 @@ void StdMeshersGUI_CreateHypothesisDlg::CreateDlgLayout(const QString & theCapti myParamMap.insert( param, info ); } } + myPreview = new SMESHGUI_FunctionPreview( GroupC1 ); + GroupC1Layout->addWidget( myPreview, row, 1 ); StdMeshersGUI_CreateHypothesisDlgLayout->addWidget( GroupC1, 1 ); @@ -284,7 +288,8 @@ bool StdMeshersGUI_CreateHypothesisDlg::ClickOnApply() break; } - SetParameters( Hyp, aParamList ); + if( !SetParameters( Hyp, aParamList ) ) + return false; //set new Attribute Comment for hypothesis which parameters were set QString aParams = ""; @@ -394,7 +399,29 @@ void StdMeshersGUI_CreateHypothesisDlg::onValueChanged() if( anIt.data().editor == w ) { param = anIt.key(); - param->TakeValue( w ); + param->TakeValue( w ); + + SMESHGUI_strParameter* str_param = dynamic_cast( param.operator->() ); + SMESHGUI_tableParameter* tab_param = dynamic_cast( param.operator->() ); + SMESHGUI_boolParameter* bool_param = dynamic_cast( param.operator->() ); + + if( str_param && str_param->needPreview() ) + { + QString val; str_param->GetNewText( val ); + myPreview->setParams( val ); + } + else if( tab_param && tab_param->needPreview() ) + { + SMESH::double_array d; + tab_param->data( d ); + myPreview->setParams( d ); + } + else if( bool_param && bool_param->needPreview() ) + { + int exp=0; + bool_param->GetNewInt( exp ); + myPreview->setIsExp( exp ); + } UpdateShown( param ); break; } @@ -426,10 +453,18 @@ void StdMeshersGUI_CreateHypothesisDlg::UpdateShown( const SMESHGUI_aParameterPt ParameterMap::const_iterator anIt = myParamMap.begin(), aLast = myParamMap.end(); + bool preview = false; for( ; anIt!=aLast; anIt++ ) { bool shown = hasValue && map[ val ].contains( (*anIt).order ); (*anIt).editor->setShown( shown ); (*anIt).label->setShown( shown ); + if( shown ) + { + SMESHGUI_strParameter* str_param = dynamic_cast( anIt.key().operator->() ); + SMESHGUI_tableParameter* tab_param = dynamic_cast( anIt.key().operator->() ); + preview = preview || ( str_param && str_param->needPreview() ) || ( tab_param && tab_param->needPreview() ); + } } + myPreview->setShown( preview ); } diff --git a/src/StdMeshersGUI/StdMeshersGUI_CreateHypothesisDlg.h b/src/StdMeshersGUI/StdMeshersGUI_CreateHypothesisDlg.h index 5d61f408b..852fd468d 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_CreateHypothesisDlg.h +++ b/src/StdMeshersGUI/StdMeshersGUI_CreateHypothesisDlg.h @@ -46,6 +46,7 @@ class QLineEdit; class QPushButton; class SMESHGUI; class SMESHGUI_SpinBox; +class SMESHGUI_FunctionPreview; //================================================================================= // class : StdMeshersGUI_CreateHypothesisDlg @@ -108,6 +109,7 @@ private: QPushButton* buttonOk; QPushButton* buttonApply; QPushButton* buttonCancel; + SMESHGUI_FunctionPreview* myPreview; private slots: diff --git a/src/StdMeshersGUI/StdMeshersGUI_Parameters.cxx b/src/StdMeshersGUI/StdMeshersGUI_Parameters.cxx index 7d52876d9..67d4f450c 100644 --- a/src/StdMeshersGUI/StdMeshersGUI_Parameters.cxx +++ b/src/StdMeshersGUI/StdMeshersGUI_Parameters.cxx @@ -134,8 +134,8 @@ void StdMeshersGUI_Parameters::SetInitValue( SMESHGUI_aParameterPtr param, #define DOUBLE_PARAM(v,l,b,t,s,d) SMESHGUI_aParameterPtr(new SMESHGUI_doubleParameter(v,l,b,t,s,d)) #define INT_PARAM(v,l,b,t) SMESHGUI_aParameterPtr(new SMESHGUI_intParameter(v,l,b,t)) #define ENUM_PARAM(v,i,l) SMESHGUI_aParameterPtr(new SMESHGUI_enumParameter(v,i,l)) -#define STR_PARAM(i,l) SMESHGUI_aParameterPtr(new SMESHGUI_strParameter(i,l)) -#define BOOL_PARAM(i,l) SMESHGUI_aParameterPtr(new SMESHGUI_boolParameter(i,l)) +#define STR_PARAM(i,l,preview) SMESHGUI_aParameterPtr(new SMESHGUI_strParameter(i,l,preview)) +#define BOOL_PARAM(i,l,preview) SMESHGUI_aParameterPtr(new SMESHGUI_boolParameter(i,l,preview)) void StdMeshersGUI_Parameters::GetParameters (const QString& hypType, list & paramList ) @@ -183,7 +183,7 @@ void StdMeshersGUI_Parameters::GetParameters (const QString& hyp paramList.push_back ( DOUBLE_PARAM (1.0, QObject::tr("SMESH_NB_SEGMENTS_SCALE_PARAM"), VALUE_SMALL, VALUE_MAX, 0.1, 6 )); - SMESHGUI_tableParameter* tab = new SMESHGUI_tableParameter( 0.0, QObject::tr( "SMESH_TAB_FUNC" ) ); + SMESHGUI_tableParameter* tab = new SMESHGUI_tableParameter( 0.0, QObject::tr( "SMESH_TAB_FUNC" ), true ); tab->setRowCount( 5 ); tab->setColCount( 2 ); //default size of table: 5x2 @@ -198,10 +198,10 @@ void StdMeshersGUI_Parameters::GetParameters (const QString& hyp paramList.push_back ( SMESHGUI_aParameterPtr( tab ) ); //4-th parameter in list - paramList.push_back ( STR_PARAM ( "", QObject::tr( "SMESH_EXPR_FUNC" ) ) ); + paramList.push_back ( STR_PARAM ( "", QObject::tr( "SMESH_EXPR_FUNC" ), true ) ); //5-th parameter in list - paramList.push_back ( BOOL_PARAM ( false, QObject::tr( "SMESH_EXP_MODE" ) ) ); + paramList.push_back ( BOOL_PARAM ( false, QObject::tr( "SMESH_EXP_MODE" ), true ) ); } else if (hypType.compare("Arithmetic1D") == 0) { @@ -291,7 +291,7 @@ void StdMeshersGUI_Parameters::GetParameters (SMESH::SMESH_Hypothesis_ptr the { char* expr_func = NOS->GetExpressionFunction(); SetInitValue( *anIt, expr_func ); - delete expr_func; + //delete expr_func; } anIt++; -- 2.30.2