Salome HOME
Copyrights update
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_FunctionPreview.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/
19 //
20
21 #include "SMESHGUI_FunctionPreview.h"
22 #include <Expr_NamedUnknown.hxx>
23 #include <Expr_GeneralExpression.hxx>
24 #include <CASCatch_CatchSignals.hxx>
25 #include <CASCatch_Failure.hxx> 
26 #include <CASCatch_ErrorHandler.hxx>
27 #include <OSD.hxx>
28
29 SMESHGUI_FunctionPreview::SMESHGUI_FunctionPreview( QWidget* p )
30 : QwtPlot( p ),
31   myXmin( 0.0 ),
32   myXmax( 1.0 ),
33   myPoints( 50 ),
34   myIsTable( false ),
35   myVars( 1, 1 ),
36   myValues( 1, 1 ),
37   myIsExp( false ),
38   myIsDone( true )
39 {
40   myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" );
41   myCurve = insertCurve( QString() );
42   setCurvePen( myCurve, QPen( Qt::red, 1 ) );
43 }
44
45 SMESHGUI_FunctionPreview::~SMESHGUI_FunctionPreview()
46 {
47 }
48
49 bool SMESHGUI_FunctionPreview::isTableFunc() const
50 {
51   return myIsTable;
52 }
53
54 void SMESHGUI_FunctionPreview::tableFunc( SMESH::double_array& f ) const
55 {
56   f = myTableFunc;
57 }
58
59 QString SMESHGUI_FunctionPreview::function() const
60 {
61   return myFunction;
62 }
63
64 void SMESHGUI_FunctionPreview::interval( double& xmin, double& xmax ) const
65 {
66   xmin = myXmin;
67   xmax = myXmax;
68 }
69
70 int SMESHGUI_FunctionPreview::pointsCount() const
71 {
72   return myPoints;
73 }
74
75 void SMESHGUI_FunctionPreview::setIsExp( const bool exp, const bool update )
76 {
77   myIsExp = exp;
78   if( update )
79     repaint();
80 }
81
82 bool SMESHGUI_FunctionPreview::setParams( const QString& func,
83                                                const double xmin, const double xmax,
84                                                const int points, const bool update )
85 {
86   myIsTable = false;
87   myTableFunc = SMESH::double_array();
88   myFunction = func.isEmpty() ? "0" : func;
89   myXmin = xmin;
90   myXmax = xmax<myXmin ? myXmax : xmax;
91   myPoints = points>0 ? points : 2;
92   bool res = init( func );
93   if( update )
94     repaint();
95   return res;
96 }
97
98 bool SMESHGUI_FunctionPreview::setParams( const SMESH::double_array& f, const double xmin, const double xmax,
99                                                const bool update )
100 {
101   myIsTable = true;
102   myTableFunc = f;
103   if( myTableFunc.length()%2==1 )
104     myTableFunc.length( myTableFunc.length()-1 );
105
106   myFunction = "0";
107   myXmin = xmin;
108   myXmax = xmax<myXmin ? myXmax : xmax;
109   myPoints = myTableFunc.length()/2;
110
111   if( update )
112     repaint();
113
114   return myTableFunc.length()>0;
115 }
116
117 bool SMESHGUI_FunctionPreview::createTable( SMESH::double_array& func )
118 {
119   if( myExpr.IsNull() )
120   {
121     func.length( 0 );
122     return false;
123   }
124
125   double d = (myXmax-myXmin)/double(myPoints-1);
126   func.length( 2*myPoints );
127   int err = 0;
128   for( int i=0, j=0; i<myPoints; j++ )
129   {
130     bool ok;
131     double t = myXmin + d*j, f = funcValue( t, ok );
132     if( ok )
133     {
134       func[2*i] = t;
135       func[2*i+1] = f;
136       i++;
137     }
138     else
139       err++;
140   }
141   func.length( func.length()-2*err );
142   return err==0;
143 }
144
145 void SMESHGUI_FunctionPreview::drawContents( QPainter* p )
146 {
147   SMESH::double_array f;
148   if( isTableFunc() )
149   {
150     myIsDone = true;
151     f = myTableFunc;
152   }
153   else
154     myIsDone = createTable( f );
155
156   int size = f.length()/2;
157   if( size==0 )
158   {
159     setAxisScale( curveXAxis( myCurve ), 0.0, 0.0 );
160     setAxisScale( curveYAxis( myCurve ), 0.0, 0.0 );
161     setCurveData( myCurve, 0, 0, 0 );
162     replot();
163     QwtPlot::drawContents( p );
164     return;
165   }
166
167   double* x = new double[size], *y = new double[size];
168   double min_x, max_x, min_y, max_y;
169   for( int i=0; i<size; i++ )
170   {
171     x[i] = f[2*i];
172     y[i] = myIsExp ? pow( 10.0, f[2*i+1] ) : f[2*i+1];
173     if( i==0 || y[i]<min_y )
174       min_y = y[i];
175     if( i==0 || y[i]>max_y )
176       max_y = y[i];
177     if( i==0 || x[i]<min_x )
178       min_x = x[i];
179     if( i==0 || x[i]>max_x )
180       max_x = x[i];
181   }
182
183   setAxisScale( curveXAxis( myCurve ), min_x, max_x );
184   setAxisScale( curveYAxis( myCurve ), min_y, max_y );
185   setCurveData( myCurve, x, y, size );
186   delete[] x;
187   delete[] y;
188
189   replot();
190   QwtPlot::drawContents( p );
191 }
192
193 bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr )
194 {
195   Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr );
196   if( !sub.IsNull() )
197     return sub->GetName()=="t";
198
199   bool res = true;
200   for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
201   {
202     Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i );
203     Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub );
204     if( !name.IsNull() )
205     {
206       if( name->GetName()!="t" )
207         res = false;
208     }
209     else
210       res = isCorrectArg( sub );
211   }
212   return res;
213 }
214
215 bool SMESHGUI_FunctionPreview::init( const QString& str )
216 {
217   myExpr = ExprIntrp_GenExp::Create();
218   myExpr->Process( ( Standard_CString ) str.latin1() );
219
220   bool syntax = false, args = false;
221   if( myExpr->IsDone() )
222   {
223     syntax = true;
224     args = isCorrectArg( myExpr->Expression() );
225   }
226
227   bool res = syntax && args;
228   if( !res )
229     myExpr.Nullify();
230   return res;
231 }
232
233 double SMESHGUI_FunctionPreview::funcValue( const double t, bool& ok )
234 {
235   if( myExpr.IsNull() )
236     return 0;
237
238   myValues.ChangeValue( 1 ) = t;
239
240   ok = true;
241   double res = calc( ok );
242
243   return res;
244 }
245
246 double SMESHGUI_FunctionPreview::calc( bool& ok )
247 {
248   OSD::SetSignal( true );
249   double res = 0.0;
250
251   CASCatch_CatchSignals aCatchSignals;
252   aCatchSignals.Activate();
253
254   ok = true;
255   CASCatch_TRY {   
256     res = myExpr->Expression()->Evaluate( myVars, myValues );
257   }
258   CASCatch_CATCH(CASCatch_Failure) {
259     aCatchSignals.Deactivate();
260     Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught();
261     ok = false;
262     res = 0.0;
263   }
264   aCatchSignals.Deactivate();
265   return res;
266 }
267
268 bool SMESHGUI_FunctionPreview::isDone() const
269 {
270   return myIsDone;
271 }