00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00057
00058
00059
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
00068 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel,FXGLCanvas,GUITLLogicPhasesTrackerPanelMap,ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap))
00069
00070
00071
00072
00073
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),
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
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
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
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
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
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 &,
00197 const MSSimpleTrafficLightLogic::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
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
00244 myFirstPhase2Show = 0;
00245 myFirstPhaseOffset = 0;
00246 size_t leftOffset = 0;
00247 myFirstTime2Show = 0;
00248 if (!myAmInTrackingMode) {
00249 myPhases.clear();
00250 myDurations.clear();
00251
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
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 (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
00281 myFirstPhase2Show = 0;
00282 myFirstPhaseOffset = 0;
00283 leftOffset = (size_t) myBeginOffset->getValue() - durs;
00284 }
00285 }
00286 }
00287
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
00296 glColor3d(1, 1, 1);
00297
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
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
00312 glBegin(GL_LINES);
00313 glVertex2d(0, h);
00314 glVertex2d((SUMOReal)(30. / width), h);
00315 glEnd();
00316
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
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
00343
00344 myLock.lock();
00345
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
00352 PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
00353 DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show;
00354 size_t fpo = myFirstPhaseOffset;
00355
00356
00357 for (i=30; i<width&&pd!=myDurations.end();) {
00358
00359 size_t duration = *pd - fpo;
00360
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
00367 for (unsigned int j=0; j<(unsigned int) myTLLogic->getLinks().size(); j++) {
00368
00369 MSLink::LinkState state = (*pi).getSignalState(j);
00370
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
00403 h -= h20;
00404 }
00405
00406 i += duration;
00407 pi++;
00408 pd++;
00409 x = x2;
00410
00411 fpo = 0;
00412 }
00413
00414 myLock.unlock();
00415
00416 glColor3d(1, 1, 1);
00417 if (myPhases.size()!=0) {
00418 int tickDist = 10;
00419
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
00426 h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12);
00427 SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
00428
00429
00430
00431 pfSetScaleXY((SUMOReal)(.05*300./width), (SUMOReal)(.05*300./height));
00432
00433 SUMOTime currTime = myFirstTime2Show;
00434 int pos = 31;
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
00466 myLock.lock();
00467
00468 if (myPhases.size()==0) {
00469 myBeginTime = def.first;
00470 }
00471
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
00479 myLastTime = def.first;
00480
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