SUMO - Simulation of Urban MObility

GUITLLogicPhasesTrackerWindow.cpp

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines