Salome HOME
f763fbd9c27b032f4e0099c6eb16da0a9bddd268
[modules/smesh.git] / src / StdMeshersGUI / StdMeshersGUI_DistrPreview.cxx
1
2 #include "StdMeshersGUI_DistrPreview.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 StdMeshersGUI_DistrPreview::StdMeshersGUI_DistrPreview( QWidget* p, StdMeshers::StdMeshers_NumberOfSegments_ptr h )
11 : QwtPlot( p ),
12   myPoints( 50 ),
13   myIsTable( false ),
14   myVars( 1, 1 ),
15   myValues( 1, 1 ),
16   myConv( CUT_NEGATIVE ),
17   myIsDone( true ),
18   myNbSeg( 1 )
19 {
20   myHypo = StdMeshers::StdMeshers_NumberOfSegments::_duplicate( h );
21   myVars.ChangeValue( 1 ) = new Expr_NamedUnknown( "t" );
22   myCurve1 = insertCurve( QString() );
23   myCurve2 = insertCurve( QString() );
24   myMsg = insertMarker( new QwtPlotMarker( this ) );
25   setMarkerPos( myMsg, 0.5, 0.5 );
26   setMarkerLabelPen( myMsg, QPen( Qt::red, 1 ) );
27   QFont f = markerFont( myMsg );
28   f.setPointSize( 14 );
29   f.setBold( true );
30   setMarkerFont( myMsg, f );
31   setCurvePen( myCurve1, QPen( Qt::red, 1 ) );
32
33   QColor dc = Qt::blue;
34   setCurvePen( myCurve2, QPen( dc, 1 ) );
35   setCurveSymbol( myCurve2, QwtSymbol( QwtSymbol::XCross, QBrush( dc ), QPen( dc ), QSize( 5, 5 ) ) );
36 }
37
38 StdMeshersGUI_DistrPreview::~StdMeshersGUI_DistrPreview()
39 {
40 }
41
42 bool StdMeshersGUI_DistrPreview::isTableFunc() const
43 {
44   return myIsTable;
45 }
46
47 void StdMeshersGUI_DistrPreview::tableFunc( SMESH::double_array& f ) const
48 {
49   f = myTableFunc;
50 }
51
52 QString StdMeshersGUI_DistrPreview::function() const
53 {
54   return myFunction;
55 }
56
57 int StdMeshersGUI_DistrPreview::nbSeg() const
58 {
59   return myNbSeg;
60 }
61
62 int StdMeshersGUI_DistrPreview::pointsCount() const
63 {
64   return myPoints;
65 }
66
67 void StdMeshersGUI_DistrPreview::setConversion( Conversion conv, const bool upd )
68 {
69   myConv = conv;
70   if( upd )
71     update();
72 }
73
74 bool StdMeshersGUI_DistrPreview::setParams( const QString& func, const int nbSeg, const int points, const bool upd )
75 {
76   myIsTable = false;
77   myTableFunc = SMESH::double_array();
78   myFunction = func.isEmpty() ? "0" : func;
79   myPoints = points>0 ? points : 2;
80   myNbSeg = nbSeg>0 ? nbSeg : 1;
81   bool res = init( func );
82   if( upd )
83     update();
84   return res;
85 }
86
87 bool StdMeshersGUI_DistrPreview::setParams( const SMESH::double_array& f, const int nbSeg, const bool upd )
88 {
89   myIsTable = true;
90   myTableFunc = f;
91   if( myTableFunc.length()%2==1 )
92     myTableFunc.length( myTableFunc.length()-1 );
93
94   myFunction = "0";
95   myPoints = myTableFunc.length()/2;
96   myNbSeg = nbSeg>0 ? nbSeg : 1;
97
98   if( upd )
99     update();
100
101   return myTableFunc.length()>0;
102 }
103
104 bool StdMeshersGUI_DistrPreview::createTable( SMESH::double_array& func )
105 {
106   if( myExpr.IsNull() )
107   {
108     func.length( 0 );
109     return false;
110   }
111
112   const double xmin = 0.0, xmax = 1.0;
113
114   double d = (xmax-xmin)/double(myPoints-1);
115   func.length( 2*myPoints );
116   int err = 0;
117   for( int i=0, j=0; i<myPoints; j++ )
118   {
119     bool ok;
120     double t = xmin + d*j, f = funcValue( t, ok );
121     if( ok )
122     {
123       func[2*i] = t;
124       func[2*i+1] = f;
125       i++;
126     }
127     else
128       err++;
129   }
130   func.length( func.length()-2*err );
131   return err==0;
132 }
133
134 void StdMeshersGUI_DistrPreview::update()
135 {
136   SMESH::double_array graph, distr;
137   if( isTableFunc() )
138   {
139     myIsDone = true;
140     graph = myTableFunc;
141   }
142   else
143     myIsDone = createTable( graph );
144
145   if( graph.length()>=2 )
146   {
147     StdMeshers::StdMeshers_NumberOfSegments_var h = 
148       StdMeshers::StdMeshers_NumberOfSegments::_narrow( myHypo );
149
150     if( !CORBA::is_nil( h.in() ) )
151     {
152       SMESH::double_array* arr = 0;
153       if( isTableFunc() )
154         arr = h->BuildDistributionTab( myTableFunc, myNbSeg, ( int )myConv );
155       else
156         arr = h->BuildDistributionExpr( myFunction.latin1(), myNbSeg, ( int )myConv );
157       if( arr )
158       {
159         distr = *arr;
160         delete arr;
161       }
162     }
163   }
164
165   bool correct = graph.length()>=2 && distr.length()>=2;
166   if( !correct )
167   {
168     showError();
169     return;
170   }
171   else
172     setMarkerLabel( myMsg, QString() );
173
174   int size = graph.length()/2;
175   double* x = new double[size], *y = new double[size];
176   double min_x, max_x, min_y, max_y;
177   for( int i=0; i<size; i++ )
178   {
179     x[i] = graph[2*i];
180     y[i] = graph[2*i+1];
181     if( !convert( y[i] ) )
182     {
183       min_x = 0.0; max_x = 1.0; min_y = 0.0; max_y = 1.0;
184       delete[] x; delete[] y;
185       x = y = 0;
186       showError();
187       return;
188     }
189     if( i==0 || y[i]<min_y )
190       min_y = y[i];
191     if( i==0 || y[i]>max_y )
192       max_y = y[i];
193     if( i==0 || x[i]<min_x )
194       min_x = x[i];
195     if( i==0 || x[i]>max_x )
196       max_x = x[i];
197   }
198
199   setAxisScale( curveXAxis( myCurve1 ), min_x, max_x );
200   setAxisScale( curveYAxis( myCurve1 ), min( 0.0, min_y ), max( 0.0, max_y ) );
201   setCurveData( myCurve1, x, y, size );
202   if( x )
203     delete[] x;
204   if( y )
205     delete[] y;
206   x = y = 0;
207
208   size = distr.length();
209   x = new double[size];
210   y = new double[size];
211   for( int i=0; i<size; i++ )
212   {
213     x[i] = distr[i];
214     y[i] = 0;
215   }
216   setCurveData( myCurve2, x, y, size );
217   delete[] x;
218   delete[] y;
219   x = y = 0;
220   replot();
221 }
222
223 void StdMeshersGUI_DistrPreview::showError()
224 {
225   setAxisScale( curveXAxis( myCurve1 ), 0.0, 1.0 );
226   setAxisScale( curveYAxis( myCurve1 ), 0.0, 1.0 );
227   setCurveData( myCurve1, 0, 0, 0 );
228   setCurveData( myCurve2, 0, 0, 0 );
229   setMarkerLabel( myMsg, tr( "SMESH_INVALID_FUNCTION" ) );
230   replot();
231 }
232
233 bool isCorrectArg( const Handle( Expr_GeneralExpression )& expr )
234 {
235   Handle( Expr_NamedUnknown ) sub = Handle( Expr_NamedUnknown )::DownCast( expr );
236   if( !sub.IsNull() )
237     return sub->GetName()=="t";
238
239   bool res = true;
240   for( int i=1, n=expr->NbSubExpressions(); i<=n && res; i++ )
241   {
242     Handle( Expr_GeneralExpression ) sub = expr->SubExpression( i );
243     Handle( Expr_NamedUnknown ) name = Handle( Expr_NamedUnknown )::DownCast( sub );
244     if( !name.IsNull() )
245     {
246       if( name->GetName()!="t" )
247         res = false;
248     }
249     else
250       res = isCorrectArg( sub );
251   }
252   return res;
253 }
254
255 bool StdMeshersGUI_DistrPreview::init( const QString& str )
256 {
257   CASCatch_CatchSignals aCatchSignals;
258   aCatchSignals.Activate();
259
260   bool parsed_ok = true;
261   CASCatch_TRY
262   {
263     myExpr = ExprIntrp_GenExp::Create();
264     myExpr->Process( ( Standard_CString ) str.latin1() );
265   }
266   CASCatch_CATCH(CASCatch_Failure)
267   {
268     aCatchSignals.Deactivate();
269     Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught();
270     parsed_ok = false;
271   }
272   aCatchSignals.Deactivate();
273
274   bool syntax = false, args = false;
275   if( parsed_ok && myExpr->IsDone() )
276   {
277     syntax = true;
278     args = isCorrectArg( myExpr->Expression() );
279   }
280
281   bool res = parsed_ok && syntax && args;
282   if( !res )
283     myExpr.Nullify();
284   return res;
285 }
286
287 double StdMeshersGUI_DistrPreview::funcValue( const double t, bool& ok )
288 {
289   if( myExpr.IsNull() )
290     return 0;
291
292   myValues.ChangeValue( 1 ) = t;
293
294   ok = true;
295   double res = calc( ok );
296
297   return res;
298 }
299
300 double StdMeshersGUI_DistrPreview::calc( bool& ok )
301 {
302   OSD::SetSignal( true );
303   double res = 0.0;
304
305   CASCatch_CatchSignals aCatchSignals;
306   aCatchSignals.Activate();
307
308   ok = true;
309   CASCatch_TRY {   
310     res = myExpr->Expression()->Evaluate( myVars, myValues );
311   }
312   CASCatch_CATCH(CASCatch_Failure) {
313     aCatchSignals.Deactivate();
314     Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught();
315     ok = false;
316     res = 0.0;
317   }
318   aCatchSignals.Deactivate();
319   return res;
320 }
321
322 bool StdMeshersGUI_DistrPreview::isDone() const
323 {
324   return myIsDone;
325 }
326
327 bool StdMeshersGUI_DistrPreview::convert( double& v ) const
328 {
329   CASCatch_CatchSignals aCatchSignals;
330   aCatchSignals.Activate();
331
332   bool ok = true;
333   switch( myConv )
334   {
335   case EXPONENT:
336     {
337       CASCatch_TRY
338       { 
339         v = pow( 10.0, v );
340       }
341       CASCatch_CATCH(CASCatch_Failure)
342       {
343         aCatchSignals.Deactivate();
344         Handle(CASCatch_Failure) aFail = CASCatch_Failure::Caught();
345         v = 0.0;
346         ok = false;
347       }
348     }
349     break;
350
351   case CUT_NEGATIVE:
352     if( v<0 )
353       v = 0;
354     break;
355   }
356   aCatchSignals.Deactivate();
357   return ok;
358 }