Eclipse SUMO - Simulation of Urban MObility
NBPTStopCont.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
15 // Container for pt stops during the netbuilding process
16 /****************************************************************************/
17 
18 
20 #include <utils/geom/Boundary.h>
22 #include <microsim/MSLane.h>
23 #include "NBPTStopCont.h"
24 #include "NBEdgeCont.h"
25 #include "NBEdge.h"
26 #include "NBNode.h"
27 #include <utils/geom/Position.h>
28 
29 
31  for (auto& myPTStop : myPTStops) {
32  delete myPTStop.second;
33  }
34  myPTStops.clear();
35 }
36 
37 
38 bool
40  std::string id = ptStop->getID();
41  auto i = myPTStops.find(id);
42  if (i != myPTStops.end()) {
43  return false;
44  }
45  myPTStops[id] = ptStop;
46  return true;
47 }
48 
49 
50 NBPTStop*
51 NBPTStopCont::get(std::string id) {
52  if (myPTStops.find(id) != myPTStops.end()) {
53  return myPTStops.find(id)->second;
54  }
55  return nullptr;
56 }
57 
58 
59 void
61  std::vector<NBPTStop*> reverseStops;
62  //first pass localize pt stop at correct side of the street; create stop for opposite side if needed
63  for (auto& myPTStop : myPTStops) {
64 
65  NBPTStop* stop = myPTStop.second;
66 
67  bool multipleStopPositions = stop->getIsMultipleStopPositions();
68  bool platformsDefined = !stop->getPlatformCands().empty();
69  if (!platformsDefined) {
70  //create pt stop for reverse edge if edge exists
71  NBPTStop* reverseStop = getReverseStop(stop, cont);
72  if (reverseStop != nullptr) {
73  reverseStops.push_back(reverseStop);
74  }
75  } else if (multipleStopPositions) {
76  //create pt stop for closest platform at corresponding edge
78 
79  } else {
80  //create pt stop for each side of the street where a platform is defined (create additional pt stop as needed)
81  NBPTStop* additionalStop = assignAndCreatNewPTStopAsNeeded(stop, cont);
82  if (additionalStop != nullptr) {
83  reverseStops.push_back(additionalStop);
84  }
85  }
86  }
87 
88  //insrt new stops if any
89  for (auto& reverseStop : reverseStops) {
90  insert(reverseStop);
91  }
92 }
93 
94 
96  //scnd pass set correct lane
97  for (auto i = myPTStops.begin(); i != myPTStops.end();) {
98  NBPTStop* stop = i->second;
99 
100  if (!stop->findLaneAndComputeBusStopExtent(cont)) {
101  WRITE_WARNING("Could not find corresponding edge or compatible lane for pt stop: " + i->second->getName()
102  + ". Thus, it will be removed!");
103  EdgeVector edgeVector = cont.getGeneratedFrom((*i).second->getOrigEdgeId());
104  //std::cout << edgeVector.size() << std::endl;
105  myPTStops.erase(i++);
106  } else {
107  i++;
108  }
109  }
110 }
111 
112 
113 int
115  //scnd pass set correct lane
116  std::vector<NBPTStop*> toAdd;
117  for (auto i = myPTStops.begin(); i != myPTStops.end(); i++) {
118  NBPTStop* stop = i->second;
119  NBEdge* edge = ec.getByID(stop->getEdgeId());
120  if (edge != nullptr && edge->isBidiRail()) {
121  NBEdge* bidiEdge = edge->getTurnDestination(true);
122  assert(bidiEdge != 0);
123  const std::string id = getReverseID(stop->getID());
124  if (myPTStops.count(id) > 0) {
125  if (myPTStops[id]->getEdgeId() != bidiEdge->getID()) {
126  WRITE_WARNING("Could not create reverse-direction stop for superposed edge '" + bidiEdge->getID()
127  + "' (origStop '" + i->first + "'). Stop id '" + id
128  + "' already in use by stop on edge '" + myPTStops[id]->getEdgeId() + "'.");
129  }
130  continue;
131  }
132  NBPTStop* bidiStop = new NBPTStop(id,
133  stop->getPosition(),
134  bidiEdge->getID(),
135  stop->getOrigEdgeId(),
136  stop->getLength(),
137  stop->getName(),
138  stop->getPermissions());
139  if (bidiStop->findLaneAndComputeBusStopExtent(ec)) {
140  toAdd.push_back(bidiStop);
141  stop->setBidiStop(bidiStop);
142  bidiStop->setBidiStop(stop);
143  } else {
144  // should not happen
145  assert(false);
146  }
147  }
148  }
149  for (NBPTStop* newStop : toAdd) {
150  myPTStops[newStop->getID()] = newStop;
151  }
152  if (toAdd.size() > 0) {
153  WRITE_MESSAGE("Added " + toString(toAdd.size()) + " stops for superposed rail edges.");
154  }
155  return (int)toAdd.size();
156 }
157 
158 
159 NBPTStop*
161  std::string edgeId = pStop->getEdgeId();
162  NBEdge* edge = cont.getByID(edgeId);
163  NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
164  if (reverse != nullptr) {
165  const std::string reverseID = getReverseID(pStop->getID());
166  if (myPTStops.count(reverseID) == 0) {
167  return new NBPTStop(reverseID, pStop->getPosition(), reverse->getID(), reverse->getID(),
168  pStop->getLength(), pStop->getName(), pStop->getPermissions());
169  } else {
170  return myPTStops[reverseID];
171  }
172  }
173  return nullptr;
174 }
175 
176 
177 NBPTStop*
179  std::string edgeId = pStop->getEdgeId();
180  NBEdge* edge = cont.getByID(edgeId);
181  bool rightOfEdge = false;
182  bool leftOfEdge = false;
183  const NBPTPlatform* left = nullptr;
184  for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
185  double crossProd = computeCrossProductEdgePosition(edge, platform.getPos());
186  //TODO consider driving on the left!!! [GL May '17]
187  if (crossProd > 0) {
188  leftOfEdge = true;
189  left = &platform;
190  } else {
191  rightOfEdge = true;
192  pStop->setMyPTStopLength(platform.getLength());
193  }
194  }
195 
196  if (leftOfEdge && rightOfEdge) {
197  NBPTStop* leftStop = getReverseStop(pStop, cont);
198  leftStop->setMyPTStopLength(left->getLength());
199  return leftStop;
200  } else if (leftOfEdge) {
201  NBEdge* reverse = getReverseEdge(edge);
202  if (reverse != nullptr) {
203  pStop->setEdgeId(reverse->getID(), cont);
204  pStop->setMyPTStopLength(left->getLength());
205  }
206  }
207 
208  return nullptr;
209 }
210 
211 
212 void
214  std::string edgeId = pStop->getEdgeId();
215  NBEdge* edge = cont.getByID(edgeId);
216  NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
217  const NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
218  pStop->setMyPTStopLength(closestPlatform->getLength());
219  if (reverse != nullptr) {
220 
221  //TODO make isLeft in PositionVector static [GL May '17]
222 // if (PositionVector::isLeft(edge->getFromNode()->getPosition(),edge->getToNode()->getPosition(),closestPlatform)){
223 //
224 // }
225  double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getPos());
226 
227  //TODO consider driving on the left!!! [GL May '17]
228  if (crossProd > 0) { //pt stop is on the left of the orig edge
229  pStop->setEdgeId(reverse->getID(), cont);
230  }
231  }
232 }
233 
234 
235 double
236 NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const {
237  PositionVector geom = edge->getGeometry();
238  int idxTmp = geom.indexOfClosest(closestPlatform);
239  double offset = geom.nearest_offset_to_point2D(closestPlatform, true);
240  double offset2 = geom.offsetAtIndex2D(idxTmp);
241  int idx1, idx2;
242  if (offset2 < offset) {
243  idx1 = idxTmp;
244  idx2 = idx1 + 1;
245  } else {
246  idx2 = idxTmp;
247  idx1 = idxTmp - 1;
248  }
249  if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
250  WRITE_WARNING("Could not determine cross product");
251  return 0;
252  }
253  Position p1 = geom[idx1];
254  Position p2 = geom[idx2];
255 
256  double x0 = p1.x();
257  double y0 = p1.y();
258  double x1 = p2.x();
259  double y1 = p2.y();
260  double x2 = closestPlatform.x();
261  double y2 = closestPlatform.y();
262  double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
263  return crossProd;
264 }
265 
266 
267 const NBPTPlatform*
269  Position stopPosition = pStop->getPosition();
270  const NBPTPlatform* closest = nullptr;
271  double minSqrDist = std::numeric_limits<double>::max();
272  for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
273  double sqrDist = stopPosition.distanceSquaredTo2D(platform.getPos());
274  if (sqrDist < minSqrDist) {
275  minSqrDist = sqrDist;
276  closest = &platform;
277  }
278  }
279  return closest;
280 }
281 
282 //static functions
283 
284 NBEdge*
286  if (edge != nullptr) {
287  for (auto it = edge->getToNode()->getOutgoingEdges().begin();
288  it != edge->getToNode()->getOutgoingEdges().end();
289  it++) {
290  if ((*it)->getToNode() == edge->getFromNode()) {
291  return (*it);
292  }
293  }
294  }
295  return nullptr;
296 }
297 
298 
299 void
301  for (auto i = myPTStops.begin(); i != myPTStops.end();) {
302  if (cont.getByID((*i).second->getEdgeId()) == nullptr) {
303  WRITE_WARNING("Removing pt stop:" + (*i).first + " on non existing edge: " + (*i).second->getEdgeId());
304  myPTStops.erase(i++);
305  } else {
306  i++;
307  }
308  }
309 
310 }
311 
312 
313 void
314 NBPTStopCont::addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into) {
315  if (oc.isSet("ptstop-output")) {
316  for (auto stop : myPTStops) {
317  into.insert(stop.second->getEdgeId());
318  }
319  }
320 }
321 
322 
323 void
324 NBPTStopCont::postprocess(std::set<std::string>& usedStops) {
325  for (auto i = myPTStops.begin(); i != myPTStops.end();) {
326  if (usedStops.find(i->second->getID()) == usedStops.end()) {
327  myPTStops.erase(i++);
328  } else {
329  i++;
330  }
331  }
332 }
333 
334 std::string
335 NBPTStopCont::getReverseID(const std::string& id) {
336  return id.size() > 0 && id[0] == '-' ? id.substr(1) : "-" + id;
337 }
338 
339 void
341  PTStopsCont stops = myPTStops;
342  for (auto& i : stops) {
343  const std::string& stopId = i.second->getID();
344  const char edgeSign = i.second->getEdgeId().at(0);
345  const char stopSign = stopId.at(0);
346  if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
347  i.second->setMyPTStopId(getReverseID(stopId));
348  myPTStops.erase(stopId);
349  myPTStops[i.second->getID()] = i.second;
350  }
351  }
352 }
353 
354 
355 void
356 NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor) {
357  NamedRTree r;
358  for (auto edge : cont) {
359  const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
360  float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
361  float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
362  r.Insert(min, max, edge.second);
363  }
364  for (auto& ptStop : myPTStops) {
365  const std::string& stopEdgeID = ptStop.second->getEdgeId();
366  NBEdge* stopEdge = cont.getByID(stopEdgeID);
367  //std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
368  if (stopEdge != nullptr && (stopEdge->getPermissions() & SVC_PEDESTRIAN) == 0) {
369  //if (stopEdge != 0 && isRailway(stopEdge->getPermissions())) {
370  std::set<std::string> ids;
371  Named::StoringVisitor visitor(ids);
372  const Position& pos = ptStop.second->getPosition();
373  float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
374  float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
375  r.Search(min, max, visitor);
376  std::vector<NBEdge*> edgCants;
377  for (const auto& id : ids) {
378  NBEdge* e = cont.getByID(id);
379  edgCants.push_back(e);
380  }
381  std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
382  return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
383  });
384  int cnt = 0;
385  for (auto edge : edgCants) {
386  int laneIdx = 0;
387  for (auto lane : edge->getLanes()) {
388  if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
389  double offset = lane.shape.nearest_offset_to_point2D(pos, false);
390  double finalLength = edge->getFinalLength();
391  double laneLength = lane.shape.length();
392  double accessLength = pos.distanceTo2D(lane.shape.positionAtOffset2D(offset)) * accessFactor;
393  ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength, accessLength);
394  cnt++;
395  break;
396  }
397  laneIdx++;
398  }
399  if (cnt == maxCount) {
400  break;
401  }
402  }
403  }
404  }
405 }
406 
407 
408 /****************************************************************************/
double getLength() const
bool setEdgeId(std::string edgeId, NBEdgeCont &ec)
Definition: NBPTStop.cpp:167
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition: NamedRTree.h:82
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:131
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:125
void alignIdSigns()
PTStopsCont myPTStops
The map of names to pt stops.
Definition: NBPTStopCont.h:92
EdgeVector getGeneratedFrom(const std::string &id) const
Returns the edges which have been built by splitting the edge of the given id.
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
int generateBidiStops(NBEdgeCont &cont)
duplicate stops for superposed rail edges and return the number of generated stops ...
double distance2D(const Position &p, bool perpendicular=false) const
closest 2D-distance to point p (or -1 if perpendicular is true and the point is beyond this vector) ...
const Position & getPos() const
void assignPTStopToEdgeOfClosestPlatform(NBPTStop *pStop, NBEdgeCont &cont)
int indexOfClosest(const Position &p) const
index of the closest position to p
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:244
void postprocess(std::set< std::string > &usedStops)
double y() const
Returns the y-position.
Definition: Position.h:62
The representation of a single edge during network building.
Definition: NBEdge.h:86
bool findLaneAndComputeBusStopExtent(NBEdgeCont &ec)
Definition: NBPTStop.cpp:198
const NBPTPlatform * getClosestPlatformToPTStopPosition(NBPTStop *pStop)
A RT-tree for efficient storing of SUMO&#39;s Named objects.
Definition: NamedRTree.h:64
double x() const
Returns the x-position.
Definition: Position.h:57
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:683
NBPTStop * assignAndCreatNewPTStopAsNeeded(NBPTStop *pStop, NBEdgeCont &cont)
static std::string getReverseID(const std::string &id)
void findAccessEdgesForRailStops(NBEdgeCont &cont, double maxRadius, int maxCount, double accessFactor)
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3116
std::string getID() const
Definition: NBPTStop.cpp:48
The representation of a single pt stop.
Definition: NBPTStop.h:45
std::map< std::string, NBPTStop * > PTStopsCont
Definition of the map of names to pt stops.
Definition: NBPTStopCont.h:89
double computeCrossProductEdgePosition(const NBEdge *edge, const Position &closestPlatform) const
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
SVCPermissions getPermissions() const
Definition: NBPTStop.cpp:131
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:264
void localizePTStops(NBEdgeCont &cont)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void assignLanes(NBEdgeCont &cont)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
const std::vector< NBPTPlatform > & getPlatformCands()
Definition: NBPTStop.cpp:143
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
A list of positions.
const std::string & getID() const
Definition: NBEdge.h:1364
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:61
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:119
const std::string getName() const
Definition: NBPTStop.cpp:65
void cleanupDeleted(NBEdgeCont &cont)
remove stops on non existing (removed) edges
double getLength() const
Definition: NBPTStop.cpp:161
bool getIsMultipleStopPositions() const
Definition: NBPTStop.cpp:149
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
Definition: NamedRTree.h:115
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3441
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3704
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:680
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition: Named.h:93
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:871
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
A storage for options typed value containers)
Definition: OptionsCont.h:90
NBPTStop * get(std::string id)
Retrieve a previously inserted pt stop.
double distanceSquaredTo2D(const Position &p2) const
returns the square of the distance to another position (Only using x and y positions) ...
Definition: Position.h:249
const std::string getOrigEdgeId() const
Definition: NBPTStop.cpp:53
NBPTStop * getReverseStop(NBPTStop *pStop, NBEdgeCont &cont)
double offsetAtIndex2D(int index) const
return the offset at the given index
void setBidiStop(NBPTStop *bidiStop)
Definition: NBPTStop.h:83
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:479
bool insert(NBPTStop *ptStop)
Inserts a node into the map.
const Position & getPosition() const
Definition: NBPTStop.cpp:71
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:137
static NBEdge * getReverseEdge(NBEdge *edge)
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:240
const std::string getEdgeId() const
Definition: NBPTStop.cpp:59
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
void setMyPTStopLength(double myPTStopLength)
Definition: NBPTStop.cpp:192
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486