|
SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00007 // A window displaying the phase diagram of a tl-logic 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 <cassert> 00031 #include <vector> 00032 #include <iostream> 00033 #include <utils/gui/windows/GUIMainWindow.h> 00034 #include "GUITLLogicPhasesTrackerWindow.h" 00035 #include <microsim/traffic_lights/MSTrafficLightLogic.h> 00036 #include <microsim/MSLink.h> 00037 #include <utils/common/ToString.h> 00038 #include <guisim/GUITrafficLightLogicWrapper.h> 00039 #include <utils/gui/images/GUITexturesHelper.h> 00040 #include <utils/gui/windows/GUIAppEnum.h> 00041 #include <utils/gui/images/GUIIconSubSys.h> 00042 #include <foreign/polyfonts/polyfonts.h> 00043 00044 #ifdef _WIN32 00045 #include <windows.h> 00046 #endif 00047 00048 #include <GL/gl.h> 00049 00050 #ifdef CHECK_MEMORY_LEAKS 00051 #include <foreign/nvwa/debug_new.h> 00052 #endif // CHECK_MEMORY_LEAKS 00053 00054 00055 // =========================================================================== 00056 // member method definitions 00057 // =========================================================================== 00058 /* ------------------------------------------------------------------------- 00059 * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-callbacks 00060 * ----------------------------------------------------------------------- */ 00061 FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[]= { 00062 FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onConfigure), 00063 FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onPaint), 00064 00065 }; 00066 00067 // Macro for the GLTestApp class hierarchy implementation 00068 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel,FXGLCanvas,GUITLLogicPhasesTrackerPanelMap,ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap)) 00069 00070 00071 00072 /* ------------------------------------------------------------------------- 00073 * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-methods 00074 * ----------------------------------------------------------------------- */ 00075 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::GUITLLogicPhasesTrackerPanel( 00076 FXComposite* c, GUIMainWindow& app, 00077 GUITLLogicPhasesTrackerWindow& parent) throw() 00078 : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y/*, 0, 0, 300, 200*/), 00079 myParent(&parent), myApplication(&app) {} 00080 00081 00082 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::~GUITLLogicPhasesTrackerPanel() throw() {} 00083 00084 00085 long 00086 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onConfigure( 00087 FXObject*,FXSelector,void*) { 00088 if (makeCurrent()) { 00089 int widthInPixels = getWidth(); 00090 int heightInPixels = getHeight(); 00091 if (widthInPixels!=0&&heightInPixels!=0) { 00092 glViewport(0, 0, widthInPixels-1, heightInPixels-1); 00093 glClearColor(0, 0, 0, 1); 00094 glDisable(GL_DEPTH_TEST); 00095 glDisable(GL_LIGHTING); 00096 glDisable(GL_LINE_SMOOTH); 00097 glEnable(GL_BLEND); 00098 glEnable(GL_ALPHA_TEST); 00099 glDisable(GL_COLOR_MATERIAL); 00100 glLineWidth(1); 00101 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00102 } 00103 } 00104 return 1; 00105 } 00106 00107 00108 long 00109 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel::onPaint( 00110 FXObject*,FXSelector,void*) { 00111 if (!isEnabled()) { 00112 return 1; 00113 } 00114 if (makeCurrent()) { 00115 int widthInPixels = getWidth(); 00116 int heightInPixels = getHeight(); 00117 if (widthInPixels!=0&&heightInPixels!=0) { 00118 glViewport(0, 0, widthInPixels-1, heightInPixels-1); 00119 glClearColor(0, 0, 0, 1); 00120 glDisable(GL_DEPTH_TEST); 00121 glDisable(GL_LIGHTING); 00122 glDisable(GL_LINE_SMOOTH); 00123 glEnable(GL_BLEND); 00124 glEnable(GL_ALPHA_TEST); 00125 glDisable(GL_COLOR_MATERIAL); 00126 glLineWidth(1); 00127 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); 00128 // draw 00129 glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 00130 myParent->drawValues(*this); 00131 swapBuffers(); 00132 } 00133 makeNonCurrent(); 00134 } 00135 return 1; 00136 } 00137 00138 00139 00140 /* ------------------------------------------------------------------------- 00141 * GUITLLogicPhasesTrackerWindow - FOX callback mapping 00142 * ----------------------------------------------------------------------- */ 00143 FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[]= { 00144 FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::onConfigure), 00145 FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::onPaint), 00146 FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep), 00147 00148 }; 00149 00150 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow,FXMainWindow,GUITLLogicPhasesTrackerWindowMap,ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap)) 00151 00152 00153 /* ------------------------------------------------------------------------- 00154 * GUITLLogicPhasesTrackerWindow-methods 00155 * ----------------------------------------------------------------------- */ 00156 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerWindow( 00157 GUIMainWindow& app, 00158 MSTrafficLightLogic& logic, GUITrafficLightLogicWrapper& wrapper, 00159 ValueSource<std::pair<SUMOTime, MSPhaseDefinition> > *src) throw() 00160 : FXMainWindow(app.getApp(), "TLS-Tracker",NULL,NULL,DECOR_ALL, 00161 20,20,300,200), 00162 myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(true) { 00163 // build the toolbar 00164 myToolBarDrag = new FXToolBarShell(this,FRAME_NORMAL); 00165 myToolBar = new FXToolBar(this,myToolBarDrag, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED); 00166 new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE); 00167 // interval manipulation 00168 myBeginOffset = new FXRealSpinDial(myToolBar, 10, this, MID_SIMSTEP, LAYOUT_TOP|FRAME_SUNKEN|FRAME_THICK); 00169 myBeginOffset->setFormatString("%.0f"); 00170 myBeginOffset->setIncrements(1,10,100); 00171 myBeginOffset->setRange(60,3600); 00172 myBeginOffset->setValue(240); 00173 new FXLabel(myToolBar, "(s)", 0, LAYOUT_CENTER_Y); 00174 // 00175 myConnector = new GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >(wrapper, src, this); 00176 FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8 + 30); 00177 app.addChild(this, true); 00178 for (size_t i=0; i<myTLLogic->getLinks().size(); i++) { 00179 myLinkNames.push_back(toString<size_t>(i)); 00180 } 00181 FXVerticalFrame* glcanvasFrame = 00182 new FXVerticalFrame(this, 00183 FRAME_SUNKEN|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y, 00184 0,0,0,0,0,0,0,0); 00185 myPanel = new 00186 GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this); 00187 setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str()); 00188 setIcon(GUIIconSubSys::getIcon(ICON_APP_TLSTRACKER)); 00189 setHeight(height); 00190 } 00191 00192 00193 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerWindow( 00194 GUIMainWindow& app, 00195 MSTrafficLightLogic& logic, GUITrafficLightLogicWrapper& /*wrapper*/, 00196 const MSSimpleTrafficLightLogic::Phases& /*phases*/) throw() 00197 : FXMainWindow(app.getApp(), "TLS-Tracker",NULL,NULL,DECOR_ALL, 00198 20,20,300,200), 00199 myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(false), 00200 myToolBarDrag(0), myBeginOffset(0) { 00201 myConnector = 0; 00202 FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8); 00203 setTitle("TLS-Tracker"); 00204 app.addChild(this, true); 00205 for (size_t i=0; i<myTLLogic->getLinks().size(); i++) { 00206 myLinkNames.push_back(toString<size_t>(i)); 00207 } 00208 FXVerticalFrame* glcanvasFrame = 00209 new FXVerticalFrame(this, 00210 FRAME_SUNKEN|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y, 00211 0,0,0,0,0,0,0,0); 00212 myPanel = new 00213 GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this); 00214 setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str()); 00215 setIcon(GUIIconSubSys::getIcon(ICON_APP_TLSTRACKER)); 00216 setHeight(height); 00217 } 00218 00219 00220 GUITLLogicPhasesTrackerWindow::~GUITLLogicPhasesTrackerWindow() throw() { 00221 myApplication->removeChild(this); 00222 delete myConnector; 00223 // just to quit cleanly on a failure 00224 if (myLock.locked()) { 00225 myLock.unlock(); 00226 } 00227 delete myToolBarDrag; 00228 } 00229 00230 00231 void 00232 GUITLLogicPhasesTrackerWindow::create() { 00233 FXMainWindow::create(); 00234 if (myToolBarDrag!=0) { 00235 myToolBarDrag->create(); 00236 } 00237 } 00238 00239 00240 void 00241 GUITLLogicPhasesTrackerWindow::drawValues(GUITLLogicPhasesTrackerPanel& caller) throw() { 00242 // compute what shall be shown (what is visible) 00243 myFirstPhase2Show = 0; 00244 myFirstPhaseOffset = 0; 00245 size_t leftOffset = 0; 00246 myFirstTime2Show = 0; 00247 if (!myAmInTrackingMode) { 00248 myPhases.clear(); 00249 myDurations.clear(); 00250 // insert phases 00251 const MSSimpleTrafficLightLogic::Phases& phases = static_cast<MSSimpleTrafficLightLogic*>(myTLLogic)->getPhases(); 00252 MSSimpleTrafficLightLogic::Phases::const_iterator j; 00253 myLastTime = 0; 00254 myBeginTime = 0; 00255 for (j=phases.begin(); j!=phases.end(); ++j) { 00256 myPhases.push_back(*(*j)); 00257 myDurations.push_back((*j)->duration); 00258 myLastTime += (*j)->duration; 00259 } 00260 } else { 00261 SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue()); 00262 myBeginTime = myLastTime - beginOffset; 00263 myFirstTime2Show = myBeginTime; 00264 // check whether no phases are known at all 00265 if (myDurations.size()!=0) { 00266 SUMOTime durs = 0; 00267 size_t phaseOffset = myDurations.size() - 1; 00268 DurationsVector::reverse_iterator i=myDurations.rbegin(); 00269 while (i!=myDurations.rend()) { 00270 if (durs+(*i)>beginOffset) { 00271 myFirstPhase2Show = phaseOffset; 00272 myFirstPhaseOffset = (durs+(*i)) - beginOffset; 00273 break; 00274 } 00275 durs += (*i); 00276 phaseOffset--; 00277 ++i; 00278 } 00279 if (i==myDurations.rend()) { 00280 // there are too few information stored; 00281 myFirstPhase2Show = 0; 00282 myFirstPhaseOffset = 0; 00283 leftOffset = beginOffset - durs; 00284 } 00285 } 00286 } 00287 // begin drawing 00288 glMatrixMode(GL_PROJECTION); 00289 glLoadIdentity(); 00290 glMatrixMode(GL_MODELVIEW); 00291 glLoadIdentity(); 00292 glTranslated(-1, -1, 0); 00293 glScaled(2, 2, 1); 00294 glDisable(GL_TEXTURE_2D); 00295 // draw the horizontal lines dividing the signal groups 00296 glColor3d(1, 1, 1); 00297 // compute some values needed more than once 00298 const SUMOReal height = (SUMOReal) caller.getHeight(); 00299 const SUMOReal width = (SUMOReal) caller.getWidth(); 00300 pfSetScaleXY((SUMOReal)(.08*300./width), (SUMOReal)(.08*300./height)); 00301 const SUMOReal h4 = ((SUMOReal) 4 / height); 00302 const SUMOReal h10 = ((SUMOReal) 10 / height); 00303 const SUMOReal h16 = ((SUMOReal) 16 / height); 00304 const SUMOReal h20 = ((SUMOReal) 20 / height); 00305 // draw the link names and the lines dividing them 00306 SUMOReal h = (SUMOReal)(1.0 - h10); 00307 SUMOReal h2 = 12; 00308 for (size_t i=0; i<myTLLogic->getLinks().size()+1; i++) { 00309 // draw the bar 00310 glBegin(GL_LINES); 00311 glVertex2d(0, h); 00312 glVertex2d((SUMOReal)(30. / width), h); 00313 glEnd(); 00314 // draw the name 00315 if (i<myTLLogic->getLinks().size()) { 00316 glRotated(180, 1, 0, 0); 00317 pfSetPosition(0, 0); 00318 glTranslated(0.0, -h+h20-h4, 0); 00319 pfDrawString(myLinkNames[i].c_str()); 00320 glTranslated(-0.0, h-h20+h4, 0); 00321 glRotated(-180, 1, 0, 0); 00322 h2 += 20; 00323 } 00324 h -= h20; 00325 } 00326 glBegin(GL_LINES); 00327 glVertex2d(0, h+h20); 00328 glVertex2d(1.0, h+h20); 00329 glEnd(); 00330 00331 // draw the names closure (vertical line) 00332 h += (SUMOReal) 20 / height; 00333 glColor3d(1, 1, 1); 00334 glBegin(GL_LINES); 00335 glVertex2d((SUMOReal) 30 / width, 1.0); 00336 glVertex2d((SUMOReal) 30 / width, h); 00337 glEnd(); 00338 00339 00340 // draw the phases 00341 // disable value addition while drawing 00342 myLock.lock(); 00343 // determine the initial offset 00344 SUMOReal x = ((SUMOReal) 31. / width) ; 00345 SUMOReal ta = (SUMOReal) leftOffset / width; 00346 ta *= (SUMOReal)(((width-31.0) / ((SUMOReal)(myLastTime - myBeginTime)))); 00347 x += ta; 00348 00349 // and the initial phase information 00350 PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show; 00351 DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show; 00352 size_t fpo = myFirstPhaseOffset; 00353 00354 // start drawing 00355 for (size_t i=30; pd!=myDurations.end();) { 00356 // the first phase may be drawn incompletely 00357 size_t duration = *pd - fpo; 00358 // compute the heigh and the width of the phase 00359 h = (SUMOReal)(1.0 - h10); 00360 SUMOReal a = (SUMOReal) duration / width; 00361 a *= (SUMOReal)(((width-31.0) / ((SUMOReal)(myLastTime - myBeginTime)))); 00362 SUMOReal x2 = x + a; 00363 00364 // go through the links 00365 for (unsigned int j=0; j<(unsigned int) myTLLogic->getLinks().size(); j++) { 00366 // determine the current link's color 00367 LinkState state = (*pi).getSignalState(j); 00368 // draw the bar (red is drawn as a line) 00369 switch (state) { 00370 case LINKSTATE_TL_GREEN_MAJOR: 00371 case LINKSTATE_TL_GREEN_MINOR: 00372 glColor3d(0, 1.0, 0); 00373 glBegin(GL_QUADS); 00374 glVertex2d(x, h - h16); 00375 glVertex2d(x, h - h4); 00376 glVertex2d(x2, h - h4); 00377 glVertex2d(x2, h - h16); 00378 glEnd(); 00379 break; 00380 case LINKSTATE_TL_YELLOW_MAJOR: 00381 case LINKSTATE_TL_YELLOW_MINOR: 00382 glColor3d(1.0, 1.0, 0); 00383 glBegin(GL_QUADS); 00384 glVertex2d(x, h - h16); 00385 glVertex2d(x, h - h4); 00386 glVertex2d(x2, h - h4); 00387 glVertex2d(x2, h - h16); 00388 glEnd(); 00389 break; 00390 case LINKSTATE_TL_RED: 00391 glColor3d(1.0, 0, 0); 00392 glBegin(GL_LINES); 00393 glVertex2d(x, h - h10); 00394 glVertex2d(x2, h - h10); 00395 glEnd(); 00396 break; 00397 default: 00398 break; 00399 } 00400 // proceed to next link 00401 h -= h20; 00402 } 00403 // proceed to next phase 00404 i += duration; 00405 pi++; 00406 pd++; 00407 x = x2; 00408 // all further phases are drawn in full 00409 fpo = 0; 00410 } 00411 // allow value addition 00412 myLock.unlock(); 00413 00414 glColor3d(1, 1, 1); 00415 if (myPhases.size()!=0) { 00416 SUMOTime tickDist = TIME2STEPS(10); 00417 // patch distances - hack 00418 SUMOReal t = myBeginOffset!=0 ? (SUMOReal) myBeginOffset->getValue() : STEPS2TIME(myLastTime - myBeginTime); 00419 while (t>(width-31.)/4.) { 00420 tickDist += TIME2STEPS(10); 00421 t -= (SUMOReal)((width-31.)/4.); 00422 } 00423 // draw time information 00424 h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12); 00425 SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10); 00426 // current begin time 00427 pfSetScaleXY((SUMOReal)(.05*300./width), (SUMOReal)(.05*300./height)); 00428 // time ticks 00429 SUMOTime currTime = myFirstTime2Show; 00430 int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show; 00431 SUMOReal glpos = (SUMOReal) pos / width; 00432 while (pos<width+50) { 00433 const std::string timeStr = time2string(currTime); 00434 const SUMOReal w = pfdkGetStringWidth(timeStr.c_str()); 00435 glRotated(180, 1, 0, 0); 00436 pfSetPosition(0, 0); 00437 glTranslated(glpos-w/2., -glh+h20-h4, 0); 00438 pfDrawString(timeStr.c_str()); 00439 glTranslated(-glpos+w/2., glh-h20+h4, 0); 00440 glRotated(-180, 1, 0, 0); 00441 00442 glBegin(GL_LINES); 00443 glVertex2d(glpos, glh); 00444 glVertex2d(glpos, glh-h4); 00445 glEnd(); 00446 00447 const SUMOReal a = STEPS2TIME(tickDist) * (width-31.0) / STEPS2TIME(myLastTime - myBeginTime); 00448 pos += (int) a; 00449 glpos += a / width; 00450 currTime += tickDist; 00451 } 00452 } 00453 } 00454 00455 00456 void 00457 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) throw() { 00458 // do not draw while adding 00459 myLock.lock(); 00460 // set the first time if not set before 00461 if (myPhases.size()==0) { 00462 myBeginTime = def.first; 00463 } 00464 // append or set the phase 00465 if (myPhases.size()==0||*(myPhases.end()-1)!=def.second) { 00466 myPhases.push_back(def.second); 00467 myDurations.push_back(DELTA_T); 00468 } else { 00469 *(myDurations.end()-1) += DELTA_T; 00470 } 00471 // set the last time a phase was added at 00472 myLastTime = def.first; 00473 // allow drawing 00474 myLock.unlock(); 00475 } 00476 00477 00478 long 00479 GUITLLogicPhasesTrackerWindow::onConfigure(FXObject* sender, 00480 FXSelector sel, void* data) { 00481 myPanel->onConfigure(sender, sel, data); 00482 return FXMainWindow::onConfigure(sender, sel, data); 00483 } 00484 00485 00486 long 00487 GUITLLogicPhasesTrackerWindow::onPaint(FXObject* sender, 00488 FXSelector sel, void* data) { 00489 myPanel->onPaint(sender, sel, data); 00490 return FXMainWindow::onPaint(sender, sel, data); 00491 } 00492 00493 00494 long 00495 GUITLLogicPhasesTrackerWindow::onSimStep(FXObject*, 00496 FXSelector,void*) { 00497 update(); 00498 return 1; 00499 } 00500 00501 00502 void 00503 GUITLLogicPhasesTrackerWindow::setBeginTime(SUMOTime time) throw() { 00504 myBeginTime = time; 00505 } 00506 00507 00508 /****************************************************************************/ 00509