SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
GUITLLogicPhasesTrackerWindow.cpp
Go to the documentation of this file.
1 /****************************************************************************/
9 // A window displaying the phase diagram of a tl-logic
10 /****************************************************************************/
11 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
12 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
13 /****************************************************************************/
14 //
15 // This file is part of SUMO.
16 // SUMO is free software: you can redistribute it and/or modify
17 // it under the terms of the GNU General Public License as published by
18 // the Free Software Foundation, either version 3 of the License, or
19 // (at your option) any later version.
20 //
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <cassert>
34 #include <vector>
35 #include <iostream>
39 #include <microsim/MSLink.h>
40 #include <utils/common/ToString.h>
46 
47 #ifdef _WIN32
48 #include <windows.h>
49 #endif
50 
51 #include <GL/gl.h>
52 
53 #ifdef CHECK_MEMORY_LEAKS
54 #include <foreign/nvwa/debug_new.h>
55 #endif // CHECK_MEMORY_LEAKS
56 
57 
58 // ===========================================================================
59 // member method definitions
60 // ===========================================================================
61 /* -------------------------------------------------------------------------
62  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-callbacks
63  * ----------------------------------------------------------------------- */
64 FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[] = {
67 
68 };
69 
70 // Macro for the GLTestApp class hierarchy implementation
71 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel, FXGLCanvas, GUITLLogicPhasesTrackerPanelMap, ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap))
72 
73 
74 
75 /* -------------------------------------------------------------------------
76  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-methods
77  * ----------------------------------------------------------------------- */
79  FXComposite* c, GUIMainWindow& app,
81  : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y/*, 0, 0, 300, 200*/),
82  myParent(&parent), myApplication(&app) {}
83 
84 
86 
87 
88 long
90  FXObject*, FXSelector, void*) {
91  if (makeCurrent()) {
92  int widthInPixels = getWidth();
93  int heightInPixels = getHeight();
94  if (widthInPixels != 0 && heightInPixels != 0) {
95  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
96  glClearColor(0, 0, 0, 1);
97  glDisable(GL_DEPTH_TEST);
98  glDisable(GL_LIGHTING);
99  glDisable(GL_LINE_SMOOTH);
100  glEnable(GL_BLEND);
101  glEnable(GL_ALPHA_TEST);
102  glDisable(GL_COLOR_MATERIAL);
103  glLineWidth(1);
104  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
105  }
106  }
107  return 1;
108 }
109 
110 
111 long
113  FXObject*, FXSelector, void*) {
114  if (!isEnabled()) {
115  return 1;
116  }
117  if (makeCurrent()) {
118  int widthInPixels = getWidth();
119  int heightInPixels = getHeight();
120  if (widthInPixels != 0 && heightInPixels != 0) {
121  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
122  glClearColor(0, 0, 0, 1);
123  glDisable(GL_DEPTH_TEST);
124  glDisable(GL_LIGHTING);
125  glDisable(GL_LINE_SMOOTH);
126  glEnable(GL_BLEND);
127  glEnable(GL_ALPHA_TEST);
128  glDisable(GL_COLOR_MATERIAL);
129  glLineWidth(1);
130  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
131  // draw
132  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
133  myParent->drawValues(*this);
134  swapBuffers();
135  }
136  makeNonCurrent();
137  }
138  return 1;
139 }
140 
141 
142 
143 /* -------------------------------------------------------------------------
144  * GUITLLogicPhasesTrackerWindow - FOX callback mapping
145  * ----------------------------------------------------------------------- */
146 FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[] = {
147  FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::onConfigure),
148  FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::onPaint),
149  FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep),
150 
151 };
152 
153 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow, FXMainWindow, GUITLLogicPhasesTrackerWindowMap, ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap))
154 
155 
156 /* -------------------------------------------------------------------------
157  * GUITLLogicPhasesTrackerWindow-methods
158  * ----------------------------------------------------------------------- */
160  GUIMainWindow& app,
162  ValueSource<std::pair<SUMOTime, MSPhaseDefinition> > *src)
163  : FXMainWindow(app.getApp(), "TLS-Tracker", NULL, NULL, DECOR_ALL,
164  20, 20, 300, 200),
165  myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(true) {
166  // build the toolbar
167  myToolBarDrag = new FXToolBarShell(this, FRAME_NORMAL);
168  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
169  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
170  // interval manipulation
171  myBeginOffset = new FXRealSpinDial(myToolBar, 10, this, MID_SIMSTEP, LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
172  myBeginOffset->setFormatString("%.0f");
173  myBeginOffset->setIncrements(1, 10, 100);
174  myBeginOffset->setRange(60, 3600);
175  myBeginOffset->setValue(240);
176  new FXLabel(myToolBar, "(s)", 0, LAYOUT_CENTER_Y);
177  //
179  FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8 + 30);
180  app.addChild(this, true);
181  for (size_t i = 0; i < myTLLogic->getLinks().size(); i++) {
182  myLinkNames.push_back(toString<size_t>(i));
183  }
184  FXVerticalFrame* glcanvasFrame =
185  new FXVerticalFrame(this,
186  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
187  0, 0, 0, 0, 0, 0, 0, 0);
188  myPanel = new
189  GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
190  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
192  setHeight(height);
193 }
194 
195 
197  GUIMainWindow& app,
199  const MSSimpleTrafficLightLogic::Phases& /*phases*/)
200  : FXMainWindow(app.getApp(), "TLS-Tracker", NULL, NULL, DECOR_ALL,
201  20, 20, 300, 200),
202  myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(false),
204  myConnector = 0;
205  FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8);
206  setTitle("TLS-Tracker");
207  app.addChild(this, true);
208  for (size_t i = 0; i < myTLLogic->getLinks().size(); i++) {
209  myLinkNames.push_back(toString<size_t>(i));
210  }
211  FXVerticalFrame* glcanvasFrame =
212  new FXVerticalFrame(this,
213  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
214  0, 0, 0, 0, 0, 0, 0, 0);
215  myPanel = new
216  GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
217  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
219  setHeight(height);
220 }
221 
222 
224  myApplication->removeChild(this);
225  delete myConnector;
226  // just to quit cleanly on a failure
227  if (myLock.locked()) {
228  myLock.unlock();
229  }
230  delete myToolBarDrag;
231 }
232 
233 
234 void
237  if (myToolBarDrag != 0) {
238  myToolBarDrag->create();
239  }
240 }
241 
242 
243 void
245  // compute what shall be shown (what is visible)
246  myFirstPhase2Show = 0;
247  myFirstPhaseOffset = 0;
248  size_t leftOffset = 0;
249  myFirstTime2Show = 0;
250  if (!myAmInTrackingMode) {
251  myPhases.clear();
252  myDurations.clear();
253  // insert phases
254  const MSSimpleTrafficLightLogic::Phases& phases = static_cast<MSSimpleTrafficLightLogic*>(myTLLogic)->getPhases();
255  MSSimpleTrafficLightLogic::Phases::const_iterator j;
256  myLastTime = 0;
257  myBeginTime = 0;
258  for (j = phases.begin(); j != phases.end(); ++j) {
259  myPhases.push_back(*(*j));
260  myDurations.push_back((*j)->duration);
261  myLastTime += (*j)->duration;
262  }
263  } else {
264  SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
265  myBeginTime = myLastTime - beginOffset;
267  // check whether no phases are known at all
268  if (myDurations.size() != 0) {
269  SUMOTime durs = 0;
270  size_t phaseOffset = myDurations.size() - 1;
271  DurationsVector::reverse_iterator i = myDurations.rbegin();
272  while (i != myDurations.rend()) {
273  if (durs + (*i) > beginOffset) {
274  myFirstPhase2Show = phaseOffset;
275  myFirstPhaseOffset = (durs + (*i)) - beginOffset;
276  break;
277  }
278  durs += (*i);
279  phaseOffset--;
280  ++i;
281  }
282  if (i == myDurations.rend()) {
283  // there are too few information stored;
284  myFirstPhase2Show = 0;
285  myFirstPhaseOffset = 0;
286  leftOffset = beginOffset - durs;
287  }
288  }
289  }
290  // begin drawing
291  glMatrixMode(GL_PROJECTION);
292  glLoadIdentity();
293  glMatrixMode(GL_MODELVIEW);
294  glLoadIdentity();
295  glTranslated(-1, -1, 0);
296  glScaled(2, 2, 1);
297  glDisable(GL_TEXTURE_2D);
298  // draw the horizontal lines dividing the signal groups
299  glColor3d(1, 1, 1);
300  // compute some values needed more than once
301  const SUMOReal height = (SUMOReal) caller.getHeight();
302  const SUMOReal width = (SUMOReal) caller.getWidth();
303  pfSetScaleXY((SUMOReal)(.08 * 300. / width), (SUMOReal)(.08 * 300. / height));
304  const SUMOReal h4 = ((SUMOReal) 4 / height);
305  const SUMOReal h10 = ((SUMOReal) 10 / height);
306  const SUMOReal h16 = ((SUMOReal) 16 / height);
307  const SUMOReal h20 = ((SUMOReal) 20 / height);
308  // draw the link names and the lines dividing them
309  SUMOReal h = (SUMOReal)(1.0 - h10);
310  SUMOReal h2 = 12;
311  for (size_t i = 0; i < myTLLogic->getLinks().size() + 1; i++) {
312  // draw the bar
313  glBegin(GL_LINES);
314  glVertex2d(0, h);
315  glVertex2d((SUMOReal)(30. / width), h);
316  glEnd();
317  // draw the name
318  if (i < myTLLogic->getLinks().size()) {
319  glRotated(180, 1, 0, 0);
320  pfSetPosition(0, 0);
321  glTranslated(0.0, -h + h20 - h4, 0);
322  pfDrawString(myLinkNames[i].c_str());
323  glTranslated(-0.0, h - h20 + h4, 0);
324  glRotated(-180, 1, 0, 0);
325  h2 += 20;
326  }
327  h -= h20;
328  }
329  glBegin(GL_LINES);
330  glVertex2d(0, h + h20);
331  glVertex2d(1.0, h + h20);
332  glEnd();
333 
334  // draw the names closure (vertical line)
335  h += (SUMOReal) 20 / height;
336  glColor3d(1, 1, 1);
337  glBegin(GL_LINES);
338  glVertex2d((SUMOReal) 30 / width, 1.0);
339  glVertex2d((SUMOReal) 30 / width, h);
340  glEnd();
341 
342 
343  // draw the phases
344  // disable value addition while drawing
345  myLock.lock();
346  // determine the initial offset
347  SUMOReal x = ((SUMOReal) 31. / width) ;
348  SUMOReal ta = (SUMOReal) leftOffset / width;
349  ta *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
350  x += ta;
351 
352  // and the initial phase information
353  PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
354  DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show;
355  size_t fpo = myFirstPhaseOffset;
356 
357  // start drawing
358  for (size_t i = 30; pd != myDurations.end();) {
359  // the first phase may be drawn incompletely
360  size_t duration = *pd - fpo;
361  // compute the heigh and the width of the phase
362  h = (SUMOReal)(1.0 - h10);
363  SUMOReal a = (SUMOReal) duration / width;
364  a *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
365  SUMOReal x2 = x + a;
366 
367  // go through the links
368  for (unsigned int j = 0; j < (unsigned int) myTLLogic->getLinks().size(); j++) {
369  // determine the current link's color
370  LinkState state = (*pi).getSignalState(j);
371  // draw the bar (red is drawn as a line)
372  switch (state) {
375  glColor3d(0, 1.0, 0);
376  glBegin(GL_QUADS);
377  glVertex2d(x, h - h16);
378  glVertex2d(x, h - h4);
379  glVertex2d(x2, h - h4);
380  glVertex2d(x2, h - h16);
381  glEnd();
382  break;
385  glColor3d(1.0, 1.0, 0);
386  glBegin(GL_QUADS);
387  glVertex2d(x, h - h16);
388  glVertex2d(x, h - h4);
389  glVertex2d(x2, h - h4);
390  glVertex2d(x2, h - h16);
391  glEnd();
392  break;
393  case LINKSTATE_TL_RED:
394  glColor3d(1.0, 0, 0);
395  glBegin(GL_LINES);
396  glVertex2d(x, h - h10);
397  glVertex2d(x2, h - h10);
398  glEnd();
399  break;
400  default:
401  break;
402  }
403  // proceed to next link
404  h -= h20;
405  }
406  // proceed to next phase
407  i += duration;
408  pi++;
409  pd++;
410  x = x2;
411  // all further phases are drawn in full
412  fpo = 0;
413  }
414  // allow value addition
415  myLock.unlock();
416 
417  glColor3d(1, 1, 1);
418  if (myPhases.size() != 0) {
419  SUMOTime tickDist = TIME2STEPS(10);
420  // patch distances - hack
422  while (t > (width - 31.) / 4.) {
423  tickDist += TIME2STEPS(10);
424  t -= (SUMOReal)((width - 31.) / 4.);
425  }
426  // draw time information
427  h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12);
428  SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
429  // current begin time
430  pfSetScaleXY((SUMOReal)(.05 * 300. / width), (SUMOReal)(.05 * 300. / height));
431  // time ticks
432  SUMOTime currTime = myFirstTime2Show;
433  int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show;
434  SUMOReal glpos = (SUMOReal) pos / width;
435  while (pos < width + 50) {
436  const std::string timeStr = time2string(currTime);
437  const SUMOReal w = pfdkGetStringWidth(timeStr.c_str());
438  glRotated(180, 1, 0, 0);
439  pfSetPosition(0, 0);
440  glTranslated(glpos - w / 2., -glh + h20 - h4, 0);
441  pfDrawString(timeStr.c_str());
442  glTranslated(-glpos + w / 2., glh - h20 + h4, 0);
443  glRotated(-180, 1, 0, 0);
444 
445  glBegin(GL_LINES);
446  glVertex2d(glpos, glh);
447  glVertex2d(glpos, glh - h4);
448  glEnd();
449 
450  const SUMOReal a = STEPS2TIME(tickDist) * (width - 31.0) / STEPS2TIME(myLastTime - myBeginTime);
451  pos += (int) a;
452  glpos += a / width;
453  currTime += tickDist;
454  }
455  }
456 }
457 
458 
459 void
460 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) {
461  // do not draw while adding
462  myLock.lock();
463  // set the first time if not set before
464  if (myPhases.size() == 0) {
465  myBeginTime = def.first;
466  }
467  // append or set the phase
468  if (myPhases.size() == 0 || *(myPhases.end() - 1) != def.second) {
469  myPhases.push_back(def.second);
470  myDurations.push_back(DELTA_T);
471  } else {
472  *(myDurations.end() - 1) += DELTA_T;
473  }
474  // set the last time a phase was added at
475  myLastTime = def.first;
476  // allow drawing
477  myLock.unlock();
478 }
479 
480 
481 long
483  FXSelector sel, void* data) {
484  myPanel->onConfigure(sender, sel, data);
485  return FXMainWindow::onConfigure(sender, sel, data);
486 }
487 
488 
489 long
491  FXSelector sel, void* data) {
492  myPanel->onPaint(sender, sel, data);
493  return FXMainWindow::onPaint(sender, sel, data);
494 }
495 
496 
497 long
499  FXSelector, void*) {
500  update();
501  return 1;
502 }
503 
504 
505 void
507  myBeginTime = time;
508 }
509 
510 
511 /****************************************************************************/
512