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