SUMO - Simulation of Urban MObility
|
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