LCOV - code coverage report
Current view: top level - src/guisim - GUINet.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 36.5 % 381 139
Test Date: 2025-11-14 15:59:05 Functions: 38.5 % 52 20

            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    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         7981 : GUINet::GUINet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
      84              :                MSEventControl* endOfTimestepEvents,
      85         7981 :                MSEventControl* insertionEvents) :
      86         7981 :     MSNet(vc, beginOfTimestepEvents, endOfTimestepEvents, insertionEvents, new GUIShapeContainer(myGrid)),
      87              :     GUIGlObject(GLO_NETWORK, "", nullptr),
      88         7981 :     myLastSimDuration(0), /*myLastVisDuration(0),*/ myLastIdleDuration(0),
      89        23943 :     myLastVehicleMovementCount(0), myOverallVehicleCount(0), myOverallSimDuration(0) {
      90              :     GUIGlObjectStorage::gIDStorage.setNetObject(this);
      91         7981 : }
      92              : 
      93              : 
      94        15916 : GUINet::~GUINet() {
      95         7958 :     if (myLock.locked()) {
      96            0 :         myLock.unlock();
      97              :     }
      98              :     // delete allocated wrappers
      99              :     //  of junctions
     100       100870 :     for (std::vector<GUIJunctionWrapper*>::iterator i1 = myJunctionWrapper.begin(); i1 != myJunctionWrapper.end(); i1++) {
     101        92912 :         delete (*i1);
     102              :     }
     103              :     //  of additional structures
     104         7958 :     GUIGlObject_AbstractAdd::clearDictionary();
     105              :     //  of tl-logics
     106        27400 :     for (Logics2WrapperMap::iterator i3 = myLogics2Wrapper.begin(); i3 != myLogics2Wrapper.end(); i3++) {
     107        19442 :         delete (*i3).second;
     108              :     }
     109              :     //  of detectors
     110         9057 :     for (std::vector<GUIDetectorWrapper*>::iterator i = myDetectorWrapper.begin(); i != myDetectorWrapper.end(); ++i) {
     111         1099 :         delete *i;
     112              :     }
     113              :     //  of calibrators
     114         8042 :     for (GUICalibrator* cw : myCalibratorWrapper) {
     115           84 :         delete cw;
     116              :     }
     117         7958 :     for (auto& item : myLoadedEdgeData) {
     118            0 :         delete item.second;
     119              :     }
     120        23874 : }
     121              : 
     122              : 
     123              : const Boundary&
     124            0 : GUINet::getBoundary() const {
     125            0 :     return myBoundary;
     126              : }
     127              : 
     128              : 
     129              : MSTransportableControl&
     130      4012938 : GUINet::getPersonControl() {
     131      4012938 :     if (myPersonControl == nullptr) {
     132         1532 :         myPersonControl = new GUITransportableControl(true);
     133              :     }
     134      4012938 :     return *myPersonControl;
     135              : }
     136              : 
     137              : 
     138              : MSTransportableControl&
     139       148161 : GUINet::getContainerControl() {
     140       148161 :     if (myContainerControl == nullptr) {
     141          173 :         myContainerControl = new GUITransportableControl(false);
     142              :     }
     143       148161 :     return *myContainerControl;
     144              : }
     145              : 
     146              : 
     147              : void
     148         7726 : GUINet::initTLMap() {
     149              :     // go through the loaded tl-logics
     150        27179 :     for (MSTrafficLightLogic* const tll : getTLSControl().getAllLogics()) {
     151        19453 :         createTLWrapper(tll);
     152         7726 :     }
     153         7726 : }
     154              : 
     155              : 
     156              : void
     157        19465 : GUINet::createTLWrapper(MSTrafficLightLogic* tll) {
     158              :     if (myLogics2Wrapper.count(tll) > 0) {
     159              :         return;
     160              :     }
     161              :     // get the links
     162        19465 :     const MSTrafficLightLogic::LinkVectorVector& links = tll->getLinks();
     163        19465 :     if (links.size() == 0) { // @legacy this should never happen in 0.13.0+ networks
     164              :         return;
     165              :     }
     166              :     // build the wrapper
     167        19464 :     GUITrafficLightLogicWrapper* tllw = new GUITrafficLightLogicWrapper(*myLogics, *tll);
     168        38928 :     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       222859 :     for (j = links.begin(); j != links.end(); ++j) {
     174              :         MSTrafficLightLogic::LinkVector::const_iterator j2;
     175       406467 :         for (j2 = (*j).begin(); j2 != (*j).end(); ++j2) {
     176       203072 :             myLinks2Logic[*j2] = tll->getID();
     177              :         }
     178              :     }
     179        19464 :     myGrid.addAdditionalGLObject(tllw);
     180        19464 :     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        60602 : GUINet::getLinkTLID(const MSLink* const link) const {
     199              :     if (myLinks2Logic.count(link) == 0) {
     200              :         //assert(false);
     201              :         return 0;
     202              :     }
     203       121168 :     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        60584 :     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              : GUITrafficLightLogicWrapper*
     226            0 : GUINet::getTLLWrapper(MSTrafficLightLogic* tll) {
     227            0 :     if (myLogics2Wrapper.find(tll) == myLogics2Wrapper.end()) {
     228              :         return nullptr;
     229              :     }
     230            0 :     return myLogics2Wrapper.find(tll)->second;
     231              : }
     232              : 
     233              : 
     234              : void
     235      6481294 : GUINet::guiSimulationStep() {
     236      6481294 :     GLObjectValuePassConnector<double>::updateAll();
     237      6481294 :     GLObjectValuePassConnector<std::pair<SUMOTime, MSPhaseDefinition> >::updateAll();
     238      6481294 : }
     239              : 
     240              : 
     241              : void
     242      6481416 : GUINet::simulationStep() {
     243      6481416 :     FXMutexLock locker(myLock);
     244      6481416 :     MSNet::simulationStep();
     245      6481294 : }
     246              : 
     247              : 
     248              : std::vector<GUIGlID>
     249            0 : GUINet::getJunctionIDs(bool includeInternal) const {
     250              :     std::vector<GUIGlID> ret;
     251            0 :     for (std::vector<GUIJunctionWrapper*>::const_iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     252            0 :         if (!(*i)->isInternal() || includeInternal) {
     253            0 :             ret.push_back((*i)->getGlID());
     254              :         }
     255              :     }
     256            0 :     return ret;
     257            0 : }
     258              : 
     259              : 
     260              : std::vector<GUIGlID>
     261            0 : GUINet::getTLSIDs() const {
     262              :     std::vector<GUIGlID> ret;
     263              :     std::vector<std::string> ids;
     264            0 :     for (std::map<MSTrafficLightLogic*, GUITrafficLightLogicWrapper*>::const_iterator i = myLogics2Wrapper.begin(); i != myLogics2Wrapper.end(); ++i) {
     265            0 :         std::string sid = (*i).second->getMicrosimID();
     266            0 :         if (find(ids.begin(), ids.end(), sid) == ids.end()) {
     267            0 :             ret.push_back((*i).second->getGlID());
     268            0 :             ids.push_back(sid);
     269              :         }
     270              :     }
     271            0 :     return ret;
     272            0 : }
     273              : 
     274              : 
     275              : void
     276         7726 : GUINet::initGUIStructures() {
     277              :     // initialise detector storage for gui
     278         7726 :     const std::vector<SumoXMLTag> types = myDetectorControl->getAvailableTypes();
     279         8215 :     for (std::vector<SumoXMLTag>::const_iterator i = types.begin(); i != types.end(); ++i) {
     280         1625 :         for (const auto& j : myDetectorControl->getTypedDetectors(*i)) {
     281         1136 :             GUIDetectorWrapper* wrapper = j.second->buildDetectorGUIRepresentation();
     282         1136 :             if (wrapper != nullptr) {
     283         1105 :                 myDetectorWrapper.push_back(wrapper);
     284         1105 :                 myGrid.addAdditionalGLObject(wrapper);
     285              :             }
     286              :         }
     287              :     }
     288              :     // let's always track emission parameters for the GUI
     289         7726 :     MSGlobals::gHaveEmissions = true;
     290              :     // initialise calibrators
     291         7810 :     for (auto& item : MSCalibrator::getInstances()) {
     292           84 :         GUICalibrator* wrapper = new GUICalibrator(item.second);
     293           84 :         myCalibratorWrapper.push_back(wrapper);
     294           84 :         myGrid.addAdditionalGLObject(wrapper);
     295              :     }
     296              :     // initialise the tl-map
     297         7726 :     initTLMap();
     298              :     // initialise edge storage for gui
     299         7726 :     const MSEdgeVector& edges = MSEdge::getAllEdges();
     300         7726 :     myEdgeWrapper.reserve(edges.size());
     301       335302 :     for (MSEdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
     302              :         // VISIM connector edges shall be drawn (they have lanes)
     303       327576 :         if (!(*i)->isTazConnector() || (*i)->getLanes().size() > 0) {
     304       324188 :             myEdgeWrapper.push_back(static_cast<GUIEdge*>(*i));
     305              :         }
     306              :     }
     307              :     // initialise junction storage for gui
     308         7726 :     int size = myJunctions->size();
     309         7726 :     myJunctionWrapper.reserve(size);
     310              :     std::map<MSJunction*, std::string> junction2TLL;
     311        27179 :     for (const auto tls : getTLSControl().getAllLogics()) {
     312       222641 :         for (const auto& links : tls->getLinks()) {
     313       406057 :             for (const MSLink* l : links) {
     314       405738 :                 junction2TLL[l->getJunction()] = l->getTLLogic()->getID();
     315              :             }
     316              :         }
     317         7726 :     }
     318       100846 :     for (const auto& i : *myJunctions) {
     319        93120 :         myJunctionWrapper.push_back(new GUIJunctionWrapper(*i.second, junction2TLL[i.second]));
     320              :     }
     321              :     // build the visualization tree
     322       331914 :     for (std::vector<GUIEdge*>::iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
     323       324188 :         GUIEdge* edge = *i;
     324       324188 :         Boundary b;
     325              :         const std::vector<MSLane*>& lanes = edge->getLanes();
     326       705380 :         for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
     327       381192 :             b.add((*j)->getShape().getBoxBoundary());
     328              :         }
     329              :         // make sure persons are always drawn and selectable since they depend on their edge being drawn
     330       324188 :         b.grow(MSPModel::SIDEWALK_OFFSET + 1 + lanes.front()->getWidth() / 2);
     331       324188 :         const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     332       324188 :         const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     333       324188 :         myGrid.Insert(cmin, cmax, edge);
     334       324188 :         myBoundary.add(b);
     335       324188 :         if (myBoundary.getWidth() > 10e16 || myBoundary.getHeight() > 10e16) {
     336            0 :             throw ProcessError(TL("Network size exceeds 1 Lightyear. Please reconsider your inputs.\n"));
     337              :         }
     338              :     }
     339       100846 :     for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     340        93120 :         GUIJunctionWrapper* junction = *i;
     341              :         Boundary b = junction->getBoundary();
     342        93120 :         b.grow(2.);
     343        93120 :         const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     344        93120 :         const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     345        93120 :         myGrid.Insert(cmin, cmax, junction);
     346        93120 :         myBoundary.add(b);
     347              :     }
     348         7726 :     myGrid.add(myBoundary);
     349              : 
     350        15452 :     if (OptionsCont::getOptions().isSet("alternative-net-file")) {
     351              :         // build secondary visualization tree
     352            0 :         for (GUIEdge* edge : myEdgeWrapper) {
     353            0 :             Boundary b;
     354            0 :             for (MSLane* lane : edge->getLanes()) {
     355            0 :                 b.add(static_cast<GUILane*>(lane)->getShape(true).getBoxBoundary());
     356              :             }
     357              :             // make sure persons are always drawn and selectable since they depend on their edge being drawn
     358            0 :             b.grow(MSPModel::SIDEWALK_OFFSET + 1);
     359            0 :             const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     360            0 :             const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     361            0 :             myGrid2.Insert(cmin, cmax, edge);
     362              :         }
     363            0 :         for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     364            0 :             GUIJunctionWrapper* junction = *i;
     365            0 :             Position pos = junction->getJunction().getPosition(true);
     366            0 :             Boundary b = Boundary(pos.x() - 3., pos.y() - 3., pos.x() + 3., pos.y() + 3.);
     367            0 :             const float cmin[2] = { (float)b.xmin(), (float)b.ymin() };
     368            0 :             const float cmax[2] = { (float)b.xmax(), (float)b.ymax() };
     369            0 :             myGrid2.Insert(cmin, cmax, junction);
     370              :         }
     371              :     }
     372         7726 : }
     373              : 
     374              : 
     375              : void
     376         3373 : GUINet::registerRenderedObject(GUIGlObject* o) {
     377         3373 :     getVisualisationSpeedUp().addAdditionalGLObject(o);
     378         6746 :     if (OptionsCont::getOptions().isSet("alternative-net-file")) {
     379            0 :         GUIGlobals::gSecondaryShape = true;
     380            0 :         myGrid2.addAdditionalGLObject(o);
     381            0 :         GUIGlobals::gSecondaryShape = false;
     382              :     }
     383         3373 : }
     384              : 
     385              : 
     386              : int
     387            0 : GUINet::getWholeDuration() const {
     388            0 :     return myLastSimDuration +/*myLastVisDuration+*/myLastIdleDuration;
     389              : }
     390              : 
     391              : 
     392              : int
     393            0 : GUINet::getSimDuration() const {
     394            0 :     return myLastSimDuration;
     395              : }
     396              : 
     397              : /*
     398              : int
     399              : GUINet::getVisDuration() const
     400              : {
     401              :     return myLastVisDuration;
     402              : }
     403              : */
     404              : 
     405              : 
     406              : double
     407            0 : GUINet::getRTFactor() const {
     408            0 :     if (myLastSimDuration == 0) {
     409              :         return -1;
     410              :     }
     411            0 :     return (double)DELTA_T / (double)myLastSimDuration;
     412              : }
     413              : 
     414              : 
     415              : double
     416            0 : GUINet::getUPS() const {
     417            0 :     if (myLastSimDuration == 0) {
     418              :         return -1;
     419              :     }
     420            0 :     return (double) myLastVehicleMovementCount / (double) myLastSimDuration * (double) 1000.;
     421              : }
     422              : 
     423              : 
     424              : double
     425            0 : GUINet::getMeanRTFactor(int duration) const {
     426            0 :     if (myOverallSimDuration == 0) {
     427              :         return -1;
     428              :     }
     429            0 :     return ((double)(duration) * (double) 1000. / (double)myOverallSimDuration);
     430              : }
     431              : 
     432              : 
     433              : double
     434            0 : GUINet::getMeanUPS() const {
     435            0 :     if (myOverallSimDuration == 0) {
     436              :         return -1;
     437              :     }
     438            0 :     return ((double)myVehiclesMoved / (double)myOverallSimDuration * (double) 1000.);
     439              : }
     440              : 
     441              : 
     442              : int
     443            0 : GUINet::getIdleDuration() const {
     444            0 :     return myLastIdleDuration;
     445              : }
     446              : 
     447              : 
     448              : void
     449      6481416 : GUINet::setSimDuration(int val) {
     450      6481416 :     myLastSimDuration = val;
     451      6481416 :     myOverallSimDuration += val;
     452      6481416 :     myLastVehicleMovementCount = getVehicleControl().getRunningVehicleNo();
     453      6481416 :     myOverallVehicleCount += myLastVehicleMovementCount;
     454      6481416 : }
     455              : 
     456              : /*
     457              : void
     458              : GUINet::setVisDuration(int val)
     459              : {
     460              :     myLastVisDuration = val;
     461              : }
     462              : */
     463              : 
     464              : void
     465      6473925 : GUINet::setIdleDuration(int val) {
     466      6473925 :     myLastIdleDuration = val;
     467      6473925 : }
     468              : 
     469              : 
     470              : GUIGLObjectPopupMenu*
     471            0 : GUINet::getPopUpMenu(GUIMainWindow& app,
     472              :                      GUISUMOAbstractView& parent) {
     473            0 :     GUIGLObjectPopupMenu* ret = new GUIGLObjectPopupMenu(app, parent, this);
     474            0 :     buildPopupHeader(ret, app);
     475            0 :     buildCenterPopupEntry(ret);
     476            0 :     buildShowParamsPopupEntry(ret);
     477            0 :     buildPositionCopyEntry(ret, app);
     478            0 :     if (GeoConvHelper::getFinal().usingGeoProjection()) {
     479            0 :         GUIDesigns::buildFXMenuCommand(ret, TL("Copy view geo-boundary to clipboard"), nullptr, ret, MID_COPY_VIEW_GEOBOUNDARY);
     480              :     }
     481            0 :     return ret;
     482              : }
     483              : 
     484              : 
     485              : GUIParameterTableWindow*
     486            0 : GUINet::getParameterWindow(GUIMainWindow& app,
     487              :                            GUISUMOAbstractView& parent) {
     488            0 :     GUIParameterTableWindow* ret = new GUIParameterTableWindow(app, *this);
     489              :     // add items
     490            0 :     ret->mkItem(TL("loaded vehicles [#]"), true,
     491            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getLoadedVehicleNo));
     492            0 :     ret->mkItem(TL("insertion-backlogged vehicles [#]"), true,
     493            0 :                 new FunctionBinding<MSInsertionControl, int>(&getInsertionControl(), &MSInsertionControl::getWaitingVehicleNo));
     494            0 :     ret->mkItem(TL("departed vehicles [#]"), true,
     495            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDepartedVehicleNo));
     496            0 :     ret->mkItem(TL("running vehicles [#]"), true,
     497            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getRunningVehicleNo));
     498            0 :     ret->mkItem(TL("arrived vehicles [#]"), true,
     499            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getArrivedVehicleNo));
     500            0 :     ret->mkItem(TL("discarded vehicles [#]"), true,
     501            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getDiscardedVehicleNo));
     502            0 :     ret->mkItem(TL("collisions [#]"), true,
     503            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getCollisionCount));
     504            0 :     ret->mkItem(TL("teleports [#]"), true,
     505            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getTeleportCount));
     506            0 :     ret->mkItem(TL("halting [#]"), true,
     507            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getHaltingVehicleNo));
     508            0 :     ret->mkItem(TL("stopped [#]"), true,
     509            0 :                 new FunctionBinding<MSVehicleControl, int>(&getVehicleControl(), &MSVehicleControl::getStoppedVehiclesCount));
     510            0 :     ret->mkItem(TL("avg. speed [m/s]"), true,
     511            0 :                 new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeed));
     512            0 :     ret->mkItem(TL("avg. relative speed"), true,
     513            0 :                 new FunctionBinding<MSVehicleControl, double>(&getVehicleControl(), &MSVehicleControl::getVehicleMeanSpeedRelative));
     514            0 :     if (myPersonControl != nullptr) {
     515            0 :         ret->mkItem(TL("loaded persons [#]"), true,
     516            0 :                     new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getLoadedNumber));
     517            0 :         ret->mkItem(TL("running persons [#]"), true,
     518            0 :                     new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getRunningNumber));
     519            0 :         ret->mkItem(TL("jammed persons [#]"), true,
     520            0 :                     new FunctionBinding<MSTransportableControl, int>(&getPersonControl(), &MSTransportableControl::getJammedNumber));
     521              :     }
     522            0 :     ret->mkItem(TL("end time [s]"), false, OptionsCont::getOptions().getString("end"));
     523            0 :     ret->mkItem(TL("begin time [s]"), false, OptionsCont::getOptions().getString("begin"));
     524              : //    ret->mkItem(TL("time step [s]"), true, new FunctionBinding<GUINet, SUMOTime>(this, &GUINet::getCurrentTimeStep));
     525            0 :     if (logSimulationDuration()) {
     526            0 :         ret->mkItem(TL("step duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getWholeDuration));
     527            0 :         ret->mkItem(TL("FPS"), true, new FunctionBinding<GUISUMOAbstractView, double>(&parent, &GUISUMOAbstractView::getFPS));
     528            0 :         ret->mkItem(TL("simulation duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getSimDuration));
     529              :         /*
     530              :         ret->mkItem(TL("visualisation duration [ms]"), true,
     531              :             new CastingFunctionBinding<GUINet, double, int>(
     532              :                 &(getNet()), &GUINet::getVisDuration));
     533              :         */
     534            0 :         ret->mkItem(TL("idle duration [ms]"), true, new FunctionBinding<GUINet, int>(this, &GUINet::getIdleDuration));
     535            0 :         ret->mkItem(TL("duration factor"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getRTFactor));
     536              :         /*
     537              :         ret->mkItem(TL("mean duration factor []"), true,
     538              :             new FuncBinding_IntParam<GUINet, double>(
     539              :                 &(getNet()), &GUINet::getMeanRTFactor), 1);
     540              :                 */
     541            0 :         ret->mkItem(TL("updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getUPS));
     542            0 :         ret->mkItem(TL("avg. updates per second"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getMeanUPS));
     543              :     }
     544            0 :     if (OptionsCont::getOptions().isSet("tripinfo-output") || OptionsCont::getOptions().getBool("duration-log.statistics")) {
     545            0 :         ret->mkItem(TL("avg. trip length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgRouteLength));
     546            0 :         ret->mkItem(TL("avg. trip duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDuration));
     547            0 :         ret->mkItem(TL("avg. trip waiting time [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWaitingTime));
     548            0 :         ret->mkItem(TL("avg. trip time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTimeLoss));
     549            0 :         ret->mkItem(TL("avg. trip depart delay [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgDepartDelay));
     550            0 :         ret->mkItem(TL("avg. trip speed [m/s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgTripSpeed));
     551            0 :         if (myPersonControl != nullptr) {
     552            0 :             ret->mkItem(TL("avg. walk length [m]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkRouteLength));
     553            0 :             ret->mkItem(TL("avg. walk duration [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkDuration));
     554            0 :             ret->mkItem(TL("avg. walk time loss [s]"), true, new FunctionBinding<GUINet, double>(this, &GUINet::getAvgWalkTimeLoss));
     555              :         }
     556              :     }
     557            0 :     ret->mkItem(TL("nodes [#]"), false, (int)getJunctionIDs(false).size());
     558            0 :     ret->mkItem(TL("edges [#]"), false, (int)GUIEdge::getIDs(false).size());
     559            0 :     ret->mkItem(TL("total edge length [km]"), false, GUIEdge::getTotalLength(false, false) / 1000);
     560            0 :     ret->mkItem(TL("total lane length [km]"), false, GUIEdge::getTotalLength(false, true) / 1000);
     561            0 :     ret->mkItem(TL("network version "), false, toString(myVersion));
     562              : 
     563              :     // close building
     564            0 :     ret->closeBuilding();
     565            0 :     return ret;
     566              : }
     567              : 
     568              : 
     569              : void
     570            0 : GUINet::drawGL(const GUIVisualizationSettings& /*s*/) const {
     571            0 : }
     572              : 
     573              : 
     574              : Boundary
     575            0 : GUINet::getCenteringBoundary() const {
     576            0 :     return getBoundary();
     577              : }
     578              : 
     579              : 
     580              : GUINet*
     581      1078283 : GUINet::getGUIInstance() {
     582      1078283 :     GUINet* net = dynamic_cast<GUINet*>(MSNet::getInstance());
     583      1078283 :     if (net != nullptr) {
     584      1078283 :         return net;
     585              :     }
     586            0 :     throw ProcessError("A gui-network was not yet constructed.");
     587              : }
     588              : 
     589              : 
     590              : GUIVehicleControl*
     591            0 : GUINet::getGUIVehicleControl() {
     592            0 :     return dynamic_cast<GUIVehicleControl*>(myVehicleControl);
     593              : }
     594              : 
     595              : 
     596              : void
     597            5 : GUINet::lock() {
     598            5 :     myLock.lock();
     599            5 : }
     600              : 
     601              : 
     602              : void
     603            5 : GUINet::unlock() {
     604            5 :     myLock.unlock();
     605            5 : }
     606              : 
     607              : GUIMEVehicleControl*
     608       419090 : GUINet::getGUIMEVehicleControl() {
     609       419090 :     return dynamic_cast<GUIMEVehicleControl*>(myVehicleControl);
     610              : }
     611              : 
     612              : 
     613              : double
     614            0 : GUINet::getEdgeData(const MSEdge* edge, const std::string& attr) {
     615              :     auto it = myLoadedEdgeData.find(attr);
     616            0 :     if (it != myLoadedEdgeData.end()) {
     617              :         double value;
     618            0 :         bool found = it->second->retrieveExistingEffort(edge, STEPS2TIME(getCurrentTimeStep()), value);
     619            0 :         if (found) {
     620            0 :             return value;
     621              :         } else {
     622            0 :             return GUIVisualizationSettings::MISSING_DATA;
     623              :         }
     624              :     } else {
     625            0 :         return GUIVisualizationSettings::MISSING_DATA;
     626              :     }
     627              : }
     628              : 
     629              : 
     630              : double
     631            0 : GUINet::getMeanData(const MSLane* lane, const std::string& id, const std::string& attr) {
     632            0 :     auto item = myDetectorControl->getMeanData().find(id);
     633            0 :     if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
     634            0 :         SumoXMLAttr a = (SumoXMLAttr)SUMOXMLDefinitions::Attrs.get(attr);
     635            0 :         return item->second.front()->getAttributeValue(lane, a, GUIVisualizationSettings::MISSING_DATA);
     636              :     } else {
     637            0 :         return GUIVisualizationSettings::MISSING_DATA;
     638              :     }
     639              : }
     640              : 
     641              : 
     642              : void
     643            0 : GUINet::DiscoverAttributes::myStartElement(int element, const SUMOSAXAttributes& attrs) {
     644            0 :     if (element == SUMO_TAG_EDGE || element == SUMO_TAG_LANE) {
     645            0 :         std::vector<std::string> tmp = attrs.getAttributeNames();
     646              :         edgeAttrs.insert(tmp.begin(), tmp.end());
     647            0 :     } else if (element == SUMO_TAG_EDGEREL) {
     648            0 :         for (const std::string& a : attrs.getAttributeNames()) {
     649            0 :             if (a != "from" && a != "to") {
     650              :                 edgeAttrs.insert(a);
     651              :             }
     652            0 :         }
     653            0 :     } else if (element == SUMO_TAG_INTERVAL) {
     654              :         bool ok;
     655            0 :         numIntervals++;
     656            0 :         firstIntervalBegin = MIN2(firstIntervalBegin, attrs.getSUMOTimeReporting(SUMO_ATTR_BEGIN, nullptr, ok));
     657            0 :         lastIntervalEnd = MAX2(lastIntervalEnd, attrs.getSUMOTimeReporting(SUMO_ATTR_END, nullptr, ok));
     658              :     }
     659            0 : }
     660              : 
     661              : 
     662              : std::vector<std::string>
     663            0 : GUINet::DiscoverAttributes::getEdgeAttrs() {
     664            0 :     edgeAttrs.erase(toString(SUMO_ATTR_ID));
     665            0 :     return std::vector<std::string>(edgeAttrs.begin(), edgeAttrs.end());
     666              : }
     667              : 
     668              : 
     669              : void
     670            0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeWeight(const std::string& id,
     671              :         double value, double begTime, double endTime) const {
     672            0 :     MSEdge* const edge = MSEdge::dictionary(id);
     673            0 :     if (edge != nullptr) {
     674            0 :         myWeightStorage->addEffort(edge, begTime, endTime, value);
     675              :     } else {
     676            0 :         WRITE_WARNINGF(TL("Trying to set data value for the unknown edge '%'."), id);
     677              :     }
     678            0 : }
     679              : 
     680              : 
     681              : void
     682            0 : GUINet::EdgeFloatTimeLineRetriever_GUI::addEdgeRelWeight(const std::string& from, const std::string& to,
     683              :         double val, double beg, double end) const {
     684            0 :     MSEdge* const fromEdge = MSEdge::dictionary(from);
     685            0 :     MSEdge* const toEdge = MSEdge::dictionary(to);
     686              :     bool haveRel = false;
     687            0 :     if (fromEdge != nullptr && toEdge != nullptr) {
     688            0 :         for (auto item : fromEdge->getViaSuccessors()) {
     689            0 :             if (item.first == toEdge) {
     690              :                 const MSEdge* edge = item.second;
     691            0 :                 while (edge != nullptr && edge->isInternal()) {
     692            0 :                     myWeightStorage->addEffort(edge, beg, end, val);
     693            0 :                     edge = edge->getViaSuccessors().front().second;
     694              :                     haveRel = true;
     695              :                 }
     696              :             }
     697              :         }
     698              :     }
     699            0 :     if (!haveRel) {
     700            0 :         WRITE_WARNINGF(TL("Trying to set data value for the unknown relation from edge '%' to edge '%'."), from, to);
     701              :     }
     702            0 : }
     703              : 
     704              : 
     705              : bool
     706            0 : GUINet::loadEdgeData(const std::string& file) {
     707              :     // discover edge attributes
     708            0 :     DiscoverAttributes discoveryHandler(file);
     709            0 :     XMLSubSys::runParser(discoveryHandler, file);
     710            0 :     std::vector<std::string> attrs = discoveryHandler.getEdgeAttrs();
     711            0 :     WRITE_MESSAGE("Loading edgedata from '" + file + "':"
     712              :                   + "\n    " + toString(discoveryHandler.numIntervals) + " intervals between"
     713              :                   + " " + time2string(discoveryHandler.firstIntervalBegin) + " and"
     714              :                   + " " + time2string(discoveryHandler.lastIntervalEnd)
     715              :                   + ".\n    Found " + toString(attrs.size())
     716              :                   + " attributes: " + toString(attrs));
     717            0 :     if (discoveryHandler.lastIntervalEnd < string2time(OptionsCont::getOptions().getString("begin"))) {
     718            0 :         WRITE_WARNING(TL("No data defined after simulation begin time."));
     719              :     }
     720            0 :     myEdgeDataEndTime = MAX2(myEdgeDataEndTime, discoveryHandler.lastIntervalEnd);
     721              :     // create a retriever for each attribute
     722              :     std::vector<EdgeFloatTimeLineRetriever_GUI> retrieverDefsInternal;
     723            0 :     retrieverDefsInternal.reserve(attrs.size());
     724              :     std::vector<SAXWeightsHandler::ToRetrieveDefinition*> retrieverDefs;
     725            0 :     for (const std::string& attr : attrs) {
     726            0 :         MSEdgeWeightsStorage* ws = new MSEdgeWeightsStorage();
     727            0 :         myLoadedEdgeData[attr] = ws;
     728            0 :         retrieverDefsInternal.push_back(EdgeFloatTimeLineRetriever_GUI(ws));
     729            0 :         retrieverDefs.push_back(new SAXWeightsHandler::ToRetrieveDefinition(attr, true, retrieverDefsInternal.back()));
     730              :     }
     731            0 :     SAXWeightsHandler handler(retrieverDefs, "");
     732              :     // temporarily modify warning threshold to avoid swamping the UI
     733            0 :     const int threshold = MsgHandler::getWarningInstance()->getAggregationThreshold();
     734            0 :     MsgHandler::getWarningInstance()->setAggregationThreshold(10);
     735            0 :     bool ok = XMLSubSys::runParser(handler, file);
     736            0 :     MsgHandler::getWarningInstance()->clear(false);
     737            0 :     MsgHandler::getWarningInstance()->setAggregationThreshold(threshold);
     738            0 :     return ok;
     739            0 : }
     740              : 
     741              : 
     742              : std::vector<std::string>
     743            0 : GUINet::getEdgeDataAttrs() const {
     744              :     std::vector<std::string> result;
     745            0 :     for (const auto& item : myLoadedEdgeData) {
     746            0 :         result.push_back(item.first);
     747              :     }
     748            0 :     return result;
     749            0 : }
     750              : 
     751              : 
     752              : std::vector<std::string>
     753            0 : GUINet::getMeanDataIDs() const {
     754              :     std::vector<std::string> result;
     755              : 
     756            0 :     for (auto item : myDetectorControl->getMeanData()) {
     757            0 :         result.push_back(item.first);
     758              :     }
     759            0 :     std::sort(result.begin(), result.end());
     760            0 :     return result;
     761            0 : }
     762              : 
     763              : std::vector<std::string>
     764            0 : GUINet::getMeanDataAttrs(const std::string& meanDataID) const {
     765            0 :     auto item = myDetectorControl->getMeanData().find(meanDataID);
     766            0 :     if (item != myDetectorControl->getMeanData().end() && !item->second.empty()) {
     767            0 :         return item->second.front()->getAttributeNames();
     768              :     } else {
     769            0 :         return std::vector<std::string>();
     770              :     }
     771              : }
     772              : 
     773              : 
     774              : bool
     775            0 : GUINet::isSelected(const MSTrafficLightLogic* tll) const {
     776              :     const auto it = myLogics2Wrapper.find(const_cast<MSTrafficLightLogic*>(tll));
     777            0 :     return it != myLogics2Wrapper.end() && gSelected.isSelected(GLO_TLLOGIC, it->second->getGlID());
     778              : }
     779              : 
     780              : void
     781           34 : GUINet::updateGUI() const {
     782              :     try {
     783              :         // gui only
     784           34 :         GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
     785              :         // update the view
     786           34 :         aw->handleEvent_SimulationStep(nullptr);
     787            0 :     } catch (ProcessError&) { }
     788           34 : }
     789              : 
     790              : void
     791            0 : GUINet::addHotkey(int key, Command* press, Command* release) {
     792              :     try {
     793              :         // gui only
     794            0 :         GUIApplicationWindow* aw = static_cast<GUIApplicationWindow*>(GUIMainWindow::getInstance());
     795              :         // update the view
     796            0 :         aw->addHotkey(key, press, release);
     797            0 :     } catch (ProcessError&) { }
     798            0 : }
     799              : 
     800              : void
     801            0 : GUINet::flushOutputsAtEnd() {
     802            0 :     mySkipFinalReset = true;
     803            0 :     myDetectorControl->close(SIMSTEP);
     804            0 :     OutputDevice::flushAll();
     805              :     // update tracker windows
     806            0 :     guiSimulationStep();
     807            0 : }
     808              : 
     809              : #ifdef HAVE_OSG
     810              : void
     811        16024 : GUINet::updateColor(const GUIVisualizationSettings& s) {
     812       280210 :     for (std::vector<GUIEdge*>::const_iterator i = myEdgeWrapper.begin(); i != myEdgeWrapper.end(); ++i) {
     813       264186 :         if (!(*i)->isInternal()) {
     814              :             const std::vector<MSLane*>& lanes = (*i)->getLanes();
     815       294881 :             for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
     816       188099 :                 static_cast<GUILane*>(*j)->updateColor(s);
     817              :             }
     818              :         }
     819              :     }
     820       139192 :     for (std::vector<GUIJunctionWrapper*>::iterator i = myJunctionWrapper.begin(); i != myJunctionWrapper.end(); ++i) {
     821       123168 :         (*i)->updateColor(s);
     822              :     }
     823        16024 : }
     824              : #endif
     825              : 
     826              : 
     827              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1