Home

Download

Features

Screenshots

Handbook

Browse Source

Authors

SourceForge.net Logo
Hosted by SourceForge.net

OSI Certified


Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   Related Pages   Search  

expressiongraph.cpp

00001 /***************************************************************************
00002                           expressiongraph.cpp  -  description
00003                              -------------------
00004     begin                : Fri Dec 20 2002
00005     copyright            : (C) 2002 by Fungmeista
00006     email                : mizunoami44@users.sourceforge.net
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
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         //stream.get(alpha,sizeof(alpha),':');
00070         //QString sy(alpha);
00071         //stream.ignore(sizeof(char));
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); //draw BasicGraph stuff (axis and grid)
00134     painter.end();
00135 }
00136 
00137 void ExpressionGraph::print(
00138     #ifdef KDE_APP
00139     KPrinter *printer
00140     #else
00141     QPrinter *printer
00142     #endif //KDE_APP
00143     )
00144 {
00145     if ( printer->setup(this) )
00146     {               // printer dialog
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; //temporarily make the functions bigger for printing
00154         functionWidth = 2;
00155                 paint(&p); //paint stuff from BasicGraph
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         //if (!isValidExpression(functions[i])) //do a few checks before deleting this...
00183         //  return;
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++; //control reaches here only if the expression at this index of i is showing so increase number of shown expressions
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 void ExpressionGraph::callDrawExpression(Expression &expression, QPainter *painter)
00212 {
00213 //  FungParser fp(angle);
00214 
00215 //  std::string s = expression.expression();
00216 //  parseExpression(s,&fp);
00217 
00218     drawExpression(painter,expression);
00219 }
00220 */
00221 /*void ExpressionGraph::setColor(const QColor& c, unsigned int index)
00222 {
00223     functions[index]->color = c;
00224     repaint(false);
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("")); //clear coordinates
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         //node->setDeleteable(true);
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) // oops, there is no current function
00333         {
00334             putUndefinedMessage(getMouseX(),getMouseY());
00335             repaint(false); //repaint to clear trace cursor
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); //there's nothing this class should do with the mouse, pass it to BasicGraph for default behavior
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 FungParser * ExpressionGraph::getParsedExpression( int index, int i )
00407 {
00408     qDebug("ExpressionGraph::getParsedExpression()");
00409     FungParser *fp = new FungParser(getAngle());
00410     if (functions.size() < index + 1)
00411         return 0;
00412     std::string s = functions[index]->getExpression(dependent_var(i)); 
00413     int ret = fp->Parse(s,independent_vars(),dependent_var(i),functions,'n',animatorValue());
00414     if (ret != -1)
00415         return 0;
00416     return fp;   
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 }