Eclipse SUMO - Simulation of Urban MObility
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-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 /****************************************************************************/
19 // The representation of one direction of a single pt line
20 /****************************************************************************/
22 
23 #include <utility>
24 #include <utils/common/ToString.h>
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 // ===========================================================================
37 NBPTLine::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 
53 void
54 NBPTLine::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 
67 const std::vector<std::shared_ptr<NBPTStop> >&
69  return myPTStops;
70 }
71 
72 
73 void
75  device.openTag(SUMO_TAG_PT_LINE);
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) {
110  device.openTag(SUMO_TAG_BUS_STOP);
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 
120 void
121 NBPTLine::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 
131 const std::vector<long long int>*
132 NBPTLine::getWayNodes(std::string wayId) {
133  if (myWayNodes.find(wayId) != myWayNodes.end()) {
134  return &myWayNodes[wayId];
135  }
136  return nullptr;
137 }
138 
139 
140 void
141 NBPTLine::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 
165 void
166 NBPTLine::setNumOfStops(int numStops, int missingBefore, int missingAfter) {
167  myNumOfStops = numStops;
168  myMissingStopsBefore = missingBefore;
169  myMissingStopsAfter = missingAfter;
170 }
171 
172 
173 const std::vector<NBEdge*>&
175  return myRoute;
176 }
177 
178 
179 std::vector<std::pair<NBEdge*, std::string> >
181  std::vector<std::pair<NBEdge*, std::string> > result;
182  for (std::shared_ptr<NBPTStop> stop : myPTStops) {
183  NBEdge* e = ec.retrieve(stop->getEdgeId());
184  if (e != nullptr) {
185  result.push_back({e, stop->getID()});
186  }
187  }
188  return result;
189 }
190 
191 
192 NBEdge*
194  std::vector<NBEdge*> validEdges;
195  // filter out edges that have been removed due to joining junctions
196  for (NBEdge* e : myRoute) {
197  if (ec.retrieve(e->getID())) {
198  validEdges.push_back(e);
199  }
200  }
201  if (validEdges.size() == 0) {
202  return nullptr;
203  }
204  // filter out edges after the first stop
205  if (myPTStops.size() > 0) {
206  NBEdge* firstStopEdge = ec.retrieve(myPTStops.front()->getEdgeId());
207  if (firstStopEdge == nullptr) {
208  WRITE_WARNINGF(TL("Could not retrieve edge '%' for first stop of line '%'."), myPTStops.front()->getEdgeId(), myPTLineId);
209  return nullptr;
210 
211  }
212  auto it = std::find(validEdges.begin(), validEdges.end(), firstStopEdge);
213  if (it == validEdges.end()) {
214  WRITE_WARNINGF(TL("First stop edge '%' is not part of the route of line '%'."), firstStopEdge->getID(), myPTLineId);
215  return nullptr;
216  }
217  }
218  return validEdges.front();
219 }
220 
221 
222 NBEdge*
224  std::vector<NBEdge*> validEdges;
225  // filter out edges that have been removed due to joining junctions
226  for (NBEdge* e : myRoute) {
227  if (ec.retrieve(e->getID())) {
228  validEdges.push_back(e);
229  }
230  }
231  if (validEdges.size() == 0) {
232  return nullptr;
233  }
234  // filter out edges after the last stop
235  if (myPTStops.size() > 0) {
236  NBEdge* lastStopEdge = ec.retrieve(myPTStops.back()->getEdgeId());
237  if (lastStopEdge == nullptr) {
238  WRITE_WARNINGF(TL("Could not retrieve edge '%' for last stop of line '%'."), myPTStops.back()->getEdgeId(), myPTLineId);
239  return nullptr;
240 
241  }
242  auto it = std::find(validEdges.begin(), validEdges.end(), lastStopEdge);
243  if (it == validEdges.end()) {
244  WRITE_WARNINGF(TL("Last stop edge '%' is not part of the route of line '%'."), lastStopEdge->getID(), myPTLineId);
245  return nullptr;
246  }
247  }
248  return validEdges.back();
249 }
250 
251 
252 bool
253 NBPTLine::isConsistent(std::vector<NBEdge*> stops) const {
254  if (myRoute.empty() || stops.empty()) {
255  return true;
256  }
257  if (stops.size() > 1 && stops.front() == stops.back()) {
258  // circular route where we don't expect the route edges to occur twice
259  if (myRoute.front() == stops.front()) {
260  stops.pop_back();
261  } else if (myRoute.back() == stops.back()) {
262  stops.erase(stops.begin());
263  }
264  }
265  std::vector<NBEdge*>::const_iterator stopIt = stops.begin();
266  for (const NBEdge* const e : myRoute) {
267  while (stopIt != stops.end() && e == *stopIt) {
268  ++stopIt;
269  }
270  if (stopIt == stops.end()) {
271  return true;
272  }
273  }
274  return false;
275 }
276 
277 
278 void
279 NBPTLine::replaceStop(std::shared_ptr<NBPTStop> oldStop, std::shared_ptr<NBPTStop> newStop) {
280  for (int i = 0; i < (int)myPTStops.size(); i++) {
281  if (myPTStops[i] == oldStop) {
282  myPTStops[i] = newStop;
283  }
284  }
285 }
286 
287 
288 void
289 NBPTLine::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
290  EdgeVector oldRoute = myRoute;
291  myRoute.clear();
292  for (NBEdge* e : oldRoute) {
293  if (e->getID() == edgeID) {
294  for (NBEdge* e2 : replacement) {
295  if (myRoute.empty() || myRoute.back() != e2) {
296  myRoute.push_back(e2);
297  }
298  }
299  } else {
300  myRoute.push_back(e);
301  }
302  }
303 }
304 
305 
306 void
308  // delete stops that are missing or have no edge
309  for (auto it = myPTStops.begin(); it != myPTStops.end();) {
310  std::shared_ptr<NBPTStop> stop = *it;
311  if (sc.get(stop->getID()) == nullptr ||
312  ec.getByID(stop->getEdgeId()) == nullptr) {
313  WRITE_WARNINGF(TL("Removed invalid stop '%' from line '%'."), stop->getID(), getLineID());
314  it = myPTStops.erase(it);
315  } else {
316  it++;
317  }
318 
319  }
320 }
321 
322 
323 void
325  // delete subsequent stops that belong to the same stopArea
326  long long int lastAreaID = -1;
327  std::string lastName = "";
328  for (auto it = myPTStops.begin(); it != myPTStops.end();) {
329  std::shared_ptr<NBPTStop> stop = *it;
330  if (lastAreaID != -1 && stop->getAreaID() == lastAreaID) {
331  WRITE_WARNINGF(TL("Removed duplicate stop '%' at area '%' from line '%'."), stop->getID(), toString(lastAreaID), getLineID());
332  it = myPTStops.erase(it);
333  } else if (lastName != "" && stop->getName() == lastName) {
334  WRITE_WARNINGF(TL("Removed duplicate stop '%' named '%' from line '%'."), stop->getID(), lastName, getLineID());
335  it = myPTStops.erase(it);
336  } else {
337  it++;
338  }
339  lastAreaID = stop->getAreaID();
340  lastName = stop->getName();
341  }
342 }
343 
344 
345 void
347  for (int i = 0; i < (int)myRoute.size();) {
348  const std::pair<NBEdge*, NBEdge*>* split = ec.getSplit(myRoute[i]);
349  if (split != nullptr) {
350  myRoute[i] = split->first;
351  myRoute.insert(myRoute.begin() + i + 1, split->second);
352  } else if (ec.retrieve(myRoute[i]->getID()) == nullptr) {
353  myRoute.erase(myRoute.begin() + i);
354  } else {
355  i++;
356  }
357  }
358 }
359 
360 
361 /****************************************************************************/
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define TL(string)
Definition: MsgHandler.h:315
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
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
begin/end of the 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:48
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.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:281
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
The representation of a single edge during network building.
Definition: NBEdge.h:92
const std::string & getID() const
Definition: NBEdge.h:1522
void replaceStop(std::shared_ptr< NBPTStop > oldStop, std::shared_ptr< NBPTStop > newStop)
replace the given stop
Definition: NBPTLine.cpp:279
void setNumOfStops(int numStops, int missingBefore, int missingAfter)
Definition: NBPTLine.cpp:166
int myMissingStopsAfter
Definition: NBPTLine.h:153
bool isConsistent(std::vector< NBEdge * > stops) const
return whether the mentioned edges appear in that order in the route
Definition: NBPTLine.cpp:253
void deleteDuplicateStops()
Definition: NBPTLine.cpp:324
const std::vector< long long int > * getWayNodes(std::string wayId)
Definition: NBPTLine.cpp:132
int myMissingStopsBefore
Definition: NBPTLine.h:152
SUMOVehicleClass myVClass
Definition: NBPTLine.h:140
std::string myPTLineId
Definition: NBPTLine.h:131
void replaceEdge(const std::string &edgeID, const std::vector< NBEdge * > &replacement)
replace the edge with the given edge list
Definition: NBPTLine.cpp:289
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:128
std::vector< std::string > myWays
Definition: NBPTLine.h:129
void deleteInvalidStops(const NBEdgeCont &ec, const NBPTStopCont &sc)
remove invalid stops from the line
Definition: NBPTLine.cpp:307
void write(OutputDevice &device)
Definition: NBPTLine.cpp:74
std::vector< NBEdge * > myRoute
Definition: NBPTLine.h:146
void removeInvalidEdges(const NBEdgeCont &ec)
remove invalid edges from the line
Definition: NBPTLine.cpp:346
int myNumOfStops
Definition: NBPTLine.h:151
const std::string & getLineID() const
Definition: NBPTLine.h:51
std::vector< std::pair< NBEdge *, std::string > > getStopEdges(const NBEdgeCont &ec) const
get stop edges and stop ids
Definition: NBPTLine.cpp:180
int myInterval
Definition: NBPTLine.h:137
std::string myName
Definition: NBPTLine.h:125
RGBColor myColor
Definition: NBPTLine.h:134
std::string myCurrentWay
Definition: NBPTLine.h:130
std::string myRef
Definition: NBPTLine.h:132
NBEdge * getRouteEnd(const NBEdgeCont &ec) const
return last valid edge of myRoute (if it doest not lie before the last stop)
Definition: NBPTLine.cpp:223
const std::vector< NBEdge * > & getRoute() const
Definition: NBPTLine.cpp:174
std::vector< std::shared_ptr< NBPTStop > > myPTStops
Definition: NBPTLine.h:127
void addWayNode(long long int way, long long int node)
Definition: NBPTLine.cpp:121
std::string myType
Definition: NBPTLine.h:126
std::string myNightService
Definition: NBPTLine.h:139
NBEdge * getRouteStart(const NBEdgeCont &ec) const
return first valid edge of myRoute (if it doest not lie after the first stop)
Definition: NBPTLine.cpp:193
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.
Definition: NBPTStopCont.h:44
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.
Definition: OutputDevice.h:61
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
Definition: OutputDevice.h:254
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.