LCOV - code coverage report
Current view: top level - src/router - RONet.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 408 449 90.9 %
Date: 2024-05-08 15:29:52 Functions: 42 42 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4             : // This program and the accompanying materials are made available under the
       5             : // terms of the Eclipse Public License 2.0 which is available at
       6             : // https://www.eclipse.org/legal/epl-2.0/
       7             : // This Source Code may also be made available under the following Secondary
       8             : // Licenses when the conditions for such availability set forth in the Eclipse
       9             : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10             : // or later which is available at
      11             : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12             : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13             : /****************************************************************************/
      14             : /// @file    RONet.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Jakob Erdmann
      17             : /// @author  Michael Behrisch
      18             : /// @date    Sept 2002
      19             : ///
      20             : // The router's network representation
      21             : /****************************************************************************/
      22             : #include <config.h>
      23             : 
      24             : #include <algorithm>
      25             : #include <utils/router/RouteCostCalculator.h>
      26             : #include <utils/vehicle/SUMOVTypeParameter.h>
      27             : #include <utils/router/SUMOAbstractRouter.h>
      28             : #include <utils/options/OptionsCont.h>
      29             : #include <utils/common/UtilExceptions.h>
      30             : #include <utils/common/ToString.h>
      31             : #include <utils/common/StringUtils.h>
      32             : #include <utils/common/RandHelper.h>
      33             : #include <utils/common/SUMOVehicleClass.h>
      34             : #include <utils/iodevices/OutputDevice.h>
      35             : #include "ROEdge.h"
      36             : #include "ROLane.h"
      37             : #include "RONode.h"
      38             : #include "ROPerson.h"
      39             : #include "RORoute.h"
      40             : #include "RORouteDef.h"
      41             : #include "ROVehicle.h"
      42             : #include "ROAbstractEdgeBuilder.h"
      43             : #include "RONet.h"
      44             : 
      45             : 
      46             : // ===========================================================================
      47             : // static member definitions
      48             : // ===========================================================================
      49             : RONet* RONet::myInstance = nullptr;
      50             : 
      51             : 
      52             : // ===========================================================================
      53             : // method definitions
      54             : // ===========================================================================
      55             : RONet*
      56     4274619 : RONet::getInstance(void) {
      57     4274619 :     if (myInstance != nullptr) {
      58     4274619 :         return myInstance;
      59             :     }
      60           0 :     throw ProcessError(TL("A network was not yet constructed."));
      61             : }
      62             : 
      63             : 
      64        5068 : RONet::RONet() :
      65        5068 :     myVehicleTypes(), myDefaultVTypeMayBeDeleted(true),
      66        5068 :     myDefaultPedTypeMayBeDeleted(true),
      67        5068 :     myDefaultBikeTypeMayBeDeleted(true),
      68        5068 :     myDefaultTaxiTypeMayBeDeleted(true),
      69        5068 :     myDefaultRailTypeMayBeDeleted(true),
      70        5068 :     myHaveActiveFlows(true),
      71        5068 :     myRoutesOutput(nullptr), myRouteAlternativesOutput(nullptr), myTypesOutput(nullptr),
      72        5068 :     myReadRouteNo(0), myDiscardedRouteNo(0), myWrittenRouteNo(0),
      73        5068 :     myHavePermissions(false),
      74        5068 :     myNumInternalEdges(0),
      75        5068 :     myErrorHandler(OptionsCont::getOptions().exists("ignore-errors")
      76        9412 :                    && OptionsCont::getOptions().getBool("ignore-errors") ? MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance()),
      77        5068 :     myKeepVTypeDist(OptionsCont::getOptions().exists("keep-vtype-distributions")
      78       13748 :                     && OptionsCont::getOptions().getBool("keep-vtype-distributions")),
      79        5068 :     myDoPTRouting(!OptionsCont::getOptions().exists("ptline-routing")
      80        8685 :                   || OptionsCont::getOptions().getBool("ptline-routing")),
      81       10136 :     myHasBidiEdges(false) {
      82        5068 :     if (myInstance != nullptr) {
      83           0 :         throw ProcessError(TL("A network was already constructed."));
      84             :     }
      85        5068 :     SUMOVTypeParameter* type = new SUMOVTypeParameter(DEFAULT_VTYPE_ID, SVC_PASSENGER);
      86        5068 :     type->onlyReferenced = true;
      87        5068 :     myVehicleTypes.add(type->id, type);
      88             : 
      89        5068 :     SUMOVTypeParameter* defPedType = new SUMOVTypeParameter(DEFAULT_PEDTYPE_ID, SVC_PEDESTRIAN);
      90        5068 :     defPedType->onlyReferenced = true;
      91        5068 :     defPedType->parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
      92        5068 :     myVehicleTypes.add(defPedType->id, defPedType);
      93             : 
      94        5068 :     SUMOVTypeParameter* defBikeType = new SUMOVTypeParameter(DEFAULT_BIKETYPE_ID, SVC_BICYCLE);
      95        5068 :     defBikeType->onlyReferenced = true;
      96        5068 :     defBikeType->parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
      97        5068 :     myVehicleTypes.add(defBikeType->id, defBikeType);
      98             : 
      99        5068 :     SUMOVTypeParameter* defTaxiType = new SUMOVTypeParameter(DEFAULT_TAXITYPE_ID, SVC_TAXI);
     100        5068 :     defTaxiType->onlyReferenced = true;
     101        5068 :     defTaxiType->parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
     102        5068 :     myVehicleTypes.add(defTaxiType->id, defTaxiType);
     103             : 
     104        5068 :     SUMOVTypeParameter* defRailType = new SUMOVTypeParameter(DEFAULT_RAILTYPE_ID, SVC_RAIL);
     105        5068 :     defRailType->onlyReferenced = true;
     106        5068 :     defRailType->parametersSet |= VTYPEPARS_VEHICLECLASS_SET;
     107        5068 :     myVehicleTypes.add(defRailType->id, defRailType);
     108             : 
     109        5068 :     myInstance = this;
     110        5068 : }
     111             : 
     112             : 
     113        9402 : RONet::~RONet() {
     114        5258 :     for (const auto& routables : myRoutables) {
     115         400 :         for (RORoutable* const r : routables.second) {
     116         200 :             const ROVehicle* const veh = dynamic_cast<const ROVehicle*>(r);
     117             :             // delete routes and the vehicle
     118         200 :             if (veh != nullptr && veh->getRouteDefinition()->getID()[0] == '!') {
     119         192 :                 if (!myRoutes.remove(veh->getRouteDefinition()->getID())) {
     120          76 :                     delete veh->getRouteDefinition();
     121             :                 }
     122             :             }
     123         200 :             delete r;
     124             :         }
     125             :     }
     126        5094 :     for (const RORoutable* const r : myPTVehicles) {
     127          36 :         const ROVehicle* const veh = dynamic_cast<const ROVehicle*>(r);
     128             :         // delete routes and the vehicle
     129          36 :         if (veh != nullptr && veh->getRouteDefinition()->getID()[0] == '!') {
     130          36 :             if (!myRoutes.remove(veh->getRouteDefinition()->getID())) {
     131           8 :                 delete veh->getRouteDefinition();
     132             :             }
     133             :         }
     134          36 :         delete r;
     135             :     }
     136             :     myRoutables.clear();
     137        5102 :     for (const auto& vTypeDist : myVTypeDistDict) {
     138          44 :         delete vTypeDist.second;
     139             :     }
     140       29634 : }
     141             : 
     142             : 
     143             : void
     144           1 : RONet::addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed) {
     145           1 :     myRestrictions[id][svc] = speed;
     146           1 : }
     147             : 
     148             : 
     149             : const std::map<SUMOVehicleClass, double>*
     150      308847 : RONet::getRestrictions(const std::string& id) const {
     151             :     std::map<std::string, std::map<SUMOVehicleClass, double> >::const_iterator i = myRestrictions.find(id);
     152      308847 :     if (i == myRestrictions.end()) {
     153             :         return nullptr;
     154             :     }
     155          10 :     return &i->second;
     156             : }
     157             : 
     158             : 
     159             : bool
     160      311257 : RONet::addEdge(ROEdge* edge) {
     161      311257 :     if (!myEdges.add(edge->getID(), edge)) {
     162          72 :         WRITE_ERRORF(TL("The edge '%' occurs at least twice."), edge->getID());
     163          24 :         delete edge;
     164          24 :         return false;
     165             :     }
     166      311233 :     if (edge->isInternal()) {
     167      148382 :         myNumInternalEdges += 1;
     168             :     }
     169             :     return true;
     170             : }
     171             : 
     172             : 
     173             : bool
     174        1205 : RONet::addDistrict(const std::string id, ROEdge* source, ROEdge* sink) {
     175             :     if (myDistricts.count(id) > 0) {
     176           0 :         WRITE_ERRORF(TL("The TAZ '%' occurs at least twice."), id);
     177           0 :         delete source;
     178           0 :         delete sink;
     179           0 :         return false;
     180             :     }
     181             :     sink->setFunction(SumoXMLEdgeFunc::CONNECTOR);
     182        1205 :     if (!addEdge(sink)) {
     183             :         return false;
     184             :     }
     185             :     source->setFunction(SumoXMLEdgeFunc::CONNECTOR);
     186        1205 :     if (!addEdge(source)) {
     187             :         return false;
     188             :     }
     189             :     sink->setOtherTazConnector(source);
     190             :     source->setOtherTazConnector(sink);
     191        2410 :     myDistricts[id] = std::make_pair(std::vector<std::string>(), std::vector<std::string>());
     192        1205 :     return true;
     193             : }
     194             : 
     195             : 
     196             : bool
     197        1087 : RONet::addDistrictEdge(const std::string tazID, const std::string edgeID, const bool isSource) {
     198             :     if (myDistricts.count(tazID) == 0) {
     199           0 :         WRITE_ERRORF(TL("The TAZ '%' is unknown."), tazID);
     200           0 :         return false;
     201             :     }
     202             :     ROEdge* edge = getEdge(edgeID);
     203        1087 :     if (edge == nullptr) {
     204           0 :         WRITE_ERRORF(TL("The edge '%' for TAZ '%' is unknown."), edgeID, tazID);
     205           0 :         return false;
     206             :     }
     207        1087 :     if (isSource) {
     208        1629 :         getEdge(tazID + "-source")->addSuccessor(edge);
     209         543 :         myDistricts[tazID].first.push_back(edgeID);
     210             :     } else {
     211        1632 :         edge->addSuccessor(getEdge(tazID + "-sink"));
     212         544 :         myDistricts[tazID].second.push_back(edgeID);
     213             :     }
     214             :     return true;
     215             : }
     216             : 
     217             : 
     218             : void
     219          76 : RONet::addJunctionTaz(ROAbstractEdgeBuilder& eb) {
     220         976 :     for (auto item : myNodes) {
     221             :         const std::string tazID = item.first;
     222           8 :         if (myDistricts.count(tazID) != 0) {
     223          24 :             WRITE_WARNINGF(TL("A TAZ with id '%' already exists. Not building junction TAZ."), tazID);
     224           8 :             continue;
     225             :         }
     226         892 :         const std::string sourceID = tazID + "-source";
     227         892 :         const std::string sinkID = tazID + "-sink";
     228             :         // sink must be added before source
     229         892 :         ROEdge* sink = eb.buildEdge(sinkID, nullptr, nullptr, 0);
     230         892 :         ROEdge* source = eb.buildEdge(sourceID, nullptr, nullptr, 0);
     231             :         sink->setOtherTazConnector(source);
     232             :         source->setOtherTazConnector(sink);
     233        1784 :         if (!addDistrict(tazID, source, sink)) {
     234             :             continue;
     235             :         }
     236         892 :         auto& district = myDistricts[tazID];
     237         892 :         const RONode* junction = item.second;
     238       10020 :         for (const ROEdge* edge : junction->getIncoming()) {
     239        9128 :             if (!edge->isInternal()) {
     240        2048 :                 const_cast<ROEdge*>(edge)->addSuccessor(sink);
     241        2048 :                 district.second.push_back(edge->getID());
     242             :             }
     243             :         }
     244       10020 :         for (const ROEdge* edge : junction->getOutgoing()) {
     245        9128 :             if (!edge->isInternal()) {
     246        2048 :                 source->addSuccessor(const_cast<ROEdge*>(edge));
     247        2048 :                 district.first.push_back(edge->getID());
     248             :             }
     249             :         }
     250             :     }
     251          76 : }
     252             : 
     253             : 
     254             : void
     255        3635 : RONet::setBidiEdges(const std::map<ROEdge*, std::string>& bidiMap) {
     256       15315 :     for (const auto& item : bidiMap) {
     257       11680 :         ROEdge* bidi = myEdges.get(item.second);
     258       11680 :         if (bidi == nullptr) {
     259           0 :             WRITE_ERRORF(TL("The bidi edge '%' is not known."), item.second);
     260             :         }
     261       11680 :         item.first->setBidiEdge(bidi);
     262       11680 :         myHasBidiEdges = true;
     263             :     }
     264        3635 : }
     265             : 
     266             : 
     267             : void
     268       73873 : RONet::addNode(RONode* node) {
     269       73873 :     if (!myNodes.add(node->getID(), node)) {
     270           0 :         WRITE_ERRORF(TL("The node '%' occurs at least twice."), node->getID());
     271           0 :         delete node;
     272             :     }
     273       73873 : }
     274             : 
     275             : 
     276             : void
     277        1796 : RONet::addStoppingPlace(const std::string& id, const SumoXMLTag category, SUMOVehicleParameter::Stop* stop) {
     278        3472 :     if (!myStoppingPlaces[category == SUMO_TAG_TRAIN_STOP ? SUMO_TAG_BUS_STOP : category].add(id, stop)) {
     279          12 :         WRITE_ERRORF(TL("The % '%' occurs at least twice."), toString(category), id);
     280           4 :         delete stop;
     281             :     }
     282        1796 : }
     283             : 
     284             : 
     285             : bool
     286      243675 : RONet::addRouteDef(RORouteDef* def) {
     287      243675 :     return myRoutes.add(def->getID(), def);
     288             : }
     289             : 
     290             : 
     291             : void
     292        2906 : RONet::openOutput(const OptionsCont& options) {
     293       11621 :     if (options.isSet("output-file") && options.getString("output-file") != "") {
     294        3701 :         myRoutesOutput = &OutputDevice::getDevice(options.getString("output-file"));
     295        2899 :         if (myRoutesOutput->isNull()) {
     296           1 :             myRoutesOutput = nullptr;
     297             :         } else {
     298        2898 :             myRoutesOutput->writeHeader<ROEdge>(SUMO_TAG_ROUTES);
     299        8694 :             myRoutesOutput->writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/routes_file.xsd");
     300             :         }
     301             :     }
     302       11379 :     if (options.exists("alternatives-output") && options.isSet("alternatives-output")
     303       13533 :             && !(options.exists("write-trips") && options.getBool("write-trips"))) {
     304        5060 :         myRouteAlternativesOutput = &OutputDevice::getDevice(options.getString("alternatives-output"));
     305        2598 :         if (myRouteAlternativesOutput->isNull()) {
     306          48 :             myRouteAlternativesOutput = nullptr;
     307             :         } else {
     308        2550 :             myRouteAlternativesOutput->writeHeader<ROEdge>(SUMO_TAG_ROUTES);
     309        7650 :             myRouteAlternativesOutput->writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/routes_file.xsd");
     310             :         }
     311             :     }
     312        5800 :     if (options.isSet("vtype-output")) {
     313          36 :         myTypesOutput = &OutputDevice::getDevice(options.getString("vtype-output"));
     314          26 :         myTypesOutput->writeHeader<ROEdge>(SUMO_TAG_ROUTES);
     315          78 :         myTypesOutput->writeAttr("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance").writeAttr("xsi:noNamespaceSchemaLocation", "http://sumo.dlr.de/xsd/routes_file.xsd");
     316             :     }
     317        2900 : }
     318             : 
     319             : 
     320             : void
     321        2647 : RONet::writeIntermodal(const OptionsCont& options, ROIntermodalRouter& router) const {
     322       10572 :     if (options.exists("intermodal-network-output") && options.isSet("intermodal-network-output")) {
     323          32 :         OutputDevice::createDeviceByOption("intermodal-network-output", "intermodal");
     324          48 :         router.writeNetwork(OutputDevice::getDevice(options.getString("intermodal-network-output")));
     325             :     }
     326       10580 :     if (options.exists("intermodal-weight-output") && options.isSet("intermodal-weight-output")) {
     327          16 :         OutputDevice::createDeviceByOption("intermodal-weight-output", "weights", "meandata_file.xsd");
     328           8 :         OutputDevice& dev = OutputDevice::getDeviceByOption("intermodal-weight-output");
     329           8 :         dev.openTag(SUMO_TAG_INTERVAL);
     330             :         dev.writeAttr(SUMO_ATTR_ID, "intermodalweights");
     331           8 :         dev.writeAttr(SUMO_ATTR_BEGIN, 0);
     332           8 :         dev.writeAttr(SUMO_ATTR_END, SUMOTime_MAX);
     333           8 :         router.writeWeights(dev);
     334          16 :         dev.closeTag();
     335             :     }
     336        2647 : }
     337             : 
     338             : 
     339             : void
     340        2905 : RONet::cleanup() {
     341             :     // end writing
     342        2905 :     if (myRoutesOutput != nullptr) {
     343        2898 :         myRoutesOutput->close();
     344             :     }
     345             :     // only if opened
     346        2905 :     if (myRouteAlternativesOutput != nullptr) {
     347        2550 :         myRouteAlternativesOutput->close();
     348             :     }
     349             :     // only if opened
     350        2905 :     if (myTypesOutput != nullptr) {
     351          26 :         myTypesOutput->close();
     352             :     }
     353             :     RouteCostCalculator<RORoute, ROEdge, ROVehicle>::cleanup();
     354             : #ifdef HAVE_FOX
     355        2905 :     if (myThreadPool.size() > 0) {
     356          38 :         myThreadPool.clear();
     357             :     }
     358             : #endif
     359        2905 : }
     360             : 
     361             : 
     362             : 
     363             : SUMOVTypeParameter*
     364      346992 : RONet::getVehicleTypeSecure(const std::string& id) {
     365             :     // check whether the type was already known
     366             :     SUMOVTypeParameter* type = myVehicleTypes.get(id);
     367      346992 :     if (id == DEFAULT_VTYPE_ID) {
     368      291197 :         myDefaultVTypeMayBeDeleted = false;
     369       55795 :     } else if (id == DEFAULT_PEDTYPE_ID) {
     370        2884 :         myDefaultPedTypeMayBeDeleted = false;
     371       52911 :     } else if (id == DEFAULT_BIKETYPE_ID) {
     372          12 :         myDefaultBikeTypeMayBeDeleted = false;
     373       52899 :     } else if (id == DEFAULT_TAXITYPE_ID) {
     374          48 :         myDefaultTaxiTypeMayBeDeleted = false;
     375       52851 :     } else if (id == DEFAULT_RAILTYPE_ID) {
     376           0 :         myDefaultRailTypeMayBeDeleted = false;
     377             :     }
     378      346992 :     if (type != nullptr) {
     379             :         return type;
     380             :     }
     381             :     VTypeDistDictType::iterator it2 = myVTypeDistDict.find(id);
     382        1478 :     if (it2 != myVTypeDistDict.end()) {
     383        1148 :         return it2->second->get();
     384             :     }
     385         330 :     if (id == "") {
     386             :         // ok, no vehicle type or an unknown type was given within the user input
     387             :         //  return the default type
     388           0 :         myDefaultVTypeMayBeDeleted = false;
     389             :         return myVehicleTypes.get(DEFAULT_VTYPE_ID);
     390             :     }
     391             :     return type;
     392             : }
     393             : 
     394             : 
     395             : bool
     396        2041 : RONet::checkVType(const std::string& id) {
     397        2041 :     if (id == DEFAULT_VTYPE_ID) {
     398          55 :         if (myDefaultVTypeMayBeDeleted) {
     399          55 :             myVehicleTypes.remove(id);
     400          55 :             myDefaultVTypeMayBeDeleted = false;
     401             :         } else {
     402             :             return false;
     403             :         }
     404        1986 :     } else if (id == DEFAULT_PEDTYPE_ID) {
     405           0 :         if (myDefaultPedTypeMayBeDeleted) {
     406           0 :             myVehicleTypes.remove(id);
     407           0 :             myDefaultPedTypeMayBeDeleted = false;
     408             :         } else {
     409             :             return false;
     410             :         }
     411        1986 :     } else if (id == DEFAULT_BIKETYPE_ID) {
     412           0 :         if (myDefaultBikeTypeMayBeDeleted) {
     413           0 :             myVehicleTypes.remove(id);
     414           0 :             myDefaultBikeTypeMayBeDeleted = false;
     415             :         } else {
     416             :             return false;
     417             :         }
     418        1986 :     } else if (id == DEFAULT_TAXITYPE_ID) {
     419           0 :         if (myDefaultTaxiTypeMayBeDeleted) {
     420           0 :             myVehicleTypes.remove(id);
     421           0 :             myDefaultTaxiTypeMayBeDeleted = false;
     422             :         } else {
     423             :             return false;
     424             :         }
     425        1986 :     } else if (id == DEFAULT_RAILTYPE_ID) {
     426           0 :         if (myDefaultRailTypeMayBeDeleted) {
     427           0 :             myVehicleTypes.remove(id);
     428           0 :             myDefaultRailTypeMayBeDeleted = false;
     429             :         } else {
     430             :             return false;
     431             :         }
     432             :     } else {
     433        1986 :         if (myVehicleTypes.get(id) != 0 || myVTypeDistDict.find(id) != myVTypeDistDict.end()) {
     434           0 :             return false;
     435             :         }
     436             :     }
     437             :     return true;
     438             : }
     439             : 
     440             : 
     441             : bool
     442        1997 : RONet::addVehicleType(SUMOVTypeParameter* type) {
     443        1997 :     if (checkVType(type->id)) {
     444        1997 :         myVehicleTypes.add(type->id, type);
     445             :     } else {
     446           0 :         WRITE_ERRORF(TL("The vehicle type '%' occurs at least twice."), type->id);
     447           0 :         delete type;
     448           0 :         return false;
     449             :     }
     450        1997 :     return true;
     451             : }
     452             : 
     453             : 
     454             : bool
     455          44 : RONet::addVTypeDistribution(const std::string& id, RandomDistributor<SUMOVTypeParameter*>* vehTypeDistribution) {
     456          44 :     if (checkVType(id)) {
     457          44 :         myVTypeDistDict[id] = vehTypeDistribution;
     458          44 :         return true;
     459             :     }
     460           0 :     delete vehTypeDistribution;
     461             :     return false;
     462             : }
     463             : 
     464             : 
     465             : bool
     466      276388 : RONet::addVehicle(const std::string& id, ROVehicle* veh) {
     467      276388 :     if (myVehIDs.find(id) == myVehIDs.end()) {
     468      552736 :         myVehIDs[id] = veh->getParameter().departProcedure == DepartDefinition::TRIGGERED ? -1 : veh->getDepartureTime();
     469             : 
     470      276384 :         if (veh->isPublicTransport()) {
     471          44 :             if (!veh->isPartOfFlow()) {
     472          36 :                 myPTVehicles.push_back(veh);
     473             :             }
     474          44 :             if (!myDoPTRouting) {
     475             :                 return true;
     476             :             }
     477             :         }
     478      276348 :         myRoutables[veh->getDepart()].push_back(veh);
     479      276348 :         return true;
     480             :     }
     481          12 :     WRITE_ERRORF(TL("Another vehicle with the id '%' exists."), id);
     482           4 :     delete veh;
     483             :     return false;
     484             : }
     485             : 
     486             : 
     487             : bool
     488         240 : RONet::knowsVehicle(const std::string& id) const {
     489         240 :     return myVehIDs.find(id) != myVehIDs.end();
     490             : }
     491             : 
     492             : SUMOTime
     493          20 : RONet::getDeparture(const std::string& vehID) const {
     494             :     auto it = myVehIDs.find(vehID);
     495          20 :     if (it != myVehIDs.end()) {
     496          20 :         return it->second;
     497             :     } else {
     498           0 :         throw ProcessError(TLF("Requesting departure time for unknown vehicle '%'", vehID));
     499             :     }
     500             : }
     501             : 
     502             : 
     503             : bool
     504        1941 : RONet::addFlow(SUMOVehicleParameter* flow, const bool randomize) {
     505        1941 :     if (randomize && flow->repetitionOffset >= 0) {
     506          12 :         myDepartures[flow->id].reserve(flow->repetitionNumber);
     507         132 :         for (int i = 0; i < flow->repetitionNumber; ++i) {
     508         120 :             myDepartures[flow->id].push_back(flow->depart + RandHelper::rand(flow->repetitionNumber * flow->repetitionOffset));
     509             :         }
     510          12 :         std::sort(myDepartures[flow->id].begin(), myDepartures[flow->id].end());
     511          12 :         std::reverse(myDepartures[flow->id].begin(), myDepartures[flow->id].end());
     512             :     }
     513        1941 :     const bool added = myFlows.add(flow->id, flow);
     514        1941 :     if (added) {
     515        1937 :         myHaveActiveFlows = true;
     516             :     }
     517        1941 :     return added;
     518             : }
     519             : 
     520             : 
     521             : bool
     522        1930 : RONet::addPerson(ROPerson* person) {
     523             :     if (myPersonIDs.count(person->getID()) == 0) {
     524             :         myPersonIDs.insert(person->getID());
     525        1930 :         myRoutables[person->getDepart()].push_back(person);
     526        1930 :         return true;
     527             :     }
     528           0 :     WRITE_ERRORF(TL("Another person with the id '%' exists."), person->getID());
     529           0 :     return false;
     530             : }
     531             : 
     532             : 
     533             : void
     534          56 : RONet::addContainer(const SUMOTime depart, const std::string desc) {
     535          56 :     myContainers.insert(std::pair<const SUMOTime, const std::string>(depart, desc));
     536          56 : }
     537             : 
     538             : 
     539             : void
     540       13396 : RONet::checkFlows(SUMOTime time, MsgHandler* errorHandler) {
     541       13396 :     myHaveActiveFlows = false;
     542       51561 :     for (const auto& i : myFlows) {
     543       38165 :         SUMOVehicleParameter* const pars = i.second;
     544       38165 :         if (pars->line != "" && !myDoPTRouting) {
     545         546 :             continue;
     546             :         }
     547       37619 :         if (pars->repetitionProbability > 0) {
     548         108 :             if (pars->repetitionEnd > pars->depart && pars->repetitionsDone < pars->repetitionNumber) {
     549          96 :                 myHaveActiveFlows = true;
     550             :             }
     551             :             const SUMOTime origDepart = pars->depart;
     552        1020 :             while (pars->depart < time && pars->repetitionsDone < pars->repetitionNumber) {
     553         928 :                 if (pars->repetitionEnd <= pars->depart) {
     554             :                     break;
     555             :                 }
     556             :                 // only call rand if all other conditions are met
     557         912 :                 if (RandHelper::rand() < (pars->repetitionProbability * TS)) {
     558         168 :                     SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
     559         336 :                     newPars->id = pars->id + "." + toString(pars->repetitionsDone);
     560         168 :                     newPars->depart = pars->depart;
     561         168 :                     for (std::vector<SUMOVehicleParameter::Stop>::iterator stop = newPars->stops.begin(); stop != newPars->stops.end(); ++stop) {
     562           0 :                         if (stop->until >= 0) {
     563           0 :                             stop->until += pars->depart - origDepart;
     564             :                         }
     565             :                     }
     566         168 :                     pars->repetitionsDone++;
     567             :                     // try to build the vehicle
     568         168 :                     const SUMOVTypeParameter* type = getVehicleTypeSecure(pars->vtypeid);
     569         168 :                     if (type == nullptr) {
     570          32 :                         type = getVehicleTypeSecure(DEFAULT_VTYPE_ID);
     571         136 :                     } else if (!myKeepVTypeDist) {
     572             :                         // fix the type id in case we used a distribution
     573         136 :                         newPars->vtypeid = type->id;
     574             :                     }
     575         168 :                     const SUMOTime stopOffset = pars->routeid[0] == '!' ? pars->depart - origDepart : pars->depart;
     576         336 :                     RORouteDef* route = getRouteDef(pars->routeid)->copy("!" + newPars->id, stopOffset);
     577         168 :                     ROVehicle* veh = new ROVehicle(*newPars, route, type, this, errorHandler);
     578         168 :                     addVehicle(newPars->id, veh);
     579         168 :                     delete newPars;
     580             :                 }
     581         912 :                 pars->depart += DELTA_T;
     582             :             }
     583             :         } else {
     584       37511 :             SUMOTime depart = static_cast<SUMOTime>(pars->depart + pars->repetitionTotalOffset);
     585       72196 :             while (pars->repetitionsDone < pars->repetitionNumber && pars->repetitionEnd >= depart) {
     586       45973 :                 myHaveActiveFlows = true;
     587       45973 :                 depart = static_cast<SUMOTime>(pars->depart + pars->repetitionTotalOffset);
     588       45973 :                 if (myDepartures.find(pars->id) != myDepartures.end()) {
     589         132 :                     depart = myDepartures[pars->id].back();
     590             :                 }
     591       45973 :                 if (depart >= time + DELTA_T) {
     592             :                     break;
     593             :                 }
     594       34685 :                 if (myDepartures.find(pars->id) != myDepartures.end()) {
     595         120 :                     myDepartures[pars->id].pop_back();
     596             :                 }
     597       34685 :                 SUMOVehicleParameter* newPars = new SUMOVehicleParameter(*pars);
     598       69370 :                 newPars->id = pars->id + "." + toString(pars->repetitionsDone);
     599       34685 :                 newPars->depart = depart;
     600       34805 :                 for (std::vector<SUMOVehicleParameter::Stop>::iterator stop = newPars->stops.begin(); stop != newPars->stops.end(); ++stop) {
     601         120 :                     if (stop->until >= 0) {
     602           0 :                         stop->until += depart - pars->depart;
     603             :                     }
     604             :                 }
     605       34685 :                 pars->incrementFlow(1);
     606             :                 // try to build the vehicle
     607       34685 :                 const SUMOVTypeParameter* type = getVehicleTypeSecure(pars->vtypeid);
     608       34685 :                 if (type == nullptr) {
     609          62 :                     type = getVehicleTypeSecure(DEFAULT_VTYPE_ID);
     610             :                 } else {
     611             :                     // fix the type id in case we used a distribution
     612       34623 :                     newPars->vtypeid = type->id;
     613             :                 }
     614       34685 :                 const SUMOTime stopOffset = pars->routeid[0] == '!' ? depart - pars->depart : depart;
     615       69370 :                 RORouteDef* route = getRouteDef(pars->routeid)->copy("!" + newPars->id, stopOffset);
     616       34685 :                 ROVehicle* veh = new ROVehicle(*newPars, route, type, this, errorHandler);
     617       34685 :                 addVehicle(newPars->id, veh);
     618       34685 :                 delete newPars;
     619             :             }
     620             :         }
     621             :     }
     622       13396 : }
     623             : 
     624             : 
     625             : void
     626          20 : RONet::createBulkRouteRequests(const RORouterProvider& provider, const SUMOTime time, const bool removeLoops) {
     627             :     std::map<const int, std::vector<RORoutable*> > bulkVehs;
     628          30 :     for (RoutablesMap::const_iterator i = myRoutables.begin(); i != myRoutables.end(); ++i) {
     629          20 :         if (i->first >= time) {
     630             :             break;
     631             :         }
     632         590 :         for (RORoutable* const routable : i->second) {
     633         580 :             const ROEdge* const depEdge = routable->getDepartEdge();
     634         580 :             bulkVehs[depEdge->getNumericalID()].push_back(routable);
     635         580 :             RORoutable* const first = bulkVehs[depEdge->getNumericalID()].front();
     636         580 :             if (first->getMaxSpeed() != routable->getMaxSpeed()) {
     637           6 :                 WRITE_WARNINGF(TL("Bulking different maximum speeds ('%' and '%') may lead to suboptimal routes."), first->getID(), routable->getID());
     638             :             }
     639         580 :             if (first->getVClass() != routable->getVClass()) {
     640           6 :                 WRITE_WARNINGF(TL("Bulking different vehicle classes ('%' and '%') may lead to invalid routes."), first->getID(), routable->getID());
     641             :             }
     642             :         }
     643             :     }
     644             : #ifdef HAVE_FOX
     645             :     int workerIndex = 0;
     646             : #endif
     647          78 :     for (std::map<const int, std::vector<RORoutable*> >::const_iterator i = bulkVehs.begin(); i != bulkVehs.end(); ++i) {
     648             : #ifdef HAVE_FOX
     649          58 :         if (myThreadPool.size() > 0) {
     650             :             bool bulk = true;
     651         132 :             for (RORoutable* const r : i->second) {
     652         120 :                 myThreadPool.add(new RoutingTask(r, removeLoops, myErrorHandler), workerIndex);
     653         120 :                 if (bulk) {
     654          12 :                     myThreadPool.add(new BulkmodeTask(true), workerIndex);
     655             :                     bulk = false;
     656             :                 }
     657             :             }
     658          12 :             myThreadPool.add(new BulkmodeTask(false), workerIndex);
     659          12 :             workerIndex++;
     660          12 :             if (workerIndex == (int)myThreadPool.size()) {
     661             :                 workerIndex = 0;
     662             :             }
     663          12 :             continue;
     664          12 :         }
     665             : #endif
     666         506 :         for (RORoutable* const r : i->second) {
     667         460 :             r->computeRoute(provider, removeLoops, myErrorHandler);
     668         460 :             provider.setBulkMode(true);
     669             :         }
     670          46 :         provider.setBulkMode(false);
     671             :     }
     672          20 : }
     673             : 
     674             : 
     675             : SUMOTime
     676       19170 : RONet::saveAndRemoveRoutesUntil(OptionsCont& options, const RORouterProvider& provider,
     677             :                                 SUMOTime time) {
     678       19170 :     MsgHandler* mh = (options.getBool("ignore-errors") ?
     679       19170 :                       MsgHandler::getWarningInstance() : MsgHandler::getErrorInstance());
     680       19170 :     if (myHaveActiveFlows) {
     681       13396 :         checkFlows(time, mh);
     682             :     }
     683             :     SUMOTime lastTime = -1;
     684       19170 :     const bool removeLoops = options.getBool("remove-loops");
     685             : #ifdef HAVE_FOX
     686       38340 :     const int maxNumThreads = options.getInt("routing-threads");
     687             : #endif
     688       19170 :     if (myRoutables.size() != 0) {
     689       18476 :         if (options.getBool("bulk-routing")) {
     690             : #ifdef HAVE_FOX
     691          28 :             while ((int)myThreadPool.size() < maxNumThreads) {
     692           8 :                 new WorkerThread(myThreadPool, provider);
     693             :             }
     694             : #endif
     695          20 :             createBulkRouteRequests(provider, time, removeLoops);
     696             :         } else {
     697      179130 :             for (RoutablesMap::const_iterator i = myRoutables.begin(); i != myRoutables.end(); ++i) {
     698      176203 :                 if (i->first >= time) {
     699             :                     break;
     700             :                 }
     701      447426 :                 for (RORoutable* const routable : i->second) {
     702             : #ifdef HAVE_FOX
     703             :                     // add task
     704      277514 :                     if (maxNumThreads > 0) {
     705             :                         const int numThreads = (int)myThreadPool.size();
     706         836 :                         if (numThreads == 0) {
     707             :                             // This is the very first routing. Since at least the CHRouter needs initialization
     708             :                             // before it gets cloned, we do not do this in parallel
     709          32 :                             routable->computeRoute(provider, removeLoops, myErrorHandler);
     710          32 :                             new WorkerThread(myThreadPool, provider);
     711             :                         } else {
     712             :                             // add thread if necessary
     713         804 :                             if (numThreads < maxNumThreads && myThreadPool.isFull()) {
     714          18 :                                 new WorkerThread(myThreadPool, provider);
     715             :                             }
     716         804 :                             myThreadPool.add(new RoutingTask(routable, removeLoops, myErrorHandler));
     717             :                         }
     718         836 :                         continue;
     719         836 :                     }
     720             : #endif
     721      276678 :                     routable->computeRoute(provider, removeLoops, myErrorHandler);
     722             :                 }
     723             :             }
     724             :         }
     725             : #ifdef HAVE_FOX
     726        9222 :         myThreadPool.waitAll();
     727             : #endif
     728             :     }
     729             :     // write all vehicles (and additional structures)
     730      189124 :     while (myRoutables.size() != 0 || myContainers.size() != 0) {
     731             :         // get the next vehicle, person or container
     732             :         RoutablesMap::iterator routables = myRoutables.begin();
     733      176263 :         const SUMOTime routableTime = routables == myRoutables.end() ? SUMOTime_MAX : routables->first;
     734             :         ContainerMap::iterator container = myContainers.begin();
     735      176263 :         const SUMOTime containerTime = container == myContainers.end() ? SUMOTime_MAX : container->first;
     736             :         // check whether it shall not yet be computed
     737      176263 :         if (routableTime >= time && containerTime >= time) {
     738             :             lastTime = MIN2(routableTime, containerTime);
     739             :             break;
     740             :         }
     741             :         const SUMOTime minTime = MIN2(routableTime, containerTime);
     742      169970 :         if (routableTime == minTime) {
     743             :             // check whether to print the output
     744      169922 :             if (lastTime != routableTime && lastTime != -1) {
     745             :                 // report writing progress
     746      163720 :                 if (options.getInt("stats-period") >= 0 && ((int)routableTime % options.getInt("stats-period")) == 0) {
     747           0 :                     WRITE_MESSAGE("Read: " + toString(myVehIDs.size()) + ",  Discarded: " + toString(myDiscardedRouteNo) + ",  Written: " + toString(myWrittenRouteNo));
     748             :                 }
     749             :             }
     750             :             lastTime = routableTime;
     751      448000 :             for (const RORoutable* const r : routables->second) {
     752             :                 // ok, check whether it has been routed
     753      278078 :                 if (r->getRoutingSuccess()) {
     754             :                     // write the route
     755      274630 :                     r->write(myRoutesOutput, myRouteAlternativesOutput, myTypesOutput, options);
     756      274630 :                     myWrittenRouteNo++;
     757             :                 } else {
     758        3448 :                     myDiscardedRouteNo++;
     759             :                 }
     760             :                 // we need to keep individual public transport vehicles but not the flows
     761      278078 :                 if (!r->isPublicTransport() || r->isPartOfFlow()) {
     762             :                     // delete routes and the vehicle
     763      278078 :                     const ROVehicle* const veh = dynamic_cast<const ROVehicle*>(r);
     764      278078 :                     if (veh != nullptr && veh->getRouteDefinition()->getID()[0] == '!') {
     765      276156 :                         if (!myRoutes.remove(veh->getRouteDefinition()->getID())) {
     766       36047 :                             delete veh->getRouteDefinition();
     767             :                         }
     768             :                     }
     769      278078 :                     delete r;
     770             :                 }
     771             :             }
     772             :             myRoutables.erase(routables);
     773             :         }
     774      169970 :         if (containerTime == minTime) {
     775          48 :             myRoutesOutput->writePreformattedTag(container->second);
     776          48 :             if (myRouteAlternativesOutput != nullptr) {
     777             :                 myRouteAlternativesOutput->writePreformattedTag(container->second);
     778             :             }
     779             :             myContainers.erase(container);
     780             :         }
     781             :     }
     782       19154 :     return lastTime;
     783             : }
     784             : 
     785             : 
     786             : bool
     787       41270 : RONet::furtherStored() {
     788       41270 :     return myRoutables.size() > 0 || (myFlows.size() > 0 && myHaveActiveFlows) || myContainers.size() > 0;
     789             : }
     790             : 
     791             : 
     792             : int
     793         173 : RONet::getEdgeNumber() const {
     794         173 :     return myEdges.size();
     795             : }
     796             : 
     797             : 
     798             : int
     799           1 : RONet::getInternalEdgeNumber() const {
     800           1 :     return myNumInternalEdges;
     801             : }
     802             : 
     803             : 
     804             : ROEdge*
     805        7746 : RONet::getEdgeForLaneID(const std::string& laneID) const {
     806       15492 :     return getEdge(SUMOXMLDefinitions::getEdgeIDFromLane(laneID));
     807             : }
     808             : 
     809             : 
     810             : ROLane*
     811        1136 : RONet::getLane(const std::string& laneID) const {
     812        1136 :     int laneIndex = SUMOXMLDefinitions::getIndexFromLane(laneID);
     813        1136 :     return getEdgeForLaneID(laneID)->getLanes()[laneIndex];
     814             : }
     815             : 
     816             : 
     817             : void
     818         516 : RONet::adaptIntermodalRouter(ROIntermodalRouter& router) {
     819         516 :     double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
     820         792 :     for (const auto& stopType : myInstance->myStoppingPlaces) {
     821             :         // add access to all stopping places
     822         276 :         const SumoXMLTag element = stopType.first;
     823        1882 :         for (const auto& stop : stopType.second) {
     824        1606 :             router.getNetwork()->addAccess(stop.first, myInstance->getEdgeForLaneID(stop.second->lane),
     825        1606 :                                            stop.second->startPos, stop.second->endPos, 0., element, false, taxiWait);
     826             :             // add access to all public transport stops
     827        1606 :             if (element == SUMO_TAG_BUS_STOP) {
     828        3190 :                 for (const auto& a : stop.second->accessPos) {
     829        1604 :                     router.getNetwork()->addAccess(stop.first, myInstance->getEdgeForLaneID(std::get<0>(a)),
     830             :                                                    std::get<1>(a), std::get<1>(a), std::get<2>(a), SUMO_TAG_BUS_STOP, true, taxiWait);
     831             :                 }
     832             :             }
     833             :         }
     834             :     }
     835             :     // fill the public transport router with pre-parsed public transport lines
     836        1078 :     for (const auto& i : myInstance->myFlows) {
     837         562 :         if (i.second->line != "") {
     838         550 :             const RORouteDef* const route = myInstance->getRouteDef(i.second->routeid);
     839             :             const std::vector<SUMOVehicleParameter::Stop>* addStops = nullptr;
     840        1100 :             if (route != nullptr && route->getFirstRoute() != nullptr) {
     841             :                 addStops = &route->getFirstRoute()->getStops();
     842             :             }
     843         550 :             router.getNetwork()->addSchedule(*i.second, addStops);
     844             :         }
     845             :     }
     846         552 :     for (const RORoutable* const veh : myInstance->myPTVehicles) {
     847             :         // add single vehicles with line attribute which are not part of a flow
     848             :         // no need to add route stops here, they have been added to the vehicle before
     849          36 :         router.getNetwork()->addSchedule(veh->getParameter());
     850             :     }
     851             :     // add access to transfer from walking to taxi-use
     852         516 :     if ((router.getCarWalkTransfer() & ROIntermodalRouter::Network::TAXI_PICKUP_ANYWHERE) != 0) {
     853         728 :         for (const ROEdge* edge : ROEdge::getAllEdges()) {
     854         712 :             if ((edge->getPermissions() & SVC_PEDESTRIAN) != 0 && (edge->getPermissions() & SVC_TAXI) != 0) {
     855         288 :                 router.getNetwork()->addCarAccess(edge, SVC_TAXI, taxiWait);
     856             :             }
     857             :         }
     858             :     }
     859         516 : }
     860             : 
     861             : 
     862             : bool
     863     4256818 : RONet::hasPermissions() const {
     864     4256818 :     return myHavePermissions;
     865             : }
     866             : 
     867             : 
     868             : void
     869      248797 : RONet::setPermissionsFound() {
     870      248797 :     myHavePermissions = true;
     871      248797 : }
     872             : 
     873             : bool
     874          13 : RONet::hasLoadedEffort() const {
     875          46 :     for (const auto& item : myEdges) {
     876          42 :         if (item.second->hasStoredEffort()) {
     877             :             return true;
     878             :         }
     879             :     }
     880             :     return false;
     881             : }
     882             : 
     883             : const std::string
     884        1574 : RONet::getStoppingPlaceName(const std::string& id) const {
     885        1766 :     for (const auto& mapItem : myStoppingPlaces) {
     886             :         SUMOVehicleParameter::Stop* stop = mapItem.second.get(id);
     887        1574 :         if (stop != nullptr) {
     888             :             // see RONetHandler::parseStoppingPlace
     889             :             return stop->busstop;
     890             :         }
     891             :     }
     892           0 :     return "";
     893             : }
     894             : 
     895             : const std::string
     896        1454 : RONet::getStoppingPlaceElement(const std::string& id) const {
     897        1598 :     for (const auto& mapItem : myStoppingPlaces) {
     898             :         SUMOVehicleParameter::Stop* stop = mapItem.second.get(id);
     899        1454 :         if (stop != nullptr) {
     900             :             // see RONetHandler::parseStoppingPlace
     901             :             return stop->actType;
     902             :         }
     903             :     }
     904           0 :     return toString(SUMO_TAG_BUS_STOP);
     905             : }
     906             : 
     907             : 
     908             : #ifdef HAVE_FOX
     909             : // ---------------------------------------------------------------------------
     910             : // RONet::RoutingTask-methods
     911             : // ---------------------------------------------------------------------------
     912             : void
     913         924 : RONet::RoutingTask::run(MFXWorkerThread* context) {
     914         924 :     myRoutable->computeRoute(*static_cast<WorkerThread*>(context), myRemoveLoops, myErrorHandler);
     915         924 : }
     916             : #endif
     917             : 
     918             : 
     919             : /****************************************************************************/

Generated by: LCOV version 1.14