Salome HOME
2add301760d92733c96751000079b0f4440c2414
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_FunctionPreview.cxx
1
2 #include "SMESHGUI_FunctionPreview.h"
3 #include <Expr_NamedUnknown.hxx>
4 #include <Expr_GeneralExpression.hxx>
5 #include <CASCatch_CatchSignals.hxx>
6 #include <CASCatch_Failure.hxx> 
7 #include <CASCatch_ErrorHandler.hxx>
8 #include <OSD.hxx>
9
10 SMESHGUI_FunctionPreview::SMESHGUI_FunctionPreview( QWidget* p )
11 : QwtPlot( p ),
12   myXmin( 0.0 ),
13   myXmax( 1.0 ),
14   myPoints( 50 ),
15   myIsTable( false ),
16   myVars( 1, 1 ),
17   myValues( 1, 1 ),
18   myIsExp( false ),
19   myIsDone( true )
20 {
21   myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" );
22   myCurve = insertCurve( QString() );
23   setCurvePen( myCurve, QPen( Qt::red, 1 ) );
24 }
25
26 SMESHGUI_FunctionPreview::~SMESHGUI_FunctionPreview()
27 {
28 }
29
30 bool SMESHGUI_FunctionPreview::isTableFunc() const
31 {
32   return myIsTable;
33 }
34
35 void SMESHGUI_FunctionPreview::tableFunc( SMESH::double_array& f ) const
36 {
37   f = myTableFunc;
38 }
39
40 QString SMESHGUI_FunctionPreview::function() const
41 {
42   return myFunction;
43 }
44
45 void SMESHGUI_FunctionPreview::interval( double& xmin, double& xmax ) const
46 {
47   xmin = myXmin;
48   xmax = myXmax;
49 }
50
51 int SMESHGUI_FunctionPreview::pointsCount() const
52 {
53   return myPoints;
54 }
55
56 void SMESHGUI_FunctionPreview::setIsExp( const bool exp, const bool update )
57 {
58   myIsExp = exp;
59   if( update )
60     repaint();
61 }
62
63 bool SMESHGUI_FunctionPreview::setParams( const QString& func,
64                                                const double xmin, const double xmax,
65                                                const int points, const bool update )
66 {
67   myIsTable = false;
68   myTableFunc = SMESH::double_array();
69   myFunction = func.isEmpty() ? "0" : func;
70   myXmin = xmin;
71   myXmax = xmax<myXmin ? myXmax : xmax;
72   myPoints = points>0 ? points : 2;
73   bool res = init( func );
74   if( update )
75     repaint();
76   return res;
77 }
78
79 bool SMESHGUI_FunctionPreview::setParams( const SMESH::double_array& f, const double xmin, const double xmax,
80                                                const bool update )
81 {
82   myIsTable = true;
83   myTableFunc = f;
84   if( myTableFunc.length()%2==1 )
85     myTableFunc.length( myTableFunc.length()-1 );
86
87   myFunction = "0";
88   myXmin = xmin;
89   myXmax = xmax<myXmin ? myXmax : xmax;
90   myPoints = myTableFunc.length()/2;
91
92   if( update )
93     repaint();
94
95   return myTableFunc.length()>0;
96 }
97
98 bool SMESHGUI_FunctionPreview::createTable( SMESH::double_array& func )
99 {
100   if( myExpr.IsNull() )
101   {
102     func.length( 0 );
103     return false;
104   }
105
106   double d = (myXmax-myXmin)/double(myPoints-1);
107   func.length( 2*myPoints );
108   int err = 0;
109   for( int i=0, j=0; i<myPoints; j++ )
110   {
111     bool ok;
112     double t = myXmin + d*j, f = funcValue( t, ok );
113     if( ok )
114     {
115       func[2*i] = t;
116       func[2*i+1] = f;
117       i++;
118     }
119     else
120       err++;
121   }
122   func.length( func.length()-2*err );
123   return err==0;
124 }
125
126 void SMESHGUI_FunctionPreview::drawContents( QPainter* p )
127 {
128   SMESH::double_array f;
129   if( isTableFunc() )
130   {
131     myIsDone = true;
132     f = myTableFunc;
133   }
134   else
135     myIsDone = createTable( f );
136
137   int size = f.length()/2;
138   if( size==0 )
139   {
140     setAxisScale( curveXAxis( myCurve ), 0.0, 0.0 );
141     setAxisScale( curveYAxis( myCurve ), 0.0, 0.0 );
142     setCurveData( myCurve, 0, 0, 0 );
143     replot();
144     QwtPlot::drawContents( p );
145     return;
146   }
147
148   double* x = new double[size], *y = new double[size];
149   double min_x, max_x, min_y, max_y;
150   for( int i=0; i<size; i++ )
151   {
152     x[i] = f[2*i];
153     y[i] = myIsExp ? pow( 10.0, f[2*i+1] ) : f[2*i+1];
154     if( i==0 || y[i]<min_y )
155       min_y = y[i];
156     if( i==0 || y[i]>max_y )
157       max_y = y[i];
158     if( i==0 || x[i]<min_x )
159       min_x = x[i];
160     if( i==0 || x[i]>max_x )
161       max_x = x[i];
162   }
163
164   setAxisScale( curveXAxis( myCurve ), min_x, max_x );
165   setAxisScale( curveYAxis( myCurve ), min_y, max_y );
166   setCurveData( myCurve, x, y, size );
167   delete[] x;
168   delete[] y;
169
170   replot();
171   QwtPlot::drawContents( p );
172 }
173
174 bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr )
175 {
176   Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr );
177   if( !sub.IsNull() )
178     return sub->GetName()=="t";
179
180   bool res = true;
181   for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
182   {
183     Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i );
184     Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub );
185     if( !name.IsNull() )
186     {
187       if( name->GetName()!="t" )
188         res = false;
189     }
190     else
191       res = isCorrectArg( sub );
192   }
193   return res;
194 }
195
196 bool SMESHGUI_FunctionPreview::init( const QString& str )
197 {
198   myExpr = ExprIntrp_GenExp::Create();
199   myExpr->Process( ( Standard_CString ) str.latin1() );
200
201   bool syntax = false, args = false;
202   if( myExpr->IsDone() )
203   {
204     syntax = true;
205     args = isCorrectArg( myExpr->Expression() );
206   }
207
208   bool res = syntax && args;
209   if( !res )
210     myExpr.Nullify();
211   return res;
212 }
213
214 double SMESHGUI_FunctionPreview::funcValue( const double t, bool& ok )
215 {
216   if( myExpr.IsNull() )
217     return 0;
218
219   myValues.ChangeValue( 1 ) = t;
220
221   ok = true;
222   double res = calc( ok );
223
224   return res;
225 }
226
227 double SMESHGUI_FunctionPreview::calc( bool& ok )
228 {
229   OSD::SetSignal( true );
230   double res = 0.0;
231
232   CASCatch_CatchSignals aCatchSignals;
233   aCatchSignals.Activate();
234
235   ok = true;
236   CASCatch_TRY {   
237     res = myExpr->Expression()->Evaluate( myVars, myValues );
238   }
239   CASCatch_CATCH(CASCatch_Failure) {
240     aCatchSignals.Deactivate();
241     Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught();
242     ok = false;
243     res = 0.0;
244   }
245   aCatchSignals.Deactivate();
246   return res;
247 }
248
249 bool SMESHGUI_FunctionPreview::isDone() const
250 {
251   return myIsDone;
252 }