LCOV - code coverage report
Current view: top level - src/microsim/transportables - MSStageTrip.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.5 % 219 196
Test Date: 2026-04-16 16:39:47 Functions: 81.2 % 16 13

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 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    MSStageTrip.cpp
      15              : /// @author  Melanie Weber
      16              : /// @author  Andreas Kendziorra
      17              : /// @author  Michael Behrisch
      18              : /// @author  Jakob Erdmann
      19              : /// @date    Wed, 1 Jun 2022
      20              : ///
      21              : // An intermodal routing request (to be transformed into a sequence of walks and rides)
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #include <utils/common/StringTokenizer.h>
      26              : #include <utils/geom/GeomHelper.h>
      27              : #include <utils/options/OptionsCont.h>
      28              : #include <utils/vehicle/SUMOVehicleParameter.h>
      29              : #include <utils/router/PedestrianRouter.h>
      30              : #include <utils/router/IntermodalRouter.h>
      31              : #include <microsim/MSEdge.h>
      32              : #include <microsim/MSLane.h>
      33              : #include <microsim/MSNet.h>
      34              : #include <microsim/MSStoppingPlace.h>
      35              : #include <microsim/MSVehicleControl.h>
      36              : #include <microsim/devices/MSDevice_Taxi.h>
      37              : #include <microsim/transportables/MSStageDriving.h>
      38              : #include <microsim/transportables/MSStageWaiting.h>
      39              : #include <microsim/transportables/MSStageWalking.h>
      40              : #include <microsim/transportables/MSTransportable.h>
      41              : #include <microsim/transportables/MSPerson.h>
      42              : #include <microsim/transportables/MSStageTrip.h>
      43              : 
      44              : 
      45              : // ===========================================================================
      46              : // method definitions
      47              : // ===========================================================================
      48              : 
      49              : /* -------------------------------------------------------------------------
      50              : * MSStageTrip - methods
      51              : * ----------------------------------------------------------------------- */
      52       186864 : MSStageTrip::MSStageTrip(const MSEdge* origin, MSStoppingPlace* fromStop,
      53              :                          const MSEdge* destination, MSStoppingPlace* toStop,
      54              :                          const SUMOTime duration, const SVCPermissions modeSet,
      55              :                          const std::string& vTypes, const double speed, const double walkFactor,
      56              :                          const std::string& group,
      57       186864 :                          const double departPosLat, const bool hasArrivalPos, const double arrivalPos):
      58              :     MSStage(MSStageType::TRIP, destination, toStop, arrivalPos, 0.0, group),
      59       186864 :     myOrigin(origin),
      60       186864 :     myOriginStop(fromStop),
      61       186864 :     myDuration(duration),
      62       186864 :     myModeSet(modeSet),
      63       186864 :     myVTypes(vTypes),
      64       186864 :     mySpeed(speed),
      65       186864 :     myWalkFactor(walkFactor),
      66       186864 :     myDepartPosLat(departPosLat),
      67       186864 :     myHaveArrivalPos(hasArrivalPos) {
      68       186864 : }
      69              : 
      70              : 
      71       373718 : MSStageTrip::~MSStageTrip() {}
      72              : 
      73              : MSStage*
      74       178061 : MSStageTrip::clone() const {
      75       178061 :     MSStage* const clon = new MSStageTrip(myOrigin, const_cast<MSStoppingPlace*>(myOriginStop),
      76       178061 :                                           myDestination, myDestinationStop, myDuration,
      77       178061 :                                           myModeSet, myVTypes, mySpeed, myWalkFactor, myGroup,
      78       178061 :                                           myDepartPosLat, myHaveArrivalPos, myArrivalPos);
      79       178061 :     clon->setParameters(*this);
      80       178061 :     return clon;
      81              : }
      82              : 
      83              : 
      84              : Position
      85            0 : MSStageTrip::getPosition(SUMOTime /* now */) const {
      86              :     // may be called concurrently while the trip is still being routed
      87            0 :     return getEdgePosition(myOrigin, myDepartPos, ROADSIDE_OFFSET * (MSGlobals::gLefthand ? -1 : 1));
      88              : }
      89              : 
      90              : 
      91              : double
      92            0 : MSStageTrip::getAngle(SUMOTime /* now */) const {
      93              :     // may be called concurrently while the trip is still being routed
      94            0 :     return getEdgeAngle(myOrigin, myDepartPos) + M_PI / 2 * (MSGlobals::gLefthand ? -1 : 1);
      95              : }
      96              : 
      97              : 
      98              : const MSEdge*
      99       338723 : MSStageTrip::getEdge() const {
     100       338723 :     return myOrigin;
     101              : }
     102              : 
     103              : 
     104              : double
     105       330286 : MSStageTrip::getEdgePos(SUMOTime /* now */) const {
     106       330286 :     return myDepartPos;
     107              : }
     108              : 
     109              : 
     110              : std::vector<SUMOVehicle*>
     111       166566 : MSStageTrip::getVehicles(MSVehicleControl& vehControl, MSTransportable* transportable, const MSEdge* origin) {
     112              :     std::vector<SUMOVehicleParameter*> pars;
     113       333256 :     for (StringTokenizer st(myVTypes); st.hasNext();) {
     114          124 :         pars.push_back(new SUMOVehicleParameter());
     115          248 :         pars.back()->vtypeid = st.next();
     116          124 :         pars.back()->parametersSet |= VEHPARS_VTYPE_SET;
     117          124 :         pars.back()->departProcedure = DepartDefinition::TRIGGERED;
     118          248 :         pars.back()->id = transportable->getID() + "_" + toString(pars.size() - 1);
     119       166566 :     }
     120       166566 :     if (pars.empty()) {
     121       166446 :         if ((myModeSet & SVC_PASSENGER) != 0) {
     122         1589 :             pars.push_back(new SUMOVehicleParameter());
     123         3178 :             pars.back()->id = transportable->getID() + "_0";
     124         1589 :             pars.back()->departProcedure = DepartDefinition::TRIGGERED;
     125              :         }
     126       166446 :         if ((myModeSet & SVC_TAXI) != 0) {
     127          468 :             for (const auto& item : MSDevice_Taxi::getTaxiTypes()) {
     128          257 :                 pars.push_back(new SUMOVehicleParameter());
     129          257 :                 pars.back()->vtypeid = item.second;
     130          771 :                 pars.back()->id = transportable->getID() + "_taxi_" + item.second;
     131          257 :                 pars.back()->line = "taxi";
     132              :             }
     133              :         }
     134       166446 :         if ((myModeSet & SVC_BICYCLE) != 0) {
     135           37 :             pars.push_back(new SUMOVehicleParameter());
     136           37 :             pars.back()->vtypeid = DEFAULT_BIKETYPE_ID;
     137           74 :             pars.back()->id = transportable->getID() + "_b0";
     138           37 :             pars.back()->departProcedure = DepartDefinition::TRIGGERED;
     139              :         }
     140              :     }
     141       333132 :     ConstMSRoutePtr const routeDummy = std::make_shared<MSRoute>(transportable->getID() + "_0", ConstMSEdgeVector({ origin }), false, nullptr, StopParVector());
     142              :     std::vector<SUMOVehicle*> result;
     143       168573 :     for (SUMOVehicleParameter* vehPar : pars) {
     144         2007 :         const bool isTaxi = vehPar->line == "taxi" && (myModeSet & SVC_TAXI) != 0;
     145         2007 :         if (myDepartPos != 0) {
     146          143 :             vehPar->departPosProcedure = DepartPosDefinition::GIVEN;
     147          143 :             vehPar->departPos = myDepartPos;
     148          143 :             vehPar->parametersSet |= VEHPARS_DEPARTPOS_SET;
     149              :         }
     150         2007 :         vehPar->parametersSet |= VEHPARS_ARRIVALPOS_SET;
     151         2007 :         vehPar->arrivalPosProcedure = ArrivalPosDefinition::GIVEN;
     152         2007 :         vehPar->parametersSet |= VEHPARS_ARRIVALSPEED_SET;
     153         2007 :         vehPar->arrivalSpeedProcedure = ArrivalSpeedDefinition::GIVEN;
     154         2007 :         vehPar->arrivalSpeed = 0;
     155         2007 :         MSVehicleType* type = vehControl.getVType(vehPar->vtypeid);
     156         2007 :         if (type->getVehicleClass() != SVC_IGNORING && (origin->getPermissions() & type->getVehicleClass()) == 0 && !isTaxi) {
     157          120 :             WRITE_WARNINGF(TL("Ignoring vehicle type '%' when routing person '%' because it is not allowed on the start edge."), type->getID(), transportable->getID());
     158           40 :             delete vehPar;
     159              :         } else {
     160         3934 :             result.push_back(vehControl.buildVehicle(vehPar, routeDummy, type, !MSGlobals::gCheckRoutes));
     161              :         }
     162              :     }
     163       166566 :     if (result.empty()) {
     164              :         // walking only but may use access infrastructure
     165       164679 :         result.push_back(nullptr);
     166              :     }
     167       166566 :     return result;
     168       166566 : }
     169              : 
     170              : 
     171              : const std::string
     172       166566 : MSStageTrip::reroute(const SUMOTime time, MSTransportableRouter& router, MSTransportable* const transportable,
     173              :                      MSStage* previous, const MSEdge* origin, const MSEdge* destination, std::vector<MSStage*>& stages) {
     174       166566 :     if (origin->isTazConnector() && origin->getSuccessors().size() == 0) {
     175              :         // previous stage ended at a taz sink-edge
     176          299 :         origin = transportable->getNextStage(-1)->getDestination();
     177              :     }
     178       166566 :     MSVehicleControl& vehControl = MSNet::getInstance()->getVehicleControl();
     179              :     double minCost = std::numeric_limits<double>::max();
     180              :     std::vector<MSTransportableRouter::TripItem> minResult;
     181              :     SUMOVehicle* minVehicle = nullptr;
     182       333212 :     for (SUMOVehicle* vehicle : getVehicles(vehControl, transportable, origin)) {
     183              :         std::vector<MSTransportableRouter::TripItem> result;
     184       166646 :         double departPos = previous->getArrivalPos();
     185              :         MSStoppingPlace* const prevStop = previous->getDestinationStop();
     186       166646 :         if (MSGlobals::gUseMesoSim && prevStop != nullptr) {
     187          198 :             departPos = (prevStop->getBeginLanePosition() + prevStop->getEndLanePosition()) / 2.;
     188              :         }
     189       352905 :         if (router.compute(origin, destination, departPos, prevStop == nullptr ? "" : prevStop->getID(),
     190       302699 :                            myArrivalPos, myDestinationStop == nullptr ? "" : myDestinationStop->getID(),
     191       166646 :                            transportable->getMaxSpeed() * myWalkFactor, vehicle, transportable->getVTypeParameter(), myModeSet, time, result)) {
     192              :             double totalCost = 0;
     193       358561 :             for (const MSTransportableRouter::TripItem& item : result) {
     194       192005 :                 totalCost += item.cost;
     195              :             }
     196       166556 :             if (totalCost < minCost) {
     197              :                 minCost = totalCost;
     198              :                 minResult.swap(result);
     199              :                 std::swap(minVehicle, vehicle);
     200              :             }
     201              :         }
     202       166646 :         if (vehicle != nullptr) {
     203           87 :             vehControl.deleteVehicle(vehicle, true);
     204              :             vehControl.discountRoutingVehicle();
     205              :         }
     206       333212 :     }
     207       166566 :     if (minCost != std::numeric_limits<double>::max()) {
     208       166488 :         const bool isTaxi = minVehicle != nullptr && (myModeSet & SVC_TAXI) != 0 && minVehicle->getParameter().line == "taxi";
     209              :         bool carUsed = false;
     210       358379 :         for (std::vector<MSTransportableRouter::TripItem>::iterator it = minResult.begin(); it != minResult.end(); ++it) {
     211       191891 :             if (!it->edges.empty()) {
     212       172303 :                 MSStoppingPlace* bs = MSNet::getInstance()->getStoppingPlace(it->destStop);
     213       172303 :                 double localArrivalPos = bs != nullptr ? bs->getAccessPos(it->edges.back()) : it->arrivalPos;
     214       172303 :                 const MSEdge* const first = it->edges.front();
     215       172303 :                 const MSEdge* const rideOrigin = origin->isTazConnector() && stages.empty() ? first : nullptr;
     216       172303 :                 if (it + 1 == minResult.end() && myHaveArrivalPos) {
     217         5567 :                     localArrivalPos = myArrivalPos;
     218              :                 }
     219       172303 :                 if (it->line == "") {
     220              :                     // determine walk departPos
     221       167671 :                     double depPos = previous->getArrivalPos();
     222       167671 :                     if (previous->getDestinationStop() != nullptr) {
     223        22314 :                         depPos = previous->getDestinationStop()->getAccessPos(first, first->getLanes()[0]->getRNG());
     224       145357 :                     } else if (origin->isTazConnector()) {
     225              :                         // walk the whole length of the first edge
     226          105 :                         if (std::find(first->getPredecessors().begin(), first->getPredecessors().end(), origin) != first->getPredecessors().end()) {
     227              :                             depPos = 0;
     228              :                         } else {
     229              :                             depPos = first->getLength();
     230              :                         }
     231       145252 :                     } else if (previous->getDestination() != first) {
     232           52 :                         if ((previous->getDestination()->getToJunction() == first->getToJunction())
     233           52 :                                 || (previous->getDestination()->getFromJunction() == first->getToJunction())) {
     234              :                             depPos = first->getLength();
     235              :                         } else {
     236              :                             depPos = 0.;
     237              :                         }
     238              :                     }
     239       167671 :                     if (destination->isTazConnector()) {
     240              :                         // walk the whole length of the last edge
     241          913 :                         const MSEdge* last = it->edges.back();
     242          913 :                         if (std::find(last->getSuccessors().begin(), last->getSuccessors().end(), destination) != last->getSuccessors().end()) {
     243              :                             localArrivalPos = last->getLength();
     244              :                         } else {
     245              :                             localArrivalPos = 0;
     246              :                         }
     247              :                     }
     248       167671 :                     previous = new MSStageWalking(transportable->getID(), it->edges, bs, myDuration, mySpeed, depPos, localArrivalPos, myDepartPosLat);
     249       167671 :                     previous->setParameters(*this);
     250       167671 :                     previous->setCosts(it->cost);
     251              :                     previous->setTrip(this);
     252       167671 :                     stages.push_back(previous);
     253         4632 :                 } else if (isTaxi && it->line == minVehicle->getID()) {
     254          213 :                     const ConstMSEdgeVector& prevEdges = previous->getEdges();
     255          213 :                     if (prevEdges.size() >= 2 && previous->getDestinationStop() == nullptr) {
     256              :                         // determine walking direction and let the previous
     257              :                         // stage end after entering its final edge
     258            6 :                         const MSEdge* last = prevEdges.back();
     259            6 :                         const MSEdge* prev = prevEdges[prevEdges.size() - 2];
     260            6 :                         if (last->getFromJunction() == prev->getToJunction() || prev->getFromJunction() == last->getFromJunction()) {
     261              :                             previous->setArrivalPos(MIN2(last->getLength(), 10.0));
     262              :                         } else {
     263            6 :                             previous->setArrivalPos(MAX2(0.0, last->getLength() - 10));
     264              :                         }
     265              :                     }
     266          639 :                     previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ "taxi" }), myGroup);
     267          213 :                     previous->setParameters(*this);
     268          213 :                     previous->setCosts(it->cost);
     269              :                     previous->setTrip(this);
     270          213 :                     stages.push_back(previous);
     271         4632 :                 } else if (minVehicle != nullptr && it->line == minVehicle->getID()) {
     272         4605 :                     previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ it->line }));
     273         1535 :                     previous->setParameters(*this);
     274         1535 :                     previous->setCosts(it->cost);
     275              :                     previous->setTrip(this);
     276         1535 :                     stages.push_back(previous);
     277         1535 :                     minVehicle->replaceRouteEdges(it->edges, -1, 0, "person:" + transportable->getID(), true);
     278         1535 :                     minVehicle->setArrivalPos(localArrivalPos);
     279         1535 :                     const_cast<SUMOVehicleParameter&>(minVehicle->getParameter()).arrivalPos = localArrivalPos;
     280         1535 :                     vehControl.addVehicle(minVehicle->getID(), minVehicle);
     281              :                     carUsed = true;
     282              :                 } else {
     283         2884 :                     const std::string line = OptionsCont::getOptions().getBool("persontrip.ride-public-line") ? it->line : LINE_ANY;
     284         8652 :                     previous = new MSStageDriving(rideOrigin, it->edges.back(), bs, localArrivalPos, 0.0, std::vector<std::string>({ line }), myGroup, it->intended, TIME2STEPS(it->depart));
     285         2884 :                     previous->setParameters(*this);
     286         2884 :                     previous->setCosts(it->cost);
     287              :                     previous->setTrip(this);
     288              :                     stages.push_back(previous);
     289              :                 }
     290              :             }
     291              :         }
     292       166488 :         if (wasSet(VEHPARS_ARRIVALPOS_SET) && !stages.empty()) {
     293              :             // mark the last stage
     294         1181 :             stages.back()->markSet(VEHPARS_ARRIVALPOS_SET);
     295              :         }
     296              :         setCosts(minCost);
     297       166488 :         if (minVehicle != nullptr && (isTaxi || !carUsed)) {
     298          345 :             vehControl.deleteVehicle(minVehicle, true);
     299              :             vehControl.discountRoutingVehicle();
     300              :         }
     301              :     } else {
     302              :         // append stage so the GUI won't crash due to inconsistent state
     303           78 :         previous = new MSStageWalking(transportable->getID(), ConstMSEdgeVector({ origin, destination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat);
     304           78 :         previous->setParameters(*this);
     305           78 :         stages.push_back(previous);
     306           78 :         if (MSGlobals::gCheckRoutes) {  // if not pedestrians will teleport
     307          156 :             return "No connection found between " + getOriginDescription() + " and " + getDestinationDescription() + " for person '" + transportable->getID() + "'.";
     308              :         }
     309              :     }
     310       166514 :     if (stages.empty()) {
     311              :         // append stage so the GUI won't crash due to inconsistent state
     312           14 :         if (myOriginStop != nullptr && myOriginStop == myDestinationStop) {
     313           28 :             stages.push_back(new MSStageWaiting(destination, myDestinationStop, 0, -1, previous->getArrivalPos(), "sameStop", false));
     314              :         } else {
     315            0 :             stages.push_back(new MSStageWalking(transportable->getID(), ConstMSEdgeVector({ origin, destination }), myDestinationStop, myDuration, mySpeed, previous->getArrivalPos(), myArrivalPos, myDepartPosLat));
     316            0 :             if (MSGlobals::gCheckRoutes) {  // if not pedestrians will teleport
     317            0 :                 return "Empty route between " + getOriginDescription() + " and " + getDestinationDescription() + " for person '" + transportable->getID() + "'.";
     318              :             }
     319              :         }
     320              :     }
     321       166514 :     return "";
     322       166992 : }
     323              : 
     324              : 
     325              : const std::string
     326       166486 : MSStageTrip::setArrived(MSNet* net, MSTransportable* transportable, SUMOTime now, const bool vehicleArrived) {
     327       332972 :     MSStage::setArrived(net, transportable, now, vehicleArrived);
     328              :     std::vector<MSStage*> stages;
     329              :     std::string result;
     330       166486 :     if (transportable->getCurrentStageIndex() == 0) {
     331            0 :         myDepartPos = transportable->getParameter().departPos;
     332            0 :         if (transportable->getParameter().departPosProcedure == DepartPosDefinition::RANDOM) {
     333              :             // TODO we should probably use the rng of the lane here
     334            0 :             myDepartPos = RandHelper::rand(myOrigin->getLength());
     335              :         }
     336            0 :         MSStageWaiting start(myOrigin, myOriginStop, -1, transportable->getParameter().depart, myDepartPos, "start", true);
     337            0 :         result = reroute(transportable->getParameter().depart, net->getIntermodalRouter(0), transportable, &start, myOrigin, myDestination, stages);
     338            0 :     } else {
     339              :         MSStage* previous = transportable->getNextStage(-1);
     340       166486 :         myDepartPos = previous->getArrivalPos();
     341       332972 :         result = reroute(now, net->getIntermodalRouter(0), transportable, previous, myOrigin, myDestination, stages);
     342              :     }
     343              :     int idx = 1;
     344       338757 :     for (MSStage* stage : stages) {
     345       172271 :         transportable->appendStage(stage, idx++);
     346              :     }
     347       166486 :     return result;
     348       166486 : }
     349              : 
     350              : 
     351              : void
     352       166486 : MSStageTrip::proceed(MSNet* net, MSTransportable* transportable, SUMOTime now, MSStage* /* previous */) {
     353              :     // just skip the stage, every interesting happens in setArrived
     354       166486 :     transportable->proceed(net, now);
     355       166434 : }
     356              : 
     357              : 
     358              : std::string
     359           52 : MSStageTrip::getOriginDescription() const {
     360           52 :     return (myOriginStop != nullptr
     361          111 :             ? toString(myOriginStop->getElement()) + " '" + myOriginStop->getID()
     362           97 :             : "edge '" + myOrigin->getID()) + "'";
     363              : }
     364              : 
     365              : std::string
     366           52 : MSStageTrip::getDestinationDescription() const {
     367           52 :     return (myDestinationStop != nullptr
     368          119 :             ? toString(myDestinationStop->getElement()) + " '" + myDestinationStop->getID()
     369           89 :             : "edge '" + myDestination->getID()) + "'";
     370              : }
     371              : 
     372              : std::string
     373            0 : MSStageTrip::getStageSummary(const bool) const {
     374            0 :     return "trip from " + getOriginDescription() + " to " + getDestinationDescription();
     375              : }
     376              : 
     377              : void
     378         1604 : MSStageTrip::routeOutput(const bool /*isPerson*/, OutputDevice& os, const bool /*withRouteLength*/, const MSStage* const previous) const {
     379         1604 :     if (myArrived < 0) {
     380           10 :         const bool walkFactorSet = myWalkFactor != OptionsCont::getOptions().getFloat("persontrip.walkfactor");
     381           10 :         const bool groupSet = myGroup != OptionsCont::getOptions().getString("persontrip.default.group");
     382              :         // could still be a persontrip but most likely it was a walk in the input
     383           10 :         SumoXMLTag tag = myModeSet == 0 && !walkFactorSet && !groupSet ? SUMO_TAG_WALK : SUMO_TAG_PERSONTRIP;
     384           10 :         os.openTag(tag);
     385           10 :         if (previous == nullptr || previous->getStageType() == MSStageType::WAITING_FOR_DEPART) {
     386            4 :             os.writeAttr(SUMO_ATTR_FROM, myOrigin->getID());
     387              :         }
     388           10 :         if (myDestinationStop == nullptr) {
     389           10 :             os.writeAttr(SUMO_ATTR_TO, myDestination->getID());
     390           10 :             if (wasSet(VEHPARS_ARRIVALPOS_SET)) {
     391            6 :                 os.writeAttr(SUMO_ATTR_ARRIVALPOS, myArrivalPos);
     392              :             }
     393              :         } else {
     394            0 :             os.writeAttr(toString(myDestinationStop->getElement()), myDestinationStop->getID());
     395              :         }
     396              :         std::vector<std::string> modes;
     397           10 :         if ((myModeSet & SVC_PASSENGER) != 0) {
     398            4 :             modes.push_back("car");
     399              :         }
     400           10 :         if ((myModeSet & SVC_BICYCLE) != 0) {
     401            0 :             modes.push_back("bicycle");
     402              :         }
     403           10 :         if ((myModeSet & SVC_TAXI) != 0) {
     404            0 :             modes.push_back("taxi");
     405              :         }
     406           10 :         if ((myModeSet & SVC_BUS) != 0) {
     407            0 :             modes.push_back("public");
     408              :         }
     409           10 :         if (modes.size() > 0) {
     410            2 :             os.writeAttr(SUMO_ATTR_MODES, modes);
     411              :         }
     412           10 :         if (myVTypes.size() > 0) {
     413            0 :             os.writeAttr(SUMO_ATTR_VTYPES, myVTypes);
     414              :         }
     415           10 :         if (groupSet) {
     416            0 :             os.writeAttr(SUMO_ATTR_GROUP, myGroup);
     417              :         }
     418           10 :         if (walkFactorSet) {
     419            0 :             os.writeAttr(SUMO_ATTR_WALKFACTOR, myWalkFactor);
     420              :         }
     421           20 :         if (OptionsCont::getOptions().getBool("vehroute-output.cost")) {
     422            0 :             os.writeAttr(SUMO_ATTR_COST, getCosts());
     423              :         }
     424           10 :         os.closeTag();
     425           10 :     }
     426         1604 : }
     427              : 
     428              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1