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  

glexpressiongraph.cpp

00001 /***************************************************************************
00002                           glexpressiongraph.cpp  -  description
00003                              -------------------
00004     begin                : Mon Dec 2 2002
00005     copyright            : (C) 2002-03 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 "glexpressiongraph.h"
00019 
00020 #include <cmath>
00021 #include <sstream>
00022 
00023 #include <qapp.h>
00024 #include <qimage.h>
00025 
00026 #include "fungparser.h"
00027 #include "cartesian3dcoord.h"
00028 
00029 GLExpressionGraph::GLExpressionGraph(QWidget *parent, const char *name) : GLBasicGraph(parent,name), Animator()
00030 {
00031     expressionIndex = 0;
00032 
00033     angle = 0;
00034 
00035     drawConnected = true;
00036     showGrid = true;
00037     _gridColor = QColor(0,0,0);
00038     doTrace = false;
00039 
00040     x_percent_res = y_percent_res = 10;
00041 
00042     initializeAnimator( this );
00043 }
00044 
00045 GLExpressionGraph::~GLExpressionGraph()
00046 {
00047     for( std::vector<Expression*>::const_iterator it = functions.begin(); it != functions.end(); it++ )
00048         delete (*it);
00049 }
00050 
00051 void GLExpressionGraph::load_key( const char *key, const char *value )
00052 {
00053     GLBasicGraph::load_key(key,value);
00054     Animator::load_key(key,value);
00055     
00056     if (strcmp(key,"Function=") == 0)
00057     {
00058         char alpha[256];
00059         std::stringstream stream(value);
00060 
00061         stream.get(alpha,sizeof(alpha),':');
00062         QString sx(alpha);
00063         stream.ignore(sizeof(char));
00064 
00065         //stream.get(alpha,sizeof(alpha),':');
00066         //QString sy(alpha);
00067         //stream.ignore(sizeof(char));
00068         stream>>alpha;
00069 
00070         QColor color(alpha);
00071         stream>>alpha;
00072         bool show;
00073         if ( strcmp( alpha,"0" ) == 0 )
00074             show = false;
00075         else
00076             show = true;
00077 
00078         addExpression(Expression(sx,show,color));
00079         nextExpression();
00080     }
00081     else if (strcmp(key,"drawConnected=") == 0)
00082     {
00083         bool show;
00084         if ( strcmp( value,"0" ) == 0 )
00085             show = false;
00086         else
00087             show = true;
00088         setDrawConnected(show);
00089     }
00090     else if (strcmp(key,"trace=") == 0)
00091     {
00092         bool show;
00093         if ( strcmp( value,"0" ) == 0 )
00094             show = false;
00095         else
00096             show = true;
00097         setTrace(show);
00098     }
00099     else if (strcmp(key,"resolution=") == 0)
00100     {
00101         setResolution(QString(value).toInt());
00102     }
00103 }
00104 
00105 void GLExpressionGraph::resizeGL( int w, int h )
00106 {
00107     GLBasicGraph::resizeGL( w, h );
00108 
00109     qDebug("resizing GLExpressionGraph( w = %d, h = %d",w,h); 
00110 
00111     setResolution(x_percent_res); //resolution depends upon the physical height and width of graph so update
00112 }
00113 
00114 void GLExpressionGraph::initializeGL()
00115 {
00116     GLBasicGraph::initializeGL();
00117     
00118     recompileLists();
00119 }
00120 
00121 void GLExpressionGraph::paintGL()
00122 {
00123     GLBasicGraph::paintGL(); //this will call glPushMatrix() without a coresponding glPopMatrix()
00124 
00125     glEnable( GL_POLYGON_OFFSET_FILL );
00126     glPolygonOffset( 1.0, 1.5 );
00127 
00128     for (unsigned int i=0; i<functions.size(); i++)
00129     {
00130         if (functions[i]->show)
00131         {
00132             //qglColor(functions[i]->color);
00133             glCallList(functions[i]->name);
00134             //glPushMatrix();
00135                 //glLoadIdentity();
00136                 //qglColor(functions[i]->color);
00137 //              drawText(getXMin()+0.5f, getYMin()+i+0.5f, 0.0f, QString("z%1(x,y)=").arg(i+1)+functions[i]->expression);
00138             //glPopMatrix();
00139 
00140         }
00141     }
00142 
00143     if (isTracing())
00144     {
00145         glColor3f(0.0f,1.0f,0.0f);
00146         drawCube(lastX,lastY,lastZ,5.0f,5.0f);
00147     }
00148     
00149     glPopMatrix();
00150 }
00151 
00152 void GLExpressionGraph::drawCube(GLfloat x, GLfloat y, GLfloat z, GLfloat percentx, GLfloat percenty )
00153 {
00154     GLfloat width  = fabs( getXMaxView() / ( _width /(getXMax() - getXMin()) ) ) * percentx / 100.0;
00155     GLfloat height = fabs( getYMaxView() / ( _height/(getYMax() - getYMin()) ) ) * percenty / 100.0;
00156     GLfloat depth = width;
00157 
00158     glBegin(GL_LINES);
00159         glVertex3f(x-width/2, y-height/2, z-depth/2); glVertex3f(x+width/2, y-height/2, z-depth/2);
00160         glVertex3f(x-width/2, y-height/2, z-depth/2); glVertex3f(x-width/2, y+height/2, z-depth/2);
00161         glVertex3f(x-width/2, y-height/2, z-depth/2); glVertex3f(x-width/2, y-height/2, z+depth/2);
00162         glVertex3f(x-width/2, y-height/2, z+depth/2); glVertex3f(x-width/2, y+height/2, z+depth/2);
00163         glVertex3f(x-width/2, y-height/2, z+depth/2); glVertex3f(x+width/2, y-height/2, z+depth/2);
00164         glVertex3f(x+width/2, y-height/2, z-depth/2); glVertex3f(x+width/2, y-height/2, z+depth/2);
00165         glVertex3f(x+width/2, y-height/2, z-depth/2); glVertex3f(x+width/2, y+height/2, z-depth/2);
00166         glVertex3f(x+width/2, y+height/2, z+depth/2); glVertex3f(x+width/2, y+height/2, z-depth/2);
00167         glVertex3f(x+width/2, y+height/2, z+depth/2); glVertex3f(x+width/2, y-height/2, z+depth/2);
00168         glVertex3f(x+width/2, y+height/2, z+depth/2); glVertex3f(x-width/2, y+height/2, z+depth/2);
00169         glVertex3f(x-width/2, y+height/2, z+depth/2); glVertex3f(x-width/2, y+height/2, z-depth/2);
00170         glVertex3f(x-width/2, y+height/2, z-depth/2); glVertex3f(x+width/2, y+height/2, z-depth/2);
00171     glEnd();
00172 }
00173 
00174 void GLExpressionGraph::recompileLists()
00175 {
00176     for (unsigned int i=0; i<functions.size(); i++)
00177     {
00178         FungParser fp;
00179         std::string s = functions[i]->getExpression(dependent_var());
00180         fp.Parse(s,std::string(std::string(independent_vars())+",n").c_str(),dependent_var(),functions,!angle);
00181         compileList(functions[i]->name,fp,s,functions[i]->color);
00182     }
00183 }
00184 
00185 void GLExpressionGraph::compileList(GLuint name, FungParser &fp, std::string &, const QColor &c)
00186 {
00187     GLfloat min, max;
00188     Cartesian3DCoord2DVector values = getValues(fp,&min,&max);
00189 
00190     if (isDrawConnected())
00191     {
00192         glNewList(name, GL_COMPILE);
00193             GLfloat z1, z2;
00194             for( unsigned int x = 0; x < values.size() - 1; x++ )
00195             {
00196                 glBegin(GL_QUAD_STRIP);
00197                     for ( unsigned int y = 0; y < values[x].size(); y++ )
00198                     {
00199                         z1 = values[x][y].z();
00200                         doColorBlend(z1,c,min,max);
00201                         glVertex3f(values[x][y].x(),values[x][y].y(),z1);
00202                     
00203                         z2 = values[x+1][y].z();
00204                         doColorBlend(z2,c,min,max);
00205                         glVertex3f(values[x+1][y].x(),values[x+1][y].y(),z2);
00206                     }
00207                 glEnd();
00208             }
00209 
00210             if (getGridState())
00211             {
00212                 qglColor(gridColor());
00213                 for( unsigned int x = 0; x < values.size() - 1; x++ )
00214                 {
00215                     glBegin(GL_LINES);
00216                         for ( unsigned int y = 0; y < values[x].size() - 1; y++ )
00217                         {
00218                             //qDebug("xsize: %d, ysize %d, x: %d, y: %d",values.size(),values[x].size(),x,y);
00219                             glVertex3f(values[x][y].x(),values[x][y].y(),values[x][y].z());
00220                             glVertex3f(values[x+1][y].x(),values[x+1][y].y(),values[x+1][y].z());
00221 
00222                             glVertex3f(values[x][y].x(),values[x][y].y(),values[x][y].z());
00223                             glVertex3f(values[x][y+1].x(),values[x][y+1].y(),values[x][y+1].z());
00224                         }
00225                     glEnd();
00226                 }
00227             }
00228             /*glPushMatrix();
00229                 glLoadIdentity();
00230                 drawText(getXMin(), getYMax() - 0.5f, 0.0f, expression.c_str());
00231             glPopMatrix();*/
00232         glEndList();
00233     }
00234     else      //draw not connected
00235     {
00236         glNewList(name, GL_COMPILE);
00237             glBegin(GL_POINTS);
00238                 qglColor(c);
00239                 for( unsigned int x = 0; x < values.size(); x++ )
00240                 {
00241                     for ( unsigned int y = 0; y < values[x].size(); y++ )
00242                     {
00243                         glVertex3f(values[x][y].x(),values[x][y].y(),values[x][y].z());
00244                     }
00245                 }
00246             glEnd();
00247         glEndList();
00248     }
00249 }
00250 
00251 void GLExpressionGraph::addExpression(const Expression & expression)
00252 {
00253     FungParser fp;
00254 
00255     std::string s = expression.getExpression(dependent_var());
00256     int ret = fp.Parse(s,std::string(std::string(independent_vars())+",n").c_str(),dependent_var(),functions,!angle);
00257 
00258     if (ret == -1)
00259     {
00260         emit infoMessageReady("");
00261                         
00262         Expression *node = new Expression(s,expression.show,expression.color,glGenLists(1));
00263 
00264         if (functions.size() < expressionIndex + 1)
00265             functions.resize(functions.size()+1);
00266         else
00267         {
00268             //glDeleteLists(functions[expressionIndex]->name,1);
00269             delete functions[expressionIndex];
00270         }
00271 
00272         functions[expressionIndex]=node;
00273 
00274         compileList(functions[expressionIndex]->name,fp,s,functions[expressionIndex]->color);
00275 
00276         updateGL();
00277     }
00278     else
00279         emit infoMessageReady(fp.ErrorMsg());
00280 }
00281 
00282 void GLExpressionGraph::removeExpression(unsigned int index)
00283 {
00284     if (functions.size() >= index + 1)
00285     {
00286         delete functions[index]; //delete the actual value in the pointer, functions[index]
00287         functions.erase(functions.begin()+index); //remove the pointer to functions[index] from the vector
00288     }
00289 
00290     updateGL();
00291 }
00292 
00293 void GLExpressionGraph::prevExpression()
00294 {
00295     if ( expressionIndex == 0 )
00296         expressionIndex = functions.size();
00297     else
00298         expressionIndex--;
00299 
00300     updateGL();
00301 }
00302 
00303 void GLExpressionGraph::nextExpression()
00304 {
00305     if ( expressionIndex == functions.size() )
00306         expressionIndex = 0;
00307     else
00308         expressionIndex++;
00309 
00310     updateGL();
00311 }
00312 
00313 void GLExpressionGraph::setShowCurrentExpression(bool state)
00314 {
00315     if ( expressionIndex < functions.size() )
00316     {
00317         functions[expressionIndex]->show = state;
00318         updateGL();
00319     }
00320 }
00321 
00322 void GLExpressionGraph::orthoChanged()
00323 {
00324     xScale = (getXMax()-getXMin())/xRes;
00325     yScale = (getYMax()-getYMin())/yRes;
00326 
00327     recompileLists();
00328 }
00329 
00330 void GLExpressionGraph::mouseMoveEvent(QMouseEvent *m)
00331 {
00332     if ( isTracing() && ( functions.size() > expressionIndex ) )
00333     {
00334         setMouseX(toGraphXCoord(m->x()));
00335         setMouseY(toGraphYCoord(m->y()));
00336 
00337         FungParser fp;
00338 
00339         std::string s = functions[expressionIndex]->getExpression(dependent_var());
00340         int ret = fp.Parse(s,std::string(std::string(independent_vars())+",n").c_str(),dependent_var(),functions,!angle);
00341         if (ret != -1){return;}
00342 
00343         trace(
00344             traceDepX(getMouseX()),
00345             traceDepY(getMouseY()),
00346             fp,
00347             &lastX,&lastY,&lastZ
00348         );
00349         updateGL();
00350     }
00351     GLBasicGraph::mouseMoveEvent(m);
00352 }
00353 
00354 void GLExpressionGraph::setResolution(int percent)
00355 {
00356     x_percent_res = y_percent_res = percent;
00357 
00358     if (percent < 0)
00359         percent = 0;
00360     if (percent > 100)
00361         percent = 100;
00362 
00363     setXRes(percent/100.0f*_width);
00364     setYRes(percent/100.0f*_height);
00365 
00366     recompileLists();
00367     updateGL();
00368 }
00369 
00370 int GLExpressionGraph::getResolution() const
00371 {
00372     return x_percent_res;
00373 }
00374 
00375 void GLExpressionGraph::doColorBlend(GLfloat f, const QColor & c, GLfloat z_min, GLfloat z_max)
00376 {
00377     glColor3f( (static_cast<double>(c.red())/255.0f) *((f-z_min)/(z_max-z_min)), (static_cast<double>(c.green())/255.0f) *((f-z_min)/(z_max-z_min)), (static_cast<double>(c.blue())/255.0f) *((f-z_min)/(z_max-z_min)) );
00378 }
00379 
00380 void GLExpressionGraph::nextFrameReady()
00381 {
00382     emit animationValueChanged(animatorValue());
00383     recompileLists();
00384     updateGL();
00385     
00386     /*if (isSaving())
00387     {
00388         QImage image = grabFrameBuffer();
00389         image.save(QString("/home/fungmeista/%1.png").arg(time(0)),"PNG");
00390     }*/
00391 }
00392 
00393 void GLExpressionGraph::exportToDXF( const char * file )
00394 {
00395     emit infoMessageReady("Exporting to DXF...");
00396 
00397     std::ofstream output;
00398     output.open(file);
00399     
00400     output << "0\n";
00401     output << "SECTION\n";
00402     output << "2\n";
00403     output << "ENTITIES\n"; 
00404     
00405     for ( unsigned int i = 0; i < functions.size(); i++ )
00406     {
00407         if ( functions[i]->show )
00408         {
00409             FungParser fp;
00410 
00411             std::string s = functions[i]->getExpression(dependent_var());
00412             int ret = fp.Parse(s,std::string(std::string(independent_vars())+",n").c_str(),dependent_var(),functions,!angle);
00413 
00414             Cartesian3DCoord2DVector values = getValues(fp);
00415             exportSingleExprDXF( values,  &output, i );
00416         }
00417     }
00418 
00419     output << "0\n";
00420     output << "ENDSEC\n";
00421     output << "0\n";
00422     output << "EOF\n";
00423     
00424     output.close();
00425     
00426     emit infoMessageReady("Exporting to DXF... done");
00427 }
00428 
00429 void GLExpressionGraph::exportSingleExprDXF( const Cartesian3DCoord2DVector &values, std::ofstream *output, int layer )
00430 {
00431     for( unsigned int x = 0; x < values.size() - 1; x++ )
00432     {
00433         for ( unsigned int y = 0; y < values[x].size() - 1; y++ )
00434         {
00435             *output << "0\n";
00436             *output << "3DFACE\n";
00437             *output << "8\n"; //layer specifier
00438             *output << "Fung-Calc " << dependent_var() << char('1'+layer) << "\n"; //layer name
00439             *output << "62\n"; //color specifier
00440             *output << "7\n"; //color index
00441 
00442             /* first vertex */
00443             *output << "10\n";
00444             *output << values[x][y].x() << "\n"; //x
00445             *output << "20\n";    
00446             *output << values[x][y].y() << "\n"; //y
00447             *output << "30\n";
00448             *output << values[x][y].z() << "\n"; //z
00449 
00450             /* second vertex */
00451             *output << "11\n";
00452             *output << values[x+1][y].x() << "\n"; 
00453             *output << "21\n";
00454             *output << values[x+1][y].y() << "\n";
00455             *output << "31\n";
00456             *output << values[x+1][y].z() << "\n";
00457 
00458             /* third vertex */
00459             *output << "12\n";
00460             *output << values[x+1][y+1].x() << "\n";
00461             *output << "22\n";
00462             *output << values[x+1][y+1].y() << "\n";
00463             *output << "32\n";
00464             *output << values[x+1][y+1].z() << "\n";
00465 
00466             /* fourth vertex */
00467             *output << "13\n";
00468             *output << values[x][y+1].x() << "\n";
00469             *output << "23\n";
00470             *output << values[x][y+1].y() << "\n";
00471             *output << "33\n";
00472             *output << values[x][y+1].z() << "\n";
00473         }
00474         qApp->processEvents();
00475         emit infoMessageReady("Exporting to DXF...");
00476     }
00477 }