LCOV - code coverage report
Current view: top level - src/gui - GUITLLogicPhasesTrackerWindow.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 580 0.0 %
Date: 2024-05-18 15:37:58 Functions: 0 28 0.0 %

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

Generated by: LCOV version 1.14