LCOV - code coverage report
Current view: top level - src/netimport - NIXMLPTHandler.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 171 191 89.5 %
Date: 2024-05-02 15:31:40 Functions: 12 13 92.3 %

          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        4326 : NIXMLPTHandler::NIXMLPTHandler(NBEdgeCont& ec, NBPTStopCont& sc, NBPTLineCont& lc) :
      48             :     SUMOSAXHandler("public transport - file"),
      49        4326 :     myEdgeCont(ec),
      50        4326 :     myStopCont(sc),
      51        4326 :     myLineCont(lc),
      52             :     myCurrentStop(nullptr),
      53        4326 :     myCurrentLine(nullptr),
      54        4326 :     myCurrentCompletion(0),
      55        8652 :     myCurrentStopWasIgnored(false)
      56        4326 : { }
      57             : 
      58             : 
      59        8652 : NIXMLPTHandler::~NIXMLPTHandler() {}
      60             : 
      61             : 
      62             : void
      63         221 : NIXMLPTHandler::myStartElement(int element,
      64             :                                const SUMOSAXAttributes& attrs) {
      65         221 :     switch (element) {
      66         133 :         case SUMO_TAG_BUS_STOP:
      67             :         case SUMO_TAG_TRAIN_STOP:
      68             :         case SUMO_TAG_STOP:
      69         133 :             if (myCurrentRouteID != "") {
      70           6 :                 addRouteStop(attrs);
      71         127 :             } else if (myCurrentLine == nullptr) {
      72          95 :                 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         221 : }
     117             : 
     118             : void
     119         221 : NIXMLPTHandler::myEndElement(int element) {
     120         221 :     switch (element) {
     121             :         case SUMO_TAG_BUS_STOP:
     122             :         case SUMO_TAG_TRAIN_STOP:
     123             :             myCurrentStop = nullptr;
     124         127 :             myCurrentStopWasIgnored = false;
     125         127 :             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         221 : }
     141             : 
     142             : 
     143             : void
     144          95 : NIXMLPTHandler::addPTStop(const SUMOSAXAttributes& attrs) {
     145          95 :     bool ok = true;
     146          95 :     const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "busStop", ok);
     147         190 :     const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
     148          95 :     const std::string laneID = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
     149          95 :     const double startPos = attrs.get<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok);
     150          95 :     const double endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok);
     151          95 :     const double parkingLength = attrs.getOpt<double>(SUMO_ATTR_PARKING_LENGTH, id.c_str(), ok, 0);
     152          95 :     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         190 :     const int laneIndex = NBEdge::getLaneIndexFromLaneID(laneID);
     155          95 :     const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
     156          95 :     NBEdge* edge = myEdgeCont.retrieve(edgeID);
     157          95 :     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          90 :     if (edge->getNumLanes() <= laneIndex) {
     167           0 :         WRITE_ERRORF(TL("Lane '%' for stop '%' not found"), laneID, id);
     168           0 :         return;
     169             :     }
     170          90 :     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          90 :     if (!isRailway(permissions) && permissions != SVC_SHIP && permissions != SVC_TAXI) {
     173           4 :         permissions = SVC_BUS;
     174             :     }
     175          90 :     if (ok) {
     176          90 :         Position pos = edge->geometryPositionAtOffset((startPos + endPos) / 2);
     177          90 :         myCurrentStop = std::make_shared<NBPTStop>(id, pos, edgeID, edgeID, endPos - startPos, name, permissions, parkingLength, color, startPos);
     178         180 :         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          17 :     myCurrentCompletion = StringUtils::toDouble(attrs.getStringSecure("completeness", "1"));
     225          17 :     myMissingBefore = StringUtils::toInt(attrs.getStringSecure("missingBefore", "0"));
     226          17 :     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             :                            ? 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             :                            ? 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 1.14