Eclipse SUMO - Simulation of Urban MObility
Loading...
Searching...
No Matches
NBPTLine.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/****************************************************************************/
19// The representation of one direction of a single pt line
20/****************************************************************************/
22
23#include <utility>
27#include "NBEdge.h"
28#include "NBEdgeCont.h"
29#include "NBPTStop.h"
30#include "NBPTStopCont.h"
31#include "NBPTLine.h"
32
33
34// ===========================================================================
35// method definitions
36// ===========================================================================
37NBPTLine::NBPTLine(const std::string& id, const std::string& name, const std::string& type, const std::string& ref, int interval, const std::string& nightService,
38 SUMOVehicleClass vClass, RGBColor color) :
39 myName(name),
40 myType(type),
41 myPTLineId(id),
42 myRef(ref != "" ? ref : name),
43 myColor(color),
44 myInterval(interval),
45 myNightService(nightService),
46 myVClass(vClass),
47 myNumOfStops(0),
48 myMissingStopsBefore(0),
49 myMissingStopsAfter(0)
50{ }
51
52
53void
54NBPTLine::addPTStop(std::shared_ptr<NBPTStop> pStop) {
55 if (!myPTStops.empty() && pStop->getName() != "" && myPTStops.back()->getName() == pStop->getName()) {
56 // avoid duplicate stop when both platform and stop_position are given as nodes
57 if (myPTStops.back()->isPlatform() && !pStop->isPlatform()) {
58 myPTStops.pop_back();
59 } else if (pStop->isPlatform()) {
60 return;
61 }
62 }
63 myPTStops.push_back(pStop);
64}
65
66
67const std::vector<std::shared_ptr<NBPTStop> >&
69 return myPTStops;
70}
71
72
73void
77 if (!myName.empty()) {
79 }
80
84 if (myInterval > 0) {
85 // write seconds
87 }
88 if (myNightService != "") {
89 device.writeAttr("nightService", myNightService);
90 }
91
92 if (myColor.isValid()) {
94 }
95 device.writeAttr("completeness", (double)myPTStops.size() / myNumOfStops);
96 if (myMissingStopsBefore != 0) {
97 device.writeAttr("missingBefore", myMissingStopsBefore);
98 }
99 if (myMissingStopsAfter != 0) {
100 device.writeAttr("missingAfter", myMissingStopsAfter);
101 }
102
103 if (!myRoute.empty()) {
104 device.openTag(SUMO_TAG_ROUTE);
106 device.closeTag();
107 }
108
109 for (auto& myPTStop : myPTStops) {
111 device.writeAttr(SUMO_ATTR_ID, myPTStop->getID());
112 device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myPTStop->getName()));
113 device.closeTag();
114 }
115 device.closeTag();
116
117}
118
119
120void
121NBPTLine::addWayNode(long long int way, long long int node) {
122 std::string wayStr = toString(way);
123 if (wayStr != myCurrentWay) {
124 myCurrentWay = wayStr;
125 myWays.push_back(wayStr);
126 }
127 myWayNodes[wayStr].push_back(node);
128}
129
130
131const std::vector<long long int>*
132NBPTLine::getWayNodes(std::string wayId) {
133 if (myWayNodes.find(wayId) != myWayNodes.end()) {
134 return &myWayNodes[wayId];
135 }
136 return nullptr;
137}
138
139
140void
141NBPTLine::setEdges(const std::vector<NBEdge*>& edges) {
142 myRoute = edges;
143 // ensure permissions
144 for (NBEdge* e : edges) {
145 SVCPermissions permissions = e->getPermissions();
146 if ((permissions & myVClass) != myVClass) {
148 if (permissions != 0 && (permissions & nVuln) == 0) {
149 // this is a footpath or sidewalk. Add another lane
150 e->addRestrictedLane(SUMO_const_laneWidth, myVClass);
151 } else {
152 // add permissions to the rightmost lane that is not exclusively used for pedestrians / bicycles
153 for (int i = 0; i < (int)e->getNumLanes(); i++) {
154 if ((e->getPermissions(i) & nVuln) != 0) {
155 e->allowVehicleClass(i, myVClass);
156 break;
157 }
158 }
159 }
160 }
161 }
162}
163
164
165void
166NBPTLine::setNumOfStops(int numStops, int missingBefore, int missingAfter) {
167 myNumOfStops = numStops;
168 myMissingStopsBefore = missingBefore;
169 myMissingStopsAfter = missingAfter;
170}
171
172
173const std::vector<NBEdge*>&
175 return myRoute;
176}
177
178
179std::vector<NBPTLine::PTStopInfo>
181 std::vector<PTStopInfo> result;
182 int i = 0;
183 for (std::shared_ptr<NBPTStop> stop : myPTStops) {
184 NBEdge* e = ec.retrieve(stop->getEdgeId());
185 if (e != nullptr) {
186 bool revised = (int)myStopsRevised.size() > i ? myStopsRevised[i] : false;
187 result.push_back(PTStopInfo(e, stop->getID(), stop->getEndPos(), revised));
188 }
189 i++;
190 }
191 return result;
192}
193
194
195NBEdge*
197 std::vector<NBEdge*> validEdges;
198 // filter out edges that have been removed due to joining junctions
199 for (NBEdge* e : myRoute) {
200 if (ec.retrieve(e->getID())) {
201 validEdges.push_back(e);
202 }
203 }
204 if (validEdges.size() == 0) {
205 return nullptr;
206 }
207 // filter out edges after the first stop
208 if (myPTStops.size() > 0) {
209 NBEdge* firstStopEdge = ec.retrieve(myPTStops.front()->getEdgeId());
210 if (firstStopEdge == nullptr) {
211 WRITE_WARNINGF(TL("Could not retrieve edge '%' for first stop of line '%'."), myPTStops.front()->getEdgeId(), myPTLineId);
212 return nullptr;
213
214 }
215 auto it = std::find(validEdges.begin(), validEdges.end(), firstStopEdge);
216 if (it == validEdges.end()) {
217 WRITE_WARNINGF(TL("First stop edge '%' is not part of the route of line '%'."), firstStopEdge->getID(), myPTLineId);
218 return nullptr;
219 }
220 }
221 return validEdges.front();
222}
223
224
225NBEdge*
227 std::vector<NBEdge*> validEdges;
228 // filter out edges that have been removed due to joining junctions
229 for (NBEdge* e : myRoute) {
230 if (ec.retrieve(e->getID())) {
231 validEdges.push_back(e);
232 }
233 }
234 if (validEdges.size() == 0) {
235 return nullptr;
236 }
237 // filter out edges after the last stop
238 if (myPTStops.size() > 0) {
239 NBEdge* lastStopEdge = ec.retrieve(myPTStops.back()->getEdgeId());
240 if (lastStopEdge == nullptr) {
241 WRITE_WARNINGF(TL("Could not retrieve edge '%' for last stop of line '%'."), myPTStops.back()->getEdgeId(), myPTLineId);
242 return nullptr;
243
244 }
245 auto it = std::find(validEdges.begin(), validEdges.end(), lastStopEdge);
246 if (it == validEdges.end()) {
247 WRITE_WARNINGF(TL("Last stop edge '%' is not part of the route of line '%'."), lastStopEdge->getID(), myPTLineId);
248 return nullptr;
249 }
250 }
251 return validEdges.back();
252}
253
254
255bool
256NBPTLine::isConsistent(std::vector<NBEdge*> stops) const {
257 if (myRoute.empty() || stops.empty()) {
258 return true;
259 }
260 if (stops.size() > 1 && stops.front() == stops.back()) {
261 // circular route where we don't expect the route edges to occur twice
262 if (myRoute.front() == stops.front()) {
263 stops.pop_back();
264 } else if (myRoute.back() == stops.back()) {
265 stops.erase(stops.begin());
266 }
267 }
268 std::vector<NBEdge*>::const_iterator stopIt = stops.begin();
269 for (const NBEdge* const e : myRoute) {
270 while (stopIt != stops.end() && e == *stopIt) {
271 ++stopIt;
272 }
273 if (stopIt == stops.end()) {
274 return true;
275 }
276 }
277 return false;
278}
279
280
281void
282NBPTLine::replaceStop(std::shared_ptr<NBPTStop> oldStop, std::shared_ptr<NBPTStop> newStop) {
283 for (int i = 0; i < (int)myPTStops.size(); i++) {
284 if (myPTStops[i] == oldStop) {
285 myPTStops[i] = newStop;
286 }
287 }
288}
289
290
291void
292NBPTLine::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
293 EdgeVector oldRoute = myRoute;
294 myRoute.clear();
295 for (NBEdge* e : oldRoute) {
296 if (e->getID() == edgeID) {
297 for (NBEdge* e2 : replacement) {
298 if (myRoute.empty() || myRoute.back() != e2) {
299 myRoute.push_back(e2);
300 }
301 }
302 } else {
303 myRoute.push_back(e);
304 }
305 }
306}
307
308
309void
311 // delete stops that are missing or have no edge
312 for (auto it = myPTStops.begin(); it != myPTStops.end();) {
313 std::shared_ptr<NBPTStop> stop = *it;
314 if (sc.get(stop->getID()) == nullptr ||
315 ec.getByID(stop->getEdgeId()) == nullptr) {
316 WRITE_WARNINGF(TL("Removed invalid stop '%' from line '%'."), stop->getID(), getLineID());
317 it = myPTStops.erase(it);
318 } else {
319 it++;
320 }
321
322 }
323}
324
325
326void
328 // delete subsequent stops that belong to the same stopArea
329 long long int lastAreaID = -1;
330 std::string lastName = "";
331 for (auto it = myPTStops.begin(); it != myPTStops.end();) {
332 std::shared_ptr<NBPTStop> stop = *it;
333 if (lastAreaID != -1 && stop->getAreaID() == lastAreaID) {
334 WRITE_WARNINGF(TL("Removed duplicate stop '%' at area '%' from line '%'."), stop->getID(), toString(lastAreaID), getLineID());
335 it = myPTStops.erase(it);
336 } else if (lastName != "" && stop->getName() == lastName) {
337 WRITE_WARNINGF(TL("Removed duplicate stop '%' named '%' from line '%'."), stop->getID(), lastName, getLineID());
338 it = myPTStops.erase(it);
339 } else {
340 it++;
341 }
342 lastAreaID = stop->getAreaID();
343 lastName = stop->getName();
344 }
345}
346
347
348void
350 for (int i = 0; i < (int)myRoute.size();) {
351 const std::pair<NBEdge*, NBEdge*>* split = ec.getSplit(myRoute[i]);
352 if (split != nullptr) {
353 myRoute[i] = split->first;
354 myRoute.insert(myRoute.begin() + i + 1, split->second);
355 } else if (ec.retrieve(myRoute[i]->getID()) == nullptr) {
356 myRoute.erase(myRoute.begin() + i);
357 } else {
358 i++;
359 }
360 }
361 // validate that all stops are actually on the route
362 auto ri = myRoute.begin();
363 for (auto it = myPTStops.begin(); it != myPTStops.end();) {
364 std::shared_ptr<NBPTStop> stop = *it;
365 NBEdge* e = ec.retrieve(stop->getEdgeId());
366 if (e == nullptr) {
367 WRITE_WARNINGF(TL("Removed stop '%' named '%' from line '%' because edge '%' is missing."),
368 stop->getID(), stop->getName(), getLineID(), stop->getEdgeId());
369 it = myPTStops.erase(it);
370 } else {
371 auto riPrev = ri;
372 ri = std::find(ri, myRoute.end(), e);
373 if (ri == myRoute.end()) {
374 std::string reason = std::find(myRoute.begin(), myRoute.end(), e) == myRoute.end()
375 ? TL("not part of the route")
376 : TL("not part of the route downstream of the previous stop");
377
378 WRITE_WARNINGF(TL("Stop '%' named '%' from line '%' on edge '%' is %."),
379 stop->getID(), stop->getName(), getLineID(), stop->getEdgeId(), reason);
380 ri = riPrev;
381 }
382 it++;
383 }
384 }
385}
386
387
388/****************************************************************************/
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
Definition MsgHandler.h:287
#define TL(string)
Definition MsgHandler.h:304
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition NBCont.h:42
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_BICYCLE
vehicle is a bicycle
@ SVC_PEDESTRIAN
pedestrian
@ SUMO_TAG_PT_LINE
A pt line.
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_ROUTE
description of a route
@ 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_COLOR
A color information.
@ SUMO_ATTR_ID
const double SUMO_const_laneWidth
Definition StdDefs.h:52
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition ToString.h:46
Storage for edges, including some functionality operating on multiple edges.
Definition NBEdgeCont.h:59
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
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:300
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
The representation of a single edge during network building.
Definition NBEdge.h:92
const std::string & getID() const
Definition NBEdge.h:1551
void replaceStop(std::shared_ptr< NBPTStop > oldStop, std::shared_ptr< NBPTStop > newStop)
replace the given stop
Definition NBPTLine.cpp:282
void setNumOfStops(int numStops, int missingBefore, int missingAfter)
Definition NBPTLine.cpp:166
int myMissingStopsAfter
Definition NBPTLine.h:171
bool isConsistent(std::vector< NBEdge * > stops) const
return whether the mentioned edges appear in that order in the route
Definition NBPTLine.cpp:256
void deleteDuplicateStops()
Definition NBPTLine.cpp:327
const std::vector< long long int > * getWayNodes(std::string wayId)
Definition NBPTLine.cpp:132
int myMissingStopsBefore
Definition NBPTLine.h:170
SUMOVehicleClass myVClass
Definition NBPTLine.h:158
std::string myPTLineId
Definition NBPTLine.h:149
void replaceEdge(const std::string &edgeID, const std::vector< NBEdge * > &replacement)
replace the edge with the given edge list
Definition NBPTLine.cpp:292
NBPTLine(const std::string &id, const std::string &name, const std::string &type, const std::string &ref, int interval, const std::string &nightService, SUMOVehicleClass vClass, RGBColor color)
Definition NBPTLine.cpp:37
std::map< std::string, std::vector< long long int > > myWayNodes
Definition NBPTLine.h:146
std::vector< std::string > myWays
Definition NBPTLine.h:147
void deleteInvalidStops(const NBEdgeCont &ec, const NBPTStopCont &sc)
remove invalid stops from the line
Definition NBPTLine.cpp:310
void write(OutputDevice &device)
Definition NBPTLine.cpp:74
std::vector< NBEdge * > myRoute
Definition NBPTLine.h:164
void removeInvalidEdges(const NBEdgeCont &ec)
remove invalid edges from the line
Definition NBPTLine.cpp:349
std::vector< bool > myStopsRevised
Definition NBPTLine.h:145
int myNumOfStops
Definition NBPTLine.h:169
int myInterval
Definition NBPTLine.h:155
std::string myName
Definition NBPTLine.h:141
RGBColor myColor
Definition NBPTLine.h:152
const std::string & getLineID() const
Definition NBPTLine.h:51
std::vector< PTStopInfo > getStopEdges(const NBEdgeCont &ec) const
Definition NBPTLine.cpp:180
std::string myCurrentWay
Definition NBPTLine.h:148
std::string myRef
Definition NBPTLine.h:150
NBEdge * getRouteEnd(const NBEdgeCont &ec) const
return last valid edge of myRoute (if it doest not lie before the last stop)
Definition NBPTLine.cpp:226
const std::vector< NBEdge * > & getRoute() const
Definition NBPTLine.cpp:174
std::vector< std::shared_ptr< NBPTStop > > myPTStops
Definition NBPTLine.h:143
void addWayNode(long long int way, long long int node)
Definition NBPTLine.cpp:121
std::string myType
Definition NBPTLine.h:142
std::string myNightService
Definition NBPTLine.h:157
NBEdge * getRouteStart(const NBEdgeCont &ec) const
return first valid edge of myRoute (if it doest not lie after the first stop)
Definition NBPTLine.cpp:196
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.
std::shared_ptr< NBPTStop > get(std::string id) const
Retrieve a previously inserted pt stop.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
bool isValid() const
check if RGBColor is valid
Definition RGBColor.cpp:120
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
get stop edges and stop ids and directional validity
Definition NBPTLine.h:82