LCOV - code coverage report
Current view: top level - src/guisim - GUINet.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 139 375 37.1 %
Date: 2024-04-27 15:34:54 Functions: 20 51 39.2 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    GUINet.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @author  Laura Bieker
      19             : /// @date    Sept 2002
      20             : ///
      21             : // A MSNet extended by some values for usage within the gui
      22             : /****************************************************************************/
      23             : #include <config.h>
      24             : 
      25             : #include <utility>
      26             : #include <set>
      27             : #include <vector>
      28             : #include <map>
      29             : #include <utils/shapes/ShapeContainer.h>
      30             : #include <utils/gui/globjects/GUIPolygon.h>
      31             : #include <utils/gui/globjects/GUIPointOfInterest.h>
      32             : #include <utils/gui/globjects/GUIGLObjectPopupMenu.h>
      33             : #include <utils/gui/div/GUIDesigns.h>
      34             : #include <utils/gui/div/GUIParameterTableWindow.h>
      35             : #include <utils/gui/div/GUIGlobalSelection.h>
      36             : #include <utils/gui/globjects/GUIShapeContainer.h>
      37             : #include <utils/xml/XMLSubSys.h>
      38             : #include <utils/common/MsgHandler.h>
      39             : #include <utils/common/StringUtils.h>
      40             : #include <utils/common/RGBColor.h>
      41             : #include <utils/iodevices/OutputDevice.h>
      42             : #include <utils/gui/div/GLObjectValuePassConnector.h>
      43             : #include <microsim/MSNet.h>
      44             : #include <microsim/MSEdgeWeightsStorage.h>
      45             : #include <microsim/MSJunction.h>
      46             : #include <microsim/output/MSDetectorControl.h>
      47             : #include <microsim/MSEdge.h>
      48             : #include <microsim/transportables/MSPModel.h>
      49             : #include <microsim/MSInsertionControl.h>
      50             : #include <microsim/traffic_lights/MSTrafficLightLogic.h>
      51             : #include <microsim/traffic_lights/MSTLLogicControl.h>
      52             : #include <microsim/MSJunctionControl.h>
      53             : #include <guisim/Command_Hotkey_TrafficLight.h>
      54             : #include <guisim/GUIEdge.h>
      55             : #include <guisim/GUILane.h>
      56             : #include <guisim/GUITransportableControl.h>
      57             : #include <guisim/GUILaneSpeedTrigger.h>
      58             : #include <guisim/GUIDetectorWrapper.h>
      59             : #include <guisim/GUICalibrator.h>
      60             : #include <guisim/GUITrafficLightLogicWrapper.h>
      61             : #include <guisim/GUIJunctionWrapper.h>
      62             : #include <guisim/GUIVehicleControl.h>
      63             : #include <gui/GUIGlobals.h>
      64             : #include <gui/GUIApplicationWindow.h>
      65             : #include "GUINet.h"
      66             : 
      67             : #include <mesogui/GUIMEVehicleControl.h>
      68             : 
      69             : 
      70             : // ===========================================================================
      71             : // definition of static variables used for visualisation of objects' values
      72             : // ===========================================================================
      73             : template std::vector< GLObjectValuePassConnector<double>* > GLObjectValuePassConnector<double>::myContainer;
      74             : template FXMutex GLObjectValuePassConnector<double>::myLock;
      75             : 
      76             : template std::vector< GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >* > GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >::myContainer;
      77             : template FXMutex GLObjectValuePassConnector<std::pair<int, class MSPhaseDefinition> >::myLock;
      78             : 
      79             : 
      80             : // ===========================================================================
      81             : // member method definitions
      82             : // ===========================================================================
      83        7230 : GUINet::GUINet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
      84             :                MSEventControl* endOfTimestepEvents,
      85        7230 :                MSEventControl* insertionEvents) :
      86        7230 :     MSNet(vc, beginOfTimestepEvents, endOfTimestepEvents, insertionEvents, new GUIShapeContainer(myGrid)),
      87             :     GUIGlObject(GLO_NETWORK, "", nullptr),
      88        7230 :     myLastSimDuration(0), /*myLastVisDuration(0),*/ myLastIdleDuration(0),
      89       21690 :     myLastVehicleMovementCount(0), myOverallVehicleCount(0), myOverallSimDuration(0) {
      90             :     GUIGlObjectStorage::gIDStorage.setNetObject(this);
      91        7230 : }
      92             : 
      93             : 
      94       14428 : GUINet::~GUINet() {
      95        7214 :     if (myLock.locked()) {
      96           0 :         myLock.unlock();
      97             :     }
      98             :     // delete allocated wrappers
      99             :     //  of junctions
     100       89127 :     for (std::vector<GUIJunctionWrapper*>::iterator i1 = myJunctionWrapper.begin(); i1 != myJunctionWrapper.end(); i1++) {
     101       81913 :         delete (*i1);
     102             :     }
     103             :     //  of additional structures
     104        7214 :     GUIGlObject_AbstractAdd::clearDictionary();
     105             :     //  of tl-logics
     106       27006 :     for (Logics2WrapperMap::iterator i3 = myLogics2Wrapper.begin(); i3 != myLogics2Wrapper.end(); i3++) {
     107       19792 :         delete (*i3).second;
     108             :     }
     109             :     //  of detectors
     110        8306 :     for (std::vector<GUIDetectorWrapper*>::iterator i = myDetectorWrapper.begin(); i != myDetectorWrapper.end(); ++i) {
     111        1092 :         delete *i;
     112             :     }
     113             :     //  of calibrators
     114        7290 :     for (GUICalibrator* cw : myCalibratorWrapper) {
     115          76 :         delete cw;
     116             :     }
     117        7214 :     for (auto& item : myLoadedEdgeData) {
     118           0 :         delete item.second;
     119             :     }
     120       21642 : }
     121             : 
     122             : 
     123             : const Boundary&
     124           0 : GUINet::getBoundary() const {
     125           0 :     return myBoundary;
     126             : }
     127             : 
     128             : 
     129             : MSTransportableControl&
     130     2487007 : GUINet::getPersonControl() {
     131     2487007 :     if (myPersonControl == nullptr) {
     132        1335 :         myPersonControl = new GUITransportableControl(true);
     133             :     }
     134     2487007 :     return *myPersonControl;
     135             : }
     136             : 
     137             : 
     138             : MSTransportableControl&
     139      101496 : GUINet::getContainerControl() {
     140      101496 :     if (myContainerControl == nullptr) {
     141         156 :         myContainerControl = new GUITransportableControl(false);
     142             :     }
     143      101496 :     return *myContainerControl;
     144             : }
     145             : 
     146             : 
     147             : void
     148        6984 : GUINet::initTLMap() {
     149             :     // go through the loaded tl-logics
     150       26785 :     for (MSTrafficLightLogic* const tll : getTLSControl().getAllLogics()) {
     151       19801 :         createTLWrapper(tll);
     152             :     }
     153        6984 : }
     154             : 
     155             : 
     156             : void
     157       19809 : GUINet::createTLWrapper(MSTrafficLightLogic* tll) {
     158             :     if (myLogics2Wrapper.count(tll) > 0) {
     159             :         return;
     160             :     }
     161             :     // get the links
     162       19809 :     const MSTrafficLightLogic::LinkVectorVector& links = tll->getLinks();
     163       19809 :     if (links.size() == 0) { // @legacy this should never happen in 0.13.0+ networks
     164             :         return;
     165             :     }
     166             :     // build the wrapper
     167       19809 :     GUITrafficLightLogicWrapper* tllw = new GUITrafficLightLogicWrapper(*myLogics, *tll);
     168       39618 :     if (tll->hasParameter("hotkeyAbort")) {
     169           0 :         Command_Hotkey_TrafficLight::registerHotkey(tll->getParameter("hotkeyAbort"), *tll);
     170             :     }
     171             :     // build the association link->wrapper
     172             :     MSTrafficLightLogic::LinkVectorVector::const_iterator j;
     173      225729 :     for (j = links.begin(); j != links.end(); ++j) {
     174             :         MSTrafficLightLogic::LinkVector::const_iterator j2;
     175      411528 :         for (j2 = (*j).begin(); j2 != (*j).end(); ++j2) {
     176      205608 :             myLinks2Logic[*j2] = tll->getID();
     177             :         }
     178             :     }
     179       19809 :     myGrid.addAdditionalGLObject(tllw);
     180       19809 :     myLogics2Wrapper[tll] = tllw;
     181             : }
     182             : 
     183             : 
     184             : Position
     185           0 : GUINet::getJunctionPosition(const std::string& name) const {
     186             :     // !!! no check for existance!
     187           0 :     return myJunctions->get(name)->getPosition();
     188             : }
     189             : 
     190             : 
     191             : bool
     192           0 : GUINet::vehicleExists(const std::string& name) const {
     193           0 :     return myVehicleControl->getVehicle(name) != nullptr;
     194             : }
     195             : 
     196             : 
     197             : int
     198       46154 : GUINet::getLinkTLID(const MSLink* const link) const {
     199             :     if (myLinks2Logic.count(link) == 0) {
     200             :         //assert(false);
     201             :         return 0;
     202             :     }
     203       92276 :     MSTrafficLightLogic* tll = myLogics->getActive(myLinks2Logic.find(link)->second);
     204             :     if (myLogics2Wrapper.count(tll) == 0) {
     205             :         // tll may have been added via traci. @see ticket #459
     206             :         return 0;
     207             :     }
     208       46138 :     return myLogics2Wrapper.find(tll)->second->getGlID();
     209             : }
     210             : 
     211             : 
     212             : int
     213           0 : GUINet::getLinkTLIndex(const MSLink* const link) const {
     214             :     Links2LogicMap::const_iterator i = myLinks2Logic.find(link);
     215           0 :     if (i == myLinks2Logic.end()) {
     216             :         return -1;
     217             :     }
     218           0 :     if (myLogics2Wrapper.find(myLogics->getActive((*i).second)) == myLogics2Wrapper.end()) {
     219             :         return -1;
     220             :     }
     221           0 :     return myLogics2Wrapper.find(myLogics->getActive((*i).second))->second->getLinkIndex(link);
     222             : }
     223             : 
     224             : 
     225             : void
     226     5325966 : GUINet::guiSimulationStep() {
     227     5325966 :     GLObjectValuePassConnector<double>::updateAll();
     228     5325966 :     GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >::updateAll();
     229     5325966 : }
     230             : 
     231             : 
     232             : void
     233     5326076 : GUINet::simulationStep() {
     234     5326076 :     FXMutexLock locker(myLock);
     235     5326076 :     MSNet::simulationStep();
     236     5325966 : }
     237             : 
     238             : 
     239             : std::vector<GUIGlID>
     240           0 : GUINet::getJunctionIDs(bool includeInternal) const {
     241             :     std::vector<GUIGlID> ret;
     242           0 :     for (std::vector<GUIJunctionWrapper*>::const_iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     243           0 :         if (!(*i)->isInternal() || includeInternal) {
     244           0 :             ret.push_back((*i)->getGlID());
     245             :         }
     246             :     }
     247           0 :     return ret;
     248             : }
     249             : 
     250             : 
     251             : std::vector<GUIGlID>
     252           0 : GUINet::getTLSIDs() const {
     253             :     std::vector<GUIGlID> ret;
     254             :     std::vector<std::string> ids;
     255           0 :     for (std::map<MSTrafficLightLogic*, GUITrafficLightLogicWrapper*>::const_iterator i = myLogics2Wrapper.begin(); i != myLogics2Wrapper.end(); ++i) {
     256           0 :         std::string sid = (*i).second->getMicrosimID();
     257           0 :         if (find(ids.begin(), ids.end(), sid) == ids.end()) {
     258           0 :             ret.push_back((*i).second->getGlID());
     259           0 :             ids.push_back(sid);
     260             :         }
     261             :     }
     262           0 :     return ret;
     263           0 : }
     264             : 
     265             : 
     266             : void
     267        6984 : GUINet::initGUIStructures() {
     268             :     // initialise detector storage for gui
     269        6984 :     const std::vector<SumoXMLTag> types = myDetectorControl->getAvailableTypes();
     270        7469 :     for (std::vector<SumoXMLTag>::const_iterator i = types.begin(); i != types.end(); ++i) {
     271        1608 :         for (const auto& j : myDetectorControl->getTypedDetectors(*i)) {
     272        1123 :             GUIDetectorWrapper* wrapper = j.second->buildDetectorGUIRepresentation();
     273        1123 :             if (wrapper != nullptr) {
     274        1096 :                 myDetectorWrapper.push_back(wrapper);
     275        1096 :                 myGrid.addAdditionalGLObject(wrapper);
     276             :             }
     277             :         }
     278             :     }
     279             :     // let's always track emission parameters for the GUI
     280        6984 :     MSGlobals::gHaveEmissions = true;
     281             :     // initialise calibrators
     282        7060 :     for (auto& item : MSCalibrator::getInstances()) {
     283          76 :         GUICalibrator* wrapper = new GUICalibrator(item.second);
     284          76 :         myCalibratorWrapper.push_back(wrapper);
     285          76 :         myGrid.addAdditionalGLObject(wrapper);
     286             :     }
     287             :     // initialise the tl-map
     288        6984 :     initTLMap();
     289             :     // initialise edge storage for gui
     290        6984 :     const MSEdgeVector& edges = MSEdge::getAllEdges();
     291        6984 :     myEdgeWrapper.reserve(edges.size());
     292      287166 :     for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
     293             :         // VISIM connector edges shall be drawn (they have lanes)
     294      280182 :         if (!(*i)->isTazConnector() || (*i)->getLanes().size() > 0) {
     295      277034 :             myEdgeWrapper.push_back(static_cast<GUIEdge*>(*i));
     296             :         }
     297             :     }
     298             :     // initialise junction storage for gui
     299        6984 :     int size = myJunctions->size();
     300        6984 :     myJunctionWrapper.reserve(size);
     301             :     std::map<MSJunction*, std::string> junction2TLL;
     302       26785 :     for (const auto tls : getTLSControl().getAllLogics()) {
     303      225575 :         for (const auto& links : tls->getLinks()) {
     304      411240 :             for (const MSLink* l : links) {
     305      410932 :                 junction2TLL[l->getJunction()] = l->getTLLogic()->getID();
     306             :             }
     307             :         }
     308             :     }
     309       89067 :     for (const auto& i : *myJunctions) {
     310       82083 :         myJunctionWrapper.push_back(new GUIJunctionWrapper(*i.second, junction2TLL[i.second]));
     311             :     }
     312             :     // build the visualization tree
     313      284018 :     for (std::vector<GUIEdge*>::iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
     314      277034 :         GUIEdge* edge = *i;
     315      277034 :         Boundary b;
     316             :         const std::vector<MSLane*>& lanes = edge->getLanes();
     317      602505 :         for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
     318      325471 :             b.add((*j)->getShape().getBoxBoundary());
     319             :         }
     320             :         // make sure persons are always drawn and selectable since they depend on their edge being drawn
     321      277034 :         b.grow(MSPModel::SIDEWALK_OFFSET + 1 + lanes.front()->getWidth() / 2);
     322      277034 :         const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     323      277034 :         const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     324      277034 :         myGrid.Insert(cmin, cmax, edge);
     325      277034 :         myBoundary.add(b);
     326      277034 :         if (myBoundary.getWidth() > 10e16 || myBoundary.getHeight() > 10e16) {
     327           0 :             throw ProcessError(TL("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n"));
     328             :         }
     329      277034 :     }
     330       89067 :     for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     331       82083 :         GUIJunctionWrapper* junction = *i;
     332             :         Boundary b = junction->getBoundary();
     333       82083 :         b.grow(2.);
     334       82083 :         const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     335       82083 :         const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     336       82083 :         myGrid.Insert(cmin, cmax, junction);
     337       82083 :         myBoundary.add(b);
     338       82083 :     }
     339        6984 :     myGrid.add(myBoundary);
     340             : 
     341       13968 :     if (OptionsCont::getOptions().isSet("alternative-net-file")) {
     342             :         // build secondary visualization tree
     343           0 :         for (GUIEdge* edge : myEdgeWrapper) {
     344           0 :             Boundary b;
     345           0 :             for (MSLane* lane : edge->getLanes()) {
     346           0 :                 b.add(static_cast<GUILane*>(lane)->getShape(true).getBoxBoundary());
     347             :             }
     348             :             // make sure persons are always drawn and selectable since they depend on their edge being drawn
     349           0 :             b.grow(MSPModel::SIDEWALK_OFFSET + 1);
     350           0 :             const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     351           0 :             const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     352           0 :             myGrid2.Insert(cmin, cmax, edge);
     353           0 :         }
     354           0 :         for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     355           0 :             GUIJunctionWrapper* junction = *i;
     356           0 :             Position pos = junction->getJunction().getPosition(true);
     357           0 :             Boundary b = Boundary(pos.x() - 3., pos.y() - 3., pos.x() + 3., pos.y() + 3.);
     358           0 :             const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     359           0 :             const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     360           0 :             myGrid2.Insert(cmin, cmax, junction);
     361           0 :         }
     362             :     }
     363        6984 : }
     364             : 
     365             : 
     366             : void
     367        2694 : GUINet::registerRenderedObject(GUIGlObject* o) {
     368        2694 :     getVisualisationSpeedUp().addAdditionalGLObject(o);
     369        5388 :     if (OptionsCont::getOptions().isSet("alternative-net-file")) {
     370           0 :         GUIGlobals::gSecondaryShape = true;
     371           0 :         myGrid2.addAdditionalGLObject(o);
     372           0 :         GUIGlobals::gSecondaryShape = false;
     373             :     }
     374        2694 : }
     375             : 
     376             : 
     377             : int
     378           0 : GUINet::getWholeDuration() const {
     379           0 :     return myLastSimDuration +/*myLastVisDuration+*/myLastIdleDuration;
     380             : }
     381             : 
     382             : 
     383             : int
     384           0 : GUINet::getSimDuration() const {
     385           0 :     return myLastSimDuration;
     386             : }
     387             : 
     388             : /*
     389             : int
     390             : GUINet::getVisDuration() const
     391             : {
     392             :     return myLastVisDuration;
     393             : }
     394             : */
     395             : 
     396             : 
     397             : double
     398           0 : GUINet::getRTFactor() const {
     399           0 :     if (myLastSimDuration == 0) {
     400             :         return -1;
     401             :     }
     402           0 :     return (double)DELTA_T / (double)myLastSimDuration;
     403             : }
     404             : 
     405             : 
     406             : double
     407           0 : GUINet::getUPS() const {
     408           0 :     if (myLastSimDuration == 0) {
     409             :         return -1;
     410             :     }
     411           0 :     return (double) myLastVehicleMovementCount / (double) myLastSimDuration * (double) 1000.;
     412             : }
     413             : 
     414             : 
     415             : double
     416           0 : GUINet::getMeanRTFactor(int duration) const {
     417           0 :     if (myOverallSimDuration == 0) {
     418             :         return -1;
     419             :     }
     420           0 :     return ((double)(duration) * (double) 1000. / (double)myOverallSimDuration);
     421             : }
     422             : 
     423             : 
     424             : double
     425           0 : GUINet::getMeanUPS() const {
     426           0 :     if (myOverallSimDuration == 0) {
     427             :         return -1;
     428             :     }
     429           0 :     return ((double)myVehiclesMoved / (double)myOverallSimDuration * (double) 1000.);
     430             : }
     431             : 
     432             : 
     433             : int
     434           0 : GUINet::getIdleDuration() const {
     435           0 :     return myLastIdleDuration;
     436             : }
     437             : 
     438             : 
     439             : void
     440     5326076 : GUINet::setSimDuration(int val) {
     441     5326076 :     myLastSimDuration = val;
     442     5326076 :     myOverallSimDuration += val;
     443     5326076 :     myLastVehicleMovementCount = getVehicleControl().getRunningVehicleNo();
     444     5326076 :     myOverallVehicleCount += myLastVehicleMovementCount;
     445     5326076 : }
     446             : 
     447             : /*
     448             : void
     449             : GUINet::setVisDuration(int val)
     450             : {
     451             :     myLastVisDuration = val;
     452             : }
     453             : */
     454             : 
     455             : void
     456     5319307 : GUINet::setIdleDuration(int val) {
     457     5319307 :     myLastIdleDuration = val;
     458     5319307 : }
     459             : 
     460             : 
     461             : GUIGLObjectPopupMenu*
     462           0 : GUINet::getPopUpMenu(GUIMainWindow& app,
     463             :                      GUISUMOAbstractView& parent) {
     464           0 :     GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, *this);
     465           0 :     buildPopupHeader(ret, app);
     466           0 :     buildCenterPopupEntry(ret);
     467           0 :     buildShowParamsPopupEntry(ret);
     468           0 :     buildPositionCopyEntry(ret, app);
     469           0 :     if (GeoConvHelper::getFinal().usingGeoProjection()) {
     470           0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Copy view geo-boundary to clipboard"), nullptr, ret, MID_COPY_VIEW_GEOBOUNDARY);
     471             :     }
     472           0 :     return ret;
     473             : }
     474             : 
     475             : 
     476             : GUIParameterTableWindow*
     477           0 : GUINet::getParameterWindow(GUIMainWindow& app,
     478             :                            GUISUMOAbstractView& parent) {
     479           0 :     GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
     480             :     // add items
     481           0 :     ret->mkItem(TL("loaded vehicles [#]"), true,
     482           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getLoadedVehicleNo));
     483           0 :     ret->mkItem(TL("insertion-backlogged vehicles [#]"), true,
     484           0 :                 new FunctionBinding<MSInsertionControl, int>(&getInsertionControl(), &MSInsertionControl::getWaitingVehicleNo));
     485           0 :     ret->mkItem(TL("departed vehicles [#]"), true,
     486           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDepartedVehicleNo));
     487           0 :     ret->mkItem(TL("running vehicles [#]"), true,
     488           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getRunningVehicleNo));
     489           0 :     ret->mkItem(TL("arrived vehicles [#]"), true,
     490           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getArrivedVehicleNo));
     491           0 :     ret->mkItem(TL("discarded vehicles [#]"), true,
     492           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDiscardedVehicleNo));
     493           0 :     ret->mkItem(TL("collisions [#]"), true,
     494           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getCollisionCount));
     495           0 :     ret->mkItem(TL("teleports [#]"), true,
     496           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getTeleportCount));
     497           0 :     ret->mkItem(TL("halting [#]"), true,
     498           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getHaltingVehicleNo));
     499           0 :     ret->mkItem(TL("stopped [#]"), true,
     500           0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getStoppedVehiclesCount));
     501           0 :     ret->mkItem(TL("avg. speed [m/s]"), true,
     502           0 :                 new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeed));
     503           0 :     ret->mkItem(TL("avg. relative speed"), true,
     504           0 :                 new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeedRelative));
     505           0 :     if (myPersonControl != nullptr) {
     506           0 :         ret->mkItem(TL("loaded persons [#]"), true,
     507           0 :                     new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getLoadedNumber));
     508           0 :         ret->mkItem(TL("running persons [#]"), true,
     509           0 :                     new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getRunningNumber));
     510           0 :         ret->mkItem(TL("jammed persons [#]"), true,
     511           0 :                     new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getJammedNumber));
     512             :     }
     513           0 :     ret->mkItem(TL("end time [s]"), false, OptionsCont::getOptions().getString("end"));
     514           0 :     ret->mkItem(TL("begin time [s]"), false, OptionsCont::getOptions().getString("begin"));
     515             : //    ret->mkItem(TL("time step [s]"), true, new FunctionBinding<GUINet, SUMOTime>(this, &GUINet::getCurrentTimeStep));
     516           0 :     if (logSimulationDuration()) {
     517           0 :         ret->mkItem(TL("step duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getWholeDuration));
     518           0 :         ret->mkItem(TL("FPS"), true, new FunctionBinding<GUISUMOAbstractView, double>(&parent, &GUISUMOAbstractView::getFPS));
     519           0 :         ret->mkItem(TL("simulation duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getSimDuration));
     520             :         /*
     521             :         ret->mkItem(TL("visualisation duration [ms]"), true,
     522             :             new CastingFunctionBinding<GUINet, double, int>(
     523             :                 &(getNet()), &GUINet::getVisDuration));
     524             :         */
     525           0 :         ret->mkItem(TL("idle duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getIdleDuration));
     526           0 :         ret->mkItem(TL("duration factor"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getRTFactor));
     527             :         /*
     528             :         ret->mkItem(TL("mean duration factor []"), true,
     529             :             new FuncBinding_IntParam<GUINet, double>(
     530             :                 &(getNet()), &GUINet::getMeanRTFactor), 1);
     531             :                 */
     532           0 :         ret->mkItem(TL("updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getUPS));
     533           0 :         ret->mkItem(TL("avg. updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getMeanUPS));
     534             :     }
     535           0 :     if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
     536           0 :         ret->mkItem(TL("avg. trip length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgRouteLength));
     537           0 :         ret->mkItem(TL("avg. trip duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDuration));
     538           0 :         ret->mkItem(TL("avg. trip waiting time [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWaitingTime));
     539           0 :         ret->mkItem(TL("avg. trip time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTimeLoss));
     540           0 :         ret->mkItem(TL("avg. trip depart delay [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDepartDelay));
     541           0 :         ret->mkItem(TL("avg. trip speed [m/s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTripSpeed));
     542           0 :         if (myPersonControl != nullptr) {
     543           0 :             ret->mkItem(TL("avg. walk length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkRouteLength));
     544           0 :             ret->mkItem(TL("avg. walk duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkDuration));
     545           0 :             ret->mkItem(TL("avg. walk time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkTimeLoss));
     546             :         }
     547             :     }
     548           0 :     ret->mkItem(TL("nodes [#]"), false, (int)getJunctionIDs(false).size());
     549           0 :     ret->mkItem(TL("edges [#]"), false, (int)GUIEdge::getIDs(false).size());
     550           0 :     ret->mkItem(TL("total edge length [km]"), false, GUIEdge::getTotalLength(false, false) / 1000);
     551           0 :     ret->mkItem(TL("total lane length [km]"), false, GUIEdge::getTotalLength(false, true) / 1000);
     552           0 :     ret->mkItem(TL("network version "), false, toString(myVersion));
     553             : 
     554             :     // close building
     555           0 :     ret->closeBuilding();
     556           0 :     return ret;
     557             : }
     558             : 
     559             : 
     560             : void
     561           0 : GUINet::drawGL(const GUIVisualizationSettings& /*s*/) const {
     562           0 : }
     563             : 
     564             : 
     565             : Boundary
     566           0 : GUINet::getCenteringBoundary() const {
     567           0 :     return getBoundary();
     568             : }
     569             : 
     570             : 
     571             : GUINet*
     572      888695 : GUINet::getGUIInstance() {
     573      888695 :     GUINet* net = dynamic_cast<GUINet*>(MSNet::getInstance());
     574      888695 :     if (net != nullptr) {
     575      888695 :         return net;
     576             :     }
     577           0 :     throw ProcessError("A gui-network was not yet constructed.");
     578             : }
     579             : 
     580             : 
     581             : GUIVehicleControl*
     582           0 : GUINet::getGUIVehicleControl() {
     583           0 :     return dynamic_cast<GUIVehicleControl*>(myVehicleControl);
     584             : }
     585             : 
     586             : 
     587             : void
     588           3 : GUINet::lock() {
     589           3 :     myLock.lock();
     590           3 : }
     591             : 
     592             : 
     593             : void
     594           3 : GUINet::unlock() {
     595           3 :     myLock.unlock();
     596           3 : }
     597             : 
     598             : GUIMEVehicleControl*
     599      321718 : GUINet::getGUIMEVehicleControl() {
     600      321718 :     return dynamic_cast<GUIMEVehicleControl*>(myVehicleControl);
     601             : }
     602             : 
     603             : 
     604             : double
     605           0 : GUINet::getEdgeData(const MSEdge* edge, const std::string& attr) {
     606             :     auto it = myLoadedEdgeData.find(attr);
     607           0 :     if (it != myLoadedEdgeData.end()) {
     608             :         double value;
     609           0 :         bool found = it->second->retrieveExistingEffort(edge, STEPS2TIME(getCurrentTimeStep()), value);
     610           0 :         if (found) {
     611           0 :             return value;
     612             :         } else {
     613           0 :             return GUIVisualizationSettings::MISSING_DATA;
     614             :         }
     615             :     } else {
     616           0 :         return GUIVisualizationSettings::MISSING_DATA;
     617             :     }
     618             : }
     619             : 
     620             : 
     621             : double
     622           0 : GUINet::getMeanData(const MSLane* lane, const std::string& id, const std::string& attr) {
     623           0 :     auto item = myDetectorControl->getMeanData().find(id);
     624           0 :     if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
     625           0 :         SumoXMLAttr a = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attr);
     626           0 :         return item->second.front()->getAttributeValue(lane, a, GUIVisualizationSettings::MISSING_DATA);
     627             :     } else {
     628           0 :         return GUIVisualizationSettings::MISSING_DATA;
     629             :     }
     630             : }
     631             : 
     632             : 
     633             : void
     634           0 : GUINet::DiscoverAttributes::myStartElement(int element, const SUMOSAXAttributes& attrs) {
     635           0 :     if (element == SUMO_TAG_EDGE || element == SUMO_TAG_LANE) {
     636           0 :         std::vector<std::string> tmp = attrs.getAttributeNames();
     637             :         edgeAttrs.insert(tmp.begin(), tmp.end());
     638           0 :     } else if (element == SUMO_TAG_EDGEREL) {
     639           0 :         for (const std::string& a : attrs.getAttributeNames()) {
     640           0 :             if (a != "from" && a != "to") {
     641             :                 edgeAttrs.insert(a);
     642             :             }
     643           0 :         }
     644           0 :     } else if (element == SUMO_TAG_INTERVAL) {
     645             :         bool ok;
     646           0 :         numIntervals++;
     647           0 :         firstIntervalBegin = MIN2(firstIntervalBegin, attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok));
     648           0 :         lastIntervalEnd = MAX2(lastIntervalEnd, attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok));
     649             :     }
     650           0 : }
     651             : 
     652             : 
     653             : std::vector<std::string>
     654           0 : GUINet::DiscoverAttributes::getEdgeAttrs() {
     655           0 :     edgeAttrs.erase(toString(SUMO_ATTR_ID));
     656           0 :     return std::vector<std::string>(edgeAttrs.begin(), edgeAttrs.end());
     657             : }
     658             : 
     659             : 
     660             : void
     661           0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeWeight(const std::string& id,
     662             :         double value, double begTime, double endTime) const {
     663           0 :     MSEdge* const edge = MSEdge::dictionary(id);
     664           0 :     if (edge != nullptr) {
     665           0 :         myWeightStorage->addEffort(edge, begTime, endTime, value);
     666             :     } else {
     667           0 :         WRITE_WARNINGF(TL("Trying to set data value for the unknown edge '%'."), id);
     668             :     }
     669           0 : }
     670             : 
     671             : 
     672             : void
     673           0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeRelWeight(const std::string& from, const std::string& to,
     674             :         double val, double beg, double end) const {
     675           0 :     MSEdge* const fromEdge = MSEdge::dictionary(from);
     676           0 :     MSEdge* const toEdge = MSEdge::dictionary(to);
     677             :     bool haveRel = false;
     678           0 :     if (fromEdge != nullptr && toEdge != nullptr) {
     679           0 :         for (auto item : fromEdge->getViaSuccessors()) {
     680           0 :             if (item.first == toEdge) {
     681             :                 const MSEdge* edge = item.second;
     682           0 :                 while (edge != nullptr && edge->isInternal()) {
     683           0 :                     myWeightStorage->addEffort(edge, beg, end, val);
     684           0 :                     edge = edge->getViaSuccessors().front().second;
     685             :                     haveRel = true;
     686             :                 }
     687             :             }
     688             :         }
     689             :     }
     690           0 :     if (!haveRel) {
     691           0 :         WRITE_WARNINGF(TL("Trying to set data value for the unknown relation from edge '%' to edge '%'."), from, to);
     692             :     }
     693           0 : }
     694             : 
     695             : 
     696             : bool
     697           0 : GUINet::loadEdgeData(const std::string& file) {
     698             :     // discover edge attributes
     699           0 :     DiscoverAttributes discoveryHandler(file);
     700           0 :     XMLSubSys::runParser(discoveryHandler, file);
     701           0 :     std::vector<std::string> attrs = discoveryHandler.getEdgeAttrs();
     702           0 :     WRITE_MESSAGE("Loading edgedata from '" + file + "':"
     703             :                   + "\n    " + toString(discoveryHandler.numIntervals) + " intervals between"
     704             :                   + " " + time2string(discoveryHandler.firstIntervalBegin) + " and"
     705             :                   + " " + time2string(discoveryHandler.lastIntervalEnd)
     706             :                   + ".\n    Found " + toString(attrs.size())
     707             :                   + " attributes: " + toString(attrs));
     708           0 :     if (discoveryHandler.lastIntervalEnd < string2time(OptionsCont::getOptions().getString("begin"))) {
     709           0 :         WRITE_WARNING(TL("No data defined after simulation begin time."));
     710             :     }
     711           0 :     myEdgeDataEndTime = MAX2(myEdgeDataEndTime, discoveryHandler.lastIntervalEnd);
     712             :     // create a retriever for each attribute
     713             :     std::vector<EdgeFloatTimeLineRetriever_GUI> retrieverDefsInternal;
     714           0 :     retrieverDefsInternal.reserve(attrs.size());
     715             :     std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
     716           0 :     for (const std::string& attr : attrs) {
     717           0 :         MSEdgeWeightsStorage* ws = new MSEdgeWeightsStorage();
     718           0 :         myLoadedEdgeData[attr] = ws;
     719           0 :         retrieverDefsInternal.push_back(EdgeFloatTimeLineRetriever_GUI(ws));
     720           0 :         retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(attr, true, retrieverDefsInternal.back()));
     721             :     }
     722           0 :     SAXWeightsHandler handler(retrieverDefs, "");
     723           0 :     return XMLSubSys::runParser(handler, file);
     724           0 : }
     725             : 
     726             : 
     727             : std::vector<std::string>
     728           0 : GUINet::getEdgeDataAttrs() const {
     729             :     std::vector<std::string> result;
     730           0 :     for (const auto& item : myLoadedEdgeData) {
     731           0 :         result.push_back(item.first);
     732             :     }
     733           0 :     return result;
     734           0 : }
     735             : 
     736             : 
     737             : std::vector<std::string>
     738           0 : GUINet::getMeanDataIDs() const {
     739             :     std::vector<std::string> result;
     740             : 
     741           0 :     for (auto item : myDetectorControl->getMeanData()) {
     742           0 :         result.push_back(item.first);
     743           0 :     }
     744           0 :     std::sort(result.begin(), result.end());
     745           0 :     return result;
     746           0 : }
     747             : 
     748             : std::vector<std::string>
     749           0 : GUINet::getMeanDataAttrs(const std::string& meanDataID) const {
     750           0 :     auto item = myDetectorControl->getMeanData().find(meanDataID);
     751           0 :     if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
     752           0 :         return item->second.front()->getAttributeNames();
     753             :     } else {
     754           0 :         return std::vector<std::string>();
     755             :     }
     756             : }
     757             : 
     758             : 
     759             : bool
     760           0 : GUINet::isSelected(const MSTrafficLightLogic* tll) const {
     761             :     const auto it = myLogics2Wrapper.find(const_cast<MSTrafficLightLogic*>(tll));
     762           0 :     return it != myLogics2Wrapper.end() && gSelected.isSelected(GLO_TLLOGIC, it->second->getGlID());
     763             : }
     764             : 
     765             : void
     766          52 : GUINet::updateGUI() const {
     767             :     try {
     768             :         // gui only
     769          52 :         GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
     770             :         // update the view
     771          52 :         aw->handleEvent_SimulationStep(nullptr);
     772           0 :     } catch (ProcessError&) { }
     773          52 : }
     774             : 
     775             : void
     776           0 : GUINet::addHotkey(int key, Command* press, Command* release) {
     777             :     try {
     778             :         // gui only
     779           0 :         GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
     780             :         // update the view
     781           0 :         aw->addHotkey(key, press, release);
     782           0 :     } catch (ProcessError&) { }
     783           0 : }
     784             : 
     785             : void
     786           0 : GUINet::flushOutputsAtEnd() {
     787           0 :     mySkipFinalReset = true;
     788           0 :     myDetectorControl->close(SIMSTEP);
     789           0 :     OutputDevice::flushAll();
     790             :     // update tracker windows
     791           0 :     guiSimulationStep();
     792           0 : }
     793             : 
     794             : #ifdef HAVE_OSG
     795             : void
     796       11471 : GUINet::updateColor(const GUIVisualizationSettings& s) {
     797      200453 :     for (std::vector<GUIEdge*>::const_iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
     798      188982 :         if (!(*i)->isInternal()) {
     799             :             const std::vector<MSLane*>& lanes = (*i)->getLanes();
     800      214153 :             for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
     801      136966 :                 static_cast<GUILane*>(*j)->updateColor(s);
     802             :             }
     803             :         }
     804             :     }
     805       98902 :     for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     806       87431 :         (*i)->updateColor(s);
     807             :     }
     808       11471 : }
     809             : #endif
     810             : 
     811             : 
     812             : /****************************************************************************/

Generated by: LCOV version 1.14