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-sim.org/
12 // Copyright (C) 2001-2013 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>
38 #include <microsim/MSLink.h>
39 #include <utils/common/ToString.h>
45 
46 #ifdef CHECK_MEMORY_LEAKS
47 #include <foreign/nvwa/debug_new.h>
48 #endif // CHECK_MEMORY_LEAKS
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), myApplication(&app) {}
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, FRAME_NORMAL);
161  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
162  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, TOOLBARGRIP_DOUBLE);
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 (size_t i = 0; i < myTLLogic->getLinks().size(); ++i) {
175  myLinkNames.push_back(toString<size_t>(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 (size_t i = 0; i < myTLLogic->getLinks().size(); ++i) {
202  myLinkNames.push_back(toString<size_t>(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  size_t 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  } else {
257  SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
258  myBeginTime = myLastTime - beginOffset;
260  // check whether no phases are known at all
261  if (myDurations.size() != 0) {
262  SUMOTime durs = 0;
263  size_t phaseOffset = myDurations.size() - 1;
264  DurationsVector::reverse_iterator i = myDurations.rbegin();
265  while (i != myDurations.rend()) {
266  if (durs + (*i) > beginOffset) {
267  myFirstPhase2Show = phaseOffset;
268  myFirstPhaseOffset = (durs + (*i)) - beginOffset;
269  break;
270  }
271  durs += (*i);
272  phaseOffset--;
273  ++i;
274  }
275  if (i == myDurations.rend()) {
276  // there are too few information stored;
277  myFirstPhase2Show = 0;
278  myFirstPhaseOffset = 0;
279  leftOffset = beginOffset - durs;
280  }
281  }
282  }
283  // begin drawing
284  glMatrixMode(GL_PROJECTION);
285  glLoadIdentity();
286  glMatrixMode(GL_MODELVIEW);
287  glLoadIdentity();
288  glTranslated(-1, -1, 0);
289  glScaled(2, 2, 1);
290  glDisable(GL_TEXTURE_2D);
291  // draw the horizontal lines dividing the signal groups
292  glColor3d(1, 1, 1);
293  // compute some values needed more than once
294  const SUMOReal height = (SUMOReal) caller.getHeight();
295  const SUMOReal width = (SUMOReal) caller.getWidth();
296  pfSetScaleXY((SUMOReal)(.08 * 300. / width), (SUMOReal)(.08 * 300. / height));
297  const SUMOReal h4 = ((SUMOReal) 4 / height);
298  const SUMOReal h10 = ((SUMOReal) 10 / height);
299  const SUMOReal h16 = ((SUMOReal) 16 / height);
300  const SUMOReal h20 = ((SUMOReal) 20 / height);
301  // draw the link names and the lines dividing them
302  SUMOReal h = (SUMOReal)(1.0 - h10);
303  SUMOReal h2 = 12;
304  for (size_t i = 0; i < myTLLogic->getLinks().size() + 1; ++i) {
305  // draw the bar
306  glBegin(GL_LINES);
307  glVertex2d(0, h);
308  glVertex2d((SUMOReal)(30. / width), h);
309  glEnd();
310  // draw the name
311  if (i < myTLLogic->getLinks().size()) {
312  glRotated(180, 1, 0, 0);
313  pfSetPosition(0, 0);
314  glTranslated(0.0, -h + h20 - h4, 0);
315  pfDrawString(myLinkNames[i].c_str());
316  glTranslated(-0.0, h - h20 + h4, 0);
317  glRotated(-180, 1, 0, 0);
318  h2 += 20;
319  }
320  h -= h20;
321  }
322  glBegin(GL_LINES);
323  glVertex2d(0, h + h20);
324  glVertex2d(1.0, h + h20);
325  glEnd();
326 
327  // draw the names closure (vertical line)
328  h += (SUMOReal) 20 / height;
329  glColor3d(1, 1, 1);
330  glBegin(GL_LINES);
331  glVertex2d((SUMOReal) 30 / width, 1.0);
332  glVertex2d((SUMOReal) 30 / width, h);
333  glEnd();
334 
335 
336  // draw the phases
337  // disable value addition while drawing
338  myLock.lock();
339  // determine the initial offset
340  SUMOReal x = ((SUMOReal) 31. / width);
341  SUMOReal ta = (SUMOReal) leftOffset / width;
342  ta *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
343  x += ta;
344 
345  // and the initial phase information
346  PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
347  DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show;
348  size_t fpo = myFirstPhaseOffset;
349 
350  // start drawing
351  for (size_t i = 30; pd != myDurations.end();) {
352  // the first phase may be drawn incompletely
353  size_t duration = *pd - fpo;
354  // compute the heigh and the width of the phase
355  h = (SUMOReal)(1.0 - h10);
356  SUMOReal a = (SUMOReal) duration / width;
357  a *= (SUMOReal)(((width - 31.0) / ((SUMOReal)(myLastTime - myBeginTime))));
358  SUMOReal x2 = x + a;
359 
360  // go through the links
361  for (unsigned int j = 0; j < (unsigned int) myTLLogic->getLinks().size(); ++j) {
362  // determine the current link's color
363  LinkState state = (*pi).getSignalState(j);
364  // draw the bar (red is drawn as a line)
365  switch (state) {
368  glColor3d(0, 1.0, 0);
369  glBegin(GL_QUADS);
370  glVertex2d(x, h - h16);
371  glVertex2d(x, h - h4);
372  glVertex2d(x2, h - h4);
373  glVertex2d(x2, h - h16);
374  glEnd();
375  break;
378  glColor3d(1.0, 1.0, 0);
379  glBegin(GL_QUADS);
380  glVertex2d(x, h - h16);
381  glVertex2d(x, h - h4);
382  glVertex2d(x2, h - h4);
383  glVertex2d(x2, h - h16);
384  glEnd();
385  break;
386  case LINKSTATE_TL_RED:
387  glColor3d(1.0, 0, 0);
388  glBegin(GL_LINES);
389  glVertex2d(x, h - h10);
390  glVertex2d(x2, h - h10);
391  glEnd();
392  break;
393  default:
394  break;
395  }
396  // proceed to next link
397  h -= h20;
398  }
399  // proceed to next phase
400  i += duration;
401  ++pi;
402  ++pd;
403  x = x2;
404  // all further phases are drawn in full
405  fpo = 0;
406  }
407  // allow value addition
408  myLock.unlock();
409 
410  glColor3d(1, 1, 1);
411  if (myPhases.size() != 0) {
412  SUMOTime tickDist = TIME2STEPS(10);
413  // patch distances - hack
415  while (t > (width - 31.) / 4.) {
416  tickDist += TIME2STEPS(10);
417  t -= (SUMOReal)((width - 31.) / 4.);
418  }
419  // draw time information
420  h = (SUMOReal)(myTLLogic->getLinks().size() * 20 + 12);
421  SUMOReal glh = (SUMOReal)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
422  // current begin time
423  pfSetScaleXY((SUMOReal)(.05 * 300. / width), (SUMOReal)(.05 * 300. / height));
424  // time ticks
425  SUMOTime currTime = myFirstTime2Show;
426  int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show;
427  SUMOReal glpos = (SUMOReal) pos / width;
428  while (pos < width + 50) {
429  const std::string timeStr = time2string(currTime);
430  const SUMOReal w = pfdkGetStringWidth(timeStr.c_str());
431  glRotated(180, 1, 0, 0);
432  pfSetPosition(0, 0);
433  glTranslated(glpos - w / 2., -glh + h20 - h4, 0);
434  pfDrawString(timeStr.c_str());
435  glTranslated(-glpos + w / 2., glh - h20 + h4, 0);
436  glRotated(-180, 1, 0, 0);
437 
438  glBegin(GL_LINES);
439  glVertex2d(glpos, glh);
440  glVertex2d(glpos, glh - h4);
441  glEnd();
442 
443  const SUMOReal a = STEPS2TIME(tickDist) * (width - 31.0) / STEPS2TIME(myLastTime - myBeginTime);
444  pos += (int) a;
445  glpos += a / width;
446  currTime += tickDist;
447  }
448  }
449 }
450 
451 
452 void
453 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) {
454  // do not draw while adding
455  myLock.lock();
456  // set the first time if not set before
457  if (myPhases.size() == 0) {
458  myBeginTime = def.first;
459  }
460  // append or set the phase
461  if (myPhases.size() == 0 || *(myPhases.end() - 1) != def.second) {
462  myPhases.push_back(def.second);
463  myDurations.push_back(DELTA_T);
464  } else {
465  *(myDurations.end() - 1) += DELTA_T;
466  }
467  // set the last time a phase was added at
468  myLastTime = def.first;
469  // allow drawing
470  myLock.unlock();
471 }
472 
473 
474 long
476  FXSelector sel, void* data) {
477  myPanel->onConfigure(sender, sel, data);
478  return FXMainWindow::onConfigure(sender, sel, data);
479 }
480 
481 
482 long
484  FXSelector sel, void* data) {
485  myPanel->onPaint(sender, sel, data);
486  return FXMainWindow::onPaint(sender, sel, data);
487 }
488 
489 
490 long
492  FXSelector, void*) {
493  update();
494  return 1;
495 }
496 
497 
498 void
500  myBeginTime = time;
501 }
502 
503 
504 /****************************************************************************/
505 
The link has green light, may pass.
int pfDrawString(const char *c)
Definition: polyfonts.c:1070
bool myAmInTrackingMode
Information whether the tracking mode is on.
GUIMainWindow * myApplication
The main application.
The link has green light, has to brake.
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:61
std::vector< std::string > myLinkNames
The names of links.
void pfSetPosition(SUMOReal x, SUMOReal y)
Definition: polyfonts.c:476
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(GUIDialog_AppSettings) GUIDialog_AppSettingsMap[]
A fixed traffic light logic.
size_t myFirstPhase2Show
The index of the first phase that fits into the window.
A Simulation step was performed.
Definition: GUIAppEnum.h:263
void drawValues(GUITLLogicPhasesTrackerPanel &caller)
Draws all values.
const std::string & getID() const
Returns the id.
Definition: Named.h:60
void addChild(FXMDIChild *child, bool updateOnSimStep=true)
Adds a further child window to the list.
SUMOTime myFirstTime2Show
The time the diagram begins at.
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.
size_t myFirstPhaseOffset
The offset to draw the first phase (left offset)
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:468
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.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
void unlock()
release mutex lock
Definition: MFXMutex.cpp:93
The link has yellow light, may pass.
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:83
SUMOReal pfdkGetStringWidth(const char *c)
Definition: polyfonts.c:1109
The parent class for traffic light logics.
MFXMutex myLock
A lock to avoid addition of new values while drawing.
#define SUMOReal
Definition: config.h:221
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:68
#define DELTA_T
Definition: SUMOTime.h:50
GUITLLogicPhasesTrackerWindow()
protected constructor for FOX
The link has yellow light, has to brake anyway.
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)
SUMOTime myBeginTime
The first time a phase was added at.
Class passing values from a GUIGlObject to another object.