00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00066
00067
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);
00112 }
00113
00114 void GLExpressionGraph::initializeGL()
00115 {
00116 GLBasicGraph::initializeGL();
00117
00118 recompileLists();
00119 }
00120
00121 void GLExpressionGraph::paintGL()
00122 {
00123 GLBasicGraph::paintGL();
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
00133 glCallList(functions[i]->name);
00134
00135
00136
00137
00138
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
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
00229
00230
00231
00232 glEndList();
00233 }
00234 else
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
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];
00287 functions.erase(functions.begin()+index);
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
00387
00388
00389
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";
00438 *output << "Fung-Calc " << dependent_var() << char('1'+layer) << "\n";
00439 *output << "62\n";
00440 *output << "7\n";
00441
00442
00443 *output << "10\n";
00444 *output << values[x][y].x() << "\n";
00445 *output << "20\n";
00446 *output << values[x][y].y() << "\n";
00447 *output << "30\n";
00448 *output << values[x][y].z() << "\n";
00449
00450
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
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
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 }