LCOV - code coverage report
Current view: top level - src/marouter - marouter_main.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 92.7 % 205 190
Test Date: 2026-10-12 15:53:19 Functions: 100.0 % 5 5

            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    marouter_main.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Laura Bieker
      18              : /// @author  Michael Behrisch
      19              : /// @date    Thu, 06 Jun 2002
      20              : ///
      21              : // Main for MAROUTER
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : 
      25              : #ifdef HAVE_VERSION_H
      26              : #include <version.h>
      27              : #endif
      28              : 
      29              : #include <iostream>
      30              : #include <string>
      31              : #include <limits.h>
      32              : #include <ctime>
      33              : #include <vector>
      34              : #include <xercesc/sax/SAXException.hpp>
      35              : #include <xercesc/sax/SAXParseException.hpp>
      36              : #include <utils/common/FileHelpers.h>
      37              : #include <utils/common/StringUtils.h>
      38              : #include <utils/common/MsgHandler.h>
      39              : #include <utils/common/UtilExceptions.h>
      40              : #include <utils/common/SystemFrame.h>
      41              : #include <utils/common/RandHelper.h>
      42              : #include <utils/common/ToString.h>
      43              : #include <utils/distribution/Distribution_Points.h>
      44              : #include <utils/iodevices/OutputDevice.h>
      45              : #include <utils/iodevices/OutputDevice_String.h>
      46              : #include <utils/options/Option.h>
      47              : #include <utils/options/OptionsCont.h>
      48              : #include <utils/options/OptionsIO.h>
      49              : #include <utils/router/RouteCostCalculator.h>
      50              : #include <utils/router/DijkstraRouter.h>
      51              : #include <utils/router/AStarRouter.h>
      52              : #include <utils/router/CHRouter.h>
      53              : #include <utils/router/CHRouterWrapper.h>
      54              : #include <utils/router/CCHRouter.h>
      55              : #include <utils/xml/XMLSubSys.h>
      56              : #include <od/ODCell.h>
      57              : #include <od/ODDistrict.h>
      58              : #include <od/ODDistrictCont.h>
      59              : #include <od/ODDistrictHandler.h>
      60              : #include <od/ODMatrix.h>
      61              : #include <router/ROCCHMetrics.h>
      62              : #include <router/ROEdge.h>
      63              : #include <router/ROLoader.h>
      64              : #include <router/RONet.h>
      65              : #include <router/RORoute.h>
      66              : #include <router/RORoutable.h>
      67              : 
      68              : #include "ROMAFrame.h"
      69              : #include "ROMAAssignments.h"
      70              : #include "ROMAEdgeBuilder.h"
      71              : #include "ROMARouteHandler.h"
      72              : #include "ROMAEdge.h"
      73              : 
      74              : 
      75              : // ===========================================================================
      76              : // Method implementation
      77              : // ===========================================================================
      78              : /* -------------------------------------------------------------------------
      79              :  * data processing methods
      80              :  * ----------------------------------------------------------------------- */
      81              : /**
      82              :  * loads the net
      83              :  * The net is in this meaning made up by the net itself and the dynamic
      84              :  * weights which may be supplied in a separate file
      85              :  */
      86              : void
      87          112 : initNet(RONet& net, ROLoader& loader, OptionsCont& oc) {
      88              :     // load the net
      89          112 :     ROMAEdgeBuilder builder;
      90          112 :     ROEdge::setGlobalOptions(oc.getBool("weights.interpolate"));
      91          112 :     loader.loadNet(net, builder);
      92              :     // load the weights when wished/available
      93          218 :     if (oc.isSet("weight-files")) {
      94            0 :         loader.loadWeights(net, "weight-files", oc.getString("weight-attribute"), false, oc.getBool("weights.expand"));
      95              :     }
      96          218 :     if (oc.isSet("lane-weight-files")) {
      97            0 :         loader.loadWeights(net, "lane-weight-files", oc.getString("weight-attribute"), true, oc.getBool("weights.expand"));
      98              :     }
      99          112 : }
     100              : 
     101              : 
     102              : double
     103           32 : getTravelTime(const ROEdge* const edge, const ROVehicle* const /* veh */, double /* time */) {
     104           32 :     return edge->getLength() / edge->getSpeedLimit();
     105              : }
     106              : 
     107              : 
     108              : /**
     109              :  * Computes all pair shortest paths, saving them
     110              :  */
     111              : void
     112            1 : computeAllPairs(RONet& net, OptionsCont& oc) {
     113            2 :     OutputDevice::createDeviceByOption("all-pairs-output");
     114            1 :     OutputDevice& outFile = OutputDevice::getDeviceByOption("all-pairs-output");
     115              :     // build the router
     116              :     typedef DijkstraRouter<ROEdge, ROVehicle> Dijkstra;
     117            1 :     Dijkstra router(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), &getTravelTime);
     118            1 :     ConstROEdgeVector into;
     119            1 :     const int numInternalEdges = net.getInternalEdgeNumber();
     120            1 :     const int numTotalEdges = (int)net.getEdgeNumber();
     121            8 :     for (int i = numInternalEdges; i < numTotalEdges; i++) {
     122              :         const Dijkstra::EdgeInfo& ei = router.getEdgeInfo(i);
     123            7 :         if (!ei.edge->isInternal()) {
     124            7 :             router.compute(ei.edge, nullptr, nullptr, 0, into);
     125            7 :             double fromEffort = router.getEffort(ei.edge, nullptr, 0);
     126           56 :             for (int j = numInternalEdges; j < numTotalEdges; j++) {
     127           49 :                 double heuTT = router.getEdgeInfo(j).effort - fromEffort;
     128           49 :                 outFile << heuTT;
     129              :                 /*
     130              :                 if (heuTT >
     131              :                         ei.edge->getDistanceTo(router.getEdgeInfo(j).edge)
     132              :                         && router.getEdgeInfo(j).traveltime != std::numeric_limits<double>::max()
     133              :                         ) {
     134              :                     std::cout << " heuristic failure: from=" << ei.edge->getID() << " to=" << router.getEdgeInfo(j).edge->getID()
     135              :                     << " fromEffort=" << fromEffort << " heuTT=" << heuTT << " airDist=" << ei.edge->getDistanceTo(router.getEdgeInfo(j).edge) << "\n";
     136              :                 }
     137              :                 */
     138              :             }
     139              :         }
     140              :     }
     141            2 : }
     142              : 
     143              : 
     144              : /**
     145              :  * Computes the routes saving them
     146              :  */
     147              : void
     148           79 : computeRoutes(RONet& net, OptionsCont& oc, ODMatrix& matrix) {
     149              :     // build the router
     150              :     SUMOAbstractRouter<ROEdge, ROVehicle>* router = nullptr;
     151           79 :     const std::string measure = oc.getString("weight-attribute");
     152           82 :     const std::string routingAlgorithm = oc.getString("routing-algorithm");
     153           79 :     const double priorityFactor = oc.getFloat("weights.priority-factor");
     154           79 :     SUMOTime begin = string2time(oc.getString("begin"));
     155           79 :     SUMOTime end = string2time(oc.getString("end"));
     156          158 :     if (oc.isDefault("begin") && matrix.getBegin() >= 0) {
     157              :         begin = matrix.getBegin();
     158              :     }
     159          158 :     if (oc.isDefault("end")) {
     160           77 :         end = matrix.getEnd() >= 0 ? matrix.getEnd() : SUMOTime_MAX;
     161              :     }
     162           79 :     DijkstraRouter<ROEdge, ROVehicle>::Operation ttOp = oc.getInt("paths") > 1 ? &ROMAAssignments::getPenalizedTT : &ROEdge::getTravelTimeStatic;
     163           79 :     if (measure == "traveltime" && priorityFactor == 0) {
     164           78 :         if (routingAlgorithm == "dijkstra") {
     165          142 :             router = new DijkstraRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttOp, nullptr, false, nullptr, net.hasPermissions());
     166            7 :         } else if (routingAlgorithm == "astar") {
     167            0 :             router = new AStarRouter<ROEdge, ROVehicle, ROMapMatcher>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), ttOp, nullptr, net.hasPermissions());
     168            7 :         } else if (routingAlgorithm == "CH" && !net.hasPermissions()) {
     169            3 :             const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
     170            3 :                                            string2time(oc.getString("weight-period")) :
     171              :                                            SUMOTime_MAX);
     172            6 :             router = new CHRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), &ROEdge::getTravelTimeStatic, SVC_IGNORING, weightPeriod, net.hasPermissions(), false);
     173            4 :         } else if (routingAlgorithm == "CHWrapper" || routingAlgorithm == "CH") {
     174              :             // use CHWrapper instead of CH if the net has permissions
     175            0 :             const SUMOTime weightPeriod = (oc.isSet("weight-files") ?
     176            0 :                                            string2time(oc.getString("weight-period")) :
     177              :                                            SUMOTime_MAX);
     178              :             router = new CHRouterWrapper<ROEdge, ROVehicle>(
     179            0 :                 ROEdge::getAllEdges(), oc.getBool("ignore-errors"), &ROEdge::getTravelTimeStatic,
     180            0 :                 begin, end, weightPeriod, net.hasPermissions(), oc.getInt("routing-threads"));
     181            4 :         } else if (routingAlgorithm == "CCH") {
     182              :             // One weight-independent hierarchy over the union graph and one
     183              :             // customized metric for the default vehicle's type, filled from
     184              :             // the travel times of the current assignment iteration.
     185              :             // ROMAAssignments resets the router after every iteration (where
     186              :             // CH rebuilds its whole hierarchy); the reset hook flags the
     187              :             // metric for re-customization at the next query, so every
     188              :             // iteration routes on exactly the travel times a Dijkstra query
     189              :             // would see. Like CH, the metric cannot follow the k shortest
     190              :             // path penalties (see ROMAFrame::checkOptions).
     191            4 :             ROCCHGraph* cchGraph = new ROCCHGraph(ROEdge::getAllEdges());
     192            4 :             ROCCHMetrics::init(cchGraph, &ROEdge::getTravelTimeStatic, begin, SUMOTime_MAX);
     193              :             SUMOAbstractRouter<ROEdge, ROVehicle>* fallback = new AStarRouter<ROEdge, ROVehicle, ROMapMatcher>(
     194            8 :                 ROEdge::getAllEdges(), oc.getBool("ignore-errors"), &ROEdge::getTravelTimeStatic, nullptr, net.hasPermissions());
     195              :             router = new CCHRouter<ROEdge, ROVehicle, ROCCHGraph>(
     196              :                 cchGraph, &ROCCHMetrics::get, &ROEdge::getTravelTimeStatic,
     197            8 :                 oc.getBool("ignore-errors"), fallback, nullptr, &ROCCHMetrics::reset);
     198              :         } else {
     199            0 :             throw ProcessError(TLF("Unknown routing Algorithm '%'!", routingAlgorithm));
     200              :         }
     201              :     } else {
     202              :         DijkstraRouter<ROEdge, ROVehicle>::Operation op;
     203            1 :         if (measure == "traveltime") {
     204            0 :             if (ROEdge::initPriorityFactor(priorityFactor)) {
     205              :                 op = &ROEdge::getTravelTimeStaticPriorityFactor;
     206              :             } else {
     207              :                 op = &ROEdge::getTravelTimeStatic;
     208              :             }
     209            1 :         } else if (measure == "CO") {
     210              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::CO>;
     211            1 :         } else if (measure == "CO2") {
     212              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::CO2>;
     213            1 :         } else if (measure == "PMx") {
     214              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::PM_X>;
     215            1 :         } else if (measure == "HC") {
     216              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::HC>;
     217            1 :         } else if (measure == "NOx") {
     218              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::NO_X>;
     219            1 :         } else if (measure == "fuel") {
     220              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::FUEL>;
     221            1 :         } else if (measure == "electricity") {
     222              :             op = &ROEdge::getEmissionEffort<PollutantsInterface::ELEC>;
     223            1 :         } else if (measure == "noise") {
     224              :             op = &ROEdge::getNoiseEffort;
     225              :         } else {
     226              :             op = &ROEdge::getStoredEffort;
     227              :         }
     228            1 :         if (measure != "traveltime" && !net.hasLoadedEffort()) {
     229            6 :             WRITE_WARNINGF(TL("No weight data was loaded for attribute '%'."), measure);
     230              :         }
     231            2 :         router = new DijkstraRouter<ROEdge, ROVehicle>(ROEdge::getAllEdges(), oc.getBool("ignore-errors"), op, ttOp, false, nullptr, net.hasPermissions());
     232              :     }
     233              :     try {
     234              :         const RORouterProvider provider(router, nullptr, nullptr, nullptr);
     235              :         // prepare the output
     236           79 :         net.openOutput(oc);
     237              :         // process route definitions
     238          156 :         if (oc.isSet("timeline")) {
     239           16 :             matrix.applyCurve(matrix.parseTimeLine(oc.getStringVector("timeline"), oc.getBool("timeline.day-in-hours")));
     240              :         }
     241           78 :         matrix.sortByBeginTime();
     242          157 :         bool haveOutput = OutputDevice::createDeviceByOption("netload-output", "meandata");
     243           77 :         ROVehicle defaultVehicle(SUMOVehicleParameter(), nullptr, net.getVehicleTypeSecure(DEFAULT_VTYPE_ID), &net);
     244          231 :         ROMAAssignments a(begin, end, oc.getBool("additive-traffic"), oc.getFloat("weight-adaption"),
     245           77 :                           oc.getInt("max-alternatives"), oc.getBool("capacities.default"), net, matrix, *router,
     246          385 :                           haveOutput ? &OutputDevice::getDeviceByOption("netload-output") : nullptr);
     247           77 :         a.resetFlows();
     248              : #ifdef HAVE_FOX
     249              :         // this is just to init the CHRouter with the default vehicle
     250           77 :         router->reset(&defaultVehicle);
     251           77 :         const int maxNumThreads = oc.getInt("routing-threads");
     252           98 :         while ((int)net.getThreadPool().size() < maxNumThreads) {
     253           21 :             new RONet::WorkerThread(net.getThreadPool(), provider);
     254              :         }
     255              : #endif
     256           77 :         std::string assignMethod = oc.getString("assignment-method");
     257           77 :         if (assignMethod == "UE") {
     258            2 :             WRITE_WARNING(TL("Deterministic user equilibrium ('UE') is not implemented yet, using stochastic method ('SUE')."));
     259              :             assignMethod = "SUE";
     260              :         }
     261           77 :         if (assignMethod == "incremental") {
     262          142 :             a.incremental(oc.getInt("max-iterations"), oc.getBool("verbose"));
     263            6 :         } else if (assignMethod == "SUE") {
     264           24 :             a.sue(oc.getInt("max-iterations"), oc.getInt("max-inner-iterations"),
     265           31 :                   oc.getInt("paths"), oc.getFloat("paths.penalty"), oc.getFloat("tolerance"), oc.getString("route-choice-method"));
     266              :         }
     267              :         // update path costs and output
     268              :         OutputDevice* dev = net.getRouteOutput();
     269           77 :         if (dev != nullptr) {
     270           76 :             std::vector<std::string> tazParamKeys;
     271          152 :             if (oc.isSet("taz-param")) {
     272            2 :                 tazParamKeys = oc.getStringVector("taz-param");
     273              :             }
     274              :             std::map<SUMOTime, std::string> sortedOut;
     275              :             SUMOTime lastEnd = -1;
     276              :             int num = 0;
     277         2125 :             for (const ODCell* const c : matrix.getCells()) {
     278         2049 :                 if (c->begin >= end || c->end <= begin ||
     279         4098 :                         c->pathsVector.empty() || c->pathsVector.front()->getEdgeVector().empty()) {
     280            3 :                     continue;
     281              :                 }
     282         2046 :                 if (lastEnd >= 0 && lastEnd <= c->begin) {
     283          282 :                     for (std::map<SUMOTime, std::string>::const_iterator desc = sortedOut.begin(); desc != sortedOut.end(); ++desc) {
     284          141 :                         dev->writePreformattedTag(desc->second);
     285              :                     }
     286              :                     sortedOut.clear();
     287              :                 }
     288         2046 :                 if (c->departures.empty()) {
     289         2013 :                     const SUMOTime b = MAX2(begin, c->begin);
     290         2013 :                     const SUMOTime e = MIN2(end, c->end);
     291         2013 :                     const int numVehs = int(c->vehicleNumber * (double)(e - b) / (double)(c->end - c->begin));
     292         2013 :                     OutputDevice_String od(1);
     293         4026 :                     od.openTag(SUMO_TAG_FLOW).writeAttr(SUMO_ATTR_ID, oc.getString("prefix") + toString(num++));
     294         2013 :                     od.writeAttr(SUMO_ATTR_BEGIN, time2string(b)).writeAttr(SUMO_ATTR_END, time2string(e));
     295         2013 :                     od.writeAttr(SUMO_ATTR_NUMBER, numVehs);
     296         2013 :                     matrix.writeDefaultAttrs(od, oc.getBool("ignore-vehicle-type"), c);
     297         2013 :                     od.openTag(SUMO_TAG_ROUTE_DISTRIBUTION);
     298         4612 :                     for (const std::shared_ptr<RORoute>& r : c->pathsVector) {
     299         2599 :                         r->setCosts(router->recomputeCosts(r->getEdgeVector(), &defaultVehicle, begin));
     300         5198 :                         r->writeXMLDefinition(od, nullptr, true, true, false, false);
     301              :                     }
     302         2013 :                     od.closeTag();
     303         2013 :                     od.closeTag();
     304         2013 :                     sortedOut[c->begin] += od.getString();
     305         2013 :                 } else {
     306           66 :                     const bool ignoreType = oc.getBool("ignore-vehicle-type");
     307         1394 :                     for (auto deps : c->departures) {
     308         1361 :                         if (deps.first >= end || deps.first < begin) {
     309              :                             continue;
     310              :                         }
     311         4876 :                         const std::string routeDistId = c->origin + "_" + c->destination + "_" + time2string(c->begin) + "_" + time2string(c->end);
     312         2484 :                         for (const SUMOVehicleParameter& veh : deps.second) {
     313         1265 :                             OutputDevice_String od(1);
     314              : 
     315         1271 :                             veh.write(od, OptionsCont::getOptions(), SUMO_TAG_VEHICLE, ignoreType || veh.vtypeid == DEFAULT_VTYPE_ID ? "" : veh.vtypeid);
     316         1265 :                             od.openTag(SUMO_TAG_ROUTE_DISTRIBUTION);
     317         3586 :                             for (const std::shared_ptr<RORoute>& r : c->pathsVector) {
     318         2321 :                                 r->setCosts(router->recomputeCosts(r->getEdgeVector(), &defaultVehicle, begin));
     319         4642 :                                 r->writeXMLDefinition(od, nullptr, true, true, false, false);
     320              :                             }
     321         2530 :                             od.closeTag();
     322         1265 :                             if (!tazParamKeys.empty()) {
     323           22 :                                 od.openTag(SUMO_TAG_PARAM).writeAttr(SUMO_ATTR_KEY, tazParamKeys[0]).writeAttr(SUMO_ATTR_VALUE, c->origin).closeTag();
     324           11 :                                 if (tazParamKeys.size() > 1) {
     325           22 :                                     od.openTag(SUMO_TAG_PARAM).writeAttr(SUMO_ATTR_KEY, tazParamKeys[1]).writeAttr(SUMO_ATTR_VALUE, c->destination).closeTag();
     326              :                                 }
     327              :                             }
     328         1265 :                             od.closeTag();
     329         1265 :                             sortedOut[deps.first] += od.getString();
     330         1265 :                         }
     331              :                     }
     332              :                 }
     333         2046 :                 if (c->end > lastEnd) {
     334              :                     lastEnd = c->end;
     335              :                 }
     336              :             }
     337         1337 :             for (std::map<SUMOTime, std::string>::const_iterator desc = sortedOut.begin(); desc != sortedOut.end(); ++desc) {
     338         1261 :                 dev->writePreformattedTag(desc->second);
     339              :             }
     340              :             haveOutput = true;
     341           76 :         }
     342            1 :         if (!haveOutput) {
     343            2 :             throw ProcessError(TL("No output file given."));
     344              :         }
     345              :         // end the processing
     346           76 :         net.cleanup();
     347           84 :     } catch (ProcessError&) {
     348            3 :         net.cleanup();
     349            3 :         throw;
     350            3 :     }
     351           76 : }
     352              : 
     353              : 
     354              : /* -------------------------------------------------------------------------
     355              :  * main
     356              :  * ----------------------------------------------------------------------- */
     357              : int
     358          118 : main(int argc, char** argv) {
     359          118 :     OptionsCont& oc = OptionsCont::getOptions();
     360          118 :     oc.setApplicationDescription(TL("Import O/D-matrices for macroscopic traffic assignment to generate SUMO routes."));
     361          236 :     oc.setApplicationName("marouter", "Eclipse SUMO marouter " VERSION_STRING);
     362              :     int ret = 0;
     363              :     RONet* net = nullptr;
     364              :     try {
     365          118 :         XMLSubSys::init();
     366          118 :         ROMAFrame::fillOptions();
     367          118 :         OptionsIO::setArgs(argc, argv);
     368          118 :         OptionsIO::getOptions();
     369          118 :         if (oc.processMetaOptions(argc < 2)) {
     370            6 :             SystemFrame::close();
     371            7 :             return 0;
     372              :         }
     373          112 :         SystemFrame::checkOptions(oc);
     374          371 :         XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"), oc.getString("xml-validation.routes"));
     375          112 :         MsgHandler::initOutputOptions();
     376          112 :         if (!ROMAFrame::checkOptions()) {
     377            0 :             throw ProcessError();
     378              :         }
     379          112 :         RandHelper::initRandGlobal();
     380              :         // load data
     381          112 :         ROLoader loader(oc, false, false);
     382          112 :         net = new RONet();
     383          112 :         initNet(*net, loader, oc);
     384          218 :         if (oc.isSet("all-pairs-output")) {
     385            1 :             computeAllPairs(*net, oc);
     386            1 :             if (net->getDistricts().empty()) {
     387            1 :                 delete net;
     388            1 :                 SystemFrame::close();
     389              :                 if (ret == 0) {
     390              :                     std::cout << "Success." << std::endl;
     391              :                 }
     392              :                 return ret;
     393              :             }
     394              :         }
     395          108 :         if (net->getDistricts().empty()) {
     396           16 :             WRITE_WARNING(TL("No districts loaded, will use edge ids!"));
     397              :         }
     398              :         // load districts
     399          108 :         ODDistrictCont districts;
     400          108 :         districts.makeDistricts(net->getDistricts());
     401              :         // load the matrix
     402          108 :         ODMatrix matrix(districts, oc.getFloat("scale"));
     403          108 :         matrix.loadMatrix(oc);
     404           90 :         ROMARouteHandler handler(matrix);
     405           90 :         matrix.loadRoutes(oc, handler);
     406           90 :         if (matrix.getNumLoaded() == matrix.getNumDiscarded()) {
     407            6 :             throw ProcessError(TL("No valid vehicles loaded."));
     408              :         }
     409          113 :         if (MsgHandler::getErrorInstance()->wasInformed() && !oc.getBool("ignore-errors")) {
     410           16 :             throw ProcessError(TL("Loading failed."));
     411              :         }
     412           79 :         MsgHandler::getErrorInstance()->clear();
     413          316 :         WRITE_MESSAGE(toString(matrix.getNumLoaded() - matrix.getNumDiscarded()) + " valid vehicles loaded (total seen: " + toString(matrix.getNumLoaded()) + ").");
     414              : 
     415              :         // build routes and parse the incremental rates if the incremental method is choosen.
     416              :         try {
     417           79 :             computeRoutes(*net, oc, matrix);
     418            3 :         } catch (XERCES_CPP_NAMESPACE::SAXParseException& e) {
     419            0 :             WRITE_ERROR(toString(e.getLineNumber()));
     420              :             ret = 1;
     421            0 :         } catch (XERCES_CPP_NAMESPACE::SAXException& e) {
     422            0 :             WRITE_ERROR(XMLSubSys::transcode(e.getMessage()));
     423              :             ret = 1;
     424            0 :         }
     425           76 :         if (MsgHandler::getErrorInstance()->wasInformed() || ret != 0) {
     426            0 :             throw ProcessError();
     427              :         }
     428          225 :     } catch (const ProcessError& e) {
     429          105 :         if (std::string(e.what()) != std::string("Process Error") && std::string(e.what()) != std::string("")) {
     430           70 :             WRITE_ERROR(e.what());
     431              :         }
     432           35 :         MsgHandler::getErrorInstance()->inform("Quitting (on error).", false);
     433              :         ret = 1;
     434           35 :     }
     435              : 
     436          111 :     delete net;
     437          111 :     SystemFrame::close();
     438          111 :     if (ret == 0) {
     439              :         std::cout << "Success." << std::endl;
     440              :     }
     441              :     return ret;
     442              : }
     443              : 
     444              : 
     445              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1