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