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 2001-2010 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             glFlush();
00132             swapBuffers();
00133         }
00134         makeNonCurrent();
00135     }
00136     return 1;
00137 }
00138 
00139 
00140 
00141 /* -------------------------------------------------------------------------
00142  * GUITLLogicPhasesTrackerWindow - FOX callback mapping
00143  * ----------------------------------------------------------------------- */
00144 FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[]={
00145     FXMAPFUNC(SEL_CONFIGURE, 0,           GUITLLogicPhasesTrackerWindow::onConfigure),
00146     FXMAPFUNC(SEL_PAINT,     0,           GUITLLogicPhasesTrackerWindow::onPaint),
00147     FXMAPFUNC(SEL_COMMAND,   MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep),
00148 
00149 };
00150 
00151 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow,FXMainWindow,GUITLLogicPhasesTrackerWindowMap,ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap))
00152 
00153 
00154 /* -------------------------------------------------------------------------
00155  * GUITLLogicPhasesTrackerWindow-methods
00156  * ----------------------------------------------------------------------- */
00157 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerWindow(
00158     GUIMainWindow &app,
00159     MSTrafficLightLogic &logic, GUITrafficLightLogicWrapper &wrapper,
00160     ValueSource<std::pair<SUMOTime, MSPhaseDefinition> > *src) throw()
00161         : FXMainWindow(app.getApp(), "TLS-Tracker",NULL,NULL,DECOR_ALL,
00162                        20,20,300,200),
00163         myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(true) {
00164     // build the toolbar
00165     myToolBarDrag = new FXToolBarShell(this,FRAME_NORMAL);
00166     myToolBar = new FXToolBar(this,myToolBarDrag, LAYOUT_SIDE_TOP|LAYOUT_FILL_X|FRAME_RAISED);
00167     new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
00168     // interval manipulation
00169     myBeginOffset = new FXRealSpinDial(myToolBar, 10, this, MID_SIMSTEP, LAYOUT_TOP|FRAME_SUNKEN|FRAME_THICK);
00170     myBeginOffset->setFormatString("%.0f");
00171     myBeginOffset->setIncrements(1,10,100);
00172     myBeginOffset->setRange(60,3600);
00173     myBeginOffset->setValue(240);
00174     new FXLabel(myToolBar, "(s)", 0, LAYOUT_CENTER_Y);
00175     //
00176     myConnector = new GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >(wrapper, src, this);
00177     FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8 + 30);
00178     app.addChild(this, true);
00179     for (size_t i=0; i<myTLLogic->getLinks().size(); i++) {
00180         myLinkNames.push_back(toString<size_t>(i));
00181     }
00182     FXVerticalFrame *glcanvasFrame =
00183         new FXVerticalFrame(this,
00184                             FRAME_SUNKEN|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y,
00185                             0,0,0,0,0,0,0,0);
00186     myPanel = new
00187     GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
00188     setTitle((logic.getID() + " - " + logic.getSubID() + " - tracker").c_str());
00189     setIcon(GUIIconSubSys::getIcon(ICON_APP_TLSTRACKER));
00190     setHeight(height);
00191 }
00192 
00193 
00194 GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerWindow(
00195     GUIMainWindow &app,
00196     MSTrafficLightLogic &logic, GUITrafficLightLogicWrapper &/*wrapper*/,
00197     const MSSimpleTrafficLightLogic::Phases &/*phases*/) throw()
00198         : FXMainWindow(app.getApp(), "TLS-Tracker",NULL,NULL,DECOR_ALL,
00199                        20,20,300,200),
00200         myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(false),
00201         myToolBarDrag(0), myBeginOffset(0) {
00202     myConnector = 0;
00203     FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8);
00204     setTitle("TLS-Tracker");
00205     app.addChild(this, true);
00206     for (size_t i=0; i<myTLLogic->getLinks().size(); i++) {
00207         myLinkNames.push_back(toString<size_t>(i));
00208     }
00209     FXVerticalFrame *glcanvasFrame =
00210         new FXVerticalFrame(this,
00211                             FRAME_SUNKEN|LAYOUT_SIDE_TOP|LAYOUT_FILL_X|LAYOUT_FILL_Y,
00212                             0,0,0,0,0,0,0,0);
00213     myPanel = new
00214     GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
00215     setTitle((logic.getID() + " - " + logic.getSubID() + " - tracker").c_str());
00216     setIcon(GUIIconSubSys::getIcon(ICON_APP_TLSTRACKER));
00217     setHeight(height);
00218 }
00219 
00220 
00221 GUITLLogicPhasesTrackerWindow::~GUITLLogicPhasesTrackerWindow() throw() {
00222     myApplication->removeChild(this);
00223     delete myConnector;
00224     // just to quit cleanly on a failure
00225     if (myLock.locked()) {
00226         myLock.unlock();
00227     }
00228     delete myToolBarDrag;
00229 }
00230 
00231 
00232 void
00233 GUITLLogicPhasesTrackerWindow::create() {
00234     FXMainWindow::create();
00235     if (myToolBarDrag!=0) {
00236         myToolBarDrag->create();
00237     }
00238 }
00239 
00240 
00241 void
00242 GUITLLogicPhasesTrackerWindow::drawValues(GUITLLogicPhasesTrackerPanel &caller) throw() {
00243     // compute what shall be shown (what is visible)
00244     myFirstPhase2Show = 0;
00245     myFirstPhaseOffset = 0;
00246     size_t leftOffset = 0;
00247     myFirstTime2Show = 0;
00248     if (!myAmInTrackingMode) {
00249         myPhases.clear();
00250         myDurations.clear();
00251         // insert phases
00252         const MSSimpleTrafficLightLogic::Phases &phases = static_cast<MSSimpleTrafficLightLogic*>(myTLLogic)->getPhases();
00253         MSSimpleTrafficLightLogic::Phases::const_iterator j;
00254         myLastTime = 0;
00255         myBeginTime = 0;
00256         for (j=phases.begin(); j!=phases.end(); ++j) {
00257             myPhases.push_back(*(*j));
00258             myDurations.push_back((*j)->duration);
00259             myLastTime += (*j)->duration;
00260         }
00261     } else {
00262         myBeginTime = myLastTime - (SUMOTime) myBeginOffset->getValue();
00263         myFirstTime2Show = myBeginTime;
00264         // check whether no phases are known at all
00265         if (myDurations.size()!=0) {
00266             size_t durs = 0;
00267             size_t phaseOffset = myDurations.size() - 1;
00268             DurationsVector::reverse_iterator i=myDurations.rbegin();
00269             while (/*noSecs>=0&&*/i!=myDurations.rend()) {
00270                 if (durs+(*i)>(size_t) myBeginOffset->getValue()) {
00271                     myFirstPhase2Show = phaseOffset;
00272                     myFirstPhaseOffset = (durs+(*i)) - (size_t) myBeginOffset->getValue();
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 = (size_t) myBeginOffset->getValue() - 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     SUMOReal height = (SUMOReal) caller.getHeight();
00299     SUMOReal width = (SUMOReal) caller.getWidth();
00300     pfSetScaleXY((SUMOReal)(.08*300./width), (SUMOReal)(.08*300./height));
00301     SUMOReal h4 = ((SUMOReal) 4 / height);
00302     SUMOReal h10 = ((SUMOReal) 10 / height);
00303     SUMOReal h16 = ((SUMOReal) 16 / height);
00304     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     size_t i;
00309 
00310     for (i=0; i<myTLLogic->getLinks().size()+1; i++) {
00311         // draw the bar
00312         glBegin(GL_LINES);
00313         glVertex2d(0, h);
00314         glVertex2d((SUMOReal)(30. / width), h);
00315         glEnd();
00316         // draw the name
00317         if (i<myTLLogic->getLinks().size()) {
00318             glRotated(180, 1, 0, 0);
00319             pfSetPosition(0, 0);
00320             glTranslated(0.0, -h+h20-h4, 0);
00321             pfDrawString(myLinkNames[i].c_str());
00322             glTranslated(-0.0, h-h20+h4, 0);
00323             glRotated(-180, 1, 0, 0);
00324             h2 += 20;
00325         }
00326         h -= h20;
00327     }
00328     glBegin(GL_LINES);
00329     glVertex2d(0, h+h20);
00330     glVertex2d(1.0, h+h20);
00331     glEnd();
00332 
00333     // draw the names closure (vertical line)
00334     h += (SUMOReal) 20 / height;
00335     glColor3d(1, 1, 1);
00336     glBegin(GL_LINES);
00337     glVertex2d((SUMOReal) 30 / width, 1.0);
00338     glVertex2d((SUMOReal) 30 / width, h);
00339     glEnd();
00340 
00341 
00342     // draw the phases
00343     // disable value addition while drawing
00344     myLock.lock();
00345     // determine the initial offset
00346     SUMOReal x = ((SUMOReal) 31. / width) ;
00347     SUMOReal ta = (SUMOReal) leftOffset / width;
00348     ta *= (SUMOReal)(((width-31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
00349     x += ta;
00350 
00351     // and the initial phase information
00352     PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
00353     DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show;
00354     size_t fpo = myFirstPhaseOffset;
00355 
00356     // start drawing
00357     for (i=30; i<width&&pd!=myDurations.end();) {
00358         // the first phase may be drawn incompletely
00359         size_t duration = *pd - fpo;
00360         // compute the heigh and the width of the phase
00361         h = (SUMOReal)(1.0 - h10);
00362         SUMOReal a = (SUMOReal) duration / width;
00363         a *= (SUMOReal)(((width-31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
00364         SUMOReal x2 = x + a;
00365 
00366         // go through the links
00367         for (unsigned int j=0; j<(unsigned int) myTLLogic->getLinks().size(); j++) {
00368             // determine the current link's color
00369             MSLink::LinkState state = (*pi).getSignalState(j);
00370             // draw the bar (red is drawn as a line)
00371             switch (state) {
00372             case MSLink::LINKSTATE_TL_GREEN_MAJOR:
00373             case MSLink::LINKSTATE_TL_GREEN_MINOR:
00374                 glColor3d(0, 1.0, 0);
00375                 glBegin(GL_QUADS);
00376                 glVertex2d(x, h - h16);
00377                 glVertex2d(x, h - h4);
00378                 glVertex2d(x2, h - h4);
00379                 glVertex2d(x2, h - h16);
00380                 glEnd();
00381                 break;
00382             case MSLink::LINKSTATE_TL_YELLOW_MAJOR:
00383             case MSLink::LINKSTATE_TL_YELLOW_MINOR:
00384                 glColor3d(1.0, 1.0, 0);
00385                 glBegin(GL_QUADS);
00386                 glVertex2d(x, h - h16);
00387                 glVertex2d(x, h - h4);
00388                 glVertex2d(x2, h - h4);
00389                 glVertex2d(x2, h - h16);
00390                 glEnd();
00391                 break;
00392             case MSLink::LINKSTATE_TL_RED:
00393                 glColor3d(1.0, 0, 0);
00394                 glBegin(GL_LINES);
00395                 glVertex2d(x, h - h10);
00396                 glVertex2d(x2, h - h10);
00397                 glEnd();
00398                 break;
00399             default:
00400                 break;
00401             }
00402             // proceed to next link
00403             h -= h20;
00404         }
00405         // proceed to next phase
00406         i += duration;
00407         pi++;
00408         pd++;
00409         x = x2;
00410         // all further phases are drawn in full
00411         fpo = 0;
00412     }
00413     // allow value addition
00414     myLock.unlock();
00415 
00416     glColor3d(1, 1, 1);
00417     if (myPhases.size()!=0) {
00418         int tickDist = 10;
00419         // patch distances - hack
00420         SUMOReal t = myBeginOffset!=0 ? (SUMOReal) myBeginOffset->getValue() : (SUMOReal)(myLastTime - myBeginTime);
00421         while (t>(width-31.)/4.) {
00422             tickDist += 10;
00423             t -= (SUMOReal)((width-31.)/4.);
00424         }
00425         // draw time information
00426         h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12);
00427         SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
00428         // current begin time
00429         //string timeStr = toString<SUMOTime>(myFirstTime2Show);
00430         //SUMOReal w = pfdkGetStringWidth(timeStr.c_str());
00431         pfSetScaleXY((SUMOReal)(.05*300./width), (SUMOReal)(.05*300./height));
00432         // time ticks
00433         SUMOTime currTime = myFirstTime2Show;
00434         int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show;
00435         SUMOReal glpos = (SUMOReal) pos / (SUMOReal) width;
00436         while (pos<width+50) {
00437             std::string timeStr = toString<SUMOTime>(currTime);
00438             SUMOReal w = pfdkGetStringWidth(timeStr.c_str());
00439             glRotated(180, 1, 0, 0);
00440             pfSetPosition(0, 0);
00441             glTranslated(glpos-w/2., -glh+h20-h4, 0);
00442             pfDrawString(timeStr.c_str());
00443             glTranslated(-glpos+w/2., glh-h20+h4, 0);
00444             glRotated(-180, 1, 0, 0);
00445 
00446             glBegin(GL_LINES);
00447             glVertex2d(glpos, glh);
00448             glVertex2d(glpos, glh-h4);
00449             glEnd();
00450 
00451             SUMOReal a = (SUMOReal) tickDist / width;
00452             a *= (SUMOReal)(((width-31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
00453             glpos += a;
00454             SUMOReal a2 = (SUMOReal) tickDist;
00455             a2 *= (SUMOReal)(((width-31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
00456             pos += (int) a2;
00457             currTime += tickDist;
00458         }
00459     }
00460 }
00461 
00462 
00463 void
00464 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) throw() {
00465     // do not draw while adding
00466     myLock.lock();
00467     // set the first time if not set before
00468     if (myPhases.size()==0) {
00469         myBeginTime = def.first;
00470     }
00471     // append or set the phase
00472     if (myPhases.size()==0||*(myPhases.end()-1)!=def.second) {
00473         myPhases.push_back(def.second);
00474         myDurations.push_back(1);
00475     } else {
00476         *(myDurations.end()-1) += 1;
00477     }
00478     // set the last time a phase was added at
00479     myLastTime = def.first;
00480     // allow drawing
00481     myLock.unlock();
00482 }
00483 
00484 
00485 
00486 long
00487 GUITLLogicPhasesTrackerWindow::onConfigure(FXObject *sender,
00488         FXSelector sel, void *data) {
00489     myPanel->onConfigure(sender, sel, data);
00490     return FXMainWindow::onConfigure(sender, sel, data);
00491 }
00492 
00493 
00494 long
00495 GUITLLogicPhasesTrackerWindow::onPaint(FXObject *sender,
00496                                        FXSelector sel, void *data) {
00497     myPanel->onPaint(sender, sel, data);
00498     return FXMainWindow::onPaint(sender, sel, data);
00499 }
00500 
00501 
00502 long
00503 GUITLLogicPhasesTrackerWindow::onSimStep(FXObject*,
00504         FXSelector,void*) {
00505     update();
00506     return 1;
00507 }
00508 
00509 
00510 
00511 void
00512 GUITLLogicPhasesTrackerWindow::setBeginTime(SUMOTime time) throw() {
00513     myBeginTime = time;
00514 }
00515 
00516 
00517 /****************************************************************************/
00518 

Generated on Wed May 5 00:06:30 2010 for Sumo - Simulation of Urban MObility by  doxygen 1.5.6