SUMO - Simulation of Urban MObility
GUIParameterTracker.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00009 // A window which displays the time line of one (or more) value(s)
00010 /****************************************************************************/
00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
00013 /****************************************************************************/
00014 //
00015 //   This file is part of SUMO.
00016 //   SUMO is free software: you can redistribute it and/or modify
00017 //   it under the terms of the GNU General Public License as published by
00018 //   the Free Software Foundation, either version 3 of the License, or
00019 //   (at your option) any later version.
00020 //
00021 /****************************************************************************/
00022 
00023 
00024 // ===========================================================================
00025 // included modules
00026 // ===========================================================================
00027 #ifdef _MSC_VER
00028 #include <windows_config.h>
00029 #else
00030 #include <config.h>
00031 #endif
00032 
00033 #include <string>
00034 #include <fstream>
00035 #include <foreign/polyfonts/polyfonts.h>
00036 #include <utils/foxtools/MFXUtils.h>
00037 #include <utils/iodevices/OutputDevice.h>
00038 #include <utils/common/ToString.h>
00039 #include <utils/common/StringUtils.h>
00040 #include <utils/common/SUMOTime.h>
00041 #include <utils/gui/globjects/GUIGlObject.h>
00042 #include <utils/gui/div/GUIIOGlobals.h>
00043 #include <utils/gui/windows/GUIAppEnum.h>
00044 #include <utils/gui/windows/GUIMainWindow.h>
00045 #include <utils/gui/images/GUIIconSubSys.h>
00046 #include "GUIParameterTracker.h"
00047 
00048 #ifdef _WIN32
00049 #include <windows.h>
00050 #endif
00051 
00052 #include <GL/gl.h>
00053 
00054 #ifdef CHECK_MEMORY_LEAKS
00055 #include <foreign/nvwa/debug_new.h>
00056 #endif // CHECK_MEMORY_LEAKS
00057 
00058 
00059 // ===========================================================================
00060 // FOX callback mapping
00061 // ===========================================================================
00062 FXDEFMAP(GUIParameterTracker) GUIParameterTrackerMap[] = {
00063     FXMAPFUNC(SEL_CONFIGURE, 0,                       GUIParameterTracker::onConfigure),
00064     FXMAPFUNC(SEL_PAINT,     0,                       GUIParameterTracker::onPaint),
00065     FXMAPFUNC(SEL_COMMAND,   MID_SIMSTEP,             GUIParameterTracker::onSimStep),
00066     FXMAPFUNC(SEL_COMMAND,   GUIParameterTracker::MID_AGGREGATIONINTERVAL, GUIParameterTracker::onCmdChangeAggregation),
00067     FXMAPFUNC(SEL_COMMAND,   GUIParameterTracker::MID_SAVE, GUIParameterTracker::onCmdSave),
00068 
00069 };
00070 
00071 // Macro for the GLTestApp class hierarchy implementation
00072 FXIMPLEMENT(GUIParameterTracker, FXMainWindow, GUIParameterTrackerMap, ARRAYNUMBER(GUIParameterTrackerMap))
00073 
00074 
00075 // ===========================================================================
00076 // method definitions
00077 // ===========================================================================
00078 GUIParameterTracker::GUIParameterTracker(GUIMainWindow& app,
00079         const std::string& name)
00080     : FXMainWindow(app.getApp(), "Tracker", NULL, NULL, DECOR_ALL, 20, 20, 300, 200),
00081       myApplication(&app) {
00082     buildToolBar();
00083     app.addChild(this, true);
00084     FXVerticalFrame* glcanvasFrame = new FXVerticalFrame(this, FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 0, 0, 0, 0, 0, 0);
00085     myPanel = new GUIParameterTrackerPanel(glcanvasFrame, *myApplication, *this);
00086     setTitle(name.c_str());
00087     setIcon(GUIIconSubSys::getIcon(ICON_APP_TRACKER));
00088 }
00089 
00090 
00091 GUIParameterTracker::~GUIParameterTracker() {
00092     myApplication->removeChild(this);
00093     for (std::vector<TrackerValueDesc*>::iterator i1 = myTracked.begin(); i1 != myTracked.end(); i1++) {
00094         delete(*i1);
00095     }
00096     // deleted by GUINet
00097     for (std::vector<GLObjectValuePassConnector<SUMOReal>*>::iterator i2 = myValuePassers.begin(); i2 != myValuePassers.end(); i2++) {
00098         delete(*i2);
00099     }
00100     delete myToolBarDrag;
00101     delete myToolBar;
00102 }
00103 
00104 
00105 void
00106 GUIParameterTracker::create() {
00107     FXMainWindow::create();
00108     myToolBarDrag->create();
00109 }
00110 
00111 
00112 void
00113 GUIParameterTracker::buildToolBar() {
00114     myToolBarDrag = new FXToolBarShell(this, FRAME_NORMAL);
00115     myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
00116     new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
00117     // save button
00118     new FXButton(myToolBar, "\t\tSave the data...",
00119                  GUIIconSubSys::getIcon(ICON_SAVE), this, GUIParameterTracker::MID_SAVE,
00120                  ICON_ABOVE_TEXT | BUTTON_TOOLBAR | FRAME_RAISED | LAYOUT_TOP | LAYOUT_LEFT);
00121     // aggregation interval combo
00122     myAggregationInterval =
00123         new FXComboBox(myToolBar, 8, this, MID_AGGREGATIONINTERVAL,
00124                        FRAME_SUNKEN | LAYOUT_LEFT | LAYOUT_TOP | COMBOBOX_STATIC);
00125     myAggregationInterval->appendItem("1s");
00126     myAggregationInterval->appendItem("1min");
00127     myAggregationInterval->appendItem("5min");
00128     myAggregationInterval->appendItem("15min");
00129     myAggregationInterval->appendItem("30min");
00130     myAggregationInterval->appendItem("60min");
00131     myAggregationInterval->setNumVisible(6);
00132 }
00133 
00134 
00135 void
00136 GUIParameterTracker::addTracked(GUIGlObject& o, ValueSource<SUMOReal> *src,
00137                                 TrackerValueDesc* newTracked) {
00138     myTracked.push_back(newTracked);
00139     // build connection (is automatically set into an execution map)
00140     myValuePassers.push_back(new GLObjectValuePassConnector<SUMOReal>(o, src, newTracked));
00141 }
00142 
00143 
00144 long
00145 GUIParameterTracker::onConfigure(FXObject* sender, FXSelector sel, void* data) {
00146     myPanel->onConfigure(sender, sel, data);
00147     return FXMainWindow::onConfigure(sender, sel, data);
00148 }
00149 
00150 
00151 long
00152 GUIParameterTracker::onPaint(FXObject* sender, FXSelector sel, void* data) {
00153     myPanel->onPaint(sender, sel, data);
00154     return FXMainWindow::onPaint(sender, sel, data);
00155 }
00156 
00157 
00158 long
00159 GUIParameterTracker::onSimStep(FXObject*, FXSelector, void*) {
00160     update();
00161     return 1;
00162 }
00163 
00164 
00165 long
00166 GUIParameterTracker::onCmdChangeAggregation(FXObject*, FXSelector, void*) {
00167     int index = myAggregationInterval->getCurrentItem();
00168     size_t aggInt = 0;
00169     switch (index) {
00170         case 0:
00171             aggInt = 1;
00172             break;
00173         case 1:
00174             aggInt = 60;
00175             break;
00176         case 2:
00177             aggInt = 60 * 5;
00178             break;
00179         case 3:
00180             aggInt = 60 * 15;
00181             break;
00182         case 4:
00183             aggInt = 60 * 30;
00184             break;
00185         case 5:
00186             aggInt = 60 * 60;
00187             break;
00188         default:
00189             throw 1;
00190             break;
00191     }
00192     for (std::vector<TrackerValueDesc*>::iterator i1 = myTracked.begin(); i1 != myTracked.end(); i1++) {
00193         (*i1)->setAggregationSpan(TIME2STEPS(aggInt));
00194     }
00195     return 1;
00196 }
00197 
00198 
00199 long
00200 GUIParameterTracker::onCmdSave(FXObject*, FXSelector, void*) {
00201     FXString file = MFXUtils::getFilename2Write(this, "Save Data", ".csv", GUIIconSubSys::getIcon(ICON_EMPTY), gCurrentFolder);
00202     if (file == "") {
00203         return 1;
00204     }
00205     try {
00206         OutputDevice& dev = OutputDevice::getDevice(file.text());
00207         // write header
00208         std::vector<TrackerValueDesc*>::iterator i;
00209         dev << "# ";
00210         for (i = myTracked.begin(); i != myTracked.end(); ++i) {
00211             if (i != myTracked.begin()) {
00212                 dev << ';';
00213             }
00214             TrackerValueDesc* tvd = *i;
00215             dev << tvd->getName();
00216         }
00217         dev << '\n';
00218         // count entries
00219         size_t max = 0;
00220         for (i = myTracked.begin(); i != myTracked.end(); ++i) {
00221             TrackerValueDesc* tvd = *i;
00222             size_t sizei = tvd->getAggregatedValues().size();
00223             if (max < sizei) {
00224                 max = sizei;
00225             }
00226             tvd->unlockValues();
00227         }
00228         // write entries
00229         for (unsigned int j = 0; j < max; j++) {
00230             for (i = myTracked.begin(); i != myTracked.end(); ++i) {
00231                 if (i != myTracked.begin()) {
00232                     dev << ';';
00233                 }
00234                 TrackerValueDesc* tvd = *i;
00235                 dev << tvd->getAggregatedValues()[j];
00236                 tvd->unlockValues();
00237             }
00238             dev << '\n';
00239         }
00240         dev.close();
00241     } catch (IOError& e) {
00242         FXMessageBox::error(this, MBOX_OK, "Storing failed!", "%s", e.what());
00243     }
00244     return 1;
00245 }
00246 
00247 
00248 /* -------------------------------------------------------------------------
00249  * GUIParameterTracker::GUIParameterTrackerPanel-methods
00250  * ----------------------------------------------------------------------- */
00251 FXDEFMAP(GUIParameterTracker::GUIParameterTrackerPanel) GUIParameterTrackerPanelMap[] = {
00252     FXMAPFUNC(SEL_CONFIGURE, 0, GUIParameterTracker::GUIParameterTrackerPanel::onConfigure),
00253     FXMAPFUNC(SEL_PAINT,     0, GUIParameterTracker::GUIParameterTrackerPanel::onPaint),
00254 
00255 };
00256 
00257 // Macro for the GLTestApp class hierarchy implementation
00258 FXIMPLEMENT(GUIParameterTracker::GUIParameterTrackerPanel, FXGLCanvas, GUIParameterTrackerPanelMap, ARRAYNUMBER(GUIParameterTrackerPanelMap))
00259 
00260 
00261 
00262 GUIParameterTracker::GUIParameterTrackerPanel::GUIParameterTrackerPanel(
00263     FXComposite* c, GUIMainWindow& app,
00264     GUIParameterTracker& parent)
00265     : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y, 0, 0, 300, 200),
00266       myParent(&parent), myApplication(&app) {}
00267 
00268 
00269 GUIParameterTracker::GUIParameterTrackerPanel::~GUIParameterTrackerPanel() {}
00270 
00271 
00272 void
00273 GUIParameterTracker::GUIParameterTrackerPanel::drawValues() {
00274     pfSetScale((SUMOReal) 0.1);
00275     pfSetScaleXY((SUMOReal)(.1 * 300. / myWidthInPixels), (SUMOReal)(.1 * 300. / (SUMOReal) myHeightInPixels));
00276     //
00277     glMatrixMode(GL_PROJECTION);
00278     glLoadIdentity();
00279     glMatrixMode(GL_MODELVIEW);
00280     glLoadIdentity();
00281     glDisable(GL_TEXTURE_2D);
00282     size_t run = 0;
00283     for (std::vector<TrackerValueDesc*>::iterator i = myParent->myTracked.begin(); i != myParent->myTracked.end(); i++) {
00284         TrackerValueDesc* desc = *i;
00285         drawValue(*desc,
00286                   (SUMOReal) myWidthInPixels / (SUMOReal) myParent->myTracked.size() * (SUMOReal) run);
00287         run++;
00288     }
00289 }
00290 
00291 
00292 void
00293 GUIParameterTracker::GUIParameterTrackerPanel::drawValue(TrackerValueDesc& desc,
00294         SUMOReal /*namePos*/) {
00295     // apply scaling
00296     glPushMatrix();
00297 
00298     // apply the positiopn offset of the display
00299     glScaled(0.8, 0.8, 1);
00300     // apply value range scaling
00301     SUMOReal ys = (SUMOReal) 2.0 / (SUMOReal) desc.getRange();
00302     glScaled(1.0, ys, 1.0);
00303     glTranslated(-1.0, -desc.getYCenter(), 0);
00304 
00305     // set color
00306     const RGBColor& col = desc.getColor();
00307     SUMOReal red = (SUMOReal) col.red();
00308     SUMOReal green = (SUMOReal) col.green();
00309     SUMOReal blue = (SUMOReal) col.blue();
00310     // draw value bounderies
00311     // draw minimum boundary
00312     glBegin(GL_LINES);
00313     glVertex2d(0, desc.getMin());
00314     glVertex2d(2.0, desc.getMin());
00315     glEnd();
00316     glBegin(GL_LINES);
00317     glVertex2d(0, desc.getMax());
00318     glVertex2d(2.0, desc.getMax());
00319     glEnd();
00320     glColor4f(red, green, blue, 0.3f);
00321     for (int a = 1; a < 6; a++) {
00322         SUMOReal ypos = (desc.getRange()) / (SUMOReal) 6.0 * (SUMOReal) a + desc.getMin();
00323         glBegin(GL_LINES);
00324         glVertex2d(0, ypos);
00325         glVertex2d(2.0, ypos);
00326         glEnd();
00327     }
00328     const std::vector<SUMOReal> &values = desc.getAggregatedValues();
00329     SUMOReal latest = 0;
00330     if (values.size() < 2) {
00331         glPopMatrix();
00332         desc.unlockValues();
00333         return;
00334     } else {
00335         latest = values.back();
00336         // init values
00337         SUMOReal xStep = (SUMOReal) 2.0 / (SUMOReal) values.size();
00338         std::vector<SUMOReal>::const_iterator i = values.begin();
00339         SUMOReal yp = (*i);
00340         SUMOReal xp = 0;
00341         i++;
00342         glColor4f(red, green, blue, 1.0f);
00343         for (; i != values.end(); i++) {
00344             SUMOReal yn = (*i);
00345             SUMOReal xn = xp + xStep;
00346             glBegin(GL_LINES);
00347             glVertex2d(xp, yp);
00348             glVertex2d(xn, yn);
00349             glEnd();
00350             yp = yn;
00351             xp = xn;
00352         }
00353         desc.unlockValues();
00354         glPopMatrix();
00355     }
00356 
00357     // draw value bounderies and descriptions
00358     glColor3d(red, green, blue);
00359 
00360     // draw min time
00361     SUMOTime beginStep = desc.getRecordingBegin();
00362     std::string begStr = time2string(beginStep);
00363     SUMOReal w = pfdkGetStringWidth(begStr.c_str());
00364     glRotated(180, 1, 0, 0);
00365     pfSetPosition(0, 0);
00366     glTranslated(-0.8 - w / 2., 0.88, 0);
00367     pfDrawString(begStr.c_str());
00368     glTranslated(0.8 + w / 2., -0.88, 0);
00369     glRotated(-180, 1, 0, 0);
00370 
00371     // draw max time
00372     glRotated(180, 1, 0, 0);
00373     pfSetPosition(0, 0);
00374     glTranslated(0.75, 0.88, 0);
00375     pfDrawString(time2string(beginStep + static_cast<SUMOTime>(values.size() * desc.getAggregationSpan())).c_str());
00376     glTranslated(-0.75, -0.88, 0);
00377     glRotated(-180, 1, 0, 0);
00378 
00379     // draw min value
00380     glRotated(180, 1, 0, 0);
00381     pfSetPosition(0, 0);
00382     glTranslated(-0.98, 0.82, 0);
00383     pfDrawString(toString(desc.getMin()).c_str());
00384     glTranslated(0.98, -0.82, 0);
00385     glRotated(-180, 1, 0, 0);
00386 
00387     // draw max value
00388     glRotated(180, 1, 0, 0);
00389     pfSetPosition(0, 0);
00390     glTranslated(-0.98, -0.78, 0);
00391     pfDrawString(toString(desc.getMax()).c_str());
00392     glTranslated(0.98, 0.78, 0);
00393     glRotated(-180, 1, 0, 0);
00394 
00395     // draw current value
00396     glRotated(180, 1, 0, 0);
00397     pfSetPosition(0, 0);
00398     SUMOReal p = (SUMOReal) 0.8 -
00399                  ((SUMOReal) 1.6 / (desc.getMax() - desc.getMin()) * (latest - desc.getMin()));
00400     glTranslated(-0.98, p + .02, 0);
00401     pfDrawString(toString(latest).c_str());
00402     glTranslated(0.98, -(p + .02), 0);
00403     glRotated(-180, 1, 0, 0);
00404 
00405     // draw name
00406     glRotated(180, 1, 0, 0);
00407     pfSetPosition(0, 0);
00408     glTranslated(-0.98, -.92, 0);
00409     pfDrawString(desc.getName().c_str());
00410     glTranslated(0.98, .92, 0);
00411     glRotated(-180, 1, 0, 0);
00412 }
00413 
00414 
00415 long
00416 GUIParameterTracker::GUIParameterTrackerPanel::onConfigure(FXObject*,
00417         FXSelector, void*) {
00418     if (makeCurrent()) {
00419         myWidthInPixels = myParent->getWidth();
00420         myHeightInPixels = myParent->getHeight();
00421         if (myWidthInPixels != 0 && myHeightInPixels != 0) {
00422             glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
00423             glClearColor(1.0, 1.0, 1.0, 1);
00424             glDisable(GL_DEPTH_TEST);
00425             glDisable(GL_LIGHTING);
00426             glDisable(GL_LINE_SMOOTH);
00427             glEnable(GL_BLEND);
00428             glEnable(GL_ALPHA_TEST);
00429             glDisable(GL_COLOR_MATERIAL);
00430             glLineWidth(1);
00431             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00432         }
00433         makeNonCurrent();
00434     }
00435     return 1;
00436 }
00437 
00438 
00439 long
00440 GUIParameterTracker::GUIParameterTrackerPanel::onPaint(FXObject*,
00441         FXSelector, void*) {
00442     if (!isEnabled()) {
00443         return 1;
00444     }
00445     if (makeCurrent()) {
00446         myWidthInPixels = getWidth();
00447         myHeightInPixels = getHeight();
00448         if (myWidthInPixels != 0 && myHeightInPixels != 0) {
00449             glViewport(0, 0, myWidthInPixels - 1, myHeightInPixels - 1);
00450             glClearColor(1.0, 1.0, 1.0, 1);
00451             glDisable(GL_DEPTH_TEST);
00452             glDisable(GL_LIGHTING);
00453             glDisable(GL_LINE_SMOOTH);
00454             glEnable(GL_BLEND);
00455             glEnable(GL_ALPHA_TEST);
00456             glDisable(GL_COLOR_MATERIAL);
00457             glLineWidth(1);
00458             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00459             // draw
00460             glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
00461             drawValues();
00462             swapBuffers();
00463         }
00464         makeNonCurrent();
00465     }
00466     return 1;
00467 }
00468 
00469 
00470 
00471 /****************************************************************************/
00472 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines