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