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