Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NIXMLPTHandler.cpp
Go to the documentation of this file.
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/****************************************************************************/
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>
35#include <netbuild/NBNodeCont.h>
36#include <netbuild/NBTypeCont.h>
38#include <netbuild/NBPTStop.h>
40#include "NIXMLNodesHandler.h"
41#include "NIXMLPTHandler.h"
42
43
44// ===========================================================================
45// method definitions
46// ===========================================================================
48 SUMOSAXHandler("public transport - file"),
49 myEdgeCont(ec),
50 myStopCont(sc),
51 myLineCont(lc),
52 myCurrentStop(nullptr),
53 myCurrentLine(nullptr),
54 myCurrentCompletion(0),
55 myCurrentStopWasIgnored(false),
56 myWarnOnly(OptionsCont::getOptions().getBool("ignore-errors"))
57{ }
58
59
61
62
63void
65 const SUMOSAXAttributes& attrs) {
66 switch (element) {
69 case SUMO_TAG_STOP:
70 if (myCurrentRouteID != "") {
71 addRouteStop(attrs);
72 } else if (myCurrentLine == nullptr) {
73 addPTStop(element, attrs);
74 } else {
75 addPTLineStop(attrs);
76 }
77 break;
78 case SUMO_TAG_ACCESS:
79 addAccess(attrs);
80 break;
82 addPTLine(attrs);
83 break;
84 case SUMO_TAG_ROUTE:
85 if (myCurrentLine == nullptr) {
86 addRoute(attrs);
87 } else {
88 addPTLineRoute(attrs);
89 }
90 break;
91 case SUMO_TAG_FLOW:
92 case SUMO_TAG_TRIP:
93 addPTLineFromFlow(attrs);
94 break;
95 case SUMO_TAG_PARAM: {
96 bool ok = true;
97 const std::string key = attrs.get<std::string>(SUMO_ATTR_KEY, nullptr, ok);
98 if (myCurrentLine != nullptr) {
99 if (key == "completeness") {
100 myCurrentCompletion = attrs.get<double>(SUMO_ATTR_VALUE, nullptr, ok);
101 } else if (key == "name") {
102 myCurrentLine->setName(attrs.get<std::string>(SUMO_ATTR_VALUE, nullptr, ok));
103 } else if (key == "missingBefore") {
104 myMissingBefore = attrs.get<int>(SUMO_ATTR_VALUE, nullptr, ok);
105 } else if (key == "missingAfter") {
106 myMissingAfter = attrs.get<int>(SUMO_ATTR_VALUE, nullptr, ok);
107 }
108 } else if (myCurrentStop != nullptr) {
109 const std::string val = attrs.hasAttribute(SUMO_ATTR_VALUE) ? attrs.getString(SUMO_ATTR_VALUE) : "";
110 myCurrentStop->setParameter(key, val);
111 }
112 }
113 break;
114 default:
115 break;
116 }
117}
118
119void
121 switch (element) {
124 myCurrentStop = nullptr;
126 break;
127 case SUMO_TAG_PT_LINE:
128 case SUMO_TAG_FLOW:
129 case SUMO_TAG_TRIP:
130 if (myCurrentLine != nullptr) {
132 }
133 myCurrentLine = nullptr;
134 break;
135 case SUMO_TAG_ROUTE:
136 myCurrentRouteID = "";
137 break;
138 default:
139 break;
140 }
141}
142
143
144bool
145NIXMLPTHandler::reportError(const std::string& msg, const std::string& edgeID, const std::string& id) {
146 const bool ignored = myEdgeCont.wasIgnored(edgeID);
147 if (!ignored && !myWarnOnly) {
148 WRITE_ERRORF(msg, edgeID, id);
149 return true;
150 } else if (!ignored) {
151 WRITE_WARNINGF(msg, edgeID, id);
152 }
153 return false;
154}
155
156
157void
159 bool ok = true;
160 const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "busStop", ok);
161 const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
162 const std::string laneID = attrs.get<std::string>(SUMO_ATTR_LANE, id.c_str(), ok);
163 double startPos = attrs.get<double>(SUMO_ATTR_STARTPOS, id.c_str(), ok);
164 double endPos = attrs.get<double>(SUMO_ATTR_ENDPOS, id.c_str(), ok);
165 const double parkingLength = attrs.getOpt<double>(SUMO_ATTR_PARKING_LENGTH, id.c_str(), ok, 0);
166 const RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor(false));
167 const std::string lines = attrs.getOpt<std::string>(SUMO_ATTR_LINES, id.c_str(), ok, "");
168 int laneIndex = NBEdge::getLaneIndexFromLaneID(laneID);
169 std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
170 NBEdge* edge = myEdgeCont.retrieve(edgeID);
171 if (edge == nullptr) {
172 edge = myEdgeCont.retrieve(edgeID, true);
173 if (edge != nullptr && myEdgeCont.getSplit(edge) == nullptr) {
174 // splits are treated later
175 edge = nullptr;
176 }
177 }
178 if (edge == nullptr) {
179 if (!reportError(TL("Edge '%' for stop '%' not found"), edgeID, id)) {
182 }
183 return;
184 }
185 if (edge->getNumLanes() <= laneIndex) {
186 if (myWarnOnly) {
187 WRITE_WARNINGF(TL("Lane '%' for stop '%' not found. Using leftmost lane"), laneID, id);
188 laneIndex = edge->getNumLanes() - 1;
189 } else {
190 WRITE_ERRORF(TL("Lane '%' for stop '%' not found"), laneID, id);
191 return;
192 }
193 }
194 SVCPermissions permissions = edge->getPermissions(laneIndex);
195 // 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
196 if (!isRailway(permissions) && permissions != SVC_SHIP && permissions != SVC_TAXI) {
197 permissions = SVC_BUS;
198 }
199 if (ok) {
200 if (startPos < 0) {
201 startPos += edge->getLoadedLength();
202 }
203 if (endPos < 0) {
204 endPos += edge->getLoadedLength();
205 }
206 if (myEdgeCont.wasRemoved(edgeID) && (
207 startPos >= endPos || startPos < 0 || endPos < 0
208 || startPos >= edge->getLoadedLength()
209 || endPos >= edge->getLoadedLength())) {
210 NBEdge* longest = myEdgeCont.getSplitBase(edgeID);
211 if (longest != nullptr) {
212 edge = longest;
213 }
214 }
215 Position pos = edge->geometryPositionAtOffset((startPos + endPos) / 2);
216 myCurrentStop = std::make_shared<NBPTStop>((SumoXMLTag)element, id, pos, edgeID, edgeID, endPos - startPos, name, permissions, parkingLength, color, startPos);
217 while (myEdgeCont.getSplit(edge) != nullptr) {
218 myCurrentStop->resetLoaded();
219 const std::pair<NBEdge*, NBEdge*> split = *myEdgeCont.getSplit(edge);
220 if (myCurrentStop->replaceEdge(edgeID, {split.first, split.second})) {
221 edge = split.first->getID() == myCurrentStop->getEdgeId() ? split.first : split.second;
222 edgeID = edge->getID();
223 }
224 }
225 for (const std::string& line : StringTokenizer(lines).getVector()) {
226 myCurrentStop->addLine(line);
227 }
229 WRITE_ERRORF(TL("Could not add public transport stop '%' (already exists)"), id);
230 }
231 }
232}
233
234void
236 if (myCurrentStop == nullptr) {
238 return;
239 } else {
240 throw InvalidArgument("Could not add access outside a stopping place.");
241 }
242 }
243 bool ok = true;
244 const std::string laneID = attrs.get<std::string>(SUMO_ATTR_LANE, "access", ok);
245 const std::string edgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
246 if (myEdgeCont.retrieve(edgeID) == nullptr) {
247 reportError(TL("Edge '%' for access to stop '%' not found"), edgeID, myCurrentStop->getID());
248 return;
249 }
250 const double pos = attrs.get<double>(SUMO_ATTR_POSITION, "access", ok);
251 const double length = attrs.getOpt<double>(SUMO_ATTR_LENGTH, "access", ok, -1);
252 if (ok) {
253 myCurrentStop->addAccess(laneID, pos, length);
254 }
255}
256
257
258void
260 bool ok = true;
261 const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "ptLine", ok);
262 const std::string name = attrs.getOpt<std::string>(SUMO_ATTR_NAME, id.c_str(), ok, "");
263 const std::string line = attrs.getOpt<std::string>(SUMO_ATTR_LINE, id.c_str(), ok, "");
264 const std::string type = attrs.getOpt<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok, "");
266 if (attrs.hasAttribute(SUMO_ATTR_VCLASS)) {
267 vClass = getVehicleClassID(attrs.get<std::string>(SUMO_ATTR_VCLASS, id.c_str(), ok));
268 }
269 RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor(false));
270 const int intervalS = attrs.getOpt<int>(SUMO_ATTR_PERIOD, id.c_str(), ok, -1);
271 const std::string nightService = attrs.getStringSecure("nightService", "");
272 myCurrentCompletion = StringUtils::toDouble(attrs.getStringSecure("completeness", "1"));
273 myMissingBefore = StringUtils::toInt(attrs.getStringSecure("missingBefore", "0"));
274 myMissingAfter = StringUtils::toInt(attrs.getStringSecure("missingAfter", "0"));
275 if (ok) {
276 // patching existing line?
278 if (myCurrentLine == nullptr) {
279 myCurrentLine = new NBPTLine(id, name, type, line, intervalS / 60, nightService, vClass, color);
281 } else {
282 WRITE_MESSAGEF(TL("Duplicate ptLine id occurred ('%'); assuming overwriting is wished."), id);
283 if (name != "") {
284 myCurrentLine->setName(name);
285 }
286 if (line != "") {
287 myCurrentLine->setRef(line);
288 }
289 if (intervalS != -1) {
290 myCurrentLine->setPeriod(intervalS);
291 }
292 }
293 }
294}
295
296
297void
299 bool ok = true;
300 myMissingBefore = 0;
301 myMissingAfter = 0;
302 const std::string id = attrs.get<std::string>(SUMO_ATTR_ID, "flow", ok);
303 const std::string line = attrs.get<std::string>(SUMO_ATTR_LINE, id.c_str(), ok);
304 const std::string type = attrs.get<std::string>(SUMO_ATTR_TYPE, id.c_str(), ok);
305 const std::string route = attrs.get<std::string>(SUMO_ATTR_ROUTE, id.c_str(), ok);
307 const int intervalS = attrs.getOpt<int>(SUMO_ATTR_PERIOD, id.c_str(), ok, -1);
308 RGBColor color = attrs.getOpt<RGBColor>(SUMO_ATTR_COLOR, id.c_str(), ok, RGBColor(false));
309 if (ok) {
310 myCurrentLine = new NBPTLine(id, "", type, line, intervalS / 60, "", vClass, color);
312 for (std::shared_ptr<NBPTStop> stop : myRouteStops[route]) {
314 }
316 }
317}
318
319
320void
322 if (myCurrentLine == nullptr) {
323 WRITE_ERROR(TL("Found route outside line definition"));
324 return;
325 }
326 bool ok = true;
327 const std::vector<std::string>& edgeIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, nullptr, ok);
328 EdgeVector edges;
329 for (const std::string& edgeID : edgeIDs) {
330 NBEdge* edge = myEdgeCont.retrieve(edgeID);
331 if (edge == nullptr) {
332 reportError(TL("Edge '%' in route of line '%' not found"), edgeID, myCurrentLine->getLineID());
333 } else {
334 edges.push_back(edge);
335 }
336 }
337 myCurrentLine->setEdges(edges);
338}
339
340
341void
343 bool ok = true;
344 myCurrentRouteID = attrs.get<std::string>(SUMO_ATTR_ID, "route", ok);
345 const std::vector<std::string>& edgeIDs = attrs.get<std::vector<std::string> >(SUMO_ATTR_EDGES, myCurrentRouteID.c_str(), ok);
346 EdgeVector edges;
347 for (const std::string& edgeID : edgeIDs) {
348 NBEdge* edge = myEdgeCont.retrieve(edgeID);
349 if (edge == nullptr) {
350 reportError(TL("Edge '%' in route of line '%' not found"), edgeID, myCurrentLine->getLineID());
351 } else {
352 edges.push_back(edge);
353 }
354 }
356}
357
358
359void
361 bool ok = true;
362 const std::string id = attrs.hasAttribute(SUMO_ATTR_ID)
363 ? attrs.get<std::string>(SUMO_ATTR_ID, "ptLine", ok)
364 : attrs.get<std::string>(SUMO_ATTR_BUS_STOP, "ptline", ok);
365 std::shared_ptr<NBPTStop> stop = myStopCont.get(id);
366 if (stop == nullptr) {
367 if (!NBPTStopCont::wasIgnored(id)) {
368 WRITE_ERRORF(TL("Stop '%' within line '%' not found"), id, toString(myCurrentLine->getLineID()));
369 }
370 return;
371 }
373}
374
375void
377 assert(myCurrentRouteID != "");
378 bool ok = true;
379 const std::string id = attrs.hasAttribute(SUMO_ATTR_ID)
380 ? attrs.get<std::string>(SUMO_ATTR_ID, "ptLine", ok)
381 : attrs.get<std::string>(SUMO_ATTR_BUS_STOP, "ptline", ok);
382 std::shared_ptr<NBPTStop> stop = myStopCont.get(id);
383 if (stop == nullptr) {
384 WRITE_ERRORF(TL("Stop '%' within route '%' not found"), id, toString(myCurrentRouteID));
385 return;
386 }
387 myRouteStops[myCurrentRouteID].push_back(stop);
388}
389
390
391/****************************************************************************/
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define WRITE_MESSAGEF(...)
Definition MsgHandler.h:289
#define WRITE_ERRORF(...)
Definition MsgHandler.h:296
#define WRITE_ERROR(msg)
Definition MsgHandler.h:295
#define TL(string)
Definition MsgHandler.h:304
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition NBCont.h:42
SUMOVehicleClass getVehicleClassID(const std::string &name)
Returns the class id of the abstract class given by its name.
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_SHIP
is an arbitrary ship
@ SVC_TAXI
vehicle is a taxi
@ SVC_BUS
vehicle is a bus
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_ACCESS
An access point for a train stop.
@ SUMO_TAG_PT_LINE
A pt line.
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_STOP
stop for vehicles
@ SUMO_TAG_FLOW
a flow definition using from and to edges or a route
@ SUMO_TAG_ROUTE
description of a route
@ SUMO_TAG_TRAIN_STOP
A train stop (alias for bus stop)
@ SUMO_TAG_PARAM
parameter associated to a certain key
@ SUMO_TAG_TRIP
a single trip definition (used by router)
@ SUMO_ATTR_STARTPOS
@ SUMO_ATTR_LINES
@ SUMO_ATTR_LANE
@ SUMO_ATTR_VALUE
@ SUMO_ATTR_PARKING_LENGTH
@ SUMO_ATTR_BUS_STOP
@ SUMO_ATTR_ENDPOS
@ SUMO_ATTR_EDGES
the edges of a route
@ SUMO_ATTR_LINE
@ SUMO_ATTR_NAME
@ SUMO_ATTR_PERIOD
@ SUMO_ATTR_VCLASS
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_LENGTH
@ SUMO_ATTR_ROUTE
@ SUMO_ATTR_COLOR
A color information.
@ SUMO_ATTR_ID
@ SUMO_ATTR_KEY
@ SUMO_ATTR_POSITION
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:49
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
const std::pair< NBEdge *, NBEdge * > * getSplit(const NBEdge *const origEdge) const
Returns the edge split if the edge has been split, nullptr otherwise.
Definition NBEdgeCont.h:303
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
Definition NBEdgeCont.h:486
bool wasRemoved(std::string id) const
Returns whether the edge with the id was deleted explicitly.
Definition NBEdgeCont.h:496
NBEdge * getSplitBase(const std::string &edgeID) const
The representation of a single edge during network building.
Definition NBEdge.h:92
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition NBEdge.cpp:4541
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition NBEdge.h:608
const std::string & getID() const
Definition NBEdge.h:1551
int getNumLanes() const
Returns the number of lanes.
Definition NBEdge.h:526
Position geometryPositionAtOffset(double offset) const
return position taking into account loaded length
Definition NBEdge.cpp:4882
static int getLaneIndexFromLaneID(const std::string laneID)
Definition NBEdge.cpp:4999
NBPTLine * retrieve(const std::string &lineID)
bool insert(NBPTLine *ptLine)
insert new line
void setNumOfStops(int numStops, int missingBefore, int missingAfter)
Definition NBPTLine.cpp:166
void setName(const std::string &name)
Definition NBPTLine.h:118
void setRef(const std::string &line)
Definition NBPTLine.h:122
const std::string & getLineID() const
Definition NBPTLine.h:51
void setPeriod(int intervalS)
Definition NBPTLine.h:126
const std::vector< std::shared_ptr< NBPTStop > > & getStops()
Definition NBPTLine.cpp:68
void addPTStop(std::shared_ptr< NBPTStop > pStop)
Definition NBPTLine.cpp:54
void setEdges(const std::vector< NBEdge * > &edges)
Definition NBPTLine.cpp:141
Container for public transport stops during the net building process.
static void addIgnored(const std::string &stopID)
std::shared_ptr< NBPTStop > get(std::string id) const
Retrieve a previously inserted pt stop.
static bool wasIgnored(const std::string &stopID)
bool insert(std::shared_ptr< NBPTStop > ptStop, bool floating=false)
Inserts a node into the map.
static SUMOVehicleClass interpretTransportType(const std::string &type, NIOSMNode *toSet=nullptr)
translate osm transport designations into sumo vehicle class
void addPTStop(int element, const SUMOSAXAttributes &attrs)
Parses an public transport stop.
NIXMLPTHandler(NBEdgeCont &ec, NBPTStopCont &sc, NBPTLineCont &lc)
Constructor.
void addPTLine(const SUMOSAXAttributes &attrs)
Parses a public transport line.
std::shared_ptr< NBPTStop > myCurrentStop
The currently processed stop.
~NIXMLPTHandler()
Destructor.
std::map< std::string, std::vector< std::shared_ptr< NBPTStop > > > myRouteStops
stand-alone route information
std::string myCurrentRouteID
The currently processed stand-alone route.
void addPTLineStop(const SUMOSAXAttributes &attrs)
Parses an public transport stop reference within a line element.
void addPTLineFromFlow(const SUMOSAXAttributes &attrs)
Parses a public transport line.
bool reportError(const std::string &msg, const std::string &edgeID, const std::string &id)
reprot error or warning depending on options and explicit edge removal
NBPTStopCont & myStopCont
The stop container (for loading of stops)
void myEndElement(int element)
Called when a closing tag occurs.
NBEdgeCont & myEdgeCont
The edges container (for retrieving referenced stop edge)
std::map< std::string, EdgeVector > myRouteEdges
NBPTLineCont & myLineCont
The line container (for loading of lines)
bool myCurrentStopWasIgnored
whether the current stop should be discarded
void addPTLineRoute(const SUMOSAXAttributes &attrs)
Parses a route as port of a public transport line.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
double myCurrentCompletion
the completion level of the current line
void addRoute(const SUMOSAXAttributes &attrs)
Parses a stand-alone route when parsing implicit ptlines from routes and flows.
void addRouteStop(const SUMOSAXAttributes &attrs)
Parses an public transport stop reference within a route element.
void addAccess(const SUMOSAXAttributes &attrs)
Parses an stop access definition.
NBPTLine * myCurrentLine
The currently processed line.
A storage for options typed value containers)
Definition OptionsCont.h:89
A point in 2D or 3D with translation and scaling methods.
Definition Position.h:37
Encapsulated SAX-Attributes.
virtual std::string getString(int id, bool *isPresent=nullptr) const =0
Returns the string-value of the named (by its enum-value) attribute.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue=T(), bool report=true) const
Tries to read given attribute assuming it is an int.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
SAX-handler base for SUMO-files.
static std::string getEdgeIDFromLane(const std::string laneID)
return edge id when given the lane ID
std::vector< std::string > getVector()
return vector of strings
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...