LCOV - code coverage report
Current view: top level - src/gui - GUIViewTraffic.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 28.2 % 379 107
Test Date: 2026-06-15 15:46:12 Functions: 39.4 % 33 13

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 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    GUIViewTraffic.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Christian Roessel
      18              : /// @author  Michael Behrisch
      19              : /// @author  Andreas Gaubatz
      20              : /// @date    Sept 2002
      21              : ///
      22              : // A view on the simulation; this view is a microscopic one
      23              : /****************************************************************************/
      24              : #include <config.h>
      25              : 
      26              : #ifdef HAVE_FFMPEG
      27              : #include <utils/gui/div/GUIVideoEncoder.h>
      28              : #endif
      29              : 
      30              : #include <iostream>
      31              : #include <utility>
      32              : #include <cmath>
      33              : #include <limits>
      34              : #include <foreign/rtree/SUMORTree.h>
      35              : #include <gui/GUIApplicationWindow.h>
      36              : #include <gui/GUIGlobals.h>
      37              : #include <guisim/GUIEdge.h>
      38              : #include <guisim/GUILane.h>
      39              : #include <guisim/GUINet.h>
      40              : #include <guisim/GUITriggeredRerouter.h>
      41              : #include <guisim/GUIVehicle.h>
      42              : #include <guisim/GUIVehicleControl.h>
      43              : #include <mesogui/GUIMEVehicle.h>
      44              : #include <mesogui/GUIMEVehicleControl.h>
      45              : #include <microsim/MSEdge.h>
      46              : #include <microsim/MSGlobals.h>
      47              : #include <microsim/MSJunctionControl.h>
      48              : #include <microsim/MSLane.h>
      49              : #include <microsim/MSStoppingPlace.h>
      50              : #include <microsim/traffic_lights/MSSimpleTrafficLightLogic.h>
      51              : #include <microsim/traffic_lights/MSTLLogicControl.h>
      52              : #include <utils/common/RGBColor.h>
      53              : #include <utils/foxtools/MFXButtonTooltip.h>
      54              : #include <utils/foxtools/MFXCheckableButton.h>
      55              : #include <utils/foxtools/MFXImageHelper.h>
      56              : #include <utils/geom/PositionVector.h>
      57              : #include <utils/gui/div/GLHelper.h>
      58              : #include <utils/gui/div/GUIDesigns.h>
      59              : #include <utils/gui/div/GUIGlobalSelection.h>
      60              : #include <utils/gui/globjects/GLIncludes.h>
      61              : #include <utils/gui/globjects/GUIGlObjectStorage.h>
      62              : #include <utils/gui/globjects/GUIShapeContainer.h>
      63              : #include <utils/gui/images/GUIIconSubSys.h>
      64              : #include <utils/gui/settings/GUICompleteSchemeStorage.h>
      65              : #include <utils/gui/windows/GUIAppEnum.h>
      66              : #include <utils/gui/windows/GUIDialog_ViewSettings.h>
      67              : #include <utils/gui/windows/GUIPerspectiveChanger.h>
      68              : #include <utils/gui/windows/GUISUMOAbstractView.h>
      69              : #include <utils/shapes/ShapeContainer.h>
      70              : 
      71              : #include "GUISUMOViewParent.h"
      72              : #include "GUIViewTraffic.h"
      73              : 
      74              : // ===========================================================================
      75              : // member method definitions
      76              : // ===========================================================================
      77         7893 : GUIViewTraffic::GUIViewTraffic(
      78              :     FXComposite* p,
      79              :     GUIMainWindow& app,
      80              :     GUISUMOViewParent* parent,
      81              :     GUINet& net, FXGLVisual* glVis,
      82         7893 :     FXGLCanvas* share) :
      83              :     GUISUMOAbstractView(p, app, parent, net.getVisualisationSpeedUp(), glVis, share),
      84         7893 :     myTrackedID(GUIGlObject::INVALID_ID),
      85         7893 :     myTLSGame(OptionsCont::getOptions().getString("game.mode") == "tls")
      86              : #ifdef HAVE_FFMPEG
      87         7893 :     , myCurrentVideo(nullptr)
      88              : #endif
      89         7893 : {}
      90              : 
      91              : 
      92        15730 : GUIViewTraffic::~GUIViewTraffic() {
      93         7865 :     endSnapshot();
      94        15730 : }
      95              : 
      96              : 
      97              : void
      98         7893 : GUIViewTraffic::buildViewToolBars(GUIGlChildWindow* v) {
      99              :     // build coloring tools
     100              :     {
     101         7893 :         const std::vector<std::string>& names = gSchemeStorage.getNames();
     102        47394 :         for (std::vector<std::string>::const_iterator i = names.begin(); i != names.end(); ++i) {
     103        39501 :             v->getColoringSchemesCombo()->appendIconItem(i->c_str());
     104        39501 :             if ((*i) == myVisualizationSettings->name) {
     105         7893 :                 v->getColoringSchemesCombo()->setCurrentItem(v->getColoringSchemesCombo()->getNumItems() - 1);
     106              :             }
     107              :         }
     108              :     }
     109              :     // for junctions
     110         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     111        23679 :                          (std::string("\t") + TL("Locate Junctions") + std::string("\t") + TL("Locate a junction within the network.")).c_str(),
     112              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEJUNCTION), v, MID_HOTKEY_SHIFT_J_LOCATEJUNCTION,
     113        23679 :                          GUIDesignButtonPopup);
     114              :     // for edges
     115         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     116        23679 :                          (std::string("\t") + TL("Locate Edges") + std::string("\t") + TL("Locate an edge within the network.")).c_str(),
     117              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEEDGE), v, MID_HOTKEY_SHIFT_E_LOCATEEDGE,
     118        23679 :                          GUIDesignButtonPopup);
     119              :     // for vehicles
     120         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     121        23679 :                          (std::string("\t") + TL("Locate Vehicles") + std::string("\t") + TL("Locate a vehicle within the network.")).c_str(),
     122              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEVEHICLE), v, MID_HOTKEY_SHIFT_V_LOCATEVEHICLE,
     123        23679 :                          GUIDesignButtonPopup);
     124              :     // for persons
     125         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     126        23679 :                          (std::string("\t") + TL("Locate Persons") + std::string("\t") + TL("Locate a person within the network.")).c_str(),
     127              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEPERSON), v, MID_HOTKEY_SHIFT_P_LOCATEPERSON,
     128        23679 :                          GUIDesignButtonPopup);
     129              :     // for containers
     130         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     131        23679 :                          (std::string("\t") + TL("Locate Container") + std::string("\t") + TL("Locate a container within the network.")).c_str(),
     132              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATECONTAINER), v, MID_HOTKEY_SHIFT_C_LOCATECONTAINER,
     133        23679 :                          GUIDesignButtonPopup);
     134              :     // for tls
     135         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     136        23679 :                          (std::string("\t") + TL("Locate TLS") + std::string("\t") + TL("Locate a tls within the network.")).c_str(),
     137              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATETLS), v, MID_HOTKEY_SHIFT_T_LOCATETLS,
     138        23679 :                          GUIDesignButtonPopup);
     139              :     // for additional stuff
     140         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     141        23679 :                          (std::string("\t") + TL("Locate Additional") + std::string("\t") + TL("Locate an additional structure within the network.")).c_str(),
     142              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEADD), v, MID_HOTKEY_SHIFT_A_LOCATEADDITIONAL,
     143        23679 :                          GUIDesignButtonPopup);
     144              :     // for pois
     145         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     146        23679 :                          (std::string("\t") + TL("Locate PoI") + std::string("\t") + TL("Locate a PoI within the network.")).c_str(),
     147              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEPOI), v, MID_HOTKEY_SHIFT_O_LOCATEPOI,
     148        23679 :                          GUIDesignButtonPopup);
     149              :     // for polygons
     150         7893 :     new MFXButtonTooltip(v->getLocatorPopup(), myApp->getStaticTooltipMenu(),
     151        23679 :                          (std::string("\t") + TL("Locate Polygon") + std::string("\t") + TL("Locate a Polygon within the network.")).c_str(),
     152              :                          GUIIconSubSys::getIcon(GUIIcon::LOCATEPOLY), v, MID_HOTKEY_SHIFT_L_LOCATEPOLY,
     153        23679 :                          GUIDesignButtonPopup);
     154         7893 : }
     155              : 
     156              : 
     157              : bool
     158           46 : GUIViewTraffic::setColorScheme(const std::string& name) {
     159           46 :     if (!gSchemeStorage.contains(name)) {
     160              :         return false;
     161              :     }
     162           43 :     if (myGUIDialogViewSettings != nullptr) {
     163            0 :         if (myGUIDialogViewSettings->getCurrentScheme() != name) {
     164            0 :             myGUIDialogViewSettings->setCurrentScheme(name);
     165              :         }
     166              :     }
     167           43 :     myVisualizationSettings = &gSchemeStorage.get(name.c_str());
     168           43 :     myVisualizationSettings->gaming = myApp->isGaming();
     169           43 :     update();
     170           43 :     return true;
     171              : }
     172              : 
     173              : 
     174              : void
     175            0 : GUIViewTraffic::buildColorRainbow(const GUIVisualizationSettings& s, GUIColorScheme& scheme, int active, GUIGlObjectType objectType,
     176              :                                   const GUIVisualizationRainbowSettings& rs) {
     177              :     assert(!scheme.isFixed());
     178              :     double minValue = std::numeric_limits<double>::infinity();
     179              :     double maxValue = -std::numeric_limits<double>::infinity();
     180              :     // retrieve range
     181              :     bool hasMissingData = false;
     182            0 :     if (objectType == GLO_LANE) {
     183              :         // XXX (see #3409) multi-colors are not currently handled. this is a quick hack
     184            0 :         if (active == 22) {
     185              :             active = 21; // segment height, fall back to start height
     186            0 :         } else if (active == 24) {
     187              :             active = 23; // segment incline, fall back to total incline
     188              :         }
     189            0 :         const MSEdgeVector& edges = MSEdge::getAllEdges();
     190            0 :         for (MSEdgeVector::const_iterator it = edges.begin(); it != edges.end(); ++it) {
     191            0 :             if (MSGlobals::gUseMesoSim) {
     192            0 :                 const double val = static_cast<GUIEdge*>(*it)->getColorValue(s, active);
     193            0 :                 if (val == s.MISSING_DATA) {
     194              :                     hasMissingData = true;
     195            0 :                     continue;
     196              :                 }
     197              :                 minValue = MIN2(minValue, val);
     198              :                 maxValue = MAX2(maxValue, val);
     199              :             } else {
     200            0 :                 const std::vector<MSLane*>& lanes = (*it)->getLanes();
     201            0 :                 for (std::vector<MSLane*>::const_iterator it_l = lanes.begin(); it_l != lanes.end(); it_l++) {
     202            0 :                     const double val = static_cast<GUILane*>(*it_l)->getColorValue(s, active);
     203            0 :                     if (val == s.MISSING_DATA) {
     204              :                         hasMissingData = true;
     205            0 :                         continue;
     206              :                     }
     207              :                     minValue = MIN2(minValue, val);
     208              :                     maxValue = MAX2(maxValue, val);
     209              :                 }
     210              :             }
     211              :         }
     212            0 :     } else if (objectType == GLO_VEHICLE) {
     213            0 :         MSVehicleControl& c = MSNet::getInstance()->getVehicleControl();
     214            0 :         for (MSVehicleControl::constVehIt it_v = c.loadedVehBegin(); it_v != c.loadedVehEnd(); ++it_v) {
     215              :             const GUIGlObject* veh;
     216            0 :             if (MSGlobals::gUseMesoSim) {
     217            0 :                 veh = static_cast<const GUIMEVehicle*>(it_v->second);
     218              :             } else {
     219            0 :                 veh = static_cast<const GUIVehicle*>(it_v->second);
     220              :             }
     221            0 :             const double val = veh->getColorValue(s, active);
     222            0 :             if (val == s.MISSING_DATA) {
     223              :                 hasMissingData = true;
     224            0 :                 continue;
     225              :             }
     226              :             minValue = MIN2(minValue, val);
     227              :             maxValue = MAX2(maxValue, val);
     228              :         }
     229            0 :     } else if (objectType == GLO_JUNCTION) {
     230            0 :         if (active == 3) {
     231              :             std::set<const MSJunction*> junctions;
     232            0 :             for (MSEdge* edge : MSEdge::getAllEdges()) {
     233            0 :                 junctions.insert(edge->getFromJunction());
     234            0 :                 junctions.insert(edge->getToJunction());
     235              :             }
     236            0 :             for (const MSJunction* junction : junctions) {
     237            0 :                 minValue = MIN2(minValue, junction->getPosition().z());
     238            0 :                 maxValue = MAX2(maxValue, junction->getPosition().z());
     239              :             }
     240              :         }
     241              :     }
     242            0 :     if (scheme.getName() == GUIVisualizationSettings::SCHEME_NAME_PERMISSION_CODE) {
     243            0 :         scheme.clear();
     244              :         // add threshold for every distinct value
     245              :         std::set<SVCPermissions> codes;
     246            0 :         for (MSEdge* edge : MSEdge::getAllEdges()) {
     247            0 :             for (MSLane* lane : edge->getLanes()) {
     248            0 :                 codes.insert(lane->getPermissions());
     249              :             }
     250              :         }
     251            0 :         int step = MAX2(1, 360 / (int)codes.size());
     252              :         int hue = 0;
     253            0 :         for (SVCPermissions p : codes) {
     254            0 :             scheme.addColor(RGBColor::fromHSV(hue, 1, 1), (double)p);
     255            0 :             hue = (hue + step) % 360;
     256              :         }
     257              :         return;
     258              :     }
     259            0 :     buildMinMaxRainbow(s, scheme, rs, minValue, maxValue, hasMissingData);
     260              : }
     261              : 
     262              : 
     263              : std::vector<std::string>
     264            0 : GUIViewTraffic::getEdgeDataAttrs() const {
     265            0 :     if (GUINet::getGUIInstance() != nullptr) {
     266            0 :         return GUINet::getGUIInstance()->getEdgeDataAttrs();
     267              :     }
     268            0 :     return std::vector<std::string>();
     269              : }
     270              : 
     271              : 
     272              : std::vector<std::string>
     273            0 : GUIViewTraffic::getMeanDataIDs() const {
     274            0 :     if (GUINet::getGUIInstance() != nullptr) {
     275            0 :         return GUINet::getGUIInstance()->getMeanDataIDs();
     276              :     }
     277            0 :     return std::vector<std::string>();
     278              : }
     279              : 
     280              : std::vector<std::string>
     281            0 : GUIViewTraffic::getMeanDataAttrs(const std::string& meanDataID) const {
     282            0 :     if (GUINet::getGUIInstance() != nullptr) {
     283            0 :         return GUINet::getGUIInstance()->getMeanDataAttrs(meanDataID);
     284              :     }
     285            0 :     return std::vector<std::string>();
     286              : }
     287              : 
     288              : 
     289              : std::vector<std::string>
     290            0 : GUIViewTraffic::getEdgeLaneParamKeys(bool edgeKeys) const {
     291              :     std::set<std::string> keys;
     292            0 :     for (const MSEdge* e : MSEdge::getAllEdges()) {
     293            0 :         if (edgeKeys) {
     294            0 :             for (const auto& item : e->getParametersMap()) {
     295            0 :                 keys.insert(item.first);
     296              :             }
     297              :         } else {
     298            0 :             for (const auto lane : e->getLanes()) {
     299            0 :                 for (const auto& item : lane->getParametersMap()) {
     300            0 :                     keys.insert(item.first);
     301              :                 }
     302              :             }
     303              :         }
     304              :     }
     305            0 :     return std::vector<std::string>(keys.begin(), keys.end());
     306              : }
     307              : 
     308              : 
     309              : std::vector<std::string>
     310            0 : GUIViewTraffic::getVehicleParamKeys(bool /*vTypeKeys*/) const {
     311              :     std::set<std::string> keys;
     312              :     MSVehicleControl* vc = nullptr;
     313            0 :     if (MSGlobals::gUseMesoSim) {
     314            0 :         vc = GUINet::getGUIInstance()->getGUIMEVehicleControl();
     315              :     } else {
     316            0 :         vc = GUINet::getGUIInstance()->getGUIVehicleControl();
     317              :     }
     318            0 :     vc->secureVehicles();
     319            0 :     for (auto vehIt = vc->loadedVehBegin(); vehIt != vc->loadedVehEnd(); ++vehIt) {
     320            0 :         for (auto kv : vehIt->second->getParameter().getParametersMap()) {
     321              :             keys.insert(kv.first);
     322              :         }
     323              :     }
     324            0 :     vc->releaseVehicles();
     325            0 :     return std::vector<std::string>(keys.begin(), keys.end());
     326              : }
     327              : 
     328              : std::vector<std::string>
     329            0 : GUIViewTraffic::getPOIParamKeys() const {
     330              :     std::set<std::string> keys;
     331            0 :     const ShapeContainer::POIs& pois = static_cast<ShapeContainer&>(GUINet::getInstance()->getShapeContainer()).getPOIs();
     332            0 :     for (auto item : pois) {
     333            0 :         for (auto kv : item.second->getParametersMap()) {
     334              :             keys.insert(kv.first);
     335              :         }
     336              :     }
     337            0 :     return std::vector<std::string>(keys.begin(), keys.end());
     338              : }
     339              : 
     340              : 
     341              : void
     342          502 : GUIViewTraffic::centerTo(GUIGlID id, bool applyZoom, double zoomDist) {
     343          502 :     GUIGlobals::gSecondaryShape = myVisualizationSettings->secondaryShape;
     344          502 :     GUISUMOAbstractView::centerTo(id, applyZoom, zoomDist);
     345          502 :     GUIGlobals::gSecondaryShape = false;
     346          502 : }
     347              : 
     348              : int
     349       863876 : GUIViewTraffic::doPaintGL(int mode, const Boundary& bound) {
     350              :     // init view settings
     351       863876 :     glRenderMode(mode);
     352       863876 :     glMatrixMode(GL_MODELVIEW);
     353       863876 :     GLHelper::pushMatrix();
     354       863876 :     glDisable(GL_TEXTURE_2D);
     355       863876 :     glDisable(GL_ALPHA_TEST);
     356       863876 :     glEnable(GL_BLEND);
     357       863876 :     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
     358       863876 :     glEnable(GL_DEPTH_TEST);
     359              : 
     360              :     // draw decals (if not in grabbing mode)
     361       863876 :     drawDecals();
     362       863876 :     myVisualizationSettings->scale = m2p(SUMO_const_laneWidth);
     363       863876 :     if (myVisualizationSettings->showGrid) {
     364            0 :         paintGLGrid();
     365              :     }
     366       863876 :     glLineWidth(1);
     367       863876 :     glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
     368       863876 :     const float minB[2] = { (float)bound.xmin(), (float)bound.ymin() };
     369       863876 :     const float maxB[2] = { (float)bound.xmax(), (float)bound.ymax() };
     370       863876 :     glEnable(GL_POLYGON_OFFSET_FILL);
     371       863876 :     glEnable(GL_POLYGON_OFFSET_LINE);
     372       863876 :     const SUMORTree& grid = GUINet::getGUIInstance()->getVisualisationSpeedUp(myVisualizationSettings->secondaryShape);
     373       863876 :     int hits2 = grid.Search(minB, maxB, *myVisualizationSettings);
     374       863876 :     GUIGlobals::gSecondaryShape = myVisualizationSettings->secondaryShape;
     375              :     // Draw additional objects
     376       863876 :     if (myAdditionallyDrawn.size() > 0) {
     377            2 :         glTranslated(0, 0, -.01);
     378            2 :         GUINet::getGUIInstance()->lock();
     379            4 :         for (auto i : myAdditionallyDrawn) {
     380            2 :             i.first->drawGLAdditional(this, *myVisualizationSettings);
     381              :         }
     382            2 :         GUINet::getGUIInstance()->unlock();
     383            2 :         glTranslated(0, 0, .01);
     384              :     }
     385       863876 :     GLHelper::popMatrix();
     386              :     /*
     387              :     // draw legends
     388              :     glMatrixMode(GL_MODELVIEW);
     389              :     glLoadIdentity();
     390              :     glTranslated(1.-.2, 1.-.5, 0.);
     391              :     glScaled(.2, .5, 1.);
     392              :     GUIColoringSchemesMap<GUILane> &sm = GUIViewTraffic::getLaneSchemesMap(); //!!!
     393              :     sm.getColorer(myVisualizationSettings->laneEdgeMode)->drawLegend();
     394              :     */
     395       863876 :     return hits2;
     396              : }
     397              : 
     398              : 
     399              : void
     400            3 : GUIViewTraffic::startTrack(int id) {
     401            3 :     myTrackedID = id;
     402            3 :     GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id);
     403            3 :     if (o != nullptr) {
     404            3 :         GUIBaseVehicle* v = dynamic_cast<GUIBaseVehicle*>(o);
     405            3 :         if (v != nullptr) {
     406            3 :             v->addActiveAddVisualisation(this, GUIBaseVehicle::VO_TRACK);
     407              :         }
     408              :     }
     409            3 : }
     410              : 
     411              : 
     412              : void
     413            3 : GUIViewTraffic::stopTrack() {
     414            3 :     myTrackedID = GUIGlObject::INVALID_ID;
     415            3 : }
     416              : 
     417              : 
     418              : GUIGlID
     419      1290699 : GUIViewTraffic::getTrackedID() const {
     420      1290699 :     return myTrackedID;
     421              : }
     422              : 
     423              : 
     424              : void
     425            0 : GUIViewTraffic::onGamingClick(Position pos) {
     426            0 :     if (myTLSGame) {
     427            0 :         MSTLLogicControl& tlsControl = MSNet::getInstance()->getTLSControl();
     428              :         MSTrafficLightLogic* minTll = nullptr;
     429              :         GUIGlObject* minRR = nullptr;
     430              :         double minDist = std::numeric_limits<double>::infinity();
     431              :         double minDistRR = std::numeric_limits<double>::infinity();
     432            0 :         for (MSTrafficLightLogic* const tll : tlsControl.getAllLogics()) {
     433            0 :             if (tlsControl.isActive(tll) && tll->getProgramID() != "off") {
     434              :                 // get the links
     435              :                 const MSTrafficLightLogic::LaneVector& lanes = tll->getLanesAt(0);
     436            0 :                 if (lanes.size() > 0) {
     437            0 :                     const Position& endPos = lanes[0]->getShape().back();
     438            0 :                     if (endPos.distanceTo(pos) < minDist) {
     439            0 :                         minDist = endPos.distanceTo(pos);
     440              :                         minTll = tll;
     441              :                     }
     442              :                 }
     443              :             }
     444            0 :         }
     445            0 :         if (makeCurrent()) {
     446            0 :             for (GUIGlObject* o : getGUIGlObjectsAtPosition(getPositionInformation(), MIN2(minDist, 20.0))) {
     447            0 :                 if (o->getType() == GLO_REROUTER_EDGE) {
     448            0 :                     const MSEdge* const edge = dynamic_cast<GUITriggeredRerouter::GUITriggeredRerouterEdge*>(o)->getEdge();
     449            0 :                     const double dist = edge->getFromJunction()->getPosition().distanceTo2D(pos);
     450            0 :                     if (dist < minDistRR) {
     451              :                         minDistRR = dist;
     452              :                         minRR = o;
     453              :                     }
     454              :                 }
     455            0 :             }
     456            0 :             makeNonCurrent();
     457              :         }
     458            0 :         if (minDistRR < minDist && minRR != nullptr) {
     459            0 :             minRR->onLeftBtnPress(nullptr);
     460            0 :             update();
     461            0 :             return;
     462              :         }
     463              : 
     464            0 :         if (minTll != nullptr) {
     465            0 :             if (minTll->getPhaseNumber() == 0) {
     466              :                 // MSRailSignal
     467              :                 return;
     468              :             }
     469            0 :             const int ci = minTll->getCurrentPhaseIndex();
     470            0 :             const int n = minTll->getPhaseNumber();
     471              :             int greenCount = 0;
     472            0 :             for (auto& phase : minTll->getPhases()) {
     473            0 :                 if (phase->isGreenPhase()) {
     474            0 :                     greenCount++;
     475              :                 }
     476              :             }
     477            0 :             int nextPhase = (ci + 1) % n;
     478              :             SUMOTime nextDuration = 0;
     479            0 :             if (minTll->getCurrentPhaseDef().isGreenPhase() || (greenCount == 1 && minTll->getCurrentPhaseDef().isAllRedPhase())) {
     480            0 :                 nextDuration = minTll->getPhase(nextPhase).duration;
     481              :             } else {
     482              :                 // we are in transition to a green phase
     483              :                 // -> skip forward to the transition into the next green phase
     484              :                 // but ensure that the total transition time is maintained
     485              :                 // taking into account how much time was already spent
     486            0 :                 SUMOTime spentTransition = minTll->getSpentDuration();
     487              :                 // the transition may consist of more than one phase so we
     488              :                 // search backwards until the prior green phase
     489            0 :                 for (int i = ci - 1; i != ci; i--) {
     490            0 :                     if (i < 0) {
     491            0 :                         i = n - 1;
     492              :                     }
     493            0 :                     if (minTll->getPhase(i).isGreenPhase()) {
     494              :                         break;
     495              :                     }
     496            0 :                     spentTransition += minTll->getPhase(i).duration;
     497              :                 }
     498              :                 // now we skip past the next greenphase
     499              :                 int numGreen = 0;
     500              :                 int i = nextPhase;
     501            0 :                 for (; numGreen < 2; i = (i + 1) % n) {
     502            0 :                     if (minTll->getPhase(i).isGreenPhase()) {
     503            0 :                         numGreen++;
     504            0 :                         continue;
     505              :                     }
     506              :                     // transition after the next green
     507            0 :                     if (numGreen == 1) {
     508            0 :                         SUMOTime dur = minTll->getPhase(i).duration;
     509            0 :                         if (dur <= spentTransition) {
     510            0 :                             spentTransition -= dur;
     511              :                         } else {
     512              :                             nextPhase = i;
     513            0 :                             nextDuration = dur - spentTransition;
     514            0 :                             break;
     515              :                         }
     516              :                     }
     517              :                 }
     518              :             }
     519            0 :             minTll->changeStepAndDuration(tlsControl, MSNet::getInstance()->getCurrentTimeStep(), nextPhase, nextDuration);
     520            0 :             update();
     521              :         }
     522              :     } else {
     523              :         // DRT game
     524            0 :         if (MSGlobals::gUseMesoSim) {
     525              :             return;
     526              :         }
     527            0 :         const auto& sel = gSelected.getSelected(GLO_VEHICLE);
     528            0 :         if (sel.size() == 0) {
     529              :             // find closest pt vehicle
     530              :             double minDist = std::numeric_limits<double>::infinity();
     531              :             GUIVehicle* closest = nullptr;
     532            0 :             MSVehicleControl& vc = MSNet::getInstance()->getVehicleControl();
     533              :             MSVehicleControl::constVehIt it = vc.loadedVehBegin();
     534              :             MSVehicleControl::constVehIt end = vc.loadedVehEnd();
     535            0 :             for (it = vc.loadedVehBegin(); it != end; ++it) {
     536            0 :                 GUIVehicle* veh = dynamic_cast<GUIVehicle*>(it->second);
     537              :                 assert(veh != 0);
     538            0 :                 if (veh->getParameter().line != "") {
     539            0 :                     const double dist = veh->getPosition().distanceTo2D(pos);
     540            0 :                     if (dist < minDist) {
     541              :                         minDist = dist;
     542              :                         closest = veh;
     543              :                     }
     544              :                 }
     545              :             }
     546            0 :             if (closest != nullptr) {
     547            0 :                 gSelected.select(closest->getGlID());
     548            0 :                 closest->addActiveAddVisualisation(this, GUIBaseVehicle::VO_SHOW_FUTURE_ROUTE);
     549              :             }
     550              :         } else {
     551              :             // find closest pt stop
     552              :             double minDist = std::numeric_limits<double>::infinity();
     553              :             MSStoppingPlace* closestStop = nullptr;
     554            0 :             const NamedObjectCont<MSStoppingPlace*>& stops = MSNet::getInstance()->getStoppingPlaces(SUMO_TAG_BUS_STOP);
     555            0 :             for (auto it = stops.begin(); it != stops.end(); ++it) {
     556            0 :                 MSStoppingPlace* stop = it->second;
     557            0 :                 const double dist = pos.distanceTo2D(stop->getLane().geometryPositionAtOffset(stop->getEndLanePosition()));
     558            0 :                 if (dist < minDist) {
     559              :                     minDist = dist;
     560              :                     closestStop = stop;
     561              :                 }
     562              :             }
     563            0 :             if (closestStop != 0) {
     564            0 :                 GUIGlID id = *sel.begin();
     565            0 :                 GUIVehicle* veh = dynamic_cast<GUIVehicle*>(GUIGlObjectStorage::gIDStorage.getObjectBlocking(id));
     566              :                 assert(veh != 0);
     567              :                 MSLane* lane = veh->getMutableLane();
     568            0 :                 lane->getVehiclesSecure();
     569            0 :                 veh->rerouteDRTStop(closestStop);
     570            0 :                 GUIGlObjectStorage::gIDStorage.unblockObject(id);
     571            0 :                 lane->releaseVehicles();
     572              :             }
     573              :         }
     574              :     }
     575              : }
     576              : 
     577              : 
     578              : void
     579            0 : GUIViewTraffic::onGamingRightClick(Position /*pos*/) {
     580            0 :     const auto& sel = gSelected.getSelected(GLO_VEHICLE);
     581            0 :     if (sel.size() > 0) {
     582            0 :         GUIGlID id = *sel.begin();
     583            0 :         GUIVehicle* veh = dynamic_cast<GUIVehicle*>(GUIGlObjectStorage::gIDStorage.getObjectBlocking(id));
     584            0 :         if (veh != 0) {
     585            0 :             veh->removeActiveAddVisualisation(this, GUIBaseVehicle::VO_SHOW_FUTURE_ROUTE);
     586              :         }
     587            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(id);
     588              :     }
     589            0 :     gSelected.clear();
     590            0 : }
     591              : 
     592              : 
     593              : SUMOTime
     594     12570321 : GUIViewTraffic::getCurrentTimeStep() const {
     595     12570321 :     return MSNet::getInstance()->getCurrentTimeStep();
     596              : }
     597              : 
     598              : 
     599              : long
     600            0 : GUIViewTraffic::onCmdCloseLane(FXObject*, FXSelector, void*) {
     601            0 :     GUILane* lane = getLaneUnderCursor();
     602            0 :     if (lane != nullptr) {
     603            0 :         lane->closeTraffic();
     604            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
     605            0 :         update();
     606              :     }
     607            0 :     return 1;
     608              : }
     609              : 
     610              : 
     611              : long
     612            0 : GUIViewTraffic::onCmdCloseEdge(FXObject*, FXSelector, void*) {
     613            0 :     GUILane* lane = getLaneUnderCursor();
     614            0 :     if (lane != nullptr) {
     615            0 :         dynamic_cast<GUIEdge*>(&lane->getEdge())->closeTraffic(lane);
     616            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
     617            0 :         update();
     618              :     }
     619            0 :     return 1;
     620              : }
     621              : 
     622              : 
     623              : long
     624            0 : GUIViewTraffic::onCmdAddRerouter(FXObject*, FXSelector, void*) {
     625            0 :     GUILane* lane = getLaneUnderCursor();
     626            0 :     if (lane != nullptr) {
     627            0 :         dynamic_cast<GUIEdge*>(&lane->getEdge())->addRerouter();
     628            0 :         GUIGlObjectStorage::gIDStorage.unblockObject(lane->getGlID());
     629            0 :         update();
     630              :     }
     631            0 :     return 1;
     632              : }
     633              : 
     634              : 
     635              : long
     636            0 : GUIViewTraffic::showLaneReachability(GUILane* lane, FXObject* menu, FXSelector) {
     637            0 :     if (lane != nullptr) {
     638              :         // reset
     639              :         const double UNREACHED = INVALID_DOUBLE;
     640            0 :         gSelected.clear();
     641            0 :         for (const MSEdge* const e : MSEdge::getAllEdges()) {
     642            0 :             for (MSLane* const l : e->getLanes()) {
     643            0 :                 GUILane* gLane = dynamic_cast<GUILane*>(l);
     644              :                 gLane->setReachability(UNREACHED);
     645              :             }
     646              :         }
     647              :         // prepare
     648            0 :         FXMenuCommand* mc = dynamic_cast<FXMenuCommand*>(menu);
     649            0 :         const SUMOVehicleClass svc = SumoVehicleClassStrings.get(mc->getText().text());
     650            0 :         const double defaultMaxSpeed = SUMOVTypeParameter::VClassDefaultValues(svc).desiredMaxSpeed;
     651              :         // find reachable
     652              :         std::map<MSEdge*, double> reachableEdges;
     653            0 :         reachableEdges[&lane->getEdge()] = 0;
     654              :         MSEdgeVector check;
     655            0 :         check.push_back(&lane->getEdge());
     656            0 :         while (check.size() > 0) {
     657            0 :             MSEdge* e = check.front();
     658              :             check.erase(check.begin());
     659            0 :             double traveltime = reachableEdges[e];
     660            0 :             for (MSLane* const l : e->getLanes()) {
     661            0 :                 if (l->allowsVehicleClass(svc)) {
     662            0 :                     GUILane* gLane = dynamic_cast<GUILane*>(l);
     663            0 :                     gSelected.select(gLane->getGlID(), false);
     664              :                     gLane->setReachability(traveltime);
     665              :                 }
     666              :             }
     667            0 :             const double dt = e->getLength() / MIN2(e->getSpeedLimit(), defaultMaxSpeed);
     668              :             // ensure algorithm termination
     669            0 :             traveltime += MAX2(dt, NUMERICAL_EPS);
     670            0 :             for (MSEdge* const nextEdge : e->getSuccessors(svc)) {
     671            0 :                 if (reachableEdges.count(nextEdge) == 0 ||
     672              :                         // revisit edge via faster path
     673            0 :                         reachableEdges[nextEdge] > traveltime) {
     674            0 :                     reachableEdges[nextEdge] = traveltime;
     675            0 :                     check.push_back(nextEdge);
     676              :                 }
     677              :             }
     678            0 :             if (svc == SVC_PEDESTRIAN) {
     679              :                 // can also walk backwards
     680            0 :                 for (MSEdge* const prevEdge : e->getPredecessors()) {
     681            0 :                     if (prevEdge->allowedLanes(*e, svc) != nullptr &&
     682            0 :                             (reachableEdges.count(prevEdge) == 0 ||
     683              :                              // revisit edge via faster path
     684            0 :                              reachableEdges[prevEdge] > traveltime)) {
     685            0 :                         reachableEdges[prevEdge] = traveltime;
     686            0 :                         check.push_back(prevEdge);
     687              :                     }
     688              :                 }
     689              :                 // and connect to arbitrary incoming if there are no walkingareas
     690            0 :                 if (!MSNet::getInstance()->hasPedestrianNetwork()) {
     691            0 :                     for (const MSEdge* const in_const : e->getToJunction()->getIncoming()) {
     692            0 :                         MSEdge* in = const_cast<MSEdge*>(in_const);
     693            0 :                         if ((in->getPermissions() & svc) == svc &&
     694            0 :                                 (reachableEdges.count(in) == 0 ||
     695              :                                  // revisit edge via faster path
     696            0 :                                  reachableEdges[in] > traveltime)) {
     697            0 :                             reachableEdges[in] = traveltime;
     698            0 :                             check.push_back(in);
     699              :                         }
     700              :                     }
     701              :                 }
     702              :             }
     703              :         }
     704            0 :         gSelected.notifyChanged();
     705            0 :     }
     706            0 :     return 1;
     707              : }
     708              : 
     709              : 
     710              : long
     711            0 : GUIViewTraffic::onCmdShowReachability(FXObject* menu, FXSelector selector, void*) {
     712            0 :     GUILane* lane = getLaneUnderCursor();
     713            0 :     if (lane != nullptr) {
     714              :         // reset
     715            0 :         showLaneReachability(lane, menu, selector);
     716              :         // switch to 'color by selection' unless coloring 'by reachability'
     717            0 :         if (myVisualizationSettings->laneColorer.getActive() != 36) {
     718              :             myVisualizationSettings->laneColorer.setActive(1);
     719              :         }
     720            0 :         update();
     721              :     }
     722            0 :     return 1;
     723              : }
     724              : 
     725              : 
     726              : GUILane*
     727            0 : GUIViewTraffic::getLaneUnderCursor() {
     728            0 :     if (makeCurrent()) {
     729            0 :         int id = getObjectUnderCursor();
     730            0 :         if (id != 0) {
     731            0 :             GUIGlObject* o = GUIGlObjectStorage::gIDStorage.getObjectBlocking(id);
     732            0 :             if (o != nullptr) {
     733            0 :                 return dynamic_cast<GUILane*>(o);
     734              :             }
     735              :         }
     736            0 :         makeNonCurrent();
     737              :     }
     738              :     return nullptr;
     739              : }
     740              : 
     741              : 
     742              : long
     743            0 : GUIViewTraffic::onDoubleClicked(FXObject*, FXSelector, void*) {
     744              :     // leave fullscreen mode
     745            0 :     if (myApp->isFullScreen()) {
     746            0 :         myApp->onCmdFullScreen(nullptr, 0, nullptr);
     747              :     } else {
     748            0 :         stopTrack();
     749              :     }
     750            0 :     return 1;
     751              : }
     752              : 
     753              : 
     754              : 
     755              : void
     756            0 : GUIViewTraffic::saveFrame(const std::string& destFile, FXColor* buf) {
     757              : #ifdef HAVE_FFMPEG
     758            0 :     if (myCurrentVideo == nullptr) {
     759            0 :         myCurrentVideo = new GUIVideoEncoder(destFile.c_str(), getWidth(), getHeight(), myApp->getDelay());
     760              :     }
     761            0 :     myCurrentVideo->writeFrame((uint8_t*)buf);
     762              : #else
     763              :     UNUSED_PARAMETER(destFile);
     764              :     UNUSED_PARAMETER(buf);
     765              : #endif
     766            0 : }
     767              : 
     768              : 
     769              : void
     770         7865 : GUIViewTraffic::endSnapshot() {
     771              : #ifdef HAVE_FFMPEG
     772         7865 :     if (myCurrentVideo != nullptr) {
     773            0 :         delete myCurrentVideo;
     774            0 :         myCurrentVideo = nullptr;
     775              :     }
     776              : #endif
     777         7865 : }
     778              : 
     779              : 
     780              : void
     781     12570321 : GUIViewTraffic::checkSnapshots() {
     782              : #ifdef HAVE_FFMPEG
     783     12570321 :     if (myCurrentVideo != nullptr) {
     784            0 :         addSnapshot(getCurrentTimeStep() - DELTA_T, "");
     785              :     }
     786              : #endif
     787     12570321 :     GUISUMOAbstractView::checkSnapshots();
     788     12570321 : }
     789              : 
     790              : 
     791              : const std::vector<SUMOTime>
     792            0 : GUIViewTraffic::retrieveBreakpoints() const {
     793            0 :     return myApp->retrieveBreakpoints();
     794              : }
     795              : 
     796              : 
     797              : void
     798            0 : GUIViewTraffic::drawPedestrianNetwork(const GUIVisualizationSettings& s) const {
     799            0 :     GUIShapeContainer& shapeContainer = dynamic_cast<GUIShapeContainer&>(GUINet::getInstance()->getShapeContainer());
     800            0 :     if (s.showPedestrianNetwork) {
     801            0 :         shapeContainer.removeInactivePolygonTypes(std::set<std::string> {"jupedsim.pedestrian_network"});
     802              :     } else {
     803            0 :         shapeContainer.addInactivePolygonTypes(std::set<std::string> {"jupedsim.pedestrian_network"});
     804              :     }
     805            0 :     update();
     806            0 : }
     807              : 
     808              : 
     809              : void
     810            0 : GUIViewTraffic::changePedestrianNetworkColor(const GUIVisualizationSettings& s) const {
     811            0 :     GUIShapeContainer& shapeContainer = dynamic_cast<GUIShapeContainer&>(GUINet::getInstance()->getShapeContainer());
     812            0 :     for (auto polygonwithID : shapeContainer.getPolygons()) {
     813            0 :         if (polygonwithID.second->getShapeType() == "jupedsim.pedestrian_network") {
     814            0 :             polygonwithID.second->setShapeColor(s.pedestrianNetworkColor);
     815              :         }
     816              :     }
     817            0 :     update();
     818            0 : }
     819              : 
     820              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1