Eclipse 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.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // A window displaying the phase diagram of a tl-logic
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <vector>
25 #include <iostream>
27 #include <utils/gui/div/GLHelper.h>
31 #include <microsim/MSLink.h>
32 #include <utils/common/ToString.h>
41 
42 
43 // ===========================================================================
44 // static member initialisation
45 // ===========================================================================
47 
48 // ===========================================================================
49 // member method definitions
50 // ===========================================================================
51 /* -------------------------------------------------------------------------
52  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-callbacks
53  * ----------------------------------------------------------------------- */
58 
59 };
60 
61 // Macro for the GLTestApp class hierarchy implementation
62 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel, FXGLCanvas, GUITLLogicPhasesTrackerPanelMap, ARRAYNUMBER(GUITLLogicPhasesTrackerPanelMap))
63 
64 
65 
66 /* -------------------------------------------------------------------------
67  * GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel-methods
68  * ----------------------------------------------------------------------- */
70  FXComposite* c, GUIMainWindow& app,
72  FXGLCanvas(c, app.getGLVisual(), app.getBuildGLCanvas(), (FXObject*) nullptr, (FXSelector) 0, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y/*, 0, 0, 300, 200*/),
73  myParent(&parent)
74 {}
75 
76 
78 
79 
80 long
82  if (makeCurrent()) {
83  int widthInPixels = getWidth();
84  int heightInPixels = getHeight();
85  if (widthInPixels != 0 && heightInPixels != 0) {
86  glViewport(0, 0, widthInPixels - 1, heightInPixels - 1);
87  glClearColor(0, 0, 0, 1);
88  glDisable(GL_DEPTH_TEST);
89  glDisable(GL_LIGHTING);
90  glDisable(GL_LINE_SMOOTH);
91  glEnable(GL_BLEND);
92  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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 long
137  FXEvent* event = (FXEvent*) ptr;
138  myMousePos.setx(event->win_x);
139  myMousePos.sety(event->win_y);
140  onPaint(nullptr, 0, nullptr);
141  return 1;
142 }
143 
144 /* -------------------------------------------------------------------------
145  * GUITLLogicPhasesTrackerWindow - FOX callback mapping
146  * ----------------------------------------------------------------------- */
147 FXDEFMAP(GUITLLogicPhasesTrackerWindow) GUITLLogicPhasesTrackerWindowMap[] = {
148  FXMAPFUNC(SEL_CONFIGURE, 0, GUITLLogicPhasesTrackerWindow::onConfigure),
149  FXMAPFUNC(SEL_PAINT, 0, GUITLLogicPhasesTrackerWindow::onPaint),
150  FXMAPFUNC(SEL_COMMAND, MID_SIMSTEP, GUITLLogicPhasesTrackerWindow::onSimStep),
151 
152 };
153 
154 FXIMPLEMENT(GUITLLogicPhasesTrackerWindow, FXMainWindow, GUITLLogicPhasesTrackerWindowMap, ARRAYNUMBER(GUITLLogicPhasesTrackerWindowMap))
155 
156 
157 /* -------------------------------------------------------------------------
158  * GUITLLogicPhasesTrackerWindow-methods
159  * ----------------------------------------------------------------------- */
161  GUIMainWindow& app,
163  ValueSource<std::pair<SUMOTime, MSPhaseDefinition> >* src) :
164  FXMainWindow(app.getApp(), "TLS-Tracker", nullptr, nullptr, DECOR_ALL, 20, 20, 300, 200),
165  myApplication(&app),
166  myTLLogic(&logic),
167  myAmInTrackingMode(true) {
168  initToolBar();
170  app.addChild(this);
171  for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
172  myLinkNames.push_back(toString<int>(i));
173  }
174  for (auto item : myTLLogic->getDetectorStates()) {
175  std::string detID = item.first;
176  if (detID.size() > 4) {
177  detID = detID.substr(detID.size() - 4);
178  }
179  myDetectorNames.push_back(detID);
180  }
181  for (auto item : myTLLogic->getConditions()) {
182  myConditionNames.push_back(item.first);
183  }
184  loadSettings();
185  const int newHeight = computeHeight();
186  FXScrollWindow* scrollWindow = new FXScrollWindow(this, LAYOUT_FILL_X | LAYOUT_FILL_Y | HSCROLLER_NEVER | FRAME_NONE);
187  FXHorizontalFrame* spacerFrame = new FXHorizontalFrame(scrollWindow, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE);
188  new FXScrollWindow(spacerFrame, LAYOUT_FIX_WIDTH | LAYOUT_FIX_HEIGHT | FRAME_NONE, 0, 0, 0, newHeight - 40);
189  FXVerticalFrame* glcanvasFrame =
190  new FXVerticalFrame(spacerFrame,
191  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
192  0, 0, 0, 0, 0, 0, 0, 0);
193  myPanel = new GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
194  setTitle((logic.getID() + " - " + logic.getProgramID() + " - tracker").c_str());
196  setHeight(newHeight);
197 }
198 
199 
201  GUIMainWindow& app,
203  const MSSimpleTrafficLightLogic::Phases& /*phases*/) :
204  FXMainWindow(app.getApp(), "TLS-Tracker", nullptr, nullptr, DECOR_ALL, 20, 20, 300, 200),
205  myApplication(&app),
206  myTLLogic(&logic),
207  myAmInTrackingMode(false),
208  myToolBarDrag(nullptr),
209  myBeginOffset(nullptr) {
210  myConnector = nullptr;
211  initToolBar();
212  app.addChild(this);
213  for (int i = 0; i < (int)myTLLogic->getLinks().size(); ++i) {
214  myLinkNames.push_back(toString<int>(i));
215  }
216  int newHeight = computeHeight();
217  FXScrollWindow* scrollWindow = new FXScrollWindow(this, LAYOUT_FILL_X | LAYOUT_FILL_Y | HSCROLLER_NEVER | FRAME_NONE);
218  FXHorizontalFrame* spacerFrame = new FXHorizontalFrame(scrollWindow, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y | FRAME_NONE);
219  new FXScrollWindow(spacerFrame, LAYOUT_FIX_WIDTH | LAYOUT_FIX_HEIGHT | FRAME_NONE, 0, 0, 0, newHeight - 40);
220  FXVerticalFrame* glcanvasFrame =
221  new FXVerticalFrame(spacerFrame,
222  FRAME_SUNKEN | LAYOUT_SIDE_TOP | LAYOUT_FILL_X | LAYOUT_FILL_Y,
223  0, 0, 0, 0, 0, 0, 0, 0);
224  myPanel = new GUITLLogicPhasesTrackerPanel(glcanvasFrame, *myApplication, *this);
225  setTitle((logic.getID() + " - " + logic.getProgramID() + " - phases").c_str());
227  setHeight(newHeight);
228  setWidth(700);
229 }
230 
231 
233  if (myAmInTrackingMode) {
234  saveSettings();
235  myLastY = -1;
236  }
237  myApplication->removeChild(this);
238  delete myConnector;
239  // just to quit cleanly on a failure
240  if (myLock.locked()) {
241  myLock.unlock();
242  }
243  delete myToolBarDrag;
244 }
245 
246 void
248  myToolBarDrag = new FXToolBarShell(this, GUIDesignToolBar);
249  myToolBar = new FXToolBar(this, myToolBarDrag, LAYOUT_SIDE_TOP | LAYOUT_FILL_X | FRAME_RAISED);
250  new FXToolBarGrip(myToolBar, myToolBar, FXToolBar::ID_TOOLBARGRIP, GUIDesignToolBarGrip);
251 
252  if (myAmInTrackingMode) {
253  // interval manipulation
254  new FXLabel(myToolBar, "range (s):", nullptr, LAYOUT_CENTER_Y);
255  myBeginOffset = new FXRealSpinner(myToolBar, 4, this, MID_SIMSTEP, LAYOUT_TOP | FRAME_SUNKEN | FRAME_THICK);
256  //myBeginOffset->setFormatString("%.0f");
257  //myBeginOffset->setIncrements(1, 10, 100);
258  myBeginOffset->setIncrement(10);
259  myBeginOffset->setRange(60, 3600);
260  myBeginOffset->setValue(240);
261  }
262 
263  new FXLabel(myToolBar, "time style:", nullptr, LAYOUT_CENTER_Y);
266  myTimeMode->appendIconItem("seconds");
267  myTimeMode->appendIconItem("MM:SS");
268  myTimeMode->appendIconItem("time in cycle");
269 
270  new FXLabel(myToolBar, "green time", nullptr, LAYOUT_CENTER_Y);
273  myGreenMode->appendIconItem("off");
274  myGreenMode->appendIconItem("phase");
275  myGreenMode->appendIconItem("running");
276 
277  myIndexMode = new FXCheckButton(myToolBar, TL("phase names"), this, MID_SIMSTEP);
278 
279  if (myAmInTrackingMode) {
280  myDetectorMode = new FXCheckButton(myToolBar, TL("detectors"), this, MID_SIMSTEP);
281  myConditionMode = new FXCheckButton(myToolBar, TL("conditions"), this, MID_SIMSTEP);
282  } else {
283  myDetectorMode = nullptr;
284  myConditionMode = nullptr;
285  }
286 }
287 
288 
289 void
291  FXMainWindow::create();
292  if (myToolBarDrag != nullptr) {
293  myToolBarDrag->create();
294  }
295 }
296 
297 int
299  int newHeight = (int)myTLLogic->getLinks().size() * 20 + 30 + 8 + 30 + 60;
300  if (myAmInTrackingMode) {
301  newHeight += 20; // time bar
302  newHeight += 10; // something extra caused by the scroll frames
303  if (myDetectorMode->getCheck()) {
304  newHeight += (int)myTLLogic->getDetectorStates().size() * 20 + 5;
305  }
306  if (myConditionMode->getCheck()) {
307  newHeight += (int)myTLLogic->getConditions().size() * 20 + 5;
308  }
309  }
310  return newHeight;
311 }
312 
313 void
315  // compute what shall be shown (what is visible)
316  myFirstPhase2Show = 0;
317  myFirstPhaseOffset = 0;
318  SUMOTime leftOffset = 0;
319  myFirstDet2Show = 0;
320  myFirstDetOffset = 0;
321  myFirstCond2Show = 0;
322  myFirstCondOffset = 0;
323  myFirstTime2Show = 0;
324  if (!myAmInTrackingMode) {
325  myPhases.clear();
326  myDurations.clear();
327  myTimeInCycle.clear();
328  myPhaseIndex.clear();
329  // insert phases
330  MSSimpleTrafficLightLogic* simpleTLLogic = dynamic_cast<MSSimpleTrafficLightLogic*>(myTLLogic);
331  if (simpleTLLogic == nullptr) {
332  return;
333  }
334  myLastTime = 0;
335  myBeginTime = 0;
336  int idx = 0;
337  for (MSPhaseDefinition* const phase : simpleTLLogic->getPhases()) {
338  myPhases.push_back(*phase);
339  myDurations.push_back(phase->duration);
340  myTimeInCycle.push_back(myLastTime);
341  myPhaseIndex.push_back(idx++);
342  myLastTime += phase->duration;
343  }
344  if (myLastTime <= myBeginTime) {
345  WRITE_ERROR(TL("Overflow in time computation occurred."));
346  return;
347  }
348  } else {
349  SUMOTime beginOffset = TIME2STEPS(myBeginOffset->getValue());
350  myBeginTime = myLastTime - beginOffset;
352  // check whether no phases are known at all
353  if (myDurations.size() != 0) {
354  SUMOTime durs = 0;
355  int phaseOffset = (int)myDurations.size() - 1;
356  DurationsVector::reverse_iterator i = myDurations.rbegin();
357  while (i != myDurations.rend()) {
358  if (durs + (*i) > beginOffset) {
359  myFirstPhase2Show = phaseOffset;
360  myFirstPhaseOffset = (durs + (*i)) - beginOffset;
361  break;
362  }
363  durs += (*i);
364  phaseOffset--;
365  ++i;
366  }
367  if (i == myDurations.rend()) {
368  // there are too few information stored;
369  myFirstPhase2Show = 0;
370  myFirstPhaseOffset = 0;
371  leftOffset = beginOffset - durs;
372  }
373  }
374  if (myDetectorDurations.size() != 0) {
375  SUMOTime durs = 0;
376  int phaseOffset = (int)myDetectorDurations.size() - 1;
377  DurationsVector::reverse_iterator i = myDetectorDurations.rbegin();
378  while (i != myDetectorDurations.rend()) {
379  if (durs + (*i) > beginOffset) {
380  myFirstDet2Show = phaseOffset;
381  myFirstDetOffset = (durs + (*i)) - beginOffset;
382  break;
383  }
384  durs += (*i);
385  phaseOffset--;
386  ++i;
387  }
388  if (i == myDetectorDurations.rend()) {
389  // there are too few information stored;
390  myFirstDet2Show = 0;
391  myFirstDetOffset = 0;
392  }
393  }
394  if (myConditionDurations.size() != 0) {
395  SUMOTime durs = 0;
396  int phaseOffset = (int)myConditionDurations.size() - 1;
397  DurationsVector::reverse_iterator i = myConditionDurations.rbegin();
398  while (i != myConditionDurations.rend()) {
399  if (durs + (*i) > beginOffset) {
400  myFirstCond2Show = phaseOffset;
401  myFirstCondOffset = (durs + (*i)) - beginOffset;
402  break;
403  }
404  durs += (*i);
405  phaseOffset--;
406  ++i;
407  }
408  if (i == myConditionDurations.rend()) {
409  // there are too few information stored;
410  myFirstCond2Show = 0;
411  myFirstCondOffset = 0;
412  }
413  }
414  }
415  // begin drawing
416  glMatrixMode(GL_PROJECTION);
417  glLoadIdentity();
418  glMatrixMode(GL_MODELVIEW);
419  glLoadIdentity();
420  glTranslated(-1, -1, 0);
421  glScaled(2, 2, 1);
422  glDisable(GL_TEXTURE_2D);
423  // draw the horizontal lines dividing the signal groups
424  glColor3d(1, 1, 1);
425  // compute some values needed more than once
426  const double panelHeight = (double) caller.getHeight();
427  const double panelWidth = (double) caller.getWidth();
428  const double barWidth = MAX2(1.0, panelWidth - 31);
429  const double fontHeight = 0.06 * 300. / panelHeight;
430  const double fontWidth = 0.06 * 300. / panelWidth;
431  const double h9 = 9. / panelHeight;
432  const double hTop = 20. / panelHeight;
433  const double h11 = 11. / panelHeight;
434  const double stateHeight = 16. / panelHeight;
435  const double h20 = 20. / panelHeight;
436  const double h30 = 15. / panelHeight;
437  const double h35 = 34. / panelHeight;
438  const double h60 = 70. / panelHeight;
439  const double h75 = 73. / panelHeight;
440  const double h80 = 90. / panelHeight;
441  const double w30 = 30 / panelWidth;
442  double h = 1. - hTop;
443  // draw the line below indices
444  glColor3d(1, 1, 1);
445  glBegin(GL_LINES);
446  glVertex2d(0, h);
447  glVertex2d(1, h);
448  glEnd();
449  // draw the link names and the lines dividing them
450  drawNames(myLinkNames, fontHeight, fontWidth, h20, w30, h, 0);
451  glBegin(GL_LINES);
452  glVertex2d(0, h + h20);
453  glVertex2d(1.0, h + h20);
454  glEnd();
455 
456  // draw the names closure (vertical line)
457  h += h20;
458  glColor3d(1, 1, 1);
459  glBegin(GL_LINES);
460  glVertex2d(w30, 1.);
461  glVertex2d(w30, h);
462  glEnd();
463 
464  if (myAmInTrackingMode) {
465  // optionally draw detector names
466  h -= h60;
467  if (myDetectorMode->getCheck()) {
468  const double top = h;
469  glBegin(GL_LINES);
470  glVertex2d(0, h);
471  glVertex2d(1.0, h);
472  glEnd();
473  drawNames(myDetectorNames, fontHeight * 0.7, fontWidth * 0.7, h20, w30, h, 3);
474  glBegin(GL_LINES);
475  glVertex2d(0, h + h20);
476  glVertex2d(1.0, h + h20);
477  glEnd();
478  // draw the names closure (vertical line)
479  glColor3d(1, 1, 1);
480  glBegin(GL_LINES);
481  glVertex2d(30. / panelWidth, top);
482  glVertex2d(30. / panelWidth, h + h20);
483  glEnd();
484  h -= h30;
485  }
486  // optionally draw condition names
487  if (myConditionMode->getCheck()) {
488  const double top = h;
489  glBegin(GL_LINES);
490  glVertex2d(0, h);
491  glVertex2d(1.0, h);
492  glEnd();
493  drawNames(myConditionNames, fontHeight * 0.7, fontWidth * 0.7, h20, w30, h, 3);
494  glBegin(GL_LINES);
495  glVertex2d(0, h + h20);
496  glVertex2d(1.0, h + h20);
497  glEnd();
498  // draw the names closure (vertical line)
499  glColor3d(1, 1, 1);
500  glBegin(GL_LINES);
501  glVertex2d(30. / panelWidth, top);
502  glVertex2d(30. / panelWidth, h + h20);
503  glEnd();
504  }
505  }
506 
507  // draw the phases
508  // disable value addition while drawing
509  myLock.lock();
510  // determine the initial offset
511  double x = 31. / panelWidth;
512  double ta = (double) leftOffset / panelWidth;
513  ta *= barWidth / ((double)(myLastTime - myBeginTime));
514  x += ta;
515 
516  // and the initial phase information
517  PhasesVector::iterator pi = myPhases.begin() + myFirstPhase2Show;
518  IndexVector::iterator ii = myPhaseIndex.begin() + myFirstPhase2Show;
519 
521  const bool phaseNames = myIndexMode->getCheck() == TRUE;
522  std::string lastName = "";
523  double spaceForName = 0;
524 
525  // start drawing
526  std::vector<SUMOTime> runningGreen(myTLLogic->getLinks().size(), 0);
527  for (DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show; pd != myDurations.end(); ++pd) {
528  // the first phase may be drawn incompletely
529  SUMOTime duration = *pd - fpo;
530  // compute the height and the width of the phase
531  h = 1. - hTop;
532  double a = (double) duration / panelWidth;
533  a *= barWidth / ((double)(myLastTime - myBeginTime));
534  const double x2 = x + a;
535 
536  // go through the links
537  for (int j = 0; j < (int) myTLLogic->getLinks().size(); ++j) {
538  // determine the current link's color
539  LinkState state = pi->getSignalState(j);
540  // draw the bar (red is drawn as a line)
542  switch (state) {
543  case LINKSTATE_TL_RED:
545  // draw a thin line
546  glBegin(GL_QUADS);
547  glVertex2d(x, h - h11);
548  glVertex2d(x, h - h9);
549  glVertex2d(x2, h - h9);
550  glVertex2d(x2, h - h11);
551  glEnd();
552  break;
553  default:
554  // draw a thick block
555  glBegin(GL_QUADS);
556  glVertex2d(x, h - stateHeight);
557  glVertex2d(x, h);
558  glVertex2d(x2, h);
559  glVertex2d(x2, h - stateHeight);
560  glEnd();
561  break;
562  }
563  if (myGreenMode->getCurrentItem() != 0) {
564  SUMOTime drawnDuration = 0;
565  double xOffset = 0;
566  if (state == LINKSTATE_TL_GREEN_MINOR || state == LINKSTATE_TL_GREEN_MAJOR) {
567  if (myGreenMode->getCurrentItem() == 1) {
568  drawnDuration = *pd;
569  } else {
570  runningGreen[j] += *pd;
571  if (pd + 1 == myDurations.end()) {
572  drawnDuration = runningGreen[j];
573  xOffset = -(double)(drawnDuration - *pd) / panelWidth * (barWidth / ((double)(myLastTime - myBeginTime)));
574  }
575  }
576  } else {
577  if (runningGreen[j] > 0) {
578  drawnDuration = runningGreen[j];
579  xOffset = -(double)drawnDuration / panelWidth * (barWidth / ((double)(myLastTime - myBeginTime)));
580  }
581  runningGreen[j] = 0;
582  }
583  if (drawnDuration > 0) {
584  GLHelper::drawText(toString((int)STEPS2TIME(drawnDuration)),
585  Position(x + xOffset, h - h9),
586  0, fontHeight, RGBColor::BLACK, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
587  }
588  }
589  // proceed to next link
590  h -= h20;
591  }
592 
593  // draw phase index / name (no names for intermediate)
594  std::string name = phaseNames ? pi->getName() : toString(*ii);
595  if (name != lastName) {
596  const double lastNameWidth = GLHelper::getTextWidth(lastName, fontWidth);
597  if (spaceForName < lastNameWidth) {
598  // clear space to avoid overdrawn text
599  glColor3d(0, 0, 0);
600  glBegin(GL_QUADS);
601  glVertex2d(x, 1 - fontHeight);
602  glVertex2d(x, 1);
603  glVertex2d(1, 1);
604  glVertex2d(1, 1 - fontHeight);
605  glEnd();
606  }
607  spaceForName = a;
608  GLHelper::drawText(name, Position(x, 1 - hTop), 0, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_BOTTOM, fontWidth);
609  } else {
610  spaceForName += a;
611  }
612  lastName = name;
613  // proceed to next phase
614  ++pi;
615  ++ii;
616  x = x2;
617  // all further phases are drawn in full
618  fpo = 0;
619  }
620 
621  if (myAmInTrackingMode) {
622  h -= h75;
623  if (myDetectorMode->getCheck()) {
624  glColor3d(0.7, 0.7, 1.0);
626  panelWidth, (double)leftOffset, barWidth, stateHeight, h20, h);
627  h -= h35;
628  }
629  if (myConditionMode->getCheck()) {
630  glColor3d(0.9, 0.6, 0.9);
632  panelWidth, (double)leftOffset, barWidth, stateHeight, h20, h);
633  }
634  }
635  // allow value addition
636  myLock.unlock();
637 
638  if (myPhases.size() != 0) {
639  const double timeRange = STEPS2TIME(myLastTime - myBeginTime);
640  SUMOTime tickDist = TIME2STEPS(10);
641  // patch distances - hack
642  double t = myBeginOffset != nullptr ? myBeginOffset->getValue() : timeRange;
643  while (t > barWidth / 4.) {
644  tickDist += TIME2STEPS(10);
645  t -= barWidth / 4.;
646  }
647  // draw time information
648  //h = (double)(myTLLogic->getLinks().size() * 20 + 12);
649  double glh = 1. - (double)myTLLogic->getLinks().size() * h20 - hTop;
650  // current begin time
651  // time ticks
652  SUMOTime currTime = myFirstTime2Show;
653  double glpos = 31. / panelWidth;
654  const double ticSize = 4. / panelHeight;
655  if (leftOffset > 0) {
656  const double a = STEPS2TIME(leftOffset) * barWidth / timeRange;
657  glpos += a / panelWidth;
658  currTime += leftOffset;
659  } else if (myFirstPhaseOffset > 0) {
660  const double a = STEPS2TIME(-myFirstPhaseOffset) * barWidth / timeRange;
661  glpos += a / panelWidth;
662  currTime -= myFirstPhaseOffset;
663  }
664  int ticShift = myFirstPhase2Show;
665  const bool mmSS = myTimeMode->getCurrentItem() == 1;
666  const bool cycleTime = myTimeMode->getCurrentItem() == 2;
667  SUMOTime lastTimeInCycle = -1;
668  lastName = "";
669  pi = myPhases.begin() + myFirstPhase2Show;
670  for (DurationsVector::iterator pd = myDurations.begin() + myFirstPhase2Show; pd != myDurations.end(); ++pd) {
671  const SUMOTime timeInCycle = myTimeInCycle[pd - myDurations.begin()];
672  // draw times at different heights
673  ticShift = (ticShift % 3) + 1;
674  const std::string timeStr = (mmSS
675  ? StringUtils::padFront(toString((currTime % 3600000) / 60000), 2, '0') + ":"
676  + StringUtils::padFront(toString((currTime % 60000) / 1000), 2, '0')
677  : toString((int)STEPS2TIME(cycleTime ? timeInCycle : currTime)));
678  const double w = 10 * (double)timeStr.size() / panelWidth;
679  glTranslated(glpos - w / 2., glh - h20 * ticShift, 0);
680  GLHelper::drawText(timeStr, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
681  glTranslated(-glpos + w / 2., -glh + h20 * ticShift, 0);
682 
683  // draw tic
684  glColor3d(1, 1, 1);
685  glBegin(GL_LINES);
686  glVertex2d(glpos, glh);
687  glVertex2d(glpos, glh - ticSize * ticShift);
688  glEnd();
689 
690  // draw vertical lines for names, detectors and conditions on each phase switch
691  if (myAmInTrackingMode) {
692  double hStart = 1;
693  if (!phaseNames || (pi->getName() != lastName)) {
694  glColor3d(0.4, 0.4, 0.4);
695  glBegin(GL_LINES);
696  glVertex2d(glpos, hStart);
697  hStart -= h20;
698  glVertex2d(glpos, hStart);
699  glEnd();
700  }
701  lastName = pi->getName();
702 
703  hStart = glh - h60;
704  if (myDetectorMode->getCheck() && glpos >= w30) {
705  glColor3d(0.4, 0.4, 0.4);
706  glBegin(GL_LINES);
707  glVertex2d(glpos, hStart);
708  hStart -= (double)myDetectorNames.size() * h20;
709  glVertex2d(glpos, hStart);
710  glEnd();
711  hStart -= h35;
712  }
713  if (myConditionMode->getCheck() && glpos >= w30) {
714  glColor3d(0.4, 0.4, 0.4);
715  glBegin(GL_LINES);
716  glVertex2d(glpos, hStart);
717  glVertex2d(glpos, hStart - (double)myConditionNames.size() * h20);
718  glEnd();
719  }
720  }
721 
722  // draw vertical line for cycle reset
723  if (timeInCycle == 0 || timeInCycle < lastTimeInCycle) {
724  const double cycle0pos = glpos - STEPS2TIME(timeInCycle) * barWidth / timeRange / panelWidth;
725  if (cycle0pos >= 31 / panelWidth) {
726  glColor3d(0.6, 0.6, 0.6);
727  glBegin(GL_LINES);
728  glVertex2d(cycle0pos, 1);
729  glVertex2d(cycle0pos, glh);
730  glEnd();
731  glColor3d(1, 1, 1);
732  }
733  }
734 
735  lastTimeInCycle = timeInCycle;
736  tickDist = *pd;
737  const double a = STEPS2TIME(tickDist) * barWidth / timeRange;
738  glpos += a / panelWidth;
739  currTime += tickDist;
740  ++pi;
741  }
742 
743  // draw bottom time bar with fixed spacing
744  if (myAmInTrackingMode && (myDetectorMode->getCheck() || myConditionMode->getCheck()) && glpos >= w30) {
745  glColor3d(1, 1, 1);
746  tickDist = TIME2STEPS(10);
747  // patch distances - hack
748  t = myBeginOffset != nullptr ? myBeginOffset->getValue() : STEPS2TIME(myLastTime - myBeginTime);
749  while (t > barWidth / 4.) {
750  tickDist += TIME2STEPS(10);
751  t -= barWidth / 4.;
752  }
753  glh = 1. - (double)myLinkNames.size() * h20 - h80;
754  glh -= h20 * (double)(myDetectorMode->getCheck() ? myDetectorNames.size() : myConditionNames.size());
755  currTime = myFirstTime2Show;
756  int pos = 31;
757  glpos = (double) pos / panelWidth;
758  if (leftOffset > 0) {
759  const double a = STEPS2TIME(leftOffset) * barWidth / timeRange;
760  pos += (int)a;
761  glpos += a / panelWidth;
762  currTime += leftOffset;
763  } else if (myFirstPhaseOffset > 0) {
764  const double a = -STEPS2TIME(myBeginTime % tickDist) * barWidth / timeRange;
765  pos += (int)a;
766  glpos += a / panelWidth;
767  currTime = myBeginTime - (myBeginTime % tickDist);
768  }
769  while (pos < panelWidth + 50.) {
770  const std::string timeStr = (mmSS
771  ? StringUtils::padFront(toString((currTime % 3600000) / 60000), 2, '0') + ":"
772  + StringUtils::padFront(toString((currTime % 60000) / 1000), 2, '0')
773  : toString((int)STEPS2TIME(cycleTime ? findTimeInCycle(currTime) : currTime)));
774  const double w = 10. * (double)timeStr.size() / panelWidth;
775  glTranslated(glpos - w / 2., glh - h20, 0);
776  GLHelper::drawText(timeStr, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, fontWidth);
777  glTranslated(-glpos + w / 2., -glh + h20, 0);
778 
779  glBegin(GL_LINES);
780  glVertex2d(glpos, glh);
781  glVertex2d(glpos, glh - ticSize);
782  glEnd();
783 
784  const double a = STEPS2TIME(tickDist) * barWidth / STEPS2TIME(myLastTime - myBeginTime);
785  pos += (int) a;
786  glpos += a / panelWidth;
787  currTime += tickDist;
788  }
789  }
790  }
791 }
792 
793 
794 void
795 GUITLLogicPhasesTrackerWindow::drawNames(const std::vector<std::string>& names, double fontHeight, double fontWidth, double divHeight, double divWidth, double& h, int extraLines) {
796  int i = 0;
797  for (const std::string& name : names) {
798  // draw the bar
799  glBegin(GL_LINES);
800  glVertex2d(0, h);
801  glVertex2d(divWidth, h);
802  glEnd();
803  // draw the name
804  glTranslated(0, h - divHeight, 0);
805  GLHelper::drawText(name, Position(0, 0), 1, fontHeight, RGBColor::WHITE, 0, FONS_ALIGN_LEFT | FONS_ALIGN_BOTTOM, fontWidth);
806  glTranslated(0, -h + divHeight, 0);
807 
808  if (extraLines > 0 && i > 0 && i % extraLines == 0) {
809  glColor3d(0.4, 0.4, 0.4);
810  glBegin(GL_LINES);
811  glVertex2d(divWidth, h);
812  glVertex2d(1.0, h);
813  glEnd();
814  glColor3d(1, 1, 1);
815  }
816  h -= divHeight;
817  i++;
818  }
819  h -= divHeight;
820 }
821 
822 
823 void
825  const AdditionalStatesVector& states,
826  const DurationsVector& durations, SUMOTime firstOffset, int first2Show, double hStart,
827  double panelWidth, double leftOffset, double barWidth, double stateHeight, double h20, double& h) {
828  double x = 31. / panelWidth;
829  double ta = leftOffset / panelWidth;
830  ta *= barWidth / ((double)(myLastTime - myBeginTime));
831  x += ta;
832  auto di = states.begin() + first2Show;
833  SUMOTime fpo = firstOffset;
834 
835  double mx = caller.getMousePos().x() / caller.getWidth();
836  double my = 1 - caller.getMousePos().y() / caller.getHeight();
837  std::string tooltip = "";
838  // start drawing
839  for (auto pd = durations.begin() + first2Show; pd != durations.end(); ++pd) {
840  // the first phase may be drawn incompletely
841  SUMOTime duration = *pd - fpo;
842  // compute the height and the width of the phase
843  h = hStart;
844  double a = (double) duration / panelWidth;
845  a *= barWidth / ((double)(myLastTime - myBeginTime));
846  const double x2 = x + a;
847  const bool tooltipX = x < mx && mx < x2;
848  //std::cout << SIMTIME << " detStates=" << toString(*di) << "\n";
849  // go through the detectors
850  for (double j : *di) {
851  if (j != 0) {
852  // draw a thick block
853  glBegin(GL_QUADS);
854  glVertex2d(x, h - stateHeight);
855  glVertex2d(x, h);
856  glVertex2d(x2, h);
857  glVertex2d(x2, h - stateHeight);
858  glEnd();
859  if (tooltipX) {
860  const bool tooltipY = (h - stateHeight) < my && my < h;
861  if (tooltipY) {
862  tooltip = toString((int)j);
863  }
864  }
865  }
866  // proceed to next link
867  h -= h20;
868  }
869  // proceed to next phase
870  ++di;
871  x = x2;
872  // all further phases are drawn in full
873  fpo = 0;
874  }
875  if (tooltip != "") {
876  // delay tool tip drawing until all bars are drawn to prevent overwriting
877  GLHelper::drawText(tooltip, Position(mx, my), 0, h20, RGBColor::YELLOW, 0, FONS_ALIGN_LEFT | FONS_ALIGN_MIDDLE, 20 / caller.getWidth());
878  }
879 }
880 
881 SUMOTime
883  // find latest cycle reset before t
884  int i = (int)myPhases.size() - 1;
885  SUMOTime lookBack = myLastTime - t - myDurations.back();
886  //std::cout << SIMTIME << " findTimeInCycle t=" << STEPS2TIME(t)
887  // << " last=" << STEPS2TIME(myLastTime)
888  // << " lastDur=" << STEPS2TIME(myDurations.back())
889  // << " lookBack=" << STEPS2TIME(lookBack)
890  // << " i0=" << i;
891  // look backwards through the phases until to the first cycle crossing before t
892  while (lookBack > 0 && i > 1) {
893  i--;
894  lookBack -= myDurations[i];
895  }
896  SUMOTime timeInCycle = myTimeInCycle[i < 0 ? 0 : i];
897  //std::cout << " iF=" << i << " lookBack2=" << STEPS2TIME(lookBack) << " tic=" << STEPS2TIME(timeInCycle) << "\n";
898  if (lookBack <= 0) {
899  return timeInCycle - lookBack;
900  }
901  return myTLLogic->mapTimeInCycle(t);
902 }
903 
904 void
905 GUITLLogicPhasesTrackerWindow::addValue(std::pair<SUMOTime, MSPhaseDefinition> def) {
906  // do not draw while adding
907  myLock.lock();
908  // set the first time if not set before
909  if (myPhases.size() == 0) {
910  myBeginTime = def.first;
911  }
912  // append or set the phase
913  if (myPhases.size() == 0 || myPhases.back() != def.second) {
914  myPhases.push_back(def.second);
915  myDurations.push_back(DELTA_T);
916  myTimeInCycle.push_back(myTLLogic->mapTimeInCycle(def.first - DELTA_T));
918  } else {
919  myDurations.back() += DELTA_T;
920  }
921  // updated detector states
922  std::vector<double> detectorStates;
923  for (auto item : myTLLogic->getDetectorStates()) {
924  detectorStates.push_back(item.second);
925  }
926  if (myDetectorStates.size() == 0 || myDetectorStates.back() != detectorStates) {
927  myDetectorStates.push_back(detectorStates);
928  myDetectorDurations.push_back(DELTA_T);
929  } else {
930  myDetectorDurations.back() += DELTA_T;
931  }
932  // updated condition states
933  std::vector<double> conditionStates;
934  for (auto item : myTLLogic->getConditions()) {
935  conditionStates.push_back(item.second);
936  }
937  if (myConditionStates.size() == 0 || myConditionStates.back() != conditionStates) {
938  myConditionStates.push_back(conditionStates);
939  myConditionDurations.push_back(DELTA_T);
940  } else {
941  myConditionDurations.back() += DELTA_T;
942  }
943  // set the last time a phase was added at
944  myLastTime = def.first;
945  // allow drawing
946  myLock.unlock();
947 }
948 
949 
950 long
951 GUITLLogicPhasesTrackerWindow::onConfigure(FXObject* sender, FXSelector sel, void* ptr) {
952  myPanel->onConfigure(sender, sel, ptr);
953  return FXMainWindow::onConfigure(sender, sel, ptr);
954 }
955 
956 
957 long
958 GUITLLogicPhasesTrackerWindow::onPaint(FXObject* sender, FXSelector sel, void* ptr) {
959  myPanel->onPaint(sender, sel, ptr);
960  return FXMainWindow::onPaint(sender, sel, ptr);
961 }
962 
963 
964 long
965 GUITLLogicPhasesTrackerWindow::onSimStep(FXObject* sender, FXSelector, void*) {
966  if (sender == myDetectorMode || sender == myConditionMode) {
967  resize(getWidth(), computeHeight());
968  }
969  update();
970  return 1;
971 }
972 
973 
974 void
976  myBeginTime = time;
977 }
978 
979 
980 void
982  getApp()->reg().writeIntEntry("TL_TRACKER", "x", getX());
983  getApp()->reg().writeIntEntry("TL_TRACKER", "y", getY());
984  getApp()->reg().writeIntEntry("TL_TRACKER", "width", getWidth());
985  getApp()->reg().writeIntEntry("TL_TRACKER", "timeRange", (int)myBeginOffset->getValue());
986  getApp()->reg().writeIntEntry("TL_TRACKER", "timeMode", myTimeMode->getCurrentItem());
987  getApp()->reg().writeIntEntry("TL_TRACKER", "greenMode", (myGreenMode->getCurrentItem()));
988  getApp()->reg().writeIntEntry("TL_TRACKER", "indexMode", (int)(myIndexMode->getCheck()));
989  getApp()->reg().writeIntEntry("TL_TRACKER", "detectorMode", (int)(myDetectorMode->getCheck()));
990  getApp()->reg().writeIntEntry("TL_TRACKER", "conditionMode", (int)(myConditionMode->getCheck()));
991 }
992 
993 
994 void
996  // ensure window is visible after switching screen resolutions
997  const FXint minSize = 400;
998  const FXint minTitlebarHeight = 20;
999  setX(MAX2(0, MIN2(getApp()->reg().readIntEntry("TL_TRACKER", "x", 150),
1000  getApp()->getRootWindow()->getWidth() - minSize)));
1001  if (myLastY == -1) {
1002  myLastY = MAX2(minTitlebarHeight,
1003  MIN2(getApp()->reg().readIntEntry("TL_TRACKER", "y", 150),
1004  getApp()->getRootWindow()->getHeight() - minSize));
1005  } else {
1006  myLastY += getHeight() + 20;
1007  }
1008  setY(myLastY);
1009  setWidth(MAX2(getApp()->reg().readIntEntry("TL_TRACKER", "width", 700), minSize));
1010  myBeginOffset->setValue(getApp()->reg().readIntEntry("TL_TRACKER", "timeRange", (int)myBeginOffset->getValue()));
1011  myTimeMode->setCurrentItem(getApp()->reg().readIntEntry("TL_TRACKER", "timeMode", myTimeMode->getCurrentItem()));
1012  myGreenMode->setCurrentItem(getApp()->reg().readIntEntry("TL_TRACKER", "greenMode", myGreenMode->getCurrentItem()));
1013  myIndexMode->setCheck((FXbool)getApp()->reg().readIntEntry("TL_TRACKER", "indexMode", (int)(myIndexMode->getCheck())));
1014  myDetectorMode->setCheck((FXbool)getApp()->reg().readIntEntry("TL_TRACKER", "detectorMode", (int)(myDetectorMode->getCheck())));
1015  myConditionMode->setCheck((FXbool)getApp()->reg().readIntEntry("TL_TRACKER", "conditionMode", (int)(myConditionMode->getCheck())));
1016 }
1017 
1018 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
@ MID_SIMSTEP
A Simulation step was performed.
Definition: GUIAppEnum.h:537
#define GUIDesignViewSettingsComboBox1
Combo boxes.
Definition: GUIDesigns.h:552
#define GUIDesignToolBarGrip
design for toolbar grip (used to change the position of toolbar with mouse)
Definition: GUIDesigns.h:452
#define GUIDesignToolBar
design for default toolbar
Definition: GUIDesigns.h:437
#define GUIDesignComboBoxVisibleItemsMedium
combo box medium small
Definition: GUIDesigns.h:53
@ APP_TLSTRACKER
FXDEFMAP(GUITLLogicPhasesTrackerWindow::GUITLLogicPhasesTrackerPanel) GUITLLogicPhasesTrackerPanelMap[]
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define TL(string)
Definition: MsgHandler.h:315
SUMOTime DELTA_T
Definition: SUMOTime.cpp:38
#define STEPS2TIME(x)
Definition: SUMOTime.h:55
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
LinkState
The right-of-way state of a link between two lanes used when constructing a NBTrafficLightLogic,...
@ LINKSTATE_TL_REDYELLOW
The link has red light (must brake) but indicates upcoming green.
@ LINKSTATE_TL_GREEN_MAJOR
The link has green light, may pass.
@ LINKSTATE_TL_RED
The link has red light (must brake)
@ LINKSTATE_TL_GREEN_MINOR
The link has green light, has to brake.
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static void setColor(const RGBColor &c)
Sets the gl-color to this value.
Definition: GLHelper.cpp:654
static double getTextWidth(const std::string &text, double size)
get required width of text
Definition: GLHelper.cpp:750
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, const int align=0, double width=-1)
Definition: GLHelper.cpp:756
Class passing values from a GUIGlObject to another object.
static FXIcon * getIcon(const GUIIcon which)
returns a icon previously defined in the enum GUIIcon
void removeChild(FXMainWindow *child)
removes the given child window from the list (FXMainWindow)
void addChild(FXMainWindow *child)
Adds a further child window to the list (FXMainWindow)
long onConfigure(FXObject *, FXSelector, void *)
called on size change
long onPaint(FXObject *, FXSelector, void *)
called if the widget shall be repainted
long onMouseMove(FXObject *, FXSelector, void *)
called on mouse movement (for updating tooltip)
This window displays a phase diagram for a chosen tl-logic.
GUITLLogicPhasesTrackerWindow()
protected constructor for FOX
AdditionalStatesVector myDetectorStates
The state of all used detectors of the current phase.
FXMutex myLock
A lock to avoid addition of new values while drawing.
SUMOTime myBeginTime
The first time a phase was added at.
MFXComboBoxIcon * myGreenMode
Whether green durations are printed.
static int myLastY
y-Position of previously opened window
DurationsVector myTimeInCycle
The time within the cycle for the current phase.
std::vector< std::string > myLinkNames
The names of links.
DurationsVector myDetectorDurations
The list of detector state durations.
FXCheckButton * myDetectorMode
Whether detector states are drawn.
FXRealSpinner * myBeginOffset
The offset changer (tracking mode)
long onSimStep(FXObject *sender, FXSelector sel, void *ptr)
called on a simulation step
GUITLLogicPhasesTrackerPanel * myPanel
The panel to draw on.
int computeHeight()
compute required windowHeight
void setBeginTime(SUMOTime time)
Sets the time the display shall be shown as beginning at.
FXToolBarShell * myToolBarDrag
The tool bar drag (tracking mode)
FXToolBar * myToolBar
The tool bar (tracking mode)
PhasesVector myPhases
The list of phases.
SUMOTime myFirstPhaseOffset
The offset to draw the first phase (left offset)
std::vector< std::string > myDetectorNames
IndexVector myPhaseIndex
The index of the current phase.
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.
MFXComboBoxIcon * myTimeMode
The time mode.
std::vector< std::string > myConditionNames
int myFirstPhase2Show
The index of the first phase that fits into the window.
long onPaint(FXObject *sender, FXSelector sel, void *ptr)
called if the widget shall be repainted
SUMOTime findTimeInCycle(SUMOTime t)
find time in cycle based on myTimeInCycle
FXCheckButton * myConditionMode
Whether detector states are drawn.
long onConfigure(FXObject *sender, FXSelector sel, void *ptr)
called on size change
SUMOTime myLastTime
The last time a phase was added at.
void create()
Creates the window (FOX-Toolkit)
MSTrafficLightLogic * myTLLogic
The logic to display.
std::vector< std::vector< double > > AdditionalStatesVector
Definition of a storage for detector and condition states.
void drawNames(const std::vector< std::string > &names, double fontHeight, double fontWidth, double divHeight, double divWidth, double &h, int extraLines)
draw row title
FXCheckButton * myIndexMode
Whether phase names shall be printed instead of indices.
std::vector< SUMOTime > DurationsVector
Definition of a storage for durations.
void drawAdditionalStates(GUITLLogicPhasesTrackerPanel &caller, const AdditionalStatesVector &states, const DurationsVector &durations, SUMOTime firstOffset, int first2Show, double hStart, double panelWidth, double leftOffset, double barWidth, double stateHeight, double h20, double &h)
draw detector and condition states
SUMOTime myFirstTime2Show
The time the diagram begins at.
GUIMainWindow * myApplication
The main application.
bool myAmInTrackingMode
Information whether the tracking mode is on.
void drawValues(GUITLLogicPhasesTrackerPanel &caller)
Draws all values.
DurationsVector myDurations
The list of phase durations.
static const RGBColor & getLinkColor(const LinkState &ls, bool realistic=false)
map from LinkState to color constants
ComboBox with icon.
long setCurrentItem(const FXint index, FXbool notify=FALSE)
Set the current item (index is zero-based)
FXint getCurrentItem() const
Get the current item's index.
FXint appendIconItem(const FXString &text, FXIcon *icon=nullptr, FXColor bgColor=FXRGB(255, 255, 255), void *ptr=nullptr)
append icon item in the last position
The definition of a single phase of a tls logic.
A fixed traffic light logic.
const Phases & getPhases() const override
Returns the phases of this tls program.
The parent class for traffic light logics.
virtual SUMOTime mapTimeInCycle(SUMOTime t) const
map the given time into the current cycle
virtual int getCurrentPhaseIndex() const =0
Returns the current index within the program.
virtual std::map< std::string, double > getDetectorStates() const
return activation state of all detectors that affect this traffic light
virtual std::map< std::string, double > getConditions() const
return all named conditions defined for this traffic light
const LinkVectorVector & getLinks() const
Returns the list of lists of all affected links.
std::vector< MSPhaseDefinition * > Phases
Definition of a list of phases, being the junction logic.
const std::string & getProgramID() const
Returns this tl-logic's id.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
double x() const
Returns the x-position.
Definition: Position.h:55
double y() const
Returns the y-position.
Definition: Position.h:60
static const RGBColor WHITE
Definition: RGBColor.h:192
static const RGBColor YELLOW
Definition: RGBColor.h:188
static const RGBColor BLACK
Definition: RGBColor.h:193
static std::string padFront(const std::string &str, int length, char padding)
@ FONS_ALIGN_MIDDLE
Definition: fontstash.h:47
@ FONS_ALIGN_LEFT
Definition: fontstash.h:42
@ FONS_ALIGN_BOTTOM
Definition: fontstash.h:48
Definition: json.hpp:4471