SUMO - Simulation of Urban MObility
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.dlr.de/
12 // Copyright (C) 2001-2016 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 <vector>
34 #include <iostream>
36 #include <utils/gui/div/GLHelper.h>
39 #include <microsim/MSLink.h>
40 #include <utils/common/ToString.h>
47 
48 #ifdef CHECK_MEMORY_LEAKS
49 #include <foreign/nvwa/debug_new.h>
50 #endif // CHECK_MEMORY_LEAKS
51 
52 
53 // ===========================================================================
54 // member method definitions
55 // ===========================================================================
56 /* -------------------------------------------------------------------------
57  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-callbacks
58  * ----------------------------------------------------------------------- */
59 FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[] = {
62 
63 };
64 
65 // Macro for the GLTestApp class hierarchy implementation
66 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel, FXGLCanvas, GUITLLogicPhasesTrackerPanelMap, ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap))
67 
68 
69 
70 /* -------------------------------------------------------------------------
71  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-methods
72  * ----------------------------------------------------------------------- */
74  FXComposite* c, GUIMainWindow& app,
76  : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y/*, 0, 0, 300, 200*/),
77  myParent(&parent) {}
78 
79 
81 
82 
83 long
85  FXObject*, FXSelector, void*) {
86  if (makeCurrent()) {
87  int widthInPixels = getWidth();
88  int heightInPixels = getHeight();
89  if (widthInPixels != 0 && heightInPixels != 0) {
90  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
91  glClearColor(0, 0, 0, 1);
92  glDisable(GL_DEPTH_TEST);
93  glDisable(GL_LIGHTING);
94  glDisable(GL_LINE_SMOOTH);
95  glEnable(GL_BLEND);
96  glEnable(GL_ALPHA_TEST);
97  glDisable(GL_COLOR_MATERIAL);
98  glLineWidth(1);
99  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
100  }
101  }
102  return 1;
103 }
104 
105 
106 long
108  FXObject*, FXSelector, void*) {
109  if (!isEnabled()) {
110  return 1;
111  }
112  if (makeCurrent()) {
113  int widthInPixels = getWidth();
114  int heightInPixels = getHeight();
115  if (widthInPixels != 0 && heightInPixels != 0) {
116  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
117  glClearColor(0, 0, 0, 1);
118  glDisable(GL_DEPTH_TEST);
119  glDisable(GL_LIGHTING);
120  glDisable(GL_LINE_SMOOTH);
121  glEnable(GL_BLEND);
122  glEnable(GL_ALPHA_TEST);
123  glDisable(GL_COLOR_MATERIAL);
124  glLineWidth(1);
125  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
126  // draw
127  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
128  myParent->drawValues(*this);
129  swapBuffers();
130  }
131  makeNonCurrent();
132  }
133  return 1;
134 }
135 
136 
137 
138 /* -------------------------------------------------------------------------
139  * GUITLLogicPhasesTrackerWindow - FOX callback mapping
140  * ----------------------------------------------------------------------- */
141 FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[] = {
142  FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::onConfigure),
143  FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::onPaint),
144  FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep),
145 
146 };
147 
148 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow, FXMainWindow, GUITLLogicPhasesTrackerWindowMap, ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap))
149 
150 
151 /* -------------------------------------------------------------------------
152  * GUITLLogicPhasesTrackerWindow-methods
153  * ----------------------------------------------------------------------- */
155  GUIMainWindow& app,
157  ValueSource<std::pair<SUMOTime, MSPhaseDefinition> >* src)
158  : FXMainWindow(app.getApp(), "TLS-Tracker", NULL, NULL, DECOR_ALL,
159  20, 20, 300, 200),
160  myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(true) {
161  // build the toolbar
162  myToolBarDrag = new FXToolBarShell(this, FRAME_NORMAL);
163  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
164  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
165  // interval manipulation
166  myBeginOffset = new FXRealSpinDial(myToolBar, 10, this, MID_SIMSTEP, LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
167  myBeginOffset->setFormatString("%.0f");
168  myBeginOffset->setIncrements(1, 10, 100);
169  myBeginOffset->setRange(60, 3600);
170  myBeginOffset->setValue(240);
171  new FXLabel(myToolBar, "(s)", 0, LAYOUT_CENTER_Y);
172  //
174  FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8 + 30);
175  app.addChild(this, true);
176  for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
177  myLinkNames.push_back(toString<int>(i));
178  }
179  FXVerticalFrame* glcanvasFrame =
180  new FXVerticalFrame(this,
181  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
182  0, 0, 0, 0, 0, 0, 0, 0);
183  myPanel = new
184  GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
185  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
187  setHeight(height);
188 }
189 
190 
192  GUIMainWindow& app,
194  const MSSimpleTrafficLightLogic::Phases& /*phases*/)
195  : FXMainWindow(app.getApp(), "TLS-Tracker", NULL, NULL, DECOR_ALL,
196  20, 20, 300, 200),
197  myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(false),
199  myConnector = 0;
200  FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8);
201  setTitle("TLS-Tracker");
202  app.addChild(this, true);
203  for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
204  myLinkNames.push_back(toString<int>(i));
205  }
206  FXVerticalFrame* glcanvasFrame =
207  new FXVerticalFrame(this,
208  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
209  0, 0, 0, 0, 0, 0, 0, 0);
210  myPanel = new
211  GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
212  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
214  setHeight(height);
215 }
216 
217 
219  myApplication->removeChild(this);
220  delete myConnector;
221  // just to quit cleanly on a failure
222  if (myLock.locked()) {
223  myLock.unlock();
224  }
225  delete myToolBarDrag;
226 }
227 
228 
229 void
231  FXMainWindow::create();
232  if (myToolBarDrag != 0) {
233  myToolBarDrag->create();
234  }
235 }
236 
237 
238 void
240  // compute what shall be shown (what is visible)
241  myFirstPhase2Show = 0;
242  myFirstPhaseOffset = 0;
243  int leftOffset = 0;
244  myFirstTime2Show = 0;
245  if (!myAmInTrackingMode) {
246  myPhases.clear();
247  myDurations.clear();
248  // insert phases
249  const MSSimpleTrafficLightLogic::Phases& phases = static_cast<MSSimpleTrafficLightLogic*>(myTLLogic)->getPhases();
250  MSSimpleTrafficLightLogic::Phases::const_iterator j;
251  myLastTime = 0;
252  myBeginTime = 0;
253  for (j = phases.begin(); j != phases.end(); ++j) {
254  myPhases.push_back(*(*j));
255  myDurations.push_back((*j)->duration);
256  myLastTime += (*j)->duration;
257  }
258  if (myLastTime <= myBeginTime) {
259  WRITE_ERROR("Overflow in time computation occured.");
260  return;
261  }
262  } else {
263  SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
264  myBeginTime = myLastTime - beginOffset;
266  // check whether no phases are known at all
267  if (myDurations.size() != 0) {
268  SUMOTime durs = 0;
269  int phaseOffset = (int)myDurations.size() - 1;
270  DurationsVector::reverse_iterator i = myDurations.rbegin();
271  while (i != myDurations.rend()) {
272  if (durs + (*i) > beginOffset) {
273  myFirstPhase2Show = phaseOffset;
274  myFirstPhaseOffset = (durs + (*i)) - beginOffset;
275  break;
276  }
277  durs += (*i);
278  phaseOffset--;
279  ++i;
280  }
281  if (i == myDurations.rend()) {
282  // there are too few information stored;
283  myFirstPhase2Show = 0;
284  myFirstPhaseOffset = 0;
285  leftOffset = beginOffset - durs;
286  }
287  }
288  }
289  // begin drawing
290  glMatrixMode(GL_PROJECTION);
291  glLoadIdentity();
292  glMatrixMode(GL_MODELVIEW);
293  glLoadIdentity();
294  glTranslated(-1, -1, 0);
295  glScaled(2, 2, 1);
296  glDisable(GL_TEXTURE_2D);
297  // draw the horizontal lines dividing the signal groups
298  glColor3d(1, 1, 1);
299  // compute some values needed more than once
300  const SUMOReal height = (SUMOReal) caller.getHeight();
301  const SUMOReal width = (SUMOReal) caller.getWidth();
302  pfSetScaleXY((SUMOReal)(.08 * 300. / width), (SUMOReal)(.08 * 300. / height));
303  const SUMOReal h4 = ((SUMOReal) 4 / height);
304  const SUMOReal h9 = ((SUMOReal) 9 / height);
305  const SUMOReal h10 = ((SUMOReal) 10 / height);
306  const SUMOReal h11 = ((SUMOReal) 11 / height);
307  const SUMOReal h16 = ((SUMOReal) 16 / height);
308  const SUMOReal h20 = ((SUMOReal) 20 / height);
309  // draw the link names and the lines dividing them
310  SUMOReal h = (SUMOReal)(1.0 - h10);
311  SUMOReal h2 = 12;
312  for (int i = 0; i < (int)myTLLogic->getLinks().size() + 1; ++i) {
313  // draw the bar
314  glBegin(GL_LINES);
315  glVertex2d(0, h);
316  glVertex2d((SUMOReal)(30. / width), h);
317  glEnd();
318  // draw the name
319  if (i < (int)myTLLogic->getLinks().size()) {
320  glRotated(180, 1, 0, 0);
321  pfSetPosition(0, 0);
322  glTranslated(0.0, -h + h20 - h4, 0);
323  pfDrawString(myLinkNames[i].c_str());
324  glTranslated(-0.0, h - h20 + h4, 0);
325  glRotated(-180, 1, 0, 0);
326  h2 += 20;
327  }
328  h -= h20;
329  }
330  glBegin(GL_LINES);
331  glVertex2d(0, h + h20);
332  glVertex2d(1.0, h + h20);
333  glEnd();
334 
335  // draw the names closure (vertical line)
336  h += (SUMOReal) 20 / height;
337  glColor3d(1, 1, 1);
338  glBegin(GL_LINES);
339  glVertex2d((SUMOReal) 30 / width, 1.0);
340  glVertex2d((SUMOReal) 30 / width, h);
341  glEnd();
342 
343 
344  // draw the phases
345  // disable value addition while drawing
346  myLock.lock();
347  // determine the initial offset
348  SUMOReal x = ((SUMOReal) 31. / width);
349  SUMOReal ta = (SUMOReal) leftOffset / width;
350  ta *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
351  x += ta;
352 
353  // and the initial phase information
354  PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
355  DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show;
356  int fpo = myFirstPhaseOffset;
357 
358  // start drawing
359  for (int i = 30; pd != myDurations.end();) {
360  // the first phase may be drawn incompletely
361  int duration = *pd - fpo;
362  // compute the heigh and the width of the phase
363  h = (SUMOReal)(1.0 - h10);
364  SUMOReal a = (SUMOReal) duration / width;
365  a *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
366  SUMOReal x2 = x + a;
367 
368  // go through the links
369  for (int j = 0; j < (int) myTLLogic->getLinks().size(); ++j) {
370  // determine the current link's color
371  LinkState state = pi->getSignalState(j);
372  // draw the bar (red is drawn as a line)
374  switch (state) {
375  case LINKSTATE_TL_RED:
377  // draw a thin line
378  glBegin(GL_QUADS);
379  glVertex2d(x, h - h11);
380  glVertex2d(x, h - h9);
381  glVertex2d(x2, h - h9);
382  glVertex2d(x2, h - h11);
383  glEnd();
384  break;
385  default:
386  // draw a thick block
387  glBegin(GL_QUADS);
388  glVertex2d(x, h - h16);
389  glVertex2d(x, h - h4);
390  glVertex2d(x2, h - h4);
391  glVertex2d(x2, h - h16);
392  glEnd();
393  break;
394  }
395  // proceed to next link
396  h -= h20;
397  }
398  // proceed to next phase
399  i += duration;
400  ++pi;
401  ++pd;
402  x = x2;
403  // all further phases are drawn in full
404  fpo = 0;
405  }
406  // allow value addition
407  myLock.unlock();
408 
409  glColor3d(1, 1, 1);
410  if (myPhases.size() != 0) {
411  SUMOTime tickDist = TIME2STEPS(10);
412  // patch distances - hack
414  while (t > (width - 31.) / 4.) {
415  tickDist += TIME2STEPS(10);
416  t -= (SUMOReal)((width - 31.) / 4.);
417  }
418  // draw time information
419  //h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12);
420  SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
421  // current begin time
422  pfSetScaleXY((SUMOReal)(.05 * 300. / width), (SUMOReal)(.05 * 300. / height));
423  // time ticks
424  SUMOTime currTime = myFirstTime2Show;
425  int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show;
426  SUMOReal glpos = (SUMOReal) pos / width;
427  while (pos < width + 50) {
428  const std::string timeStr = time2string(currTime);
429  const SUMOReal w = pfdkGetStringWidth(timeStr.c_str());
430  glRotated(180, 1, 0, 0);
431  pfSetPosition(0, 0);
432  glTranslated(glpos - w / 2., -glh + h20 - h4, 0);
433  pfDrawString(timeStr.c_str());
434  glTranslated(-glpos + w / 2., glh - h20 + h4, 0);
435  glRotated(-180, 1, 0, 0);
436 
437  glBegin(GL_LINES);
438  glVertex2d(glpos, glh);
439  glVertex2d(glpos, glh - h4);
440  glEnd();
441 
442  const SUMOReal a = STEPS2TIME(tickDist) * (width - 31.0) / STEPS2TIME(myLastTime - myBeginTime);
443  pos += (int) a;
444  glpos += a / width;
445  currTime += tickDist;
446  }
447  }
448 }
449 
450 
451 void
452 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) {
453  // do not draw while adding
454  myLock.lock();
455  // set the first time if not set before
456  if (myPhases.size() == 0) {
457  myBeginTime = def.first;
458  }
459  // append or set the phase
460  if (myPhases.size() == 0 || *(myPhases.end() - 1) != def.second) {
461  myPhases.push_back(def.second);
462  myDurations.push_back(DELTA_T);
463  } else {
464  *(myDurations.end() - 1) += DELTA_T;
465  }
466  // set the last time a phase was added at
467  myLastTime = def.first;
468  // allow drawing
469  myLock.unlock();
470 }
471 
472 
473 long
475  FXSelector sel, void* data) {
476  myPanel->onConfigure(sender, sel, data);
477  return FXMainWindow::onConfigure(sender, sel, data);
478 }
479 
480 
481 long
483  FXSelector sel, void* data) {
484  myPanel->onPaint(sender, sel, data);
485  return FXMainWindow::onPaint(sender, sel, data);
486 }
487 
488 
489 long
491  FXSelector, void*) {
492  update();
493  return 1;
494 }
495 
496 
497 void
499  myBeginTime = time;
500 }
501 
502 
503 /****************************************************************************/
504 
int pfDrawString(const char *c)
Definition: polyfonts.c:1074
long long int SUMOTime
Definition: SUMOTime.h:43
bool myAmInTrackingMode
Information whether the tracking mode is on.
GUIMainWindow * myApplication
The main application.
long onSimStep(FXObject *sender, FXSelector sel, void *data)
called on a simulation step
void create()
Creates the window (FOX-Toolkit)
const RGBColor & getLinkColor(const LinkState &ls)
Definition: StdDefs.cpp:53
std::string time2string(SUMOTime t)
Definition: SUMOTime.cpp:59
std::vector< std::string > myLinkNames
The names of links.
void pfSetPosition(SUMOReal x, SUMOReal y)
Definition: polyfonts.c:480
int myFirstPhase2Show
The index of the first phase that fits into the window.
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
PhasesVector myPhases
The list of phases.
#define TIME2STEPS(x)
Definition: SUMOTime.h:66
DurationsVector myDurations
The list of phase durations.
long onConfigure(FXObject *sender, FXSelector sel, void *data)
called on size change
FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[]
A fixed traffic light logic.
void drawValues(GUITLLogicPhasesTrackerPanel &caller)
Draws all values.
const std::string & getID() const
Returns the id.
Definition: Named.h:66
void addChild(FXMDIChild *child, bool updateOnSimStep=true)
Adds a further child window to the list.
SUMOTime myFirstTime2Show
The time the diagram begins at.
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:443
long onConfigure(FXObject *, FXSelector, void *)
called on size change
A Simulation step was performed.
Definition: GUIAppEnum.h:291
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
#define STEPS2TIME(x)
Definition: SUMOTime.h:65
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic, in MSLink and GNEInternalLane.
FXRealSpinDial * myBeginOffset
The offset changer (tracking mode)
FXToolBarShell * myToolBarDrag
The tool bar drag (tracking mode)
void removeChild(FXMDIChild *child)
removes the given child window from the list
SUMOTime myLastTime
The last time a phase was added at.
void pfSetScaleXY(SUMOReal sx, SUMOReal sy)
Definition: polyfonts.c:472
void addValue(std::pair< SUMOTime, MSPhaseDefinition > def)
Adds a further phase definition.
GLObjectValuePassConnector< std::pair< SUMOTime, MSPhaseDefinition > > * myConnector
The connector for retrieval of further phases.
int myFirstPhaseOffset
The offset to draw the first phase (left offset)
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
void unlock()
release mutex lock
Definition: MFXMutex.cpp:96
The link has red light (must brake)
MSTrafficLightLogic * myTLLogic
The logic to display.
long onPaint(FXObject *sender, FXSelector sel, void *data)
called if the widget shall be repainted
GUITLLogicPhasesTrackerPanel * myPanel
The panel to draw on.
This window displays a phase diagram for a chosen tl-logic.
void lock()
lock mutex
Definition: MFXMutex.cpp:86
SUMOReal pfdkGetStringWidth(const char *c)
Definition: polyfonts.c:1113
The parent class for traffic light logics.
MFXMutex myLock
A lock to avoid addition of new values while drawing.
#define SUMOReal
Definition: config.h:213
const std::string & getProgramID() const
Returns this tl-logic&#39;s id.
FXToolBar * myToolBar
The tool bar (tracking mode)
void setBeginTime(SUMOTime time)
Sets the time the display shall be shown as beginning at.
FXbool locked()
Definition: MFXMutex.h:70
GUITLLogicPhasesTrackerWindow()
protected constructor for FOX
long onPaint(FXObject *, FXSelector, void *)
called if the widget shall be repainted
The definition of a single phase of a tls logic.
static FXIcon * getIcon(GUIIcon which)
returns a icon previously defined in the enum GUIIcon
The link has red light (must brake) but indicates upcoming green.
SUMOTime myBeginTime
The first time a phase was added at.
Class passing values from a GUIGlObject to another object.