00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "expressiongraph.h"
00019
00020 #include <sstream>
00021
00022 #ifdef KDE_APP
00023 #include <kprinter.h>
00024 #else
00025 #include <qprinter.h>
00026 #endif //KDE_APP
00027
00028 #include <qpixmap.h>
00029 #include <qpainter.h>
00030
00031 #include "mathfunction.h"
00032 #include "expression.h"
00033 #include "fungparser.h"
00034
00035 ExpressionGraph::ExpressionGraph(QWidget *parent, const char *name ) :
00036 BasicGraph(parent,name),
00037 Animator(),
00038 doTrace(false),
00039 drawConnected(true),
00040 expressionIndex(0),
00041 functionWidth(1),
00042 angle(0),
00043 only_show_active(false),
00044 displayExpressionText(true)
00045 {
00046 initializeAnimator( this );
00047 }
00048
00049 ExpressionGraph::~ExpressionGraph()
00050 {
00051 for( ExpressionPtrVector::const_iterator it = functions.begin(); it != functions.end(); it++ )
00052 delete (*it);
00053 }
00054
00055 void ExpressionGraph::load_key( const char *key, const char *value )
00056 {
00057 BasicGraph::load_key( key, value );
00058 Animator::load_key( key, value );
00059
00060 if (strcmp(key,"Function=") == 0)
00061 {
00062 char alpha[256];
00063 std::stringstream stream(value);
00064
00065 stream.get(alpha,sizeof(alpha),':');
00066 QString sx(alpha);
00067 stream.ignore(sizeof(char));
00068
00069
00070
00071
00072 stream>>alpha;
00073
00074 QColor color(alpha);
00075 stream>>alpha;
00076 bool show;
00077 if ( strcmp( alpha,"0" ) == 0 )
00078 show = false;
00079 else
00080 show = true;
00081
00082 addExpression(Expression(sx,show,color));
00083 nextExpression();
00084 }
00085 else if (strcmp(key,"drawConnected=") == 0)
00086 {
00087 bool show;
00088 if ( strcmp( value,"0" ) == 0 )
00089 show = false;
00090 else
00091 show = true;
00092 setDrawConnected(show);
00093 }
00094 else if (strcmp(key,"trace=") == 0)
00095 {
00096 bool show;
00097 if ( strcmp( value,"0" ) == 0 )
00098 show = false;
00099 else
00100 show = true;
00101 setTrace(show);
00102 }
00103 }
00104
00105 void ExpressionGraph::paintEvent(QPaintEvent *)
00106 {
00107 buffer->fill(backgroundColor());
00108 p->begin(buffer);
00109 paint(p);
00110 p->end();
00111
00112 bitBlt(this,0,0,buffer);
00113 }
00114
00115 void ExpressionGraph::drawAfterAxis(QPainter *p)
00116 {
00117 drawExpressions(p);
00118 }
00119
00120 void ExpressionGraph::exportAsImage(const QString& file, const QString& fileType)
00121 {
00122 QPixmap pm(width(),height());
00123 getPixmap(pm);
00124
00125 pm.save(file,fileType);
00126 }
00127
00128 void ExpressionGraph::getPixmap(QPixmap &pm)
00129 {
00130 pm.fill(backgroundColor());
00131 QPainter painter;
00132 painter.begin(&pm);
00133 paint(&painter);
00134 painter.end();
00135 }
00136
00137 void ExpressionGraph::print(
00138 #ifdef KDE_APP
00139 KPrinter *printer
00140 #else
00141 QPrinter *printer
00142 #endif
00143 )
00144 {
00145 if ( printer->setup(this) )
00146 {
00147 qDebug( "Printing...");
00148 QPainter p;
00149 if ( !p.begin( printer ) )
00150 return;
00151 p.setClipRect(0,0,width(),height());
00152 p.fillRect(0,0,width(),height(),backgroundColor());
00153 int tempWidth = functionWidth;
00154 functionWidth = 2;
00155 paint(&p);
00156 functionWidth = tempWidth;
00157 p.end();
00158 qDebug( "Printing completed");
00159 }
00160 else
00161 qDebug( "Printing aborted" );
00162 }
00163
00164 Expression ExpressionGraph::getExpression(unsigned int i) const
00165 {
00166 return (functions.size() >= i + 1 && functions[i]) ? *functions[i] : Expression("",true,QColor());
00167 }
00168
00169
00170 void ExpressionGraph::drawExpressions(QPainter *painter)
00171 {
00172 QFontMetrics metrics(painter->font());
00173
00174 int shown_exp = 0;
00175 for(unsigned int i=((only_show_active)?expressionIndex:0); i<((only_show_active)?expressionIndex+1:functions.size()); i++)
00176 {
00177 if (functions.size() <= i){return;}
00178 if (functions[i]->show == false){continue;}
00179
00180 painter->setPen(QPen(functions[i]->color,functionWidth));
00181
00182
00183
00184
00185 drawExpression(painter,*functions[i]);
00186
00187 painter->setFont(graphFont);
00188 painter->setPen(QPen(functions[i]->color,functionWidth));
00189
00190 if ( displayExpressionText )
00191 {
00192 for (unsigned int n=0; n<var_count(); n++)
00193 painter->drawText(30,35+(metrics.height()+1)*(shown_exp*var_count()+n),QString("%1%2=").arg(dependent_var(n)).arg(i+1)+QString(functions[i]->getExpression(dependent_var(n)).c_str()));
00194
00195 shown_exp++;
00196 }
00197 }
00198
00199 if ( displayAnimatorValue() )
00200 {
00201 painter->setPen(QColor(255,255,255));
00202 painter->drawText(30,height()-metrics.height(),QString("n=%1").arg(animatorValue()));
00203 }
00204 }
00205
00206 void ExpressionGraph::drawExpressionAt(QPainter *, int)
00207 {
00208
00209 }
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 void ExpressionGraph::setShowCurrentExpression(bool state)
00228 {
00229 if (functions.size() >= expressionIndex + 1)
00230 functions[expressionIndex]->show = state; repaint(false);
00231 }
00232
00233 void ExpressionGraph::setTrace(bool b)
00234 {
00235 doTrace = b;
00236
00237 if ( doTrace == false )
00238 emit activeCoordinateChanged(QString(""),QString(""),QString(""));
00239
00240 repaint(false);
00241 }
00242
00243 void ExpressionGraph::addExpression(const Expression & expression)
00244 {
00245 std::string error;
00246 if (isValidExpression(expression,&error))
00247 {
00248 emit infoMessageReady("");
00249
00250 Expression *node = new Expression(expression);
00251
00252
00253 for( unsigned int i = 0; i < var_count(); i++ )
00254 {
00255 FungParser *fp = new FungParser;
00256
00257 std::string s = node->getExpression(dependent_var(i));
00258 qDebug("Adding: %s",s.c_str());
00259 parseExpression(s,fp,i);
00260 node->setParsedExpression(fp,dependent_var(i));
00261 }
00262
00263 if (functions.size() < expressionIndex+1)
00264 functions.resize(functions.size()+1);
00265 else
00266 delete functions[expressionIndex];
00267
00268 functions[expressionIndex]=node;
00269
00270 reparseAll();
00271
00272 cancelMathFunctions();
00273
00274 repaint(false);
00275 }
00276 else
00277 emit infoMessageReady(error.c_str());
00278 }
00279
00280 void ExpressionGraph::removeExpression(unsigned int index)
00281 {
00282 if (functions.size() >= index + 1)
00283 {
00284 for( unsigned int i=0; i<var_count(); i++)
00285 functions[index]->getParsedExpression(dependent_var(i));
00286
00287 functions.erase(functions.begin()+index);
00288 }
00289
00290 reparseAll();
00291
00292 cancelMathFunctions();
00293
00294 repaint(false);
00295 }
00296
00297 void ExpressionGraph::prevExpression()
00298 {
00299 if (expressionIndex == 0)
00300 expressionIndex = functions.size();
00301 else
00302 expressionIndex--;
00303
00304 cancelMathFunctions();
00305 repaint(false);
00306 }
00307
00308 void ExpressionGraph::nextExpression()
00309 {
00310 if (expressionIndex == functions.size())
00311 expressionIndex = 0;
00312 else
00313 expressionIndex++;
00314
00315 cancelMathFunctions();
00316 repaint(false);
00317 }
00318
00319 void ExpressionGraph::mouseMoveEvent(QMouseEvent *m)
00320 {
00321 if ( isTracing() && (functions.size() >= expressionIndex + 1) )
00322 {
00323 if (functions.size() < expressionIndex + 1)
00324 return;
00325
00326 setMouseX(traceDepX(toGraphXCoord(m->x())));
00327 setMouseY(traceDepY(toGraphYCoord(m->y())));
00328
00329 double mousex,mousey;
00330 int error = setXYForTrace(getMouseX(),getMouseY(),&mousex,&mousey,*functions[expressionIndex]);
00331
00332 if (error)
00333 {
00334 putUndefinedMessage(getMouseX(),getMouseY());
00335 repaint(false);
00336 return;
00337 }
00338
00339 setMouseX(mousex,false);
00340 setMouseY(mousey,false);
00341
00342 repaint(false);
00343
00344 int pixel_mouse_x = toPixelXCoord(getMouseX());
00345 int pixel_mouse_y = toPixelYCoord(getMouseY());
00346
00347 QPainter painter(this);
00348 painter.setPen(QPen(QColor(10,200,50),0,Qt::DotLine));
00349 painter.drawRect(pixel_mouse_x-3,pixel_mouse_y-3,6,6);
00350 painter.drawLine(pixel_mouse_x,0,pixel_mouse_x,height());
00351 painter.drawLine(0,pixel_mouse_y,width(),pixel_mouse_y);
00352 updateCoords();
00353 }
00354 else
00355 BasicGraph::mouseMoveEvent(m);
00356 }
00357
00358 bool ExpressionGraph::isValidExpression(const Expression &expression, std::string *errorMsg)
00359 {
00360 int ret;
00361 for (unsigned int i=0; i<var_count(); i++)
00362 {
00363 FungParser fp;
00364 std::string s = expression.getExpression(dependent_var(i));
00365 qDebug("ExpressionGraph::isValidExpression()");
00366 ret = parseExpression(s,&fp,i);
00367
00368 if (ret != -1)
00369 {
00370 if (errorMsg)
00371 *errorMsg = ((var_count() > 1) ? std::string(dependent_var(i))+": " : "") + std::string(fp.ErrorMsg());
00372 return false;
00373 }
00374 }
00375 return true;
00376 }
00377
00378 int ExpressionGraph::parseExpression( std::string & expression, FungParser *fp, int i)
00379 {
00380 return fp->Parse(expression,std::string(std::string(independent_vars())+",n").c_str(),dependent_var(i),functions,!angle);
00381 }
00382
00383 void ExpressionGraph::reparseAll()
00384 {
00385 qDebug("ExpressionGraph::reparseAll()");
00386 for ( unsigned int i = 0; i < functions.size(); i++ )
00387 {
00388 for ( unsigned int n = 0; n < var_count(); n++ )
00389 {
00390 std::string s = functions[i]->getExpression(dependent_var(n));
00391
00392 FungParser *fp = new FungParser;
00393 parseExpression( s, fp, n );
00394
00395 functions[i]->setParsedExpression(fp,dependent_var(n));
00396 }
00397 }
00398 }
00399
00400 void ExpressionGraph::putUndefinedMessage(double x, double)
00401 {
00402 emit activeCoordinateChanged( QString("%1 = %2").arg(independent_vars()).arg(x),
00403 QString("%1 = Undefined").arg(dependent_var()) );
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 FungParser * ExpressionGraph::getParsedCurrentExpression(int i)
00420 {
00421 if (functions.size() < expressionIndex + 1)
00422 return 0;
00423 return functions[expressionIndex]->getParsedExpression(dependent_var(i));
00424 }
00425
00426 void ExpressionGraph::nextFrameReady()
00427 {
00428 emit animationValueChanged(animatorValue());
00429 repaint(false);
00430 }