LCOV - code coverage report
Current view: top level - src/router - ROPerson.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 237 247 96.0 %
Date: 2024-05-07 15:28:01 Functions: 17 17 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2002-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    ROPerson.cpp
      15             : /// @author  Daniel Krajzewicz
      16             : /// @author  Axel Wegener
      17             : /// @author  Michael Behrisch
      18             : /// @author  Jakob Erdmann
      19             : /// @date    Sept 2002
      20             : ///
      21             : // A vehicle as used by router
      22             : /****************************************************************************/
      23             : #include <config.h>
      24             : 
      25             : #include <string>
      26             : #include <iostream>
      27             : #include <utils/common/StringTokenizer.h>
      28             : #include <utils/common/ToString.h>
      29             : #include <utils/common/StringUtils.h>
      30             : #include <utils/common/MsgHandler.h>
      31             : #include <utils/geom/GeoConvHelper.h>
      32             : #include <utils/vehicle/SUMOVTypeParameter.h>
      33             : #include <utils/options/OptionsCont.h>
      34             : #include <utils/iodevices/OutputDevice.h>
      35             : #include "RORouteDef.h"
      36             : #include "RORoute.h"
      37             : #include "ROVehicle.h"
      38             : #include "ROHelper.h"
      39             : #include "RONet.h"
      40             : #include "ROLane.h"
      41             : #include "ROPerson.h"
      42             : 
      43             : const std::string ROPerson::PlanItem::UNDEFINED_STOPPING_PLACE;
      44             : 
      45             : // ===========================================================================
      46             : // method definitions
      47             : // ===========================================================================
      48        1930 : ROPerson::ROPerson(const SUMOVehicleParameter& pars, const SUMOVTypeParameter* type)
      49        1930 :     : RORoutable(pars, type) {
      50        1930 : }
      51             : 
      52             : 
      53        3860 : ROPerson::~ROPerson() {
      54        3996 :     for (PlanItem* const it : myPlan) {
      55        2066 :         delete it;
      56             :     }
      57        3860 : }
      58             : 
      59             : 
      60             : void
      61        1654 : ROPerson::addTrip(std::vector<PlanItem*>& plan, const std::string& id,
      62             :                   const ROEdge* const from, const ROEdge* const to, const SVCPermissions modeSet,
      63             :                   const std::string& vTypes,
      64             :                   const double departPos, const std::string& stopOrigin,
      65             :                   const double arrivalPos, const std::string& busStop,
      66             :                   double walkFactor, const std::string& group) {
      67        1654 :     PersonTrip* trip = new PersonTrip(from, to, modeSet, departPos, stopOrigin, arrivalPos, busStop, walkFactor, group);
      68        1654 :     RONet* net = RONet::getInstance();
      69        1654 :     SUMOVehicleParameter pars;
      70        1654 :     pars.departProcedure = DepartDefinition::TRIGGERED;
      71        1654 :     if (departPos != 0) {
      72         116 :         pars.departPosProcedure = DepartPosDefinition::GIVEN;
      73         116 :         pars.departPos = departPos;
      74         116 :         pars.parametersSet |= VEHPARS_DEPARTPOS_SET;
      75             :     }
      76        3348 :     for (StringTokenizer st(vTypes); st.hasNext();) {
      77          40 :         pars.vtypeid = st.next();
      78          40 :         pars.parametersSet |= VEHPARS_VTYPE_SET;
      79          40 :         const SUMOVTypeParameter* type = net->getVehicleTypeSecure(pars.vtypeid);
      80          40 :         if (type == nullptr) {
      81           0 :             delete trip;
      82           0 :             throw InvalidArgument("The vehicle type '" + pars.vtypeid + "' in a trip for person '" + id + "' is not known.");
      83             :         }
      84          80 :         pars.id = id + "_" + toString(trip->getVehicles().size());
      85          80 :         trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), type, net));
      86             :         // update modeset with routing-category vClass
      87          40 :         if (type->vehicleClass == SVC_BICYCLE) {
      88             :             trip->updateModes(SVC_BICYCLE);
      89             :         } else {
      90             :             trip->updateModes(SVC_PASSENGER);
      91             :         }
      92        1654 :     }
      93        1654 :     if (trip->getVehicles().empty()) {
      94        1614 :         if ((modeSet & SVC_PASSENGER) != 0) {
      95         580 :             pars.id = id + "_0";
      96        1160 :             trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), net->getVehicleTypeSecure(DEFAULT_VTYPE_ID), net));
      97             :         }
      98        1614 :         if ((modeSet & SVC_BICYCLE) != 0) {
      99          24 :             pars.id = id + "_b0";
     100             :             pars.vtypeid = DEFAULT_BIKETYPE_ID;
     101          12 :             pars.parametersSet |= VEHPARS_VTYPE_SET;
     102          24 :             trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), net->getVehicleTypeSecure(DEFAULT_BIKETYPE_ID), net));
     103             :         }
     104        1614 :         if ((modeSet & SVC_TAXI) != 0) {
     105             :             // add dummy taxi for routing (never added to output)
     106             :             pars.id = "taxi"; // id is written as 'line'
     107             :             pars.vtypeid = DEFAULT_TAXITYPE_ID;
     108          96 :             trip->addVehicle(new ROVehicle(pars, new RORouteDef("!" + pars.id, 0, false, false), net->getVehicleTypeSecure(DEFAULT_TAXITYPE_ID), net));
     109             :         }
     110             :     }
     111        1654 :     plan.push_back(trip);
     112        1654 : }
     113             : 
     114             : 
     115             : void
     116          56 : ROPerson::addRide(std::vector<PlanItem*>& plan, const ROEdge* const from, const ROEdge* const to, const std::string& lines,
     117             :                   double arrivalPos, const std::string& destStop, const std::string& group) {
     118          56 :     plan.push_back(new PersonTrip(to, destStop));
     119          56 :     plan.back()->addTripItem(new Ride(-1, from, to, lines, group, -1., arrivalPos, -1., destStop));
     120          56 : }
     121             : 
     122             : 
     123             : void
     124          72 : ROPerson::addWalk(std::vector<PlanItem*>& plan, const ConstROEdgeVector& edges, const double duration, const double speed, const double departPos, const double arrivalPos, const std::string& busStop) {
     125          72 :     if (plan.empty() || plan.back()->isStop()) {
     126          68 :         plan.push_back(new PersonTrip(edges.back(), busStop));
     127             :     }
     128          72 :     plan.back()->addTripItem(new Walk(-1, edges, -1., duration, speed, departPos, arrivalPos, busStop));
     129          72 : }
     130             : 
     131             : 
     132             : void
     133         124 : ROPerson::addStop(std::vector<PlanItem*>& plan, const SUMOVehicleParameter::Stop& stopPar, const ROEdge* const stopEdge) {
     134         124 :     plan.push_back(new Stop(stopPar, stopEdge));
     135         124 : }
     136             : 
     137             : 
     138             : void
     139         782 : ROPerson::Ride::saveAsXML(OutputDevice& os, const bool extended, OptionsCont& options) const {
     140         782 :     os.openTag(SUMO_TAG_RIDE);
     141         782 :     std::string comment = "";
     142        1564 :     if ((extended || options.getBool("write-costs")) && myCost >= 0.) {
     143          20 :         os.writeAttr(SUMO_ATTR_COST, myCost);
     144             :     }
     145         782 :     if (from != nullptr) {
     146             :         os.writeAttr(SUMO_ATTR_FROM, from->getID());
     147             :     }
     148         782 :     if (to != nullptr) {
     149             :         os.writeAttr(SUMO_ATTR_TO, to->getID());
     150             :     }
     151         782 :     if (destStop != "") {
     152         646 :         const std::string element = RONet::getInstance()->getStoppingPlaceElement(destStop);
     153             :         os.writeAttr(element, destStop);
     154         646 :         const std::string name = RONet::getInstance()->getStoppingPlaceName(destStop);
     155         646 :         if (name != "") {
     156         784 :             comment =  " <!-- " + name + " -->";
     157             :         }
     158         136 :     } else if (arrPos != 0 && arrPos != std::numeric_limits<double>::infinity()) {
     159          40 :         os.writeAttr(SUMO_ATTR_ARRIVALPOS, arrPos);
     160             :     }
     161         782 :     os.writeAttr(SUMO_ATTR_LINES, lines);
     162         782 :     if (group != "") {
     163             :         os.writeAttr(SUMO_ATTR_GROUP, group);
     164             :     }
     165         782 :     if (intended != "" && intended != lines) {
     166             :         os.writeAttr(SUMO_ATTR_INTENDED, intended);
     167             :     }
     168         782 :     if (depart >= 0) {
     169        1092 :         os.writeAttr(SUMO_ATTR_DEPART, time2string(depart));
     170             :     }
     171        1564 :     if (options.getBool("exit-times")) {
     172          24 :         os.writeAttr("started", time2string(getStart()));
     173          24 :         os.writeAttr("ended", time2string(getStart() + getDuration()));
     174             :     }
     175        1564 :     if (options.getBool("route-length") && length != -1) {
     176          24 :         os.writeAttr("routeLength", length);
     177             :     }
     178         782 :     os.closeTag(comment);
     179         782 : }
     180             : 
     181             : 
     182             : void
     183         184 : ROPerson::Stop::saveAsXML(OutputDevice& os, const bool /*extended*/, const bool /*asTrip*/, OptionsCont& /*options*/) const {
     184         184 :     stopDesc.write(os, false);
     185         184 :     std::string comment = "";
     186         304 :     for (std::string sID : stopDesc.getStoppingPlaceIDs()) {
     187         120 :         const std::string name = RONet::getInstance()->getStoppingPlaceName(sID);
     188         120 :         if (name != "") {
     189          48 :             comment += name + " ";
     190             :         }
     191         184 :     }
     192         184 :     if (comment != "") {
     193          48 :         comment =  " <!-- " + comment + " -->";
     194             :     }
     195         184 :     stopDesc.writeParams(os);
     196         184 :     os.closeTag(comment);
     197         184 : }
     198             : 
     199             : void
     200        2482 : ROPerson::Walk::saveAsXML(OutputDevice& os, const bool extended, OptionsCont& options) const {
     201        2482 :     os.openTag(SUMO_TAG_WALK);
     202        2482 :     std::string comment = "";
     203        4964 :     if ((extended || options.getBool("write-costs")) && myCost >= 0.) {
     204          32 :         os.writeAttr(SUMO_ATTR_COST, myCost);
     205             :     }
     206        2482 :     if (dur > 0) {
     207           0 :         os.writeAttr(SUMO_ATTR_DURATION, dur);
     208             :     }
     209        2482 :     if (v > 0) {
     210           0 :         os.writeAttr(SUMO_ATTR_SPEED, v);
     211             :     }
     212        2482 :     os.writeAttr(SUMO_ATTR_EDGES, edges);
     213        4964 :     if (options.getBool("exit-times")) {
     214          16 :         os.writeAttr("started", time2string(getStart()));
     215          16 :         os.writeAttr("ended", time2string(getStart() + getDuration()));
     216           8 :         if (!exitTimes.empty()) {
     217          16 :             os.writeAttr("exitTimes", exitTimes);
     218             :         }
     219             :     }
     220        4964 :     if (options.getBool("route-length")) {
     221           8 :         double length = 0;
     222          28 :         for (const ROEdge* roe : edges) {
     223          20 :             length += roe->getLength();
     224             :         }
     225          16 :         os.writeAttr("routeLength", length);
     226             :     }
     227        2482 :     if (destStop != "") {
     228         808 :         const std::string element = RONet::getInstance()->getStoppingPlaceElement(destStop);
     229             :         os.writeAttr(element, destStop);
     230         808 :         const std::string name = RONet::getInstance()->getStoppingPlaceName(destStop);
     231         808 :         if (name != "") {
     232        1124 :             comment =  " <!-- " + name + " -->";
     233             :         }
     234        1674 :     } else if (arr != 0 && arr != std::numeric_limits<double>::infinity()) {
     235         348 :         os.writeAttr(SUMO_ATTR_ARRIVALPOS, arr);
     236             :     }
     237        2482 :     os.closeTag(comment);
     238        2482 : }
     239             : 
     240             : ROPerson::PlanItem*
     241         192 : ROPerson::PersonTrip::clone() const {
     242         192 :     PersonTrip* result = new PersonTrip(from, to, modes, dep, stopOrigin, arr, stopDest, walkFactor, group);
     243         212 :     for (auto* item : myTripItems) {
     244          20 :         result->myTripItems.push_back(item->clone());
     245             :     }
     246         192 :     return result;
     247             : }
     248             : 
     249             : void
     250        2886 : ROPerson::PersonTrip::saveVehicles(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options) const {
     251        3094 :     for (ROVehicle* veh : myVehicles) {
     252         208 :         if (!RONet::getInstance()->knowsVehicle(veh->getID())) {
     253         200 :             veh->saveAsXML(os, typeos, asAlternatives, options);
     254             :         }
     255             :     }
     256        2886 : }
     257             : 
     258             : void
     259        2918 : ROPerson::PersonTrip::saveAsXML(OutputDevice& os, const bool extended, const bool asTrip, OptionsCont& options) const {
     260        2918 :     if ((asTrip || extended) && from != nullptr) {
     261         940 :         const bool writeGeoTrip = asTrip && options.getBool("write-trips.geo");
     262         916 :         os.openTag(SUMO_TAG_PERSONTRIP);
     263         916 :         if (writeGeoTrip) {
     264           8 :             Position fromPos = from->getLanes()[0]->getShape().positionAtOffset2D(getDepartPos());
     265           4 :             if (GeoConvHelper::getFinal().usingGeoProjection()) {
     266           0 :                 os.setPrecision(gPrecisionGeo);
     267           0 :                 GeoConvHelper::getFinal().cartesian2geo(fromPos);
     268             :                 os.writeAttr(SUMO_ATTR_FROMLONLAT, fromPos);
     269           0 :                 os.setPrecision(gPrecision);
     270             :             } else {
     271             :                 os.writeAttr(SUMO_ATTR_FROMXY, fromPos);
     272             :             }
     273             :         } else {
     274         912 :             os.writeAttr(SUMO_ATTR_FROM, from->getID());
     275             :         }
     276         916 :         if (writeGeoTrip) {
     277           8 :             Position toPos = to->getLanes()[0]->getShape().positionAtOffset2D(MIN2(getArrivalPos(), to->getLanes()[0]->getShape().length2D()));
     278           4 :             if (GeoConvHelper::getFinal().usingGeoProjection()) {
     279           0 :                 os.setPrecision(gPrecisionGeo);
     280           0 :                 GeoConvHelper::getFinal().cartesian2geo(toPos);
     281             :                 os.writeAttr(SUMO_ATTR_TOLONLAT, toPos);
     282           0 :                 os.setPrecision(gPrecision);
     283             :             } else {
     284             :                 os.writeAttr(SUMO_ATTR_TOXY, toPos);
     285             :             }
     286             :         } else {
     287         912 :             os.writeAttr(SUMO_ATTR_TO, to->getID());
     288             :         }
     289             :         std::vector<std::string> allowedModes;
     290         916 :         if ((modes & SVC_BUS) != 0) {
     291         592 :             allowedModes.push_back("public");
     292             :         }
     293         916 :         if ((modes & SVC_PASSENGER) != 0) {
     294         424 :             allowedModes.push_back("car");
     295             :         }
     296         916 :         if ((modes & SVC_TAXI) != 0) {
     297          96 :             allowedModes.push_back("taxi");
     298             :         }
     299         916 :         if ((modes & SVC_BICYCLE) != 0) {
     300          24 :             allowedModes.push_back("bicycle");
     301             :         }
     302         916 :         if (allowedModes.size() > 0) {
     303         964 :             os.writeAttr(SUMO_ATTR_MODES, toString(allowedModes));
     304             :         }
     305         916 :         if (!writeGeoTrip) {
     306         912 :             if (dep != 0 && dep != std::numeric_limits<double>::infinity()) {
     307          68 :                 os.writeAttr(SUMO_ATTR_DEPARTPOS, dep);
     308             :             }
     309         912 :             if (arr != 0 && arr != std::numeric_limits<double>::infinity()) {
     310         140 :                 os.writeAttr(SUMO_ATTR_ARRIVALPOS, arr);
     311             :             }
     312             :         }
     313        1832 :         if (getStopDest() != "") {
     314          84 :             os.writeAttr(SUMO_ATTR_BUS_STOP, getStopDest());
     315             :         }
     316         916 :         if (walkFactor != 1) {
     317         916 :             os.writeAttr(SUMO_ATTR_WALKFACTOR, walkFactor);
     318             :         }
     319         916 :         if (extended && myTripItems.size() != 0) {
     320             :             std::vector<double> costs;
     321        2172 :             for (const TripItem* const tripItem : myTripItems) {
     322        1284 :                 costs.push_back(tripItem->getCost());
     323             :             }
     324             :             os.writeAttr(SUMO_ATTR_COSTS, costs);
     325             :         }
     326         916 :         os.closeTag();
     327         916 :     } else {
     328        5266 :         for (const TripItem* const it : myTripItems) {
     329        3264 :             it->saveAsXML(os, extended, options);
     330             :         }
     331             :     }
     332        2918 : }
     333             : 
     334             : SUMOTime
     335        1934 : ROPerson::PersonTrip::getDuration() const {
     336             :     SUMOTime result = 0;
     337        5086 :     for (TripItem* tItem : myTripItems) {
     338        3152 :         result += tItem->getDuration();
     339             :     }
     340        1934 :     return result;
     341             : }
     342             : 
     343             : bool
     344        1802 : ROPerson::computeIntermodal(SUMOTime time, const RORouterProvider& provider,
     345             :                             const PersonTrip* const trip, const ROVehicle* const veh,
     346             :                             std::vector<TripItem*>& resultItems, MsgHandler* const errorHandler) {
     347        1802 :     const double speed = getMaxSpeed() * trip->getWalkFactor();
     348             :     std::vector<ROIntermodalRouter::TripItem> result;
     349        1802 :     provider.getIntermodalRouter().compute(trip->getOrigin(), trip->getDestination(),
     350             :                                            trip->getDepartPos(), trip->getStopOrigin(),
     351        1802 :                                            trip->getArrivalPos(), trip->getStopDest(),
     352             :                                            speed, veh, trip->getModes(), time, result);
     353             :     bool carUsed = false;
     354             :     SUMOTime start = time;
     355        4902 :     for (const ROIntermodalRouter::TripItem& item : result) {
     356        3100 :         if (!item.edges.empty()) {
     357        3016 :             if (item.line == "") {
     358             :                 double depPos = trip->getDepartPos(false);
     359             :                 double arrPos = trip->getArrivalPos(false);
     360        2326 :                 if (trip->getOrigin()->isTazConnector()) {
     361             :                     // walk the whole length of the first edge
     362         252 :                     const ROEdge* first = item.edges.front();
     363         252 :                     if (std::find(first->getPredecessors().begin(), first->getPredecessors().end(), trip->getOrigin()) != first->getPredecessors().end()) {
     364             :                         depPos = 0;
     365             :                     } else {
     366             :                         depPos = first->getLength();
     367             :                     }
     368             :                 }
     369        2326 :                 if (trip->getDestination()->isTazConnector()) {
     370             :                     // walk the whole length of the last edge
     371         252 :                     const ROEdge* last = item.edges.back();
     372         252 :                     if (std::find(last->getSuccessors().begin(), last->getSuccessors().end(), trip->getDestination()) != last->getSuccessors().end()) {
     373             :                         arrPos = last->getLength();
     374             :                     } else {
     375             :                         arrPos = 0;
     376             :                     }
     377             :                 }
     378        3996 :                 if (&item == &result.back() && trip->getStopDest() == "") {
     379        1562 :                     resultItems.push_back(new Walk(start, item.edges, item.cost, item.exitTimes, depPos, arrPos));
     380             :                 } else {
     381         764 :                     resultItems.push_back(new Walk(start, item.edges, item.cost, item.exitTimes, depPos, arrPos, item.destStop));
     382             :                 }
     383         690 :             } else if (veh != nullptr && item.line == veh->getID()) {
     384         144 :                 double cost = item.cost;
     385         144 :                 if (veh->getVClass() != SVC_TAXI) {
     386         116 :                     RORoute* route = new RORoute(veh->getID() + "_RouteDef", item.edges);
     387         116 :                     route->setProbability(1);
     388         116 :                     veh->getRouteDefinition()->addLoadedAlternative(route);
     389             :                     carUsed = true;
     390          28 :                 } else if (resultItems.empty()) {
     391             :                     // if this is the first plan item the initial taxi waiting time wasn't added yet
     392          12 :                     const double taxiWait = STEPS2TIME(string2time(OptionsCont::getOptions().getString("persontrip.taxi.waiting-time")));
     393          12 :                     cost += taxiWait;
     394             :                 }
     395         144 :                 resultItems.push_back(new Ride(start, item.edges.front(), item.edges.back(), veh->getID(), trip->getGroup(), cost, item.arrivalPos, item.length, item.destStop));
     396             :             } else {
     397             :                 // write origin for first element of the plan
     398         546 :                 const ROEdge* origin = trip == myPlan.front() && resultItems.empty() ? trip->getOrigin() : nullptr;
     399         546 :                 resultItems.push_back(new Ride(start, origin, nullptr, item.line, trip->getGroup(), item.cost, item.arrivalPos, item.length, item.destStop, item.intended, TIME2STEPS(item.depart)));
     400             :             }
     401             :         }
     402        3100 :         start += TIME2STEPS(item.cost);
     403             :     }
     404        1802 :     if (result.empty()) {
     405          80 :         errorHandler->inform("No route for trip in person '" + getID() + "'.");
     406          40 :         myRoutingSuccess = false;
     407             :     }
     408        1802 :     return carUsed;
     409        1802 : }
     410             : 
     411             : 
     412             : void
     413        1922 : ROPerson::computeRoute(const RORouterProvider& provider,
     414             :                        const bool /* removeLoops */, MsgHandler* errorHandler) {
     415        1922 :     myRoutingSuccess = true;
     416        1922 :     SUMOTime time = getParameter().depart;
     417        3980 :     for (PlanItem* const it : myPlan) {
     418        2058 :         if (it->needsRouting()) {
     419             :             PersonTrip* trip = static_cast<PersonTrip*>(it);
     420             :             const std::vector<ROVehicle*>& vehicles = trip->getVehicles();
     421             :             std::vector<TripItem*> resultItems;
     422             :             std::vector<TripItem*> best;
     423             :             const ROVehicle* bestVeh = nullptr;
     424        1794 :             if (vehicles.empty()) {
     425        1122 :                 computeIntermodal(time, provider, trip, nullptr, best, errorHandler);
     426             :             } else {
     427             :                 double bestCost = std::numeric_limits<double>::infinity();
     428        1352 :                 for (const ROVehicle* const v : vehicles) {
     429         680 :                     const bool carUsed = computeIntermodal(time, provider, trip, v, resultItems, errorHandler);
     430             :                     double cost = 0.;
     431        1496 :                     for (const TripItem* const tripIt : resultItems) {
     432         816 :                         cost += tripIt->getCost();
     433             :                     }
     434         680 :                     if (cost < bestCost) {
     435             :                         bestCost = cost;
     436         672 :                         bestVeh = carUsed ? v : nullptr;
     437             :                         best.swap(resultItems);
     438             :                     }
     439         688 :                     for (const TripItem* const tripIt : resultItems) {
     440           8 :                         delete tripIt;
     441             :                     }
     442             :                     resultItems.clear();
     443             :                 }
     444             :             }
     445        1794 :             trip->setItems(best, bestVeh);
     446             :         }
     447        2058 :         time += it->getDuration();
     448             :     }
     449        1922 : }
     450             : 
     451             : 
     452             : void
     453        2898 : ROPerson::saveAsXML(OutputDevice& os, OutputDevice* const typeos, bool asAlternatives, OptionsCont& options) const {
     454             :     // write the person's vehicles
     455        8666 :     const bool writeTrip = options.exists("write-trips") && options.getBool("write-trips");
     456        2898 :     if (!writeTrip) {
     457        5932 :         for (const PlanItem* const it : myPlan) {
     458        3062 :             it->saveVehicles(os, typeos, asAlternatives, options);
     459             :         }
     460             :     }
     461             : 
     462        2898 :     if (typeos != nullptr && getType() != nullptr && !getType()->saved) {
     463          34 :         getType()->write(*typeos);
     464          34 :         getType()->saved = true;
     465             :     }
     466        2898 :     if (getType() != nullptr && !getType()->saved) {
     467         972 :         getType()->write(os);
     468         972 :         getType()->saved = asAlternatives;
     469             :     }
     470             : 
     471             :     // write the person
     472        5796 :     getParameter().write(os, options, SUMO_TAG_PERSON);
     473             : 
     474        6000 :     for (const PlanItem* const it : myPlan) {
     475        3102 :         it->saveAsXML(os, asAlternatives, writeTrip, options);
     476             :     }
     477             : 
     478             :     // write params
     479        2898 :     getParameter().writeParams(os);
     480        2898 :     os.closeTag();
     481        2898 : }
     482             : 
     483             : 
     484             : /****************************************************************************/

Generated by: LCOV version 1.14