LCOV - code coverage report
Current view: top level - src/netimport - NIXMLPTHandler.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 89.6 % 193 173
Test Date: 2024-12-21 15:45:41 Functions: 92.3 % 13 12

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    NIXMLPTHandler.cpp
      15              : /// @author  Jakob Erdmann
      16              : /// @date    Sat, 28 Jul 2018
      17              : ///
      18              : // Importer for static public transport information
      19              : /****************************************************************************/
      20              : #include <config.h>
      21              : 
      22              : #include <string>
      23              : #include <iostream>
      24              : #include <map>
      25              : #include <cmath>
      26              : #include <utils/xml/SUMOSAXHandler.h>
      27              : #include <utils/xml/SUMOXMLDefinitions.h>
      28              : #include <utils/common/MsgHandler.h>
      29              : #include <utils/common/StringUtils.h>
      30              : #include <utils/common/StringTokenizer.h>
      31              : #include <utils/geom/GeomConvHelper.h>
      32              : #include <utils/common/ToString.h>
      33              : #include <utils/options/OptionsCont.h>
      34              : #include <utils/geom/GeoConvHelper.h>
      35              : #include <netbuild/NBNodeCont.h>
      36              : #include <netbuild/NBTypeCont.h>
      37              : #include <netbuild/NBNetBuilder.h>
      38              : #include <netbuild/NBPTStop.h>
      39              : #include "NIImporter_OpenStreetMap.h"
      40              : #include "NIXMLNodesHandler.h"
      41              : #include "NIXMLPTHandler.h"
      42              : 
      43              : 
      44              : // ===========================================================================
      45              : // method definitions
      46              : // ===========================================================================
      47         3664 : NIXMLPTHandler::NIXMLPTHandler(NBEdgeCont& ec, NBPTStopCont& sc, NBPTLineCont& lc) :
      48              :     SUMOSAXHandler("public transport - file"),
      49         3664 :     myEdgeCont(ec),
      50         3664 :     myStopCont(sc),
      51         3664 :     myLineCont(lc),
      52              :     myCurrentStop(nullptr),
      53         3664 :     myCurrentLine(nullptr),
      54         3664 :     myCurrentCompletion(0),
      55         7328 :     myCurrentStopWasIgnored(false)
      56         3664 : { }
      57              : 
      58              : 
      59        10992 : NIXMLPTHandler::~NIXMLPTHandler() {}
      60              : 
      61              : 
      62              : void
      63          203 : NIXMLPTHandler::myStartElement(int element,
      64              :                                const SUMOSAXAttributes& attrs) {
      65          203 :     switch (element) {
      66          115 :         case SUMO_TAG_BUS_STOP:
      67              :         case SUMO_TAG_TRAIN_STOP:
      68              :         case SUMO_TAG_STOP:
      69          115 :             if (myCurrentRouteID != "") {
      70            6 :                 addRouteStop(attrs);
      71          109 :             } else if (myCurrentLine == nullptr) {
      72           77 :                 addPTStop(attrs);
      73              :             } else {
      74           32 :                 addPTLineStop(attrs);
      75              :             }
      76              :             break;
      77           10 :         case SUMO_TAG_ACCESS:
      78           10 :             addAccess(attrs);
      79           10 :             break;
      80           17 :         case SUMO_TAG_PT_LINE:
      81           17 :             addPTLine(attrs);
      82           17 :             break;
      83            6 :         case SUMO_TAG_ROUTE:
      84            6 :             if (myCurrentLine == nullptr) {
      85            3 :                 addRoute(attrs);
      86              :             } else {
      87            3 :                 addPTLineRoute(attrs);
      88              :             }
      89              :             break;
      90            3 :         case SUMO_TAG_FLOW:
      91              :         case SUMO_TAG_TRIP:
      92            3 :             addPTLineFromFlow(attrs);
      93            3 :             break;
      94            7 :         case SUMO_TAG_PARAM: {
      95            7 :             bool ok = true;
      96            7 :             const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
      97            7 :             if (myCurrentLine != nullptr) {
      98            6 :                 if (key == "completeness") {
      99            3 :                     myCurrentCompletion = attrs.get<double>(SUMO_ATTR_VALUE, nullptr, ok);
     100            3 :                 } else if (key == "name") {
     101            6 :                     myCurrentLine->setName(attrs.get<std::string>(SUMO_ATTR_VALUE, nullptr, ok));
     102            0 :                 } else if (key == "missingBefore") {
     103            0 :                     myMissingBefore = attrs.get<int>(SUMO_ATTR_VALUE, nullptr, ok);
     104            0 :                 } else if (key == "missingAfter") {
     105            0 :                     myMissingAfter = attrs.get<int>(SUMO_ATTR_VALUE, nullptr, ok);
     106              :                 }
     107            1 :             } else if (myCurrentStop != nullptr) {
     108            1 :                 const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
     109            1 :                 myCurrentStop->setParameter(key, val);
     110              :             }
     111              :         }
     112            7 :         break;
     113              :         default:
     114              :             break;
     115              :     }
     116          203 : }
     117              : 
     118              : void
     119          203 : NIXMLPTHandler::myEndElement(int element) {
     120          203 :     switch (element) {
     121              :         case SUMO_TAG_BUS_STOP:
     122              :         case SUMO_TAG_TRAIN_STOP:
     123              :             myCurrentStop = nullptr;
     124          109 :             myCurrentStopWasIgnored = false;
     125          109 :             break;
     126           20 :         case SUMO_TAG_PT_LINE:
     127              :         case SUMO_TAG_FLOW:
     128              :         case SUMO_TAG_TRIP:
     129           20 :             if (myCurrentLine != nullptr) {
     130           20 :                 myCurrentLine->setNumOfStops((int)((double)myCurrentLine->getStops().size() / myCurrentCompletion), myMissingBefore, myMissingAfter);
     131              :             }
     132           20 :             myCurrentLine = nullptr;
     133           20 :             break;
     134            6 :         case SUMO_TAG_ROUTE:
     135            6 :             myCurrentRouteID = "";
     136              :             break;
     137              :         default:
     138              :             break;
     139              :     }
     140          203 : }
     141              : 
     142              : 
     143              : void
     144           77 : NIXMLPTHandler::addPTStop(const SUMOSAXAttributes& attrs) {
     145           77 :     bool ok = true;
     146           77 :     const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "busStop", ok);
     147          154 :     const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
     148           77 :     const std::string laneID = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
     149           77 :     const double startPos = attrs.get<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok);
     150           77 :     const double endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok);
     151           77 :     const double parkingLength = attrs.getOpt<double>(SUMO_ATTR_PARKING_LENGTH, id.c_str(), ok, 0);
     152           77 :     const RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor(false));
     153              :     //const std::string lines = attrs.get<std::string>(SUMO_ATTR_LINES, id.c_str(), ok);
     154          154 :     const int laneIndex = NBEdge::getLaneIndexFromLaneID(laneID);
     155           77 :     const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
     156           77 :     NBEdge* edge = myEdgeCont.retrieve(edgeID);
     157           77 :     if (edge == nullptr) {
     158           10 :         if (!myEdgeCont.wasIgnored(edgeID)) {
     159            0 :             WRITE_ERRORF(TL("Edge '%' for stop '%' not found"), edgeID, id);
     160              :         } else {
     161            5 :             myCurrentStopWasIgnored = true;
     162              :             NBPTStopCont::addIgnored(id);
     163              :         }
     164            5 :         return;
     165              :     }
     166           72 :     if (edge->getNumLanes() <= laneIndex) {
     167            0 :         WRITE_ERRORF(TL("Lane '%' for stop '%' not found"), laneID, id);
     168            0 :         return;
     169              :     }
     170           72 :     SVCPermissions permissions = edge->getPermissions(laneIndex);
     171              :     // possibly the stops were written for a different network. If the lane is not a typical public transport stop lane, assume bus as the default
     172           72 :     if (!isRailway(permissions) && permissions != SVC_SHIP && permissions != SVC_TAXI) {
     173            4 :         permissions = SVC_BUS;
     174              :     }
     175           72 :     if (ok) {
     176           72 :         Position pos = edge->geometryPositionAtOffset((startPos + endPos) / 2);
     177           72 :         myCurrentStop = std::make_shared<NBPTStop>(id, pos, edgeID, edgeID, endPos - startPos, name, permissions, parkingLength, color, startPos);
     178          144 :         if (!myStopCont.insert(myCurrentStop)) {
     179            0 :             WRITE_ERRORF(TL("Could not add public transport stop '%' (already exists)"), id);
     180              :         }
     181              :     }
     182              : }
     183              : 
     184              : void
     185           10 : NIXMLPTHandler::addAccess(const SUMOSAXAttributes& attrs) {
     186           10 :     if (myCurrentStop == nullptr) {
     187            4 :         if (myCurrentStopWasIgnored) {
     188            5 :             return;
     189              :         } else {
     190            0 :             throw InvalidArgument("Could not add access outside a stopping place.");
     191              :         }
     192              :     }
     193            6 :     bool ok = true;
     194            6 :     const std::string laneID = attrs.get<std::string>(SUMO_ATTR_LANE, "access", ok);
     195            6 :     const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
     196            6 :     if (myEdgeCont.retrieve(edgeID) == nullptr) {
     197            2 :         if (!myEdgeCont.wasIgnored(edgeID)) {
     198            0 :             WRITE_ERRORF(TL("Edge '%' for access to stop '%' not found"), edgeID, myCurrentStop->getID());
     199              :         }
     200              :         return;
     201              :     }
     202            5 :     const double pos = attrs.get<double>(SUMO_ATTR_POSITION, "access", ok);
     203            5 :     const double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "access", ok, -1);
     204            5 :     if (ok) {
     205           10 :         myCurrentStop->addAccess(laneID, pos, length);
     206              :     }
     207              : }
     208              : 
     209              : 
     210              : void
     211           17 : NIXMLPTHandler::addPTLine(const SUMOSAXAttributes& attrs) {
     212           17 :     bool ok = true;
     213           17 :     const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "ptLine", ok);
     214           17 :     const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
     215           17 :     const std::string line = attrs.getOpt<std::string>(SUMO_ATTR_LINE, id.c_str(), ok, "");
     216           17 :     const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
     217           17 :     SUMOVehicleClass vClass = NIImporter_OpenStreetMap::interpretTransportType(type);
     218           17 :     if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
     219            0 :         vClass = getVehicleClassID(attrs.get<std::string>(SUMO_ATTR_VCLASS, id.c_str(), ok));
     220              :     }
     221           17 :     RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor(false));
     222           17 :     const int intervalS = attrs.getOpt<int>(SUMO_ATTR_PERIOD, id.c_str(), ok, -1);
     223           34 :     const std::string nightService = attrs.getStringSecure("nightService", "");
     224           34 :     myCurrentCompletion = StringUtils::toDouble(attrs.getStringSecure("completeness", "1"));
     225           34 :     myMissingBefore = StringUtils::toInt(attrs.getStringSecure("missingBefore", "0"));
     226           34 :     myMissingAfter = StringUtils::toInt(attrs.getStringSecure("missingAfter", "0"));
     227           17 :     if (ok) {
     228              :         // patching existing line?
     229           17 :         myCurrentLine = myLineCont.retrieve(id);
     230           17 :         if (myCurrentLine == nullptr) {
     231           16 :             myCurrentLine = new NBPTLine(id, name, type, line, intervalS / 60, nightService, vClass, color);
     232           16 :             myLineCont.insert(myCurrentLine);
     233              :         } else {
     234            3 :             WRITE_MESSAGEF(TL("Duplicate ptLine id occurred ('%'); assuming overwriting is wished."), id);
     235            1 :             if (name != "") {
     236            0 :                 myCurrentLine->setName(name);
     237              :             }
     238            1 :             if (line != "") {
     239            0 :                 myCurrentLine->setRef(line);
     240              :             }
     241            1 :             if (intervalS != -1) {
     242            1 :                 myCurrentLine->setPeriod(intervalS);
     243              :             }
     244              :         }
     245              :     }
     246           17 : }
     247              : 
     248              : 
     249              : void
     250            3 : NIXMLPTHandler::addPTLineFromFlow(const SUMOSAXAttributes& attrs) {
     251            3 :     bool ok = true;
     252            3 :     myMissingBefore = 0;
     253            3 :     myMissingAfter = 0;
     254            3 :     const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "flow", ok);
     255            3 :     const std::string line = attrs.get<std::string>(SUMO_ATTR_LINE, id.c_str(), ok);
     256            3 :     const std::string type = attrs.get<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok);
     257            3 :     const std::string route = attrs.get<std::string>(SUMO_ATTR_ROUTE, id.c_str(), ok);
     258            3 :     SUMOVehicleClass vClass = NIImporter_OpenStreetMap::interpretTransportType(type);
     259            3 :     const int intervalS = attrs.getOpt<int>(SUMO_ATTR_PERIOD, id.c_str(), ok, -1);
     260            3 :     RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor(false));
     261            3 :     if (ok) {
     262            3 :         myCurrentLine = new NBPTLine(id, "", type, line, intervalS / 60, "", vClass, color);
     263            3 :         myCurrentLine->setEdges(myRouteEdges[route]);
     264            9 :         for (std::shared_ptr<NBPTStop> stop : myRouteStops[route]) {
     265           12 :             myCurrentLine->addPTStop(stop);
     266              :         }
     267            3 :         myLineCont.insert(myCurrentLine);
     268              :     }
     269            3 : }
     270              : 
     271              : 
     272              : void
     273            3 : NIXMLPTHandler::addPTLineRoute(const SUMOSAXAttributes& attrs) {
     274            3 :     if (myCurrentLine == nullptr) {
     275            0 :         WRITE_ERROR(TL("Found route outside line definition"));
     276            0 :         return;
     277              :     }
     278            3 :     bool ok = true;
     279            3 :     const std::vector<std::string>& edgeIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, nullptr, ok);
     280              :     EdgeVector edges;
     281           10 :     for (const std::string& edgeID : edgeIDs) {
     282            7 :         NBEdge* edge = myEdgeCont.retrieve(edgeID);
     283            7 :         if (edge == nullptr) {
     284            2 :             if (!myEdgeCont.wasIgnored(edgeID)) {
     285            0 :                 WRITE_ERRORF(TL("Edge '%' in route of line '%' not found"), edgeID, myCurrentLine->getName());
     286              :             }
     287              :         } else {
     288            6 :             edges.push_back(edge);
     289              :         }
     290              :     }
     291            3 :     myCurrentLine->setEdges(edges);
     292            3 : }
     293              : 
     294              : 
     295              : void
     296            3 : NIXMLPTHandler::addRoute(const SUMOSAXAttributes& attrs) {
     297            3 :     bool ok = true;
     298            6 :     myCurrentRouteID = attrs.get<std::string>(SUMO_ATTR_ID, "route", ok);
     299            3 :     const std::vector<std::string>& edgeIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, myCurrentRouteID.c_str(), ok);
     300              :     EdgeVector edges;
     301            9 :     for (const std::string& edgeID : edgeIDs) {
     302            6 :         NBEdge* edge = myEdgeCont.retrieve(edgeID);
     303            6 :         if (edge == nullptr) {
     304            0 :             if (!myEdgeCont.wasIgnored(edgeID)) {
     305            0 :                 WRITE_ERRORF(TL("Edge '%' in route of line '%' not found"), edgeID, myCurrentLine->getName());
     306              :             }
     307              :         } else {
     308            6 :             edges.push_back(edge);
     309              :         }
     310              :     }
     311            3 :     myRouteEdges[myCurrentRouteID] = edges;
     312            3 : }
     313              : 
     314              : 
     315              : void
     316           32 : NIXMLPTHandler::addPTLineStop(const SUMOSAXAttributes& attrs) {
     317           32 :     bool ok = true;
     318           32 :     const std::string id = attrs.hasAttribute(SUMO_ATTR_ID)
     319           32 :                            ? attrs.get<std::string>(SUMO_ATTR_ID, "ptLine", ok)
     320           32 :                            : attrs.get<std::string>(SUMO_ATTR_BUS_STOP, "ptline", ok);
     321           96 :     std::shared_ptr<NBPTStop> stop = myStopCont.get(id);
     322           32 :     if (stop == nullptr) {
     323            1 :         if (!NBPTStopCont::wasIgnored(id)) {
     324            0 :             WRITE_ERRORF(TL("Stop '%' within line '%' not found"), id, toString(myCurrentLine->getLineID()));
     325              :         }
     326              :         return;
     327              :     }
     328           62 :     myCurrentLine->addPTStop(stop);
     329              : }
     330              : 
     331              : void
     332            6 : NIXMLPTHandler::addRouteStop(const SUMOSAXAttributes& attrs) {
     333              :     assert(myCurrentRouteID != "");
     334            6 :     bool ok = true;
     335            6 :     const std::string id = attrs.hasAttribute(SUMO_ATTR_ID)
     336            6 :                            ? attrs.get<std::string>(SUMO_ATTR_ID, "ptLine", ok)
     337            6 :                            : attrs.get<std::string>(SUMO_ATTR_BUS_STOP, "ptline", ok);
     338           18 :     std::shared_ptr<NBPTStop> stop = myStopCont.get(id);
     339            6 :     if (stop == nullptr) {
     340            0 :         WRITE_ERRORF(TL("Stop '%' within route '%' not found"), id, toString(myCurrentRouteID));
     341              :         return;
     342              :     }
     343            6 :     myRouteStops[myCurrentRouteID].push_back(stop);
     344              : }
     345              : 
     346              : 
     347              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1