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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
17 // Container for pt stops during the netbuilding process
18 /****************************************************************************/
19 
20 
22 #include <utils/geom/Boundary.h>
24 #include <microsim/MSLane.h>
25 #include "NBPTStopCont.h"
26 #include "NBEdgeCont.h"
27 #include "NBEdge.h"
28 #include "NBNode.h"
29 #include <utils/geom/Position.h>
30 
31 
33  for (auto& myPTStop : myPTStops) {
34  delete myPTStop.second;
35  }
36  myPTStops.clear();
37 }
38 
39 
40 bool
42  std::string id = ptStop->getID();
43  auto i = myPTStops.find(id);
44  if (i != myPTStops.end()) {
45  return false;
46  }
47  myPTStops[id] = ptStop;
48  return true;
49 }
50 
51 
52 NBPTStop*
53 NBPTStopCont::get(std::string id) {
54  if (myPTStops.find(id) != myPTStops.end()) {
55  return myPTStops.find(id)->second;
56  }
57  return nullptr;
58 }
59 
60 
61 void
63  std::vector<NBPTStop*> reverseStops;
64  //frst pass localize pt stop at correct side of the street; create stop for opposite side if needed
65  for (auto& myPTStop : myPTStops) {
66 
67  NBPTStop* stop = myPTStop.second;
68 
69  bool multipleStopPositions = stop->getIsMultipleStopPositions();
70  bool platformsDefined = !stop->getPlatformCands().empty();
71  if (!platformsDefined) {
72  //create pt stop for reverse edge if edge exist
73  NBPTStop* reverseStop = getReverseStop(stop, cont);
74  if (reverseStop != nullptr) {
75  reverseStops.push_back(reverseStop);
76  }
77  } else if (multipleStopPositions) {
78  //create pt stop for closest platform at corresponding edge
80 
81  } else {
82  //create pt stop for each side of the street where a platform is defined (create additional pt stop as needed)
83  NBPTStop* additionalStop = assignAndCreatNewPTStopAsNeeded(stop, cont);
84  if (additionalStop != nullptr) {
85  reverseStops.push_back(additionalStop);
86  }
87  }
88  }
89 
90  //insrt new stops if any
91  for (auto& reverseStop : reverseStops) {
92  insert(reverseStop);
93  }
94 }
95 
96 
98  //scnd pass set correct lane
99  for (auto i = myPTStops.begin(); i != myPTStops.end();) {
100  NBPTStop* stop = i->second;
101 
102  if (!stop->findLaneAndComputeBusStopExtend(cont)) {
103  WRITE_WARNING("Could not find corresponding edge or compatible lane for pt stop: " + i->second->getName()
104  + ". Thus, it will be removed!");
105  EdgeVector edgeVector = cont.getGeneratedFrom((*i).second->getOrigEdgeId());
106  //std::cout << edgeVector.size() << std::endl;
107  myPTStops.erase(i++);
108  } else {
109  i++;
110  }
111  }
112 }
113 
114 
115 NBPTStop*
117  std::string edgeId = pStop->getEdgeId();
118  NBEdge* edge = cont.getByID(edgeId);
119  NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
120  if (reverse != nullptr) {
121  Position* pos = new Position(pStop->getPosition());
122  NBPTStop* ret = new NBPTStop("-" + pStop->getID(), *pos, reverse->getID(), reverse->getID(),
123  pStop->getLength(), pStop->getName(), pStop->getPermissions());
124  return ret;
125  }
126  return nullptr;
127 }
128 
129 
130 NBPTStop*
132  std::string edgeId = pStop->getEdgeId();
133  NBEdge* edge = cont.getByID(edgeId);
134 
135 
136  bool rightOfEdge = false;
137  bool leftOfEdge = false;
138  NBPTPlatform* left = nullptr;
139  for (auto it = pStop->getPlatformCands().begin(); it != pStop->getPlatformCands().end(); it++) {
140  NBPTPlatform* platform = &(*it);
141  double crossProd = computeCrossProductEdgePosition(edge, platform->getMyPos());
142 
143  //TODO consider driving on the left!!! [GL May '17]
144  if (crossProd > 0) {
145  leftOfEdge = true;
146  left = platform;
147  } else {
148  rightOfEdge = true;
149  pStop->setMyPTStopLength(platform->getMyLength());
150  }
151 
152  }
153 
154  if (leftOfEdge && rightOfEdge) {
155  NBPTStop* leftStop = getReverseStop(pStop, cont);
156  leftStop->setMyPTStopLength(left->getMyLength());
157  return leftStop;
158  } else if (leftOfEdge) {
159  NBEdge* reverse = getReverseEdge(edge);
160  if (reverse != nullptr) {
161  pStop->setEdgeId(reverse->getID(), cont);
162  pStop->setMyPTStopLength(left->getMyLength());
163  }
164  }
165 
166  return nullptr;
167 }
168 
169 
170 void
172  std::string edgeId = pStop->getEdgeId();
173  NBEdge* edge = cont.getByID(edgeId);
174  NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
175  NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
176  pStop->setMyPTStopLength(closestPlatform->getMyLength());
177  if (reverse != nullptr) {
178 
179  //TODO make isLeft in PositionVector static [GL May '17]
180 // if (PositionVector::isLeft(edge->getFromNode()->getPosition(),edge->getToNode()->getPosition(),closestPlatform)){
181 //
182 // }
183  double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getMyPos());
184 
185  //TODO consider driving on the left!!! [GL May '17]
186  if (crossProd > 0) { //pt stop is on the left of the orig edge
187  pStop->setEdgeId(reverse->getID(), cont);
188  }
189  }
190 }
191 
192 
193 double
194 NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position* closestPlatform) const {
195  PositionVector geom = edge->getGeometry();
196  int idxTmp = geom.indexOfClosest(*closestPlatform);
197  double offset = geom.nearest_offset_to_point2D(*closestPlatform, true);
198  double offset2 = geom.offsetAtIndex2D(idxTmp);
199  int idx1, idx2;
200  if (offset2 < offset) {
201  idx1 = idxTmp;
202  idx2 = idx1 + 1;
203  } else {
204  idx2 = idxTmp;
205  idx1 = idxTmp - 1;
206  }
207  if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
208  WRITE_WARNING("Could not determine cross product");
209  return 0;
210  }
211  Position p1 = geom[idx1];
212  Position p2 = geom[idx2];
213 
214  double x0 = p1.x();
215  double y0 = p1.y();
216  double x1 = p2.x();
217  double y1 = p2.y();
218  double x2 = closestPlatform->x();
219  double y2 = closestPlatform->y();
220  double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
221  return crossProd;
222 }
223 
224 
227  Position stopPosition = pStop->getPosition();
228  NBPTPlatform* closest = nullptr;
229  double minSqrDist = std::numeric_limits<double>::max();
230 
231  for (auto it = pStop->getPlatformCands().begin();
232  it != pStop->getPlatformCands().end();
233  it++) {
234  NBPTPlatform platform = *it;
235  double sqrDist = stopPosition.distanceSquaredTo2D(*platform.getMyPos());
236  if (sqrDist < minSqrDist) {
237  minSqrDist = sqrDist;
238  closest = &(*it);
239  }
240  }
241  return closest;
242 }
243 
244 //static functions
245 
246 NBEdge*
248  if (edge != nullptr) {
249  for (auto it = edge->getToNode()->getOutgoingEdges().begin();
250  it != edge->getToNode()->getOutgoingEdges().end();
251  it++) {
252  if ((*it)->getToNode() == edge->getFromNode()) {
253  return (*it);
254  }
255  }
256  }
257  return 0;
258 }
259 
260 
261 void
263  for (auto i = myPTStops.begin(); i != myPTStops.end();) {
264  if (cont.getByID((*i).second->getEdgeId()) == nullptr) {
265  WRITE_WARNING("Removing pt stop:" + (*i).first + " on non existing edge: " + (*i).second->getEdgeId());
266  myPTStops.erase(i++);
267  } else {
268  i++;
269  }
270  }
271 
272 }
273 
274 
275 void
276 NBPTStopCont::addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into) {
277  if (oc.isSet("ptstop-output")) {
278  for (auto stop : myPTStops) {
279  into.insert(stop.second->getEdgeId());
280  }
281  }
282 }
283 
284 
285 void
286 NBPTStopCont::postprocess(std::set<std::string>& usedStops) {
287  for (auto i = myPTStops.begin(); i != myPTStops.end();) {
288  if (usedStops.find(i->second->getID()) == usedStops.end()) {
289  myPTStops.erase(i++);
290  } else {
291  i++;
292  }
293  }
294 }
295 
296 
297 void
299  for (auto& i : myPTStops) {
300  const std::string& stopId = i.second->getID();
301  const char edgeSign = i.second->getEdgeId().at(0);
302  const char stopSign = stopId.at(0);
303  if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
304  if (edgeSign == '-') {
305  i.second->setMyPTStopId("-" + stopId);
306  } else {
307  i.second->setMyPTStopId(stopId.substr(1, stopId.length()));
308  }
309  // TODO the map should be modified as well to hold the correct id
310  }
311  }
312 }
313 
314 
315 void
316 NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount) {
317  NamedRTree r;
318  for (auto edge : cont) {
319  const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
320  float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
321  float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
322  r.Insert(min, max, edge.second);
323  }
324  for (auto& ptStop : myPTStops) {
325  const std::string& stopEdgeID = ptStop.second->getEdgeId();
326  NBEdge* stopEdge = cont.getByID(stopEdgeID);
327  //std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
328  if (stopEdge != 0 && isRailway(stopEdge->getPermissions())) {
329  std::set<std::string> ids;
330  Named::StoringVisitor visitor(ids);
331  const Position& pos = ptStop.second->getPosition();
332  float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
333  float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
334  r.Search(min, max, visitor);
335  std::vector<NBEdge*> edgCants;
336  for (const auto& id : ids) {
337  NBEdge* e = cont.getByID(id);
338  edgCants.push_back(e);
339  }
340  std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
341  return a->getGeometry().distance2D(pos, false) < b->getGeometry().distance2D(pos, false);
342  });
343  int cnt = 0;
344  for (auto edge : edgCants) {
345  int laneIdx = 0;
346  for (auto lane : edge->getLanes()) {
347  if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
348  double offset = lane.shape.nearest_offset_to_point2D(pos, false);
349  double finalLength = edge->getFinalLength();
350  double laneLength = lane.shape.length();
351  ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength);
352  cnt++;
353  break;
354  }
355  laneIdx++;
356  }
357  if (cnt == maxCount) {
358  break;
359  }
360  }
361  }
362  }
363 }
364 
365 
366 /****************************************************************************/
bool setEdgeId(std::string edgeId, NBEdgeCont &ec)
Definition: NBPTStop.cpp:134
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition: NamedRTree.h:89
const std::string getName()
Definition: NBPTStop.cpp:69
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
Definition: NBEdgeCont.cpp:850
double ymin() const
Returns minimum y-coordinate.
Definition: Boundary.cpp:137
void reviseStops(NBEdgeCont &cont)
revise pt stops and remove stops on non existing (removed) edges
double xmax() const
Returns maximum x-coordinate.
Definition: Boundary.cpp:131
double getMyLength() const
void alignIdSigns()
PTStopsCont myPTStops
The map of names to pt stops.
Definition: NBPTStopCont.h:87
EdgeVector getGeneratedFrom(const std::string &id) const
Returns the edges which have been built by splitting the edge of the given id.
Definition: NBEdgeCont.cpp:901
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
is a pedestrian
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) ...
void assignPTStopToEdgeOfClosestPlatform(NBPTStop *pStop, NBEdgeCont &cont)
int indexOfClosest(const Position &p) const
index of the closest position to p
void findAccessEdgesForRailStops(NBEdgeCont &cont, double d, int i)
const std::string getEdgeId()
Definition: NBPTStop.cpp:64
void postprocess(std::set< std::string > &usedStops)
double y() const
Returns the y-position.
Definition: Position.h:67
NBPTPlatform * getClosestPlatformToPTStopPosition(NBPTStop *pStop)
The representation of a single edge during network building.
Definition: NBEdge.h:70
A RT-tree for efficient storing of SUMO&#39;s Named objects.
Definition: NamedRTree.h:71
double x() const
Returns the x-position.
Definition: Position.h:62
NBPTStop * assignAndCreatNewPTStopAsNeeded(NBPTStop *pStop, NBEdgeCont &cont)
std::string getID() const
Definition: NBPTStop.cpp:54
double computeCrossProductEdgePosition(const NBEdge *edge, const Position *closestPlatform) const
const std::string & getID() const
Returns the id.
Definition: Named.h:74
The representation of a single pt stop.
Definition: NBPTStop.h:51
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:47
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:199
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:254
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)
SVCPermissions getPermissions()
Definition: NBPTStop.cpp:113
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:45
A list of positions.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
double xmin() const
Returns minimum x-coordinate.
Definition: Boundary.cpp:125
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:122
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3025
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3269
bool getIsMultipleStopPositions()
Definition: NBPTStop.cpp:122
bool findLaneAndComputeBusStopExtend(NBEdgeCont &ec)
Definition: NBPTStop.cpp:155
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:602
Allows to store the object; used as context while traveling the rtree in TraCI.
Definition: Named.h:90
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:40
std::vector< NBPTPlatform > & getPlatformCands()
Definition: NBPTStop.cpp:119
A storage for options typed value containers)
Definition: OptionsCont.h:98
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:254
NBPTStop * getReverseStop(NBPTStop *pStop, NBEdgeCont &cont)
double offsetAtIndex2D(int index) const
return the offset at the given index
const Position & getPosition()
Definition: NBPTStop.cpp:72
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:426
bool insert(NBPTStop *ptStop)
Inserts a node into the map.
Position * getMyPos()
double ymax() const
Returns maximum y-coordinate.
Definition: Boundary.cpp:143
static NBEdge * getReverseEdge(NBEdge *edge)
double getLength()
Definition: NBPTStop.cpp:129
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:149
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:433