graph_inset.cpp

00001 #include <util/graph_inset.h>
00002 
00003 #include <iostream>
00004 
00005 #include <QSize>
00006 #include <QString>
00007 #include <QFile>
00008 #include <QTextStream>
00009 
00010 #include <viewer.h>
00011 #include <util/palette.h>
00012 
00013 #include <util/gl.h>
00014 
00015 namespace util
00016 {
00017 
00018   using std::endl;
00019   using std::cerr;
00020 
00021   GraphInset::GraphInset(int nb_lines)
00022     : _numberOfLines(nb_lines)
00023     , initialized(false)
00024     , closed(true)
00025   {
00026   }
00027 
00028   void GraphInset::readParms(const QString& section, util::Parms parms)
00029   {
00030     parms(section, "Size", windowSize);
00031     parms(section, "Position", windowPosition);
00032 
00033     parms(section, "ShowAll", showAll);
00034     if(!showAll)
00035     {
00036       parms(section, "Show", showIndices);
00037     }
00038     else
00039     {
00040       showIndices.clear();
00041       for(size_t i = 0 ; i < _numberOfLines ; ++i)
00042       {
00043         showIndices.push_back(i+1);
00044       }
00045     }
00046     cerr << "Number of lines to be shown: " << showIndices.size() << endl;
00047 
00048     parms.all(section, "LineColor", linesColor);
00049     parms.all(section, "LineWidth", linesWidth);
00050     parms.all(section, "LineMinMaxView", linesMinMaxView);
00051     parms.all(section, "LineOffset", linesOffset);
00052 
00053     parms(section, "ContourColor", contourColor);
00054     parms(section, "ContourWidth", contourWidth);
00055     parms(section, "ContourOffset", contourOffset);
00056     parms(section, "TimeSpan", timeSpan);
00057     parms(section, "BackColor", backColor);
00058     parms(section, "BackOffset", backgroundOffset);
00059     parms(section, "ChangeSourceColor", changeSourceColor);
00060     parms(section, "ChangeSourceWidth", changeSourceWidth);
00061     parms(section, "ChangeSourceOffset", changeSourceOffset);
00062     parms(section, "KeepAllData", keepAllData);
00063     parms(section, "AutoOpenClose", autoOpenClose);
00064     check();
00065   }
00066 
00067   void GraphInset::setNumberOfLines(size_t nb_lines)
00068   {
00069     if(_numberOfLines != nb_lines)
00070     {
00071       _numberOfLines = nb_lines;
00072       if(showAll)
00073       {
00074         showIndices.clear();
00075         for(size_t i = 0 ; i < nb_lines ; ++i)
00076         {
00077           showIndices.push_back(i);
00078         }
00079       }
00080       else
00081       {
00082         for(size_t i = 0 ; i < showIndices.size() ; ++i)
00083         {
00084           if(showIndices[i] > nb_lines)
00085           {
00086             cerr << "Warning, you are trying to show line " << showIndices[i] << " when there is only " << nb_lines << " to be seen" << endl;
00087           }
00088         }
00089       }
00090     }
00091   }
00092 
00093   void GraphInset::clear()
00094   {
00095     data.clear();
00096     if(autoOpenClose)
00097       closeGraph();
00098   }
00099 
00100   void GraphInset::addData( double t, const std::vector<double>& values, bool changed )
00101   {
00102     data.push_back(Data(t,values, changed));
00103     if(autoOpenClose)
00104       openGraph();
00105     if(time < t)
00106       time = t;
00107   }
00108 
00109   void GraphInset::dataSourceChanged()
00110   {
00111     if(!data.empty())
00112       data.back().changed = true;
00113   }
00114 
00115   void GraphInset::cleanData()
00116   {
00117     while(!data.empty() && (time - data.front().time) > timeSpan)
00118     {
00119       data.pop_front();
00120     }
00121     if(autoOpenClose && data.empty())
00122       closeGraph();
00123   }
00124 
00125   void GraphInset::draw(Viewer* viewer, const util::Palette& palette)
00126   {
00127     if(!initialized)
00128     {
00129       cerr << "Trying to draw an uninitialized graph" << endl;
00130       return;
00131     }
00132     if(!keepAllData)
00133       cleanData();
00134     if(!closed)
00135     {
00136       glPushAttrib(GL_LIGHTING_BIT|GL_LINE_BIT|GL_POLYGON_BIT);
00137       glDisable(GL_LIGHTING);
00138       QSize wndSize = viewer->size();
00139       int x1,y1,x2,y2;
00140       if(windowPosition.x() < 0)
00141         x1 = wndSize.width() + windowPosition.x();
00142       else
00143         x1 = windowPosition.x();
00144       if(windowPosition.y() < 0)
00145         y1 = wndSize.height() + windowPosition.y();
00146       else
00147         y1 = windowPosition.y();
00148       x2 = x1+(int)windowSize.x();
00149       y2 = y1+(int)windowSize.y();
00150       viewer->startScreenCoordinatesSystem();
00151       // First draw a square
00152       glPolygonMode(GL_FRONT, GL_FILL);
00153       if(backColor >= 0)
00154       {
00155         palette.useColor(backColor);
00156         glBegin(GL_POLYGON);
00157         glVertex3d(x1,y1,backgroundOffset);
00158         glVertex3d(x1,y2,backgroundOffset);
00159         glVertex3d(x2,y2,backgroundOffset);
00160         glVertex3d(x2,y1,backgroundOffset);
00161         glEnd();
00162       }
00163       glPolygonMode(GL_FRONT, GL_LINE);
00164       palette.useColor(contourColor);
00165       glLineWidth(contourWidth);
00166       glBegin(GL_POLYGON);
00167       glVertex3d(x1,y1,contourOffset);
00168       glVertex3d(x1,y2,contourOffset);
00169       glVertex3d(x2,y2,contourOffset);
00170       glVertex3d(x2,y1,contourOffset);
00171       glEnd();
00172       if((data.size() > 1) && (time - data.back().time) < timeSpan)
00173       {
00174         std::list<Data>::reverse_iterator it;
00175         double ratio_x = windowSize.x()/timeSpan;
00176         for(size_t idx = 0 ; idx < showIndices.size() ; ++idx)
00177         {
00178           size_t k = showIndices[idx]-1;
00179           if(k >= _numberOfLines)
00180             continue;
00181           glLineWidth(linesWidth[k]);
00182           double ratio_y = (windowSize.y()-contourWidth)/(linesMinMaxView[k][1] - linesMinMaxView[k][0]);
00183           double shift_y = linesMinMaxView[k][0];
00184           palette.useColor(linesColor[k]);
00185           glBegin(GL_LINE_STRIP);
00186           for(it = data.rbegin() ; it != data.rend() ; ++it)
00187           {
00188             const Data& d = *it;
00189             if((time - d.time) > timeSpan)
00190               break;
00191             const std::vector<double>& values = d.values;
00192             double x = x2 + (d.time - time)*ratio_x;
00193             glVertex3d(x, y2 - std::max(std::min((values[k]-shift_y)*ratio_y,(double)windowSize.y()), 0.0), linesOffset[k]);
00194             if(d.changed)
00195             {
00196               glEnd();
00197               glBegin(GL_LINE_STRIP);
00198             }
00199           }
00200           glEnd();
00201         }
00202         palette.useColor(changeSourceColor);
00203         glLineWidth(changeSourceWidth);
00204         glBegin(GL_LINES);
00205         for(it = data.rbegin() ; it != data.rend() ; ++it)
00206         {
00207           const Data& d = *it;
00208           if((time - d.time) > timeSpan)
00209             break;
00210           if(d.changed)
00211           {
00212             //            double x = x1 + (d.time-shift_time)*ratio_x;
00213             double x = x2 + (d.time - time)*ratio_x;
00214             glVertex3d(x, y1, changeSourceOffset);
00215             glVertex3d(x, y2, changeSourceOffset);
00216           }
00217         }
00218         glEnd();
00219       }
00220       viewer->stopScreenCoordinatesSystem();
00221       glPopAttrib();
00222     }
00223   }
00224 
00225   void GraphInset::drawWithName(size_t id, Viewer* viewer)
00226   {
00227     util::Palette palette;
00228     glPushName((GLuint)id);
00229     draw(viewer,palette);
00230     glPopName();
00231   }
00232 
00233   void GraphInset::check()
00234   {
00235     initialized = false;
00236     if(_numberOfLines <= 0)
00237     {
00238       cerr << "Number of lines <= 0" << endl;
00239       return;
00240     }
00241     forall(const Data& d, data)
00242     {
00243       if(d.values.size() != _numberOfLines)
00244       {
00245         cerr << "Number of values inconsistant with the number of lines" << endl;
00246         return;
00247       }
00248     }
00249     if(linesWidth.size() < showIndices.size())
00250     {
00251       cerr << "Number of line widths < number of shown lines" << endl;
00252       return;
00253     }
00254     if(linesColor.size() < showIndices.size())
00255     {
00256       cerr << "Number of line colors < number of shown lines" << endl;
00257       return;
00258     }
00259     if(linesMinMaxView.size() < showIndices.size())
00260     {
00261       cerr << "Number of line min max views < number of shown lines" << endl;
00262       return;
00263     }
00264     if(linesOffset.size() < showIndices.size())
00265     {
00266       cerr << "Number of line offsets < number of shown lines" << endl;
00267       return;
00268     }
00269     forall(double& w, linesWidth)
00270     {
00271       if(w < 0)
00272       {
00273         cerr << "Line width < 0" << endl;
00274         return;
00275       }
00276     }
00277     forall(int& c, linesColor)
00278     {
00279       if(c < 0 || c > 255)
00280       {
00281         cerr << "Line color < 0 or > 255" << endl;
00282         return;
00283       }
00284     }
00285     if(contourWidth < 0)
00286     {
00287       cerr << "Contour width < 0" << endl;
00288       return;
00289     }
00290     if(contourColor < 0 || contourColor > 255)
00291     {
00292       cerr << "Contour color < 0 or > 255" << endl;
00293       return;
00294     }
00295     if(changeSourceWidth < 0)
00296     {
00297       cerr << "Source width < 0" << endl;
00298       return;
00299     }
00300     if(changeSourceColor < 0 || changeSourceColor > 255)
00301     {
00302       cerr << "Source color < 0 or > 255" << endl;
00303       return;
00304     }
00305     initialized = true;
00306   }
00307 
00308   void GraphInset::closeGraph()
00309   {
00310     closed = true;
00311   }
00312 
00313   void GraphInset::openGraph()
00314   {
00315     closed = false;
00316   }
00317 
00318   bool GraphInset::writeCSV(const QString& filename)
00319   {
00320     QFile f(filename);
00321     if(!f.open(QIODevice::WriteOnly))
00322     {
00323       cerr << "Error, cannot open file " << filename.toStdString() << " for writing" << endl;
00324       return false;
00325     }
00326     QTextStream ts(&f);
00327     ts << "Time";
00328     for(size_t i = 0 ; i < _numberOfLines ; ++i)
00329     {
00330       ts << ",Data" << i;
00331     }
00332     ts << ",Source Changed\r\n";
00333     ts.setRealNumberNotation(QTextStream::SmartNotation);
00334     ts.setRealNumberPrecision(15);
00335     forall(const Data& d, data)
00336     {
00337       ts << d.time;
00338       for(size_t i = 0 ; i < _numberOfLines ; ++i)
00339       {
00340         ts << "," << d.values[i];
00341       }
00342       ts << (int)d.changed << "\r\n";
00343     }
00344     f.close();
00345     return true;
00346   }
00347 
00348 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Fri May 31 15:37:53 2013 for VVE by  doxygen 1.6.3