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