SUMO - Simulation of Urban MObility
IntermodalNetwork.h
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 /****************************************************************************/
19 // The Edge definition for the Intermodal Router
20 /****************************************************************************/
21 #ifndef IntermodalNetwork_h
22 #define IntermodalNetwork_h
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
35 #include <vector>
36 #include <algorithm>
37 #include <assert.h>
38 #include <utils/common/SUMOTime.h>
39 #include <utils/common/ToString.h>
40 #include <utils/common/Named.h>
41 #include "IntermodalEdge.h"
42 
43 //#define IntermodalRouter_DEBUG_NETWORK
44 
45 
46 // ===========================================================================
47 // class definitions
48 // ===========================================================================
50 template<class E, class L, class N, class V>
52 private:
55  typedef std::pair<_IntermodalEdge*, _IntermodalEdge*> EdgePair;
56 
57 public:
58  /* @brief build the pedestrian part of the intermodal network (once)
59  * @param edges The list of MSEdge or ROEdge to build from
60  * @param numericalID the start number for the creation of new edges
61  */
62  IntermodalNetwork(const std::vector<E*>& edges, int numericalID = 0) {
63 #ifdef IntermodalRouter_DEBUG_NETWORK
64  std::cout << "initIntermodalNetwork\n";
65 #endif
66  const bool pedestrianOnly = numericalID == 0;
67  // build the pedestrian edges and the depart / arrival connectors with lookup tables
68  bool haveSeenWalkingArea = false;
69  for (const E* const edge : edges) {
70  if (edge->isInternal() || edge->isTazConnector()) {
71  continue;
72  }
73  const L* lane = getSidewalk<E, L>(edge);
74  if (lane != 0) {
75  if (edge->isWalkingArea()) {
76  // only a single edge
77  addEdge(new _PedestrianEdge(numericalID++, edge, lane, true));
78  myBidiLookup[edge] = std::make_pair(myEdges.back(), myEdges.back());
79  myDepartLookup[edge].push_back(myEdges.back());
80  myArrivalLookup[edge].push_back(myEdges.back());
81  haveSeenWalkingArea = true;
82  } else { // regular edge or crossing
83  // forward and backward edges
84  addEdge(new _PedestrianEdge(numericalID++, edge, lane, true));
85  addEdge(new _PedestrianEdge(numericalID++, edge, lane, false));
86  myBidiLookup[edge] = std::make_pair(myEdges[numericalID - 2], myEdges.back());
87  }
88  }
89  if (!edge->isWalkingArea()) {
90  // depart and arrival edges (the router can decide the initial direction to take and the direction to arrive from)
91  _IntermodalEdge* const departConn = new _IntermodalEdge(edge->getID() + "_depart_connector", numericalID++, edge, "!connector");
92  _IntermodalEdge* const arrivalConn = new _IntermodalEdge(edge->getID() + "_arrival_connector", numericalID++, edge, "!connector");
93  addConnectors(departConn, arrivalConn, 0);
94  }
95  }
96 
97  // build the walking connectors if there are no walking areas
98  for (const E* const edge : edges) {
99  if (edge->isInternal() || edge->isTazConnector()) {
100  continue;
101  }
102  if (haveSeenWalkingArea) {
103  if (!pedestrianOnly && getSidewalk<E, L>(edge) == nullptr) {
104  const N* const node = edge->getToJunction();
105  if (myWalkingConnectorLookup.count(node) == 0) {
106  addEdge(new _IntermodalEdge(node->getID() + "_walking_connector", numericalID++, nullptr, "!connector"));
107  myWalkingConnectorLookup[node] = myEdges.back();
108  }
109  }
110  } else {
111  for (const N* const node : {
112  edge->getFromJunction(), edge->getToJunction()
113  }) {
114  if (myWalkingConnectorLookup.count(node) == 0) {
115  addEdge(new _IntermodalEdge(node->getID() + "_walking_connector", numericalID++, nullptr, "!connector"));
116  myWalkingConnectorLookup[node] = myEdges.back();
117  }
118  }
119  }
120  }
121  // build the connections
122  for (const E* const edge : edges) {
123  const L* const sidewalk = getSidewalk<E, L>(edge);
124  if (edge->isInternal() || sidewalk == 0) {
125  continue;
126  }
127  // find all incoming and outgoing lanes for the sidewalk and
128  // connect the corresponding IntermodalEdges
129  const EdgePair& pair = getBothDirections(edge);
130 #ifdef IntermodalRouter_DEBUG_NETWORK
131  std::cout << " building connections from " << sidewalk->getID() << "\n";
132 #endif
133  if (haveSeenWalkingArea) {
134  const std::vector<const L*> outgoing = sidewalk->getOutgoingLanes();
135  // if one of the outgoing lanes is a walking area it must be used.
136  // All other connections shall be ignored
137  // if it has no outgoing walking area, it probably is a walking area itself
138  bool hasWalkingArea = false;
139  for (const L* target : outgoing) {
140  if (target->getEdge().isWalkingArea()) {
141  hasWalkingArea = true;
142  break;
143  }
144  }
145  for (const L* target : outgoing) {
146  const E* const targetEdge = &(target->getEdge());
147  const bool used = (target == getSidewalk<E, L>(targetEdge)
148  && (!hasWalkingArea || targetEdge->isWalkingArea()));
149 #ifdef IntermodalRouter_DEBUG_NETWORK
150  const L* potTarget = getSidewalk<E, L>(targetEdge);
151  std::cout << " lane=" << (potTarget == 0 ? "NULL" : potTarget->getID()) << (used ? "(used)" : "") << "\n";
152 #endif
153  if (used) {
154  const EdgePair& targetPair = getBothDirections(targetEdge);
155  pair.first->addSuccessor(targetPair.first);
156  targetPair.second->addSuccessor(pair.second);
157 #ifdef IntermodalRouter_DEBUG_NETWORK
158  std::cout << " " << pair.first->getID() << " -> " << targetPair.first->getID() << "\n";
159  std::cout << " " << targetPair.second->getID() << " -> " << pair.second->getID() << "\n";
160 #endif
161  }
162  }
163  }
164  // we may have a network without pedestrian structures or a car-only edge. Assume that
165  // all sidewalks at a crossing are interconnected
166  _IntermodalEdge* const toNodeConn = myWalkingConnectorLookup[edge->getToJunction()];
167  if (toNodeConn != nullptr) {
168  pair.first->addSuccessor(toNodeConn);
169  toNodeConn->addSuccessor(pair.second);
170  }
171  _IntermodalEdge* const fromNodeConn = myWalkingConnectorLookup[edge->getFromJunction()];
172  if (fromNodeConn != nullptr) {
173  pair.second->addSuccessor(fromNodeConn);
174  fromNodeConn->addSuccessor(pair.first);
175  }
176  if (edge->isWalkingArea()) {
177  continue;
178  }
179  // build connections from depart connector
180  _IntermodalEdge* startConnector = getDepartConnector(edge);
181  startConnector->addSuccessor(pair.first);
182  startConnector->addSuccessor(pair.second);
183  // build connections to arrival connector
184  _IntermodalEdge* endConnector = getArrivalConnector(edge);
185  pair.first->addSuccessor(endConnector);
186  pair.second->addSuccessor(endConnector);
187 #ifdef IntermodalRouter_DEBUG_NETWORK
188  std::cout << " " << startConnector->getID() << " -> " << pair.first->getID() << "\n";
189  std::cout << " " << startConnector->getID() << " -> " << pair.second->getID() << "\n";
190  std::cout << " " << pair.first->getID() << " -> " << endConnector->getID() << "\n";
191  std::cout << " " << pair.second->getID() << " -> " << endConnector->getID() << "\n";
192 #endif
193  }
194  }
195 
197  for (typename std::vector<_IntermodalEdge*>::iterator it = myEdges.begin(); it != myEdges.end(); ++it) {
198  delete *it;
199  }
200  }
201 
202  void addEdge(_IntermodalEdge* edge) {
203  while ((int)myEdges.size() <= edge->getNumericalID()) {
204  myEdges.push_back(0);
205  }
206  myEdges[edge->getNumericalID()] = edge;
207  }
208 
209  void addConnectors(_IntermodalEdge* const depConn, _IntermodalEdge* const arrConn, const int splitIndex) {
210  addEdge(depConn);
211  addEdge(arrConn);
212  myDepartLookup[depConn->getEdge()].insert(myDepartLookup[depConn->getEdge()].begin() + splitIndex, depConn);
213  myArrivalLookup[arrConn->getEdge()].insert(myArrivalLookup[arrConn->getEdge()].begin() + splitIndex, arrConn);
214  }
215 
216  const std::vector<_IntermodalEdge*>& getAllEdges() {
217  return myEdges;
218  }
219 
221  const EdgePair& getBothDirections(const E* e) const {
222  typename std::map<const E*, EdgePair>::const_iterator it = myBidiLookup.find(e);
223  if (it == myBidiLookup.end()) {
224  assert(false);
225  throw ProcessError("Edge '" + e->getID() + "' not found in intermodal network '");
226  }
227  return (*it).second;
228  }
229 
231  _IntermodalEdge* getDepartEdge(const E* e, const double pos) const {
232  typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it = myDepartLookup.find(e);
233  if (it == myDepartLookup.end()) {
234  throw ProcessError("Depart edge '" + e->getID() + "' not found in intermodal network.");
235  }
236  const std::vector<_IntermodalEdge*>& splitList = it->second;
237  typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
238  double totalLength = 0.;
239  while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
240  totalLength += (*splitIt)->getLength();
241  ++splitIt;
242  }
243  return *splitIt;
244  }
245 
247  _IntermodalEdge* getDepartConnector(const E* e, const int splitIndex = 0) const {
248  return myDepartLookup.find(e)->second[splitIndex];
249  }
250 
252  _IntermodalEdge* getArrivalEdge(const E* e, const double pos) const {
253  typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it = myArrivalLookup.find(e);
254  if (it == myArrivalLookup.end()) {
255  throw ProcessError("Arrival edge '" + e->getID() + "' not found in intermodal network.");
256  }
257  const std::vector<_IntermodalEdge*>& splitList = it->second;
258  typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
259  double totalLength = 0.;
260  while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
261  totalLength += (*splitIt)->getLength();
262  ++splitIt;
263  }
264  return *splitIt;
265  }
266 
268  _IntermodalEdge* getArrivalConnector(const E* e, const int splitIndex = 0) const {
269  return myArrivalLookup.find(e)->second[splitIndex];
270  }
271 
273  _IntermodalEdge* getWalkingConnector(const E* e) const {
274  typename std::map<const N*, _IntermodalEdge*>::const_iterator it = myWalkingConnectorLookup.find(e->getToJunction());
275  if (it == myWalkingConnectorLookup.end()) {
276  const L* const sidewalk = getSidewalk<E, L>(e);
277  if (e->isInternal() || sidewalk == 0) {
278  return 0;
279  }
280  for (const L* target : sidewalk->getOutgoingLanes()) {
281  if (target->getEdge().isWalkingArea()) {
282  return getBothDirections(&target->getEdge()).first;
283  }
284  }
285  return 0;
286  }
287  return it->second;
288  }
289 
290 
291 private:
293  std::vector<_IntermodalEdge*> myEdges;
294 
296  std::map<const E*, EdgePair> myBidiLookup;
297 
299  std::map<const E*, std::vector<_IntermodalEdge*> > myDepartLookup;
300 
302  std::map<const E*, std::vector<_IntermodalEdge*> > myArrivalLookup;
303 
305  std::map<const N*, _IntermodalEdge*> myWalkingConnectorLookup;
306 
307 };
308 
309 
310 #endif
311 
312 /****************************************************************************/
const EdgePair & getBothDirections(const E *e) const
Returns the pair of forward and backward edge.
_IntermodalEdge * getArrivalEdge(const E *e, const double pos) const
Returns the arriving intermodal edge.
_IntermodalEdge * getDepartConnector(const E *e, const int splitIndex=0) const
Returns the departing intermodal connector at the given split offset.
const std::vector< _IntermodalEdge * > & getAllEdges()
std::map< const E *, EdgePair > myBidiLookup
retrieve the forward and backward edge for the given input edge E
void addEdge(_IntermodalEdge *edge)
void addSuccessor(IntermodalEdge *s)
int getNumericalID() const
IntermodalEdge< E, L, N, V > _IntermodalEdge
const std::string & getID() const
Returns the id.
Definition: Named.h:74
const E * getEdge() const
_IntermodalEdge * getWalkingConnector(const E *e) const
Returns the outgoing pedestrian edge, which is either a walking area or a walking connector...
std::vector< _IntermodalEdge * > myEdges
the edge dictionary
PedestrianEdge< E, L, N, V > _PedestrianEdge
_IntermodalEdge * getArrivalConnector(const E *e, const int splitIndex=0) const
Returns the arriving intermodal connector at the given split offset.
std::pair< _IntermodalEdge *, _IntermodalEdge * > EdgePair
std::map< const E *, std::vector< _IntermodalEdge * > > myArrivalLookup
retrieve the arrival edges for the given input edge E
the intermodal network storing edges, connections and the mappings to the "real" edges ...
the base edge type that is given to the internal router (SUMOAbstractRouter)
_IntermodalEdge * getDepartEdge(const E *e, const double pos) const
Returns the departing intermodal edge.
std::map< const N *, _IntermodalEdge * > myWalkingConnectorLookup
the walking connector edge (fake walking area)
std::map< const E *, std::vector< _IntermodalEdge * > > myDepartLookup
retrieve the depart edges for the given input edge E
IntermodalNetwork(const std::vector< E *> &edges, int numericalID=0)
the pedestrian edge type that is given to the internal router (SUMOAbstractRouter) ...
void addConnectors(_IntermodalEdge *const depConn, _IntermodalEdge *const arrConn, const int splitIndex)