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

Generated by: LCOV version 2.0-1