SUMO - Simulation of Urban MObility
GUITLLogicPhasesTrackerWindow.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
19 // A window displaying the phase diagram of a tl-logic
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <vector>
33 #include <iostream>
35 #include <utils/gui/div/GLHelper.h>
38 #include <microsim/MSLink.h>
39 #include <utils/common/ToString.h>
48 
49 
50 // ===========================================================================
51 // member method definitions
52 // ===========================================================================
53 /* -------------------------------------------------------------------------
54  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-callbacks
55  * ----------------------------------------------------------------------- */
56 FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[] = {
59 
60 };
61 
62 // Macro for the GLTestApp class hierarchy implementation
63 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel, FXGLCanvas, GUITLLogicPhasesTrackerPanelMap, ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap))
64 
65 
66 
67 /* -------------------------------------------------------------------------
68  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-methods
69  * ----------------------------------------------------------------------- */
71  FXComposite* c, GUIMainWindow& app,
73  : FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) 0, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y/*, 0, 0, 300, 200*/),
74  myParent(&parent) {}
75 
76 
78 
79 
80 long
82  FXObject*, FXSelector, void*) {
83  if (makeCurrent()) {
84  int widthInPixels = getWidth();
85  int heightInPixels = getHeight();
86  if (widthInPixels != 0 && heightInPixels != 0) {
87  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
88  glClearColor(0, 0, 0, 1);
89  glDisable(GL_DEPTH_TEST);
90  glDisable(GL_LIGHTING);
91  glDisable(GL_LINE_SMOOTH);
92  glEnable(GL_BLEND);
93  glEnable(GL_ALPHA_TEST);
94  glDisable(GL_COLOR_MATERIAL);
95  glLineWidth(1);
96  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
97  }
98  }
99  return 1;
100 }
101 
102 
103 long
105  FXObject*, FXSelector, void*) {
106  if (!isEnabled()) {
107  return 1;
108  }
109  if (makeCurrent()) {
110  int widthInPixels = getWidth();
111  int heightInPixels = getHeight();
112  if (widthInPixels != 0 && heightInPixels != 0) {
113  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
114  glClearColor(0, 0, 0, 1);
115  glDisable(GL_DEPTH_TEST);
116  glDisable(GL_LIGHTING);
117  glDisable(GL_LINE_SMOOTH);
118  glEnable(GL_BLEND);
119  glEnable(GL_ALPHA_TEST);
120  glDisable(GL_COLOR_MATERIAL);
121  glLineWidth(1);
122  glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
123  // draw
124  glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
125  myParent->drawValues(*this);
126  swapBuffers();
127  }
128  makeNonCurrent();
129  }
130  return 1;
131 }
132 
133 
134 
135 /* -------------------------------------------------------------------------
136  * GUITLLogicPhasesTrackerWindow - FOX callback mapping
137  * ----------------------------------------------------------------------- */
138 FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[] = {
139  FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::onConfigure),
140  FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::onPaint),
141  FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep),
142 
143 };
144 
145 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow, FXMainWindow, GUITLLogicPhasesTrackerWindowMap, ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap))
146 
147 
148 /* -------------------------------------------------------------------------
149  * GUITLLogicPhasesTrackerWindow-methods
150  * ----------------------------------------------------------------------- */
152  GUIMainWindow& app,
154  ValueSource<std::pair<SUMOTime, MSPhaseDefinition> >* src)
155  : FXMainWindow(app.getApp(), "TLS-Tracker", NULL, NULL, DECOR_ALL,
156  20, 20, 300, 200),
157  myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(true) {
158  // build the toolbar
159  myToolBarDrag = new FXToolBarShell(this, GUIDesignToolBarShell3);
160  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
161  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
162  // interval manipulation
163  myBeginOffset = new FXRealSpinDial(myToolBar, 10, this, MID_SIMSTEP, LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
164  myBeginOffset->setFormatString("%.0f");
165  myBeginOffset->setIncrements(1, 10, 100);
166  myBeginOffset->setRange(60, 3600);
167  myBeginOffset->setValue(240);
168  new FXLabel(myToolBar, "(s)", 0, LAYOUT_CENTER_Y);
169  //
171  FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8 + 30);
172  app.addChild(this, true);
173  for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
174  myLinkNames.push_back(toString<int>(i));
175  }
176  FXVerticalFrame* glcanvasFrame =
177  new FXVerticalFrame(this,
178  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
179  0, 0, 0, 0, 0, 0, 0, 0);
180  myPanel = new
181  GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
182  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
184  setHeight(height);
185 }
186 
187 
189  GUIMainWindow& app,
191  const MSSimpleTrafficLightLogic::Phases& /*phases*/)
192  : FXMainWindow(app.getApp(), "TLS-Tracker", NULL, NULL, DECOR_ALL,
193  20, 20, 300, 200),
194  myApplication(&app), myTLLogic(&logic), myAmInTrackingMode(false),
196  myConnector = 0;
197  FXint height = (FXint)(myTLLogic->getLinks().size() * 20 + 30 + 8);
198  setTitle("TLS-Tracker");
199  app.addChild(this, true);
200  for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
201  myLinkNames.push_back(toString<int>(i));
202  }
203  FXVerticalFrame* glcanvasFrame =
204  new FXVerticalFrame(this,
205  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
206  0, 0, 0, 0, 0, 0, 0, 0);
207  myPanel = new
208  GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
209  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
211  setHeight(height);
212 }
213 
214 
216  myApplication->removeChild(this);
217  delete myConnector;
218  // just to quit cleanly on a failure
219  if (myLock.locked()) {
220  myLock.unlock();
221  }
222  delete myToolBarDrag;
223 }
224 
225 
226 void
228  FXMainWindow::create();
229  if (myToolBarDrag != 0) {
230  myToolBarDrag->create();
231  }
232 }
233 
234 
235 void
237  // compute what shall be shown (what is visible)
238  myFirstPhase2Show = 0;
239  myFirstPhaseOffset = 0;
240  SUMOTime leftOffset = 0;
241  myFirstTime2Show = 0;
242  if (!myAmInTrackingMode) {
243  myPhases.clear();
244  myDurations.clear();
245  // insert phases
246  MSSimpleTrafficLightLogic* simpleTLLogic = dynamic_cast<MSSimpleTrafficLightLogic*>(myTLLogic);
247  if (simpleTLLogic == 0) {
248  return;
249  }
250  const MSSimpleTrafficLightLogic::Phases& phases = simpleTLLogic->getPhases();
251  MSSimpleTrafficLightLogic::Phases::const_iterator j;
252  myLastTime = 0;
253  myBeginTime = 0;
254  for (j = phases.begin(); j != phases.end(); ++j) {
255  myPhases.push_back(*(*j));
256  myDurations.push_back((*j)->duration);
257  myLastTime += (*j)->duration;
258  }
259  if (myLastTime <= myBeginTime) {
260  WRITE_ERROR("Overflow in time computation occured.");
261  return;
262  }
263  } else {
264  SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
265  myBeginTime = myLastTime - beginOffset;
267  // check whether no phases are known at all
268  if (myDurations.size() != 0) {
269  SUMOTime durs = 0;
270  int phaseOffset = (int)myDurations.size() - 1;
271  DurationsVector::reverse_iterator i = myDurations.rbegin();
272  while (i != myDurations.rend()) {
273  if (durs + (*i) > beginOffset) {
274  myFirstPhase2Show = phaseOffset;
275  myFirstPhaseOffset = (durs + (*i)) - beginOffset;
276  break;
277  }
278  durs += (*i);
279  phaseOffset--;
280  ++i;
281  }
282  if (i == myDurations.rend()) {
283  // there are too few information stored;
284  myFirstPhase2Show = 0;
285  myFirstPhaseOffset = 0;
286  leftOffset = beginOffset - durs;
287  }
288  }
289  }
290  // begin drawing
291  glMatrixMode(GL_PROJECTION);
292  glLoadIdentity();
293  glMatrixMode(GL_MODELVIEW);
294  glLoadIdentity();
295  glTranslated(-1, -1, 0);
296  glScaled(2, 2, 1);
297  glDisable(GL_TEXTURE_2D);
298  // draw the horizontal lines dividing the signal groups
299  glColor3d(1, 1, 1);
300  // compute some values needed more than once
301  const double height = (double) caller.getHeight();
302  const double width = (double) caller.getWidth();
303  const double barWidth = MAX2(1.0, width - 31);
304  const double fontHeight = 0.08 * 300. / height;
305  const double fontWidth = 0.08 * 300. / width;
306  const double h9 = ((double) 9 / height);
307  const double h10 = ((double) 10 / height);
308  const double h11 = ((double) 11 / height);
309  const double h16 = ((double) 16 / height);
310  const double h20 = ((double) 20 / height);
311  // draw the link names and the lines dividing them
312  double h = (double)(1.0 - h10);
313  double 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((double)(30. / width), h);
319  glEnd();
320  // draw the name
321  if (i < (int)myTLLogic->getLinks().size()) {
322  glTranslated(0, h - h20, 0);
323  GLHelper::drawText(myLinkNames[i], Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_BOTTOM, fontWidth);
324  glTranslated(0, -h + h20, 0);
325  h2 += 20;
326  }
327  h -= h20;
328  }
329  glBegin(GL_LINES);
330  glVertex2d(0, h + h20);
331  glVertex2d(1.0, h + h20);
332  glEnd();
333 
334  // draw the names closure (vertical line)
335  h += (double) 20 / height;
336  glColor3d(1, 1, 1);
337  glBegin(GL_LINES);
338  glVertex2d((double) 30 / width, 1.0);
339  glVertex2d((double) 30 / width, h);
340  glEnd();
341 
342 
343  // draw the phases
344  // disable value addition while drawing
345  myLock.lock();
346  // determine the initial offset
347  double x = ((double) 31. / width);
348  double ta = (double) leftOffset / width;
349  ta *= (double)((barWidth / ((double)(myLastTime - myBeginTime))));
350  x += ta;
351 
352  // and the initial phase information
353  PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
354 
356 
357  // start drawing
358  for (DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show; pd != myDurations.end(); ++pd) {
359  SUMOTime i = 30;
360  // the first phase may be drawn incompletely
361  SUMOTime duration = *pd - fpo;
362  // compute the heigh and the width of the phase
363  h = (double)(1.0 - h10);
364  double a = (double) duration / width;
365  a *= (double)((barWidth / ((double)(myLastTime - myBeginTime))));
366  const double 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);
390  glVertex2d(x2, h);
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  x = x2;
402  // all further phases are drawn in full
403  fpo = 0;
404  }
405  // allow value addition
406  myLock.unlock();
407 
408  glColor3d(1, 1, 1);
409  if (myPhases.size() != 0) {
410  SUMOTime tickDist = TIME2STEPS(10);
411  // patch distances - hack
412  double t = myBeginOffset != 0 ? (double) myBeginOffset->getValue() : STEPS2TIME(myLastTime - myBeginTime);
413  while (t > barWidth / 4.) {
414  tickDist += TIME2STEPS(10);
415  t -= (double)(barWidth / 4.);
416  }
417  // draw time information
418  //h = (double)(myTLLogic->getLinks().size() * 20 + 12);
419  double glh = (double)(1.0 - myTLLogic->getLinks().size() * h20 - h10);
420  // current begin time
421  // time ticks
422  SUMOTime currTime = myFirstTime2Show;
423  int pos = 31;// + /*!!!currTime*/ - myFirstTime2Show;
424  double glpos = (double) pos / width;
425  const double ticSize = 4 / height;
426  while (pos < width + 50) {
427  const std::string timeStr = time2string(currTime);
428  const double w = 50 / width;
429  glTranslated(glpos - w / 2., glh - h20, 0);
430  GLHelper::drawText(timeStr, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
431  glTranslated(-glpos + w / 2., -glh + h20, 0);
432 
433  glBegin(GL_LINES);
434  glVertex2d(glpos, glh);
435  glVertex2d(glpos, glh - ticSize);
436  glEnd();
437 
438  const double a = STEPS2TIME(tickDist) * barWidth / STEPS2TIME(myLastTime - myBeginTime);
439  pos += (int) a;
440  glpos += a / width;
441  currTime += tickDist;
442  }
443  }
444 }
445 
446 
447 void
448 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) {
449  // do not draw while adding
450  myLock.lock();
451  // set the first time if not set before
452  if (myPhases.size() == 0) {
453  myBeginTime = def.first;
454  }
455  // append or set the phase
456  if (myPhases.size() == 0 || *(myPhases.end() - 1) != def.second) {
457  myPhases.push_back(def.second);
458  myDurations.push_back(DELTA_T);
459  } else {
460  *(myDurations.end() - 1) += DELTA_T;
461  }
462  // set the last time a phase was added at
463  myLastTime = def.first;
464  // allow drawing
465  myLock.unlock();
466 }
467 
468 
469 long
471  FXSelector sel, void* data) {
472  myPanel->onConfigure(sender, sel, data);
473  return FXMainWindow::onConfigure(sender, sel, data);
474 }
475 
476 
477 long
479  FXSelector sel, void* data) {
480  myPanel->onPaint(sender, sel, data);
481  return FXMainWindow::onPaint(sender, sel, data);
482 }
483 
484 
485 long
487  FXSelector, void*) {
488  update();
489  return 1;
490 }
491 
492 
493 void
495  myBeginTime = time;
496 }
497 
498 
499 /****************************************************************************/
500 
bool myAmInTrackingMode
Information whether the tracking mode is on.
GUIMainWindow * myApplication
The main application.
static const RGBColor WHITE
Definition: RGBColor.h:185
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:59
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:268
static void drawText(const std::string &text, const Position &pos, const double layer, const double size, const RGBColor &col=RGBColor::BLACK, const double angle=0, int align=0, double width=-1)
Definition: GLHelper.cpp:487
int myFirstPhase2Show
The index of the first phase that fits into the window.
T MAX2(T a, T b)
Definition: StdDefs.h:73
SUMOTime DELTA_T
Definition: SUMOTime.cpp:39
PhasesVector myPhases
The list of phases.
const std::string & getID() const
Returns the id.
Definition: Named.h:65
#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:449
const std::string & getProgramID() const
Returns this tl-logic&#39;s id.
long onConfigure(FXObject *, FXSelector, void *)
called on size change
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:45
#define STEPS2TIME(x)
Definition: SUMOTime.h:64
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:205
void unlock()
release mutex lock
Definition: MFXMutex.cpp:93
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
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)
A Simulation step was performed.
Definition: GUIAppEnum.h:290
long long int SUMOTime
Definition: TraCIDefs.h:51
void setBeginTime(SUMOTime time)
Sets the time the display shall be shown as beginning at.
FXbool locked()
Definition: MFXMutex.h:69
#define GUIDesignToolBarShell3
Definition: GUIDesigns.h:276
GUITLLogicPhasesTrackerWindow()
protected constructor for FOX
const Phases & getPhases() const
Returns the phases of this tls program.
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.