LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSStageWalking.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 90.7 % 248 225
Test Date: 2024-11-23 15:47:30 Functions: 95.2 % 21 20

            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    MSStageWalking.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @author  Laura Bieker
      19              : /// @date    Mon, 9 Jul 2001
      20              : ///
      21              : // A stage performing walking on a sequence of edges.
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <string>
      26              : #include <vector>
      27              : #include <utils/iodevices/OutputDevice.h>
      28              : #include <utils/options/OptionsCont.h>
      29              : #include <utils/common/ToString.h>
      30              : #include <utils/common/StringUtils.h>
      31              : #include <utils/geom/GeomHelper.h>
      32              : #include <utils/router/IntermodalNetwork.h>
      33              : #include <microsim/MSNet.h>
      34              : #include <microsim/MSEdge.h>
      35              : #include <microsim/MSLane.h>
      36              : #include <microsim/transportables/MSTransportableControl.h>
      37              : #include <microsim/MSInsertionControl.h>
      38              : #include <microsim/MSEventControl.h>
      39              : #include <microsim/MSVehicle.h>
      40              : #include <microsim/MSVehicleControl.h>
      41              : #include <microsim/MSStoppingPlace.h>
      42              : #include <microsim/MSRouteHandler.h>
      43              : #include <microsim/devices/MSDevice_Tripinfo.h>
      44              : #include <microsim/devices/MSDevice_Taxi.h>
      45              : #include <microsim/trigger/MSTriggeredRerouter.h>
      46              : #include "MSPModel_Striping.h"
      47              : #include "MSStageTrip.h"
      48              : #include "MSPerson.h"
      49              : #include "MSStageWalking.h"
      50              : 
      51              : 
      52              : // ===========================================================================
      53              : // static member definition
      54              : // ===========================================================================
      55              : bool MSStageWalking::myWarnedInvalidTripinfo = false;
      56              : 
      57              : 
      58              : // ===========================================================================
      59              : // method definitions
      60              : // ===========================================================================
      61       242244 : MSStageWalking::MSStageWalking(const std::string& personID,
      62              :                                const ConstMSEdgeVector& route,
      63              :                                MSStoppingPlace* toStop,
      64              :                                SUMOTime walkingTime, double speed,
      65              :                                double departPos, double arrivalPos, double departPosLat, int departLane,
      66       242244 :                                const std::string& routeID) :
      67              :     MSStageMoving(MSStageType::WALKING, route, routeID, toStop, speed, departPos, arrivalPos, departPosLat, departLane),
      68       242244 :     myWalkingTime(walkingTime),
      69       242244 :     myExitTimes(nullptr),
      70       242244 :     myInternalDistance(0) {
      71       242244 :     myDepartPos = SUMOVehicleParameter::interpretEdgePos(departPos, route.front()->getLength(), SUMO_ATTR_DEPARTPOS,
      72       484488 :                   "person '" + personID + "' walking from edge '" + route.front()->getID() + "'");
      73       242244 :     myArrivalPos = SUMOVehicleParameter::interpretEdgePos(arrivalPos, route.back()->getLength(), SUMO_ATTR_ARRIVALPOS,
      74       242244 :                    "person '" + personID + "' walking to edge '" + route.back()->getID() + "'");
      75       242244 :     if (walkingTime > 0) {
      76          103 :         mySpeed = computeAverageSpeed();
      77              :     }
      78       242244 : }
      79              : 
      80              : 
      81       484356 : MSStageWalking::~MSStageWalking() {
      82       242178 :     delete myExitTimes;
      83       484356 : }
      84              : 
      85              : 
      86              : MSStage*
      87        25638 : MSStageWalking::clone() const {
      88        25638 :     std::vector<const MSEdge*> route = myRoute;
      89        25638 :     double departPos = myDepartPos;
      90        25638 :     double arrivalPos = myArrivalPos;
      91        25638 :     int departLane = myDepartLane;
      92        25638 :     if (myRouteID != "" && MSRoute::distDictionary(myRouteID) != nullptr) {
      93          576 :         route = MSRoute::dictionary(myRouteID, MSRouteHandler::getParsingRNG())->getEdges();
      94          288 :         if (departPos > route[0]->getLength()) {
      95            0 :             WRITE_WARNINGF(TL("Adjusting departPos for cloned walk with routeDistribution '%'"), myRouteID);
      96            0 :             departPos = route[0]->getLength();
      97              :         }
      98          288 :         if (arrivalPos > route.back()->getLength()) {
      99            0 :             WRITE_WARNINGF(TL("Adjusting arrivalPos for cloned walk with routeDistribution '%'"), myRouteID);
     100            0 :             arrivalPos = route.back()->getLength();
     101              :         }
     102          288 :         if (departLane >= route[0]->getNumLanes()) {
     103            0 :             WRITE_WARNINGF(TL("Adjusting departLane for cloned walk with routeDistribution '%'"), myRouteID);
     104            0 :             departLane = route[0]->getNumLanes() - 1;
     105              :         }
     106              :     }
     107        25638 :     MSStage* clon = new MSStageWalking("dummyID", route, myDestinationStop, myWalkingTime, mySpeed, departPos, arrivalPos, myDepartPosLat, departLane, myRouteID);
     108        25638 :     clon->setParameters(*this);
     109        25638 :     return clon;
     110        25638 : }
     111              : 
     112              : 
     113              : void
     114       241609 : MSStageWalking::proceed(MSNet* net, MSTransportable* person, SUMOTime now, MSStage* previous) {
     115       241609 :     myDeparted = now;
     116       241609 :     myRouteStep = myRoute.begin();
     117       241609 :     myLastEdgeEntryTime = now;
     118       241609 :     if (myWalkingTime == 0) {
     119            0 :         if (!person->proceed(net, now)) {
     120            0 :             MSNet::getInstance()->getPersonControl().erase(person);
     121              :         }
     122            0 :         return;
     123              :     }
     124       241609 :     const OptionsCont& oc = OptionsCont::getOptions();
     125       241609 :     if (previous->getEdgePos(now) >= 0 && previous->getEdge() == *myRouteStep) {
     126              :         // we need to adapt to the arrival position of the vehicle unless we have an explicit access
     127       240916 :         myDepartPos = previous->getEdgePos(now);
     128       481832 :         if (oc.getString("pedestrian.model") == "jupedsim") {
     129            0 :             myDepartPosLat = previous->getEdgePosLat(now);
     130              :         }
     131       240916 :         if (myWalkingTime > 0) {
     132           77 :             mySpeed = computeAverageSpeed();
     133              :         }
     134              :     }
     135       241609 :     MSTransportableControl& pControl = net->getPersonControl();
     136       241609 :     myPState = pControl.getMovementModel()->add(person, this, now);
     137       241605 :     if (myPState == nullptr) {
     138            8 :         pControl.erase(person);
     139            8 :         return;
     140              :     }
     141       241597 :     if (previous->getStageType() != MSStageType::WALKING || previous->getEdge() != getEdge()) {
     142              :         // we only need new move reminders if we are walking a different edge (else it is probably a rerouting)
     143       240086 :         activateEntryReminders(person, true);
     144              :     }
     145       483194 :     if (oc.getBool("vehroute-output.exit-times")) {
     146          126 :         myExitTimes = new std::vector<SUMOTime>();
     147              :     }
     148       241597 :     (*myRouteStep)->addTransportable(person);
     149              : }
     150              : 
     151              : 
     152              : void
     153         1572 : MSStageWalking::abort(MSTransportable*) {
     154         1572 :     MSNet::getInstance()->getPersonControl().getMovementModel()->remove(myPState);
     155         1572 : }
     156              : 
     157              : 
     158              : void
     159           19 : MSStageWalking::setSpeed(double speed) {
     160           19 :     mySpeed = speed;
     161           19 : }
     162              : 
     163              : 
     164              : double
     165          180 : MSStageWalking::computeAverageSpeed() const {
     166          180 :     return walkDistance() / STEPS2TIME(myWalkingTime + 1); // avoid systematic rounding errors
     167              : }
     168              : 
     169              : 
     170              : bool
     171      1095441 : MSPerson::isJammed() const {
     172      1095441 :     MSStageWalking* stage = dynamic_cast<MSStageWalking*>(getCurrentStage());
     173      1095441 :     if (stage != nullptr) {
     174      1095441 :         return stage->getPState()->isJammed();
     175              :     }
     176              :     return false;
     177              : }
     178              : 
     179              : 
     180              : double
     181       272638 : MSStageWalking::walkDistance(bool partial) const {
     182              :     double length = 0;
     183       272638 :     auto endIt = partial && myArrived < 0 ? myRouteStep + 1 : myRoute.end();
     184       738896 :     for (ConstMSEdgeVector::const_iterator i = myRoute.begin(); i != endIt; ++i) {
     185       466258 :         length += (*i)->getLength();
     186              :     }
     187       272638 :     if (myRoute.size() > 1 && MSNet::getInstance()->getPersonControl().getMovementModel()->usingInternalLanes()) {
     188       119005 :         if (myInternalDistance > 0) {
     189       106915 :             length += myInternalDistance;
     190              :         } else {
     191              :             // use lower bound for distance to pass the intersection
     192        48193 :             for (ConstMSEdgeVector::const_iterator i = myRoute.begin(); i != endIt - 1; ++i) {
     193        36103 :                 const MSEdge* fromEdge = *i;
     194        36103 :                 const MSEdge* toEdge = *(i + 1);
     195        36103 :                 const MSLane* from = getSidewalk<MSEdge, MSLane>(fromEdge);
     196        36103 :                 const MSLane* to = getSidewalk<MSEdge, MSLane>(toEdge);
     197              :                 Position fromPos;
     198              :                 Position toPos;
     199        36103 :                 if (from != nullptr && to != nullptr) {
     200        36103 :                     if (fromEdge->getToJunction() == toEdge->getFromJunction()) {
     201        36055 :                         fromPos = from->getShape().back();
     202        36055 :                         toPos = to->getShape().front();
     203           48 :                     } else if (fromEdge->getToJunction() == toEdge->getToJunction()) {
     204           26 :                         fromPos = from->getShape().back();
     205           26 :                         toPos = to->getShape().back();
     206           22 :                     } else if (fromEdge->getFromJunction() == toEdge->getFromJunction()) {
     207           10 :                         fromPos = from->getShape().front();
     208           10 :                         toPos = to->getShape().front();
     209           12 :                     } else if (fromEdge->getFromJunction() == toEdge->getToJunction()) {
     210           12 :                         fromPos = from->getShape().front();
     211           12 :                         toPos = to->getShape().back();
     212              :                     }
     213              :                     //std::cout << " from=" << from->getID() << " to=" << to->getID() << " junctionLength=" << fromPos.distanceTo2D(toPos) << "\n";
     214        36103 :                     length += fromPos.distanceTo2D(toPos);
     215              :                 }
     216              :             }
     217              :         }
     218              :     }
     219              :     // determine walking direction for depart and arrival
     220       272638 :     int dummy = 0;
     221       272638 :     const int departFwdArrivalDir = MSPModel::canTraverse(MSPModel::FORWARD, myRoute, dummy);
     222       272638 :     const int departBwdArrivalDir = MSPModel::canTraverse(MSPModel::BACKWARD, myRoute, dummy);
     223       272638 :     const bool mayStartForward = departFwdArrivalDir != MSPModel::UNDEFINED_DIRECTION;
     224       272638 :     const bool mayStartBackward = departBwdArrivalDir != MSPModel::UNDEFINED_DIRECTION;
     225       272638 :     const double arrivalPos = partial && myArrived < 0 ? getEdgePos(SIMSTEP) : myArrivalPos;
     226       272638 :     const double lengthFwd = (length - myDepartPos - (
     227              :                                   departFwdArrivalDir == MSPModel::BACKWARD
     228       272638 :                                   ? arrivalPos
     229       272638 :                                   : myRoute.back()->getLength() - arrivalPos));
     230       272638 :     const double lengthBwd = (length - (myRoute.front()->getLength() - myDepartPos) - (
     231              :                                   departBwdArrivalDir == MSPModel::BACKWARD
     232       272638 :                                   ? arrivalPos
     233       272638 :                                   : myRoute.back()->getLength() - arrivalPos));
     234              :     //std::cout << " length=" << length << " lengthFwd=" << lengthFwd << " lengthBwd=" << lengthBwd << " mayStartForward=" << mayStartForward << " mayStartBackward=" << mayStartBackward << "\n";
     235              : 
     236       272638 :     if (myRoute.size() == 1) {
     237       134008 :         if (myDepartPos > myArrivalPos) {
     238              :             length = lengthBwd;
     239              :         } else {
     240              :             length = lengthFwd;
     241              :         }
     242              :     } else {
     243       138630 :         if (mayStartForward && mayStartBackward) {
     244        10915 :             length = lengthFwd < lengthBwd ? lengthFwd : lengthBwd;
     245       127715 :         } else if (mayStartForward) {
     246              :             length = lengthFwd;
     247        47808 :         } else if (mayStartBackward) {
     248              :             length = lengthBwd;
     249              :         } else {
     250              :             length = lengthFwd;
     251              :         }
     252              :     }
     253              :     //std::cout << SIMTIME << " route=" << toString(myRoute)
     254              :     //    << " depPos=" << myDepartPos << " arPos=" << myArrivalPos
     255              :     //    << " dFwdADir=" << departFwdArrivalDir
     256              :     //    << " dBwdADir=" << departBwdArrivalDir
     257              :     //    << " lengthFwd=" << lengthFwd
     258              :     //    << " lengthBwd=" << lengthBwd
     259              :     //    << "\n";
     260              : 
     261       272638 :     return MAX2(POSITION_EPS, length);
     262              : }
     263              : 
     264              : 
     265              : SUMOTime
     266       108958 : MSStageWalking::getTimeLoss(const MSTransportable* transportable) const {
     267       108958 :     SUMOTime timeLoss = myArrived == -1 ? 0 : getDuration() - TIME2STEPS(walkDistance(true) / getMaxSpeed(transportable));
     268       108958 :     if (timeLoss < 0 && timeLoss > TIME2STEPS(-0.1)) {
     269              :         // avoid negative timeLoss due to rounding errors
     270              :         timeLoss = 0;
     271              :     }
     272       108958 :     return timeLoss;
     273              : }
     274              : 
     275              : 
     276              : void
     277        54479 : MSStageWalking::tripInfoOutput(OutputDevice& os, const MSTransportable* const person) const {
     278        54479 :     if (!myWarnedInvalidTripinfo && MSNet::getInstance()->getPersonControl().getMovementModel()->usingShortcuts()) {
     279            0 :         WRITE_WARNING(TL("The pedestrian model uses infrastructure which is not in the network, timeLoss and routeLength may be invalid."));
     280            0 :         myWarnedInvalidTripinfo = true;
     281              :     }
     282        54479 :     const double distance = walkDistance(true);
     283        54479 :     const double maxSpeed = getMaxSpeed(person);
     284        54479 :     const SUMOTime duration = myArrived - myDeparted;
     285        54479 :     const SUMOTime timeLoss = getTimeLoss(person);
     286        54479 :     MSDevice_Tripinfo::addPedestrianData(distance, duration, timeLoss);
     287        54479 :     os.openTag("walk");
     288       108958 :     os.writeAttr("depart", myDeparted >= 0 ? time2string(myDeparted) : "-1");
     289        54479 :     os.writeAttr("departPos", myDepartPos);
     290       108958 :     os.writeAttr("arrival", myArrived >= 0 ? time2string(myArrived) : "-1");
     291       108958 :     os.writeAttr("arrivalPos", myArrived >= 0 ? toString(myArrivalPos) : "-1");
     292       163431 :     os.writeAttr("duration", myDeparted < 0 ? "-1" :
     293        54473 :                  time2string(myArrived >= 0 ? duration : MSNet::getInstance()->getCurrentTimeStep() - myDeparted));
     294       108958 :     os.writeAttr("routeLength", myArrived >= 0 ? toString(distance) : "-1");
     295       108958 :     os.writeAttr("timeLoss", time2string(timeLoss));
     296        54479 :     os.writeAttr("maxSpeed", maxSpeed);
     297        54479 :     os.closeTag();
     298        54479 : }
     299              : 
     300              : 
     301              : void
     302         2136 : MSStageWalking::routeOutput(const bool /* isPerson */, OutputDevice& os, const bool withRouteLength, const MSStage* const /* previous */) const {
     303         2136 :     os.openTag("walk").writeAttr(SUMO_ATTR_EDGES, myRoute);
     304         2136 :     std::string comment = "";
     305         2136 :     if (myDestinationStop != nullptr) {
     306          310 :         os.writeAttr(toString(myDestinationStop->getElement()), myDestinationStop->getID());
     307          310 :         if (myDestinationStop->getMyName() != "") {
     308          186 :             comment =  " <!-- " + StringUtils::escapeXML(myDestinationStop->getMyName(), true) + " -->";
     309              :         }
     310         1826 :     } else if (wasSet(VEHPARS_ARRIVALPOS_SET)) {
     311          167 :         os.writeAttr(SUMO_ATTR_ARRIVALPOS, myArrivalPos);
     312              :     }
     313         2136 :     if (myWalkingTime > 0) {
     314            0 :         os.writeAttr(SUMO_ATTR_DURATION, time2string(myWalkingTime));
     315         2136 :     } else if (mySpeed > 0) {
     316           24 :         os.writeAttr(SUMO_ATTR_SPEED, mySpeed);
     317              :     }
     318         2136 :     if (withRouteLength) {
     319           36 :         if (myDeparted >= 0) {
     320           72 :             os.writeAttr("routeLength", walkDistance(true));
     321              :         } else {
     322            0 :             os.writeAttr("routeLength", "-1");
     323              :         }
     324              :     }
     325         2136 :     if (myExitTimes != nullptr) {
     326              :         std::vector<std::string> exits;
     327          444 :         for (SUMOTime t : *myExitTimes) {
     328          636 :             exits.push_back(time2string(t));
     329              :         }
     330          252 :         std::vector<std::string> missing(MAX2(0, (int)myRoute.size() - (int)myExitTimes->size()), "-1");
     331          126 :         exits.insert(exits.end(), missing.begin(), missing.end());
     332          126 :         os.writeAttr("exitTimes", exits);
     333          126 :         os.writeAttr(SUMO_ATTR_STARTED, myDeparted >= 0 ? time2string(myDeparted) : "-1");
     334          126 :         os.writeAttr(SUMO_ATTR_ENDED, myArrived >= 0 ? time2string(myArrived) : "-1");
     335          126 :     }
     336         4272 :     if (OptionsCont::getOptions().getBool("vehroute-output.cost")) {
     337          210 :         os.writeAttr(SUMO_ATTR_COST, getCosts());
     338              :     }
     339         2136 :     os.closeTag(comment);
     340         2136 : }
     341              : 
     342              : 
     343              : bool
     344       917301 : MSStageWalking::moveToNextEdge(MSTransportable* person, SUMOTime currentTime, int prevDir, MSEdge* nextInternal, const bool isReplay) {
     345       917301 :     ((MSEdge*)getEdge())->removeTransportable(person);
     346       917301 :     const MSLane* lane = getSidewalk<MSEdge, MSLane>(getEdge());
     347              :     const bool arrived = myRouteStep == myRoute.end() - 1;
     348       917301 :     if (lane != nullptr) {
     349       893839 :         const double tl = person->getVehicleType().getLength();
     350              :         const double lastPos = (arrived
     351       893839 :                                 ? (prevDir == MSPModel::FORWARD
     352       259590 :                                    ? getArrivalPos() + tl
     353        39953 :                                    : getArrivalPos() - tl)
     354       674202 :                                 : person->getPositionOnLane());
     355       893839 :         activateLeaveReminders(person, lane, lastPos, currentTime, arrived);
     356              :     }
     357       917301 :     if (myExitTimes != nullptr && nextInternal == nullptr) {
     358          318 :         myExitTimes->push_back(currentTime);
     359              :     }
     360              :     myMoveReminders.clear();
     361       917301 :     myLastEdgeEntryTime = currentTime;
     362              :     //std::cout << SIMTIME << " moveToNextEdge person=" << person->getID() << "\n";
     363       917301 :     if (myCurrentInternalEdge != nullptr) {
     364       363392 :         myInternalDistance += (myPState->getPathLength() == 0 ? myCurrentInternalEdge->getLength() : myPState->getPathLength());
     365              :     }
     366       917301 :     if (arrived) {
     367       219663 :         MSPerson* p = dynamic_cast<MSPerson*>(person);
     368       219663 :         if (!isReplay && p->hasInfluencer() && p->getInfluencer().isRemoteControlled()) {
     369            0 :             myCurrentInternalEdge = nextInternal;
     370            0 :             ((MSEdge*) getEdge())->addTransportable(person);
     371            0 :             return false;
     372              :         }
     373       219663 :         if (myDestinationStop != nullptr) {
     374        31139 :             myDestinationStop->addTransportable(person);
     375              :         }
     376       219663 :         if (isReplay) {
     377              :             // cannot do this in the replay device because the person might get deleted below
     378           40 :             MSNet::getInstance()->getPersonControl().getMovementModel()->remove(myPState);
     379              :         }
     380       219663 :         if (!person->proceed(MSNet::getInstance(), currentTime)) {
     381       213298 :             MSNet::getInstance()->getPersonControl().erase(person);
     382              :         }
     383              :         //std::cout << " end walk. myRouteStep=" << (*myRouteStep)->getID() << "\n";
     384       219663 :         return true;
     385              :     } else {
     386       697638 :         if (nextInternal == nullptr) {
     387              :             ++myRouteStep;
     388              :         }
     389       697638 :         myCurrentInternalEdge = nextInternal;
     390       697638 :         ((MSEdge*) getEdge())->addTransportable(person);
     391       697638 :         return false;
     392              :     }
     393              : }
     394              : 
     395              : 
     396              : void
     397       893839 : MSStageWalking::activateLeaveReminders(MSTransportable* person, const MSLane* lane, double lastPos, SUMOTime t, bool arrived) {
     398       893839 :     MSMoveReminder::Notification notification = arrived ? MSMoveReminder::NOTIFICATION_ARRIVED : MSMoveReminder::NOTIFICATION_JUNCTION;
     399       911567 :     for (MSMoveReminder* const rem : myMoveReminders) {
     400        17728 :         rem->updateDetector(*person, 0.0, lane->getLength(), myLastEdgeEntryTime, t, t, true);
     401        17728 :         rem->notifyLeave(*person, lastPos, notification);
     402              :     }
     403       893839 : }
     404              : 
     405              : 
     406              : void
     407       937285 : MSStageWalking::activateEntryReminders(MSTransportable* person, const bool isDepart) {
     408       937285 :     const MSLane* const nextLane = getSidewalk<MSEdge, MSLane>(getEdge());
     409       937285 :     if (nextLane != nullptr) {
     410       936980 :         for (MSMoveReminder* const rem : nextLane->getMoveReminders()) {
     411        38187 :             if (rem->notifyEnter(*person, isDepart ? MSMoveReminder::NOTIFICATION_DEPARTED : MSMoveReminder::NOTIFICATION_JUNCTION, nextLane)) {
     412        18852 :                 myMoveReminders.push_back(rem);
     413              :             }
     414              :         }
     415              :     }
     416      1874570 :     if (hasParameter("rerouter")) {
     417              :         double minDist = std::numeric_limits<double>::max();
     418              :         MSTriggeredRerouter* nearest = nullptr;
     419          190 :         for (MSMoveReminder* const rem : myMoveReminders) {
     420          120 :             MSTriggeredRerouter* rerouter = dynamic_cast<MSTriggeredRerouter*>(rem);
     421          120 :             if (rerouter != nullptr) {
     422           70 :                 const double dist2 = rerouter->getPosition().distanceSquaredTo2D(person->getPosition());
     423           70 :                 if (dist2 < minDist) {
     424              :                     nearest = rerouter;
     425              :                     minDist = dist2;
     426              :                 }
     427              :             }
     428              :         }
     429           70 :         if (nearest != nullptr) {
     430           70 :             nearest->triggerRouting(*person, MSMoveReminder::NOTIFICATION_JUNCTION);
     431              :         }
     432              :         // TODO maybe removal of the reminders? Or can we rely on movetonextedge to clean everything up?
     433              :     }
     434       937285 : }
     435              : 
     436              : 
     437              : int
     438       448660 : MSStageWalking::getRoutePosition() const {
     439       448660 :     return (int)(myRouteStep - myRoute.begin());
     440              : }
     441              : 
     442              : 
     443              : double
     444     60668706 : MSStageWalking::getMaxSpeed(const MSTransportable* const person) const {
     445     60668706 :     return mySpeed >= 0 ? mySpeed : person->getMaxSpeed();
     446              : }
     447              : 
     448              : std::string
     449            0 : MSStageWalking::getStageSummary(const bool /* isPerson */) const {
     450            0 :     const std::string dest = (getDestinationStop() == nullptr ?
     451            0 :                               " edge '" + getDestination()->getID() + "'" :
     452            0 :                               " stop '" + getDestinationStop()->getID() + "'" + (
     453            0 :                                   getDestinationStop()->getMyName() != "" ? " (" + getDestinationStop()->getMyName() + ")" : ""));
     454            0 :     return "walking to " + dest;
     455              : }
     456              : 
     457              : 
     458              : void
     459           19 : MSStageWalking::saveState(std::ostringstream& out) {
     460           38 :     out << " " << myDeparted << " " << (myRouteStep - myRoute.begin()) << " " << myLastEdgeEntryTime;
     461           19 :     myPState->saveState(out);
     462           19 : }
     463              : 
     464              : 
     465              : void
     466           24 : MSStageWalking::loadState(MSTransportable* transportable, std::istringstream& state) {
     467              :     int stepIdx;
     468           24 :     state >> myDeparted >> stepIdx >> myLastEdgeEntryTime;
     469           24 :     myRouteStep = myRoute.begin() + stepIdx;
     470           24 :     myPState = MSNet::getInstance()->getPersonControl().getMovementModel()->loadState(transportable, this, state);
     471           24 :     if (myPState->getLane() && !myPState->getLane()->isNormal()) {
     472            1 :         myCurrentInternalEdge = &myPState->getLane()->getEdge();
     473            1 :         myCurrentInternalEdge->addTransportable(transportable);
     474              :     } else {
     475           23 :         (*myRouteStep)->addTransportable(transportable);
     476              :     }
     477           24 : }
     478              : 
     479              : 
     480              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1