LCOV - code coverage report
Current view: top level - src/microsim - MSRoute.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.6 % 146 141
Test Date: 2025-12-06 15:35:27 Functions: 92.3 % 26 24

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2002-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    MSRoute.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Friedemann Wesner
      17              : /// @author  Michael Behrisch
      18              : /// @author  Jakob Erdmann
      19              : /// @date    Sept 2002
      20              : ///
      21              : // A vehicle route
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <cassert>
      26              : #include <algorithm>
      27              : #include <limits>
      28              : #include <utils/common/FileHelpers.h>
      29              : #include <utils/common/RGBColor.h>
      30              : #include <utils/iodevices/OutputDevice.h>
      31              : #include "MSEdge.h"
      32              : #include "MSLane.h"
      33              : #include "MSRoute.h"
      34              : 
      35              : 
      36              : // ===========================================================================
      37              : // static member variables
      38              : // ===========================================================================
      39              : MSRoute::RouteDict MSRoute::myDict;
      40              : MSRoute::RouteDistDict MSRoute::myDistDict;
      41              : #ifdef HAVE_FOX
      42              : FXMutex MSRoute::myDictMutex(true);
      43              : #endif
      44              : 
      45              : 
      46              : // ===========================================================================
      47              : // member method definitions
      48              : // ===========================================================================
      49      2002824 : MSRoute::MSRoute(const std::string& id,
      50              :                  const ConstMSEdgeVector& edges,
      51              :                  const bool isPermanent, const RGBColor* const c,
      52              :                  const StopParVector& stops,
      53              :                  SUMOTime replacedTime,
      54      2002824 :                  int replacedIndex) :
      55      4005648 :     Named(id), myEdges(edges), myAmPermanent(isPermanent),
      56      2002824 :     myColor(c),
      57      2002824 :     myPeriod(0),
      58      2002824 :     myCosts(-1),
      59      2002824 :     mySavings(0),
      60      2002824 :     myReroute(false),
      61      2002824 :     myStops(stops),
      62      2002824 :     myReplacedTime(replacedTime),
      63      2002824 :     myReplacedIndex(replacedIndex)
      64      2002824 : {}
      65              : 
      66              : 
      67      3731860 : MSRoute::~MSRoute() {
      68      2002766 :     delete myColor;
      69      3731860 : }
      70              : 
      71              : 
      72              : MSRouteIterator
      73   1512433355 : MSRoute::begin() const {
      74   1512433355 :     return myEdges.begin();
      75              : }
      76              : 
      77              : 
      78              : MSRouteIterator
      79   4897186906 : MSRoute::end() const {
      80   4897186906 :     return myEdges.end();
      81              : }
      82              : 
      83              : 
      84              : int
      85     20055449 : MSRoute::size() const {
      86     20055449 :     return (int)myEdges.size();
      87              : }
      88              : 
      89              : 
      90              : const MSEdge*
      91     30126053 : MSRoute::getLastEdge() const {
      92              :     assert(myEdges.size() > 0);
      93     30126053 :     return myEdges.back();
      94              : }
      95              : 
      96              : 
      97              : const MSEdge*
      98        20903 : MSRoute::getFirstEdge() const {
      99              :     assert(myEdges.size() > 0);
     100        20903 :     return myEdges.front();
     101              : }
     102              : 
     103              : 
     104              : void
     105      1373070 : MSRoute::checkRemoval(bool force) const {
     106              : #ifdef HAVE_FOX
     107              :     FXMutexLock f(myDictMutex);
     108              : #endif
     109      1373070 :     if (!myAmPermanent || force) {
     110              :         myDict.erase(getID());
     111              :     }
     112      1373070 : }
     113              : 
     114              : 
     115              : bool
     116      1729428 : MSRoute::dictionary(const std::string& id, ConstMSRoutePtr route) {
     117              : #ifdef HAVE_FOX
     118              :     FXMutexLock f(myDictMutex);
     119              : #endif
     120      1729428 :     if (myDict.find(id) == myDict.end() && myDistDict.find(id) == myDistDict.end()) {
     121      1729010 :         myDict[id] = route;
     122      1729010 :         return true;
     123              :     }
     124              :     return false;
     125              : }
     126              : 
     127              : 
     128              : bool
     129         1778 : MSRoute::dictionary(const std::string& id, RandomDistributor<ConstMSRoutePtr>* const routeDist, const bool permanent) {
     130              : #ifdef HAVE_FOX
     131              :     FXMutexLock f(myDictMutex);
     132              : #endif
     133         1778 :     if (myDict.find(id) == myDict.end() && myDistDict.find(id) == myDistDict.end()) {
     134         1778 :         myDistDict[id] = std::make_pair(routeDist, permanent);
     135         1778 :         return true;
     136              :     }
     137              :     return false;
     138              : }
     139              : 
     140              : 
     141              : ConstMSRoutePtr
     142      5506191 : MSRoute::dictionary(const std::string& id, SumoRNG* rng) {
     143              : #ifdef HAVE_FOX
     144              :     FXMutexLock f(myDictMutex);
     145              : #endif
     146              :     RouteDict::iterator it = myDict.find(id);
     147      5506191 :     if (it == myDict.end()) {
     148              :         RouteDistDict::iterator it2 = myDistDict.find(id);
     149       166909 :         if (it2 == myDistDict.end() || it2->second.first->getOverallProb() == 0) {
     150              :             return nullptr;
     151              :         }
     152         6379 :         return it2->second.first->get(rng);
     153              :     }
     154              :     return it->second;
     155              : }
     156              : 
     157              : 
     158              : bool
     159      4141924 : MSRoute::hasRoute(const std::string& id) {
     160              : #ifdef HAVE_FOX
     161              :     FXMutexLock f(myDictMutex);
     162              : #endif
     163      4141924 :     return myDict.find(id) != myDict.end();
     164              : }
     165              : 
     166              : 
     167              : RandomDistributor<ConstMSRoutePtr>*
     168        15680 : MSRoute::distDictionary(const std::string& id) {
     169              : #ifdef HAVE_FOX
     170              :     FXMutexLock f(myDictMutex);
     171              : #endif
     172              :     RouteDistDict::iterator it2 = myDistDict.find(id);
     173        15680 :     if (it2 == myDistDict.end()) {
     174              :         return nullptr;
     175              :     }
     176         2182 :     return it2->second.first;
     177              : }
     178              : 
     179              : 
     180              : void
     181        38777 : MSRoute::clear() {
     182              : #ifdef HAVE_FOX
     183              :     FXMutexLock f(myDictMutex);
     184              : #endif
     185        39211 :     for (RouteDistDict::iterator i = myDistDict.begin(); i != myDistDict.end(); ++i) {
     186          868 :         delete i->second.first;
     187              :     }
     188              :     myDistDict.clear();
     189              :     myDict.clear();
     190        38777 : }
     191              : 
     192              : 
     193              : void
     194       475244 : MSRoute::checkDist(const std::string& id) {
     195              : #ifdef HAVE_FOX
     196              :     FXMutexLock f(myDictMutex);
     197              : #endif
     198              :     RouteDistDict::iterator it = myDistDict.find(id);
     199       475244 :     if (it != myDistDict.end() && !it->second.second) {
     200         4373 :         for (ConstMSRoutePtr rp : it->second.first->getVals()) {
     201              :             const MSRoute& r = *rp;
     202         3029 :             r.checkRemoval();
     203              :         }
     204         2688 :         delete it->second.first;
     205              :         myDistDict.erase(it);
     206              :     }
     207       475244 : }
     208              : 
     209              : 
     210              : void
     211          305 : MSRoute::insertIDs(std::vector<std::string>& into) {
     212              : #ifdef HAVE_FOX
     213              :     FXMutexLock f(myDictMutex);
     214              : #endif
     215          305 :     into.reserve(myDict.size() + myDistDict.size() + into.size());
     216         1083 :     for (RouteDict::const_iterator i = myDict.begin(); i != myDict.end(); ++i) {
     217          778 :         into.push_back((*i).first);
     218              :     }
     219         1185 :     for (RouteDistDict::const_iterator i = myDistDict.begin(); i != myDistDict.end(); ++i) {
     220          880 :         into.push_back((*i).first);
     221              :     }
     222          305 : }
     223              : 
     224              : 
     225              : int
     226       318627 : MSRoute::writeEdgeIDs(OutputDevice& os, int firstIndex, int lastIndex, bool withInternal, SUMOVehicleClass svc) const {
     227              :     //std::cout << SIMTIME << " writeEdgeIDs " << getID() << " first=" << firstIndex << " lastIndex=" << lastIndex << " edges=" << toString(myEdges) << "\n";
     228       318627 :     if (lastIndex < 0) {
     229       163551 :         lastIndex = (int)myEdges.size();
     230              :     }
     231              :     int internal = 0;
     232      1798477 :     for (int i = firstIndex; i < lastIndex; i++) {
     233      1479850 :         os << myEdges[i]->getID() << ' ';
     234      1479850 :         if (withInternal && i + 1 < lastIndex) {
     235            6 :             const MSEdge* next = myEdges[i + 1];
     236            6 :             const MSEdge* edge = myEdges[i]->getInternalFollowingEdge(next, svc);
     237              :             // Take into account non-internal lengths until next non-internal edge
     238           14 :             while (edge != nullptr && edge->isInternal()) {
     239            8 :                 os << edge->getID() << ' ';
     240            8 :                 internal++;
     241            8 :                 edge = edge->getInternalFollowingEdge(next, svc);
     242              :             }
     243              :         }
     244              :     }
     245       318627 :     return internal + lastIndex - firstIndex;
     246              : }
     247              : 
     248              : 
     249              : bool
     250            0 : MSRoute::containsAnyOf(const MSEdgeVector& edgelist) const {
     251              :     MSEdgeVector::const_iterator i = edgelist.begin();
     252            0 :     for (; i != edgelist.end(); ++i) {
     253            0 :         if (contains(*i)) {
     254              :             return true;
     255              :         }
     256              :     }
     257              :     return false;
     258              : }
     259              : 
     260              : 
     261              : const MSEdge*
     262            0 : MSRoute::operator[](int index) const {
     263            0 :     return myEdges[index];
     264              : }
     265              : 
     266              : 
     267              : void
     268          476 : MSRoute::dict_saveState(OutputDevice& out) {
     269              : #ifdef HAVE_FOX
     270              :     FXMutexLock f(myDictMutex);
     271              : #endif
     272         5731 :     for (RouteDict::iterator it = myDict.begin(); it != myDict.end(); ++it) {
     273              :         ConstMSRoutePtr r = (*it).second;
     274         5255 :         out.openTag(SUMO_TAG_ROUTE);
     275         5255 :         out.writeAttr(SUMO_ATTR_ID, r->getID());
     276         5255 :         out.writeAttr(SUMO_ATTR_STATE, r->myAmPermanent);
     277         5255 :         out.writeAttr(SUMO_ATTR_EDGES, r->myEdges);
     278         5255 :         if (r->myColor != nullptr) {
     279            2 :             out.writeAttr(SUMO_ATTR_COLOR, *r->myColor);
     280              :         }
     281         5319 :         for (auto stop : r->getStops()) {
     282           64 :             stop.write(out);
     283           64 :         }
     284        10510 :         out.closeTag();
     285              :     }
     286          492 :     for (const auto& item : myDistDict) {
     287           16 :         if (item.second.first->getVals().size() > 0) {
     288           12 :             out.openTag(SUMO_TAG_ROUTE_DISTRIBUTION).writeAttr(SUMO_ATTR_ID, item.first);
     289           12 :             out.writeAttr(SUMO_ATTR_STATE, item.second.second);
     290           12 :             std::ostringstream oss;
     291              :             bool space = false;
     292           32 :             for (const auto& route : item.second.first->getVals()) {
     293           20 :                 if (space) {
     294            8 :                     oss << " ";
     295              :                 }
     296              :                 oss << route->getID();
     297              :                 space = true;
     298              :             }
     299           12 :             out.writeAttr(SUMO_ATTR_ROUTES, oss.str());
     300           12 :             out.writeAttr(SUMO_ATTR_PROBS, item.second.first->getProbs());
     301           12 :             out.closeTag();
     302           12 :         }
     303              :     }
     304          476 : }
     305              : 
     306              : 
     307              : void
     308          186 : MSRoute::dict_clearState() {
     309              : #ifdef HAVE_FOX
     310              :     FXMutexLock f(myDictMutex);
     311              : #endif
     312              :     myDistDict.clear();
     313              :     myDict.clear();
     314          186 : }
     315              : 
     316              : 
     317              : double
     318        22454 : MSRoute::getDistanceBetween(double fromPos, double toPos,
     319              :                             const MSLane* fromLane, const MSLane* toLane, int routePosition) const {
     320              :     // std::cout << SIMTIME << " getDistanceBetween from=" << fromEdge->getID() << " to=" << toEdge->getID() << " fromPos=" << fromPos << " toPos=" << toPos << "\n";
     321              :     assert(fromPos >= 0. && fromPos <= fromLane->getLength());
     322              :     assert(toPos >= 0. && toPos <= toLane->getLength());
     323              :     assert(routePosition >= 0 && routePosition < (int)myEdges.size());
     324              :     assert(routePosition == 0 || !myEdges.front()->isInternal());
     325        22454 :     const MSEdge* fromEdge = &fromLane->getEdge();
     326        22454 :     const MSEdge* toEdge = &toLane->getEdge();
     327        22454 :     if (fromEdge == toEdge && fromPos <= toPos) {
     328        16901 :         return toPos - fromPos;
     329              :     }
     330              :     // TODO If fromEdge and toEdge are identical or both are internal and directly connected,
     331              :     // the code does not check whether they are in any relation to the route.
     332         5553 :     if (fromEdge->isInternal()) {
     333              :         double minDist = std::numeric_limits<double>::max();
     334         1016 :         for (const auto& via : fromEdge->getViaSuccessors()) {
     335          508 :             const MSEdge* const succ = via.second == nullptr ? via.first : via.second;
     336              :             assert(succ != nullptr);
     337              :             // std::cout << "  recurse fromSucc=" << succ->getID() << "\n";
     338          508 :             const double d = getDistanceBetween(0., toPos, succ->getLanes()[0], toLane, routePosition);
     339          508 :             if (d != std::numeric_limits<double>::max() && fromLane->getLength() - fromPos + d  < minDist) {
     340              :                 minDist = fromLane->getLength() - fromPos + d;
     341              :             }
     342              :         }
     343          508 :         return minDist;
     344              :     }
     345         5045 :     if (toEdge->isInternal()) {
     346         1814 :         const MSEdge* const pred = toEdge->getPredecessors().front();
     347              :         assert(pred != nullptr);
     348              :         // std::cout << "  recurse toPred=" << pred->getID() << "\n";
     349         1814 :         const double d = getDistanceBetween(fromPos, pred->getLength(), fromLane, pred->getLanes()[0], routePosition);
     350         1814 :         return d == std::numeric_limits<double>::max() ? d : toPos + d;
     351              :     }
     352         3231 :     ConstMSEdgeVector::const_iterator fromIt = std::find(myEdges.begin() + routePosition, myEdges.end(), fromEdge);
     353         3231 :     if (fromIt == myEdges.end()) {
     354              :         // start not contained in route
     355              :         return std::numeric_limits<double>::max();
     356              :     }
     357         3226 :     ConstMSEdgeVector::const_iterator toIt = std::find(fromIt + 1, myEdges.end(), toEdge);
     358         3226 :     if (toIt == myEdges.end()) {
     359              :         // destination not contained in route
     360              :         return std::numeric_limits<double>::max();
     361              :     }
     362         1780 :     return getDistanceBetween(fromPos, toPos, fromIt, toIt, true);
     363              : }
     364              : 
     365              : 
     366              : double
     367        71485 : MSRoute::getDistanceBetween(double fromPos, double toPos,
     368              :                             const MSRouteIterator& fromEdge, const MSRouteIterator& toEdge, bool includeInternal) const {
     369              :     bool isFirstIteration = true;
     370        71485 :     double distance = -fromPos;
     371        71485 :     MSRouteIterator it = fromEdge;
     372        71485 :     if (fromEdge == toEdge) {
     373              :         // destination position is on start edge
     374         7985 :         if (fromPos <= toPos) {
     375         7985 :             return toPos - fromPos;
     376              :         } else {
     377              :             // we cannot go backwards. Something is wrong here
     378              :             return std::numeric_limits<double>::max();
     379              :         }
     380        63500 :     } else if (fromEdge > toEdge) {
     381              :         // we don't visit the edge again
     382              :         return std::numeric_limits<double>::max();
     383              :     }
     384       542971 :     for (; it != end(); ++it) {
     385       535815 :         if (it == toEdge && !isFirstIteration) {
     386        56344 :             distance += toPos;
     387        56344 :             break;
     388              :         } else {
     389       479471 :             distance += (*it)->getLength();
     390       479471 :             if (includeInternal && (it + 1) != end()) {
     391              :                 // XXX the length may be wrong if there are parallel internal edges for different vClasses
     392       471810 :                 distance += (*it)->getInternalFollowingLengthTo(*(it + 1), SVC_IGNORING);
     393              :             }
     394              :         }
     395              :         isFirstIteration = false;
     396              :     }
     397              :     return distance;
     398              : }
     399              : 
     400              : 
     401              : const RGBColor&
     402     15012007 : MSRoute::getColor() const {
     403     15012007 :     if (myColor == nullptr) {
     404     14365948 :         return RGBColor::DEFAULT_COLOR;
     405              :     }
     406              :     return *myColor;
     407              : }
     408              : 
     409              : 
     410              : const StopParVector&
     411      9403217 : MSRoute::getStops() const {
     412      9403217 :     return myStops;
     413              : }
     414              : 
     415              : 
     416              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1