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