Eclipse SUMO - Simulation of Urban MObility
RailEdge.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-2020 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 /****************************************************************************/
18 // The RailEdge is a wrapper around a ROEdge or a MSEdge used for railway routing
19 /****************************************************************************/
20 #pragma once
21 #include <config.h>
22 #include <cassert>
23 
24 //#define RailEdge_DEBUG_TURNS
25 //#define RailEdge_DEBUG_INIT
26 //#define RailEdge_DEBUG_SUCCESSORS
27 #define RailEdge_DEBUGID ""
28 //#define RailEdge_DEBUG_COND(obj) ((obj != 0 && (obj)->getID() == RailEdge_DEBUGID))
29 #define RailEdge_DEBUG_COND(obj) (true)
30 
31 // ===========================================================================
32 // class definitions
33 // ===========================================================================
35 template<class E, class V>
36 class RailEdge {
37 public:
39  typedef std::vector<std::pair<const _RailEdge*, const _RailEdge*> > ConstEdgePairVector;
40 
41  RailEdge(const E* orig) :
43  myOriginal(orig),
44  myTurnaround(nullptr),
45  myIsVirtual(true)
46  { }
47 
48  RailEdge(const E* turnStart, const E* turnEnd, int numericalID) :
49  myNumericalID(numericalID),
50  myID("TrainReversal!" + turnStart->getID() + "->" + turnEnd->getID()),
51  myOriginal(nullptr),
52  myTurnaround(nullptr),
53  myIsVirtual(true),
54  myMaxLength(turnStart->getLength()),
55  myStartLength(turnStart->getLength()) {
56  myViaSuccessors.push_back(std::make_pair(turnEnd->getRailwayRoutingEdge(), nullptr));
57  }
58 
59  void update(double maxTrainLength, const std::vector<const E*>& replacementEdges) {
60  if (maxTrainLength > myMaxLength) {
61  myMaxLength = maxTrainLength;
62  myReplacementEdges = replacementEdges;
63 #ifdef RailEdge_DEBUG_INIT
64  std::cout << " update RailEdge " << getID() << " myMaxLength=" << myMaxLength << " repl=" << toString(myReplacementEdges) << "\n";
65 #endif
66  }
67  }
68 
69  void addVirtualTurns(const E* forward, const E* backward,
70  std::vector<_RailEdge*>& railEdges, int& numericalID, double dist,
71  double maxTrainLength, const std::vector<const E*>& replacementEdges) {
72  // search backwards until dist and add virtual turnaround edges with
73  // replacement edges up to the real turnaround
74 #ifdef RailEdge_DEBUG_INIT
75  std::cout << "addVirtualTurns forward=" << forward->getID() << " backward=" << backward->getID() << " dist=" << dist
76  << " maxLength=" << maxTrainLength << " repl=" << toString(replacementEdges) << "\n";
77 #endif
78  if (dist <= 0) {
79  return;
80  }
81  for (const E* prev : forward->getPredecessors()) {
82  if (prev == backward) {
83  continue;
84  }
85  const E* bidi = prev->getBidiEdge();
86  if (backward->isConnectedTo(*bidi, SVC_IGNORING)) {
87  _RailEdge* prevRailEdge = prev->getRailwayRoutingEdge();
88  if (prevRailEdge->myTurnaround == nullptr) {
89  prevRailEdge->myTurnaround = new _RailEdge(prev, bidi, numericalID++);
90  prevRailEdge->myViaSuccessors.push_back(std::make_pair(prevRailEdge->myTurnaround, nullptr));
91  railEdges.push_back(prevRailEdge->myTurnaround);
92 #ifdef RailEdge_DEBUG_INIT
93  std::cout << " RailEdge " << prevRailEdge->getID() << " virtual turnaround " << prevRailEdge->myTurnaround->getID() << "\n";
94 #endif
95  }
96  prevRailEdge->myTurnaround->update(prev->getLength() + maxTrainLength, replacementEdges);
97  std::vector<const E*> replacementEdges2;
98  replacementEdges2.push_back(prev);
99  replacementEdges2.insert(replacementEdges2.end(), replacementEdges.begin(), replacementEdges.end());
100  addVirtualTurns(prev, bidi, railEdges, numericalID, dist - prev->getLength(),
101  maxTrainLength + prev->getLength(), replacementEdges2);
102  }
103  }
104  }
105 
106  void init(std::vector<_RailEdge*>& railEdges, int& numericalID, double maxTrainLength) {
107  // replace turnaround-via with an explicit RailEdge that checks length
108  for (const auto& viaPair : myOriginal->getViaSuccessors()) {
109  if (viaPair.first == myOriginal->getBidiEdge()) {
110  // direction reversal
111  if (myTurnaround == nullptr) {
112  myTurnaround = new _RailEdge(myOriginal, viaPair.first, numericalID++);
113  myViaSuccessors.push_back(std::make_pair(myTurnaround, nullptr));
114  railEdges.push_back(myTurnaround);
115 #ifdef RailEdge_DEBUG_INIT
116  std::cout << "RailEdge " << getID() << " actual turnaround " << myTurnaround->getID() << "\n";
117 #endif
118  }
119  myTurnaround->myIsVirtual = false;
120  addVirtualTurns(myOriginal, viaPair.first, railEdges, numericalID,
121  maxTrainLength - getLength(), getLength(), std::vector<const E*> {myOriginal});
122  } else {
123  myViaSuccessors.push_back(std::make_pair(viaPair.first->getRailwayRoutingEdge(),
124  viaPair.second == nullptr ? nullptr : viaPair.second->getRailwayRoutingEdge()));
125  }
126  }
127 #ifdef RailEdge_DEBUG_SUCCESSORS
128  std::cout << "RailEdge " << getID() << " successors=" << myViaSuccessors.size() << " orig=" << myOriginal->getViaSuccessors().size() << "\n";
129  for (const auto& viaPair : myViaSuccessors) {
130  std::cout << " " << viaPair.first->getID() << "\n";
131  }
132 #endif
133  }
134 
136  inline int getNumericalID() const {
137  return myNumericalID;
138  }
139 
141  const E* getOriginal() const {
142  return myOriginal;
143  }
144 
148  const std::string& getID() const {
149  return myOriginal != nullptr ? myOriginal->getID() : myID;
150  }
151 
152  void insertOriginalEdges(double length, std::vector<const E*>& into) const {
153  if (myOriginal != nullptr) {
154  into.push_back(myOriginal);
155  } else {
156  double seen = myStartLength;
157  int nPushed = 0;
158  if (seen >= length && !myIsVirtual) {
159  return;
160  }
161  // we need to find a replacement edge that has a real turn
162  for (const E* edge : myReplacementEdges) {
163  into.push_back(edge);
164  nPushed++;
165  seen += edge->getLength();
166  if (seen >= length && edge->isConnectedTo(*edge->getBidiEdge(), SVC_IGNORING)) {
167  break;
168  }
169  //std::cout << "insertOriginalEdges length=" << length << " seen=" << seen << " into=" << toString(into) << "\n";
170  }
171  const int last = (int)into.size() - 1;
172  for (int i = 0; i < nPushed; i++) {
173  into.push_back(into[last - i]->getBidiEdge());
174  }
175  }
176  }
177 
181  double getLength() const {
182  return myOriginal == nullptr ? 0 : myOriginal->getLength();
183  }
184 
185  //const RailEdge* getBidiEdge() const {
186  // return myOriginal->getBidiEdge()->getRailwayRoutingEdge();
187  //}
188 
189  bool isInternal() const {
190  return myOriginal->isInternal();
191  }
192 
193  inline bool prohibits(const V* const vehicle) const {
194 #ifdef RailEdge_DEBUG_TURNS
195  if (myOriginal == nullptr && RailEdge_DEBUG_COND(vehicle)) {
196  std::cout << getID() << " maxLength=" << myMaxLength << " veh=" << vehicle->getID() << " length=" << vehicle->getLength() << "\n";
197  }
198 #endif
199  return vehicle->getLength() > myMaxLength || (myOriginal != nullptr && myOriginal->prohibits(vehicle));
200  }
201 
202  inline bool restricts(const V* const vehicle) const {
203  return myOriginal != nullptr && myOriginal->restricts(vehicle);
204  }
205 
207  if (vClass == SVC_IGNORING || myOriginal == nullptr || myOriginal->isTazConnector()) { // || !MSNet::getInstance()->hasPermissions()) {
208  return myViaSuccessors;
209  }
210 #ifdef HAVE_FOX
211  FXMutexLock lock(mySuccessorMutex);
212 #endif
213  auto i = myClassesViaSuccessorMap.find(vClass);
214  if (i != myClassesViaSuccessorMap.end()) {
215  // can use cached value
216  return i->second;
217  }
218  // instantiate vector
220  // this vClass is requested for the first time. rebuild all successors
221  for (const auto& viaPair : myViaSuccessors) {
222  if (viaPair.first->myOriginal == nullptr
223  || viaPair.first->myOriginal->isTazConnector()
224  || myOriginal->isConnectedTo(*viaPair.first->myOriginal, vClass)) {
225  result.push_back(viaPair);
226  }
227  }
228  return result;
229  }
230 
231  bool isVirtual() const {
232  return myIsVirtual;
233  }
234 
235 private:
236  const int myNumericalID;
237  const std::string myID;
238  const E* myOriginal;
241 
243  std::vector<const E*> myReplacementEdges;
244 
246  double myMaxLength = std::numeric_limits<double>::max();
248  double myStartLength = 0;
249 
251  mutable std::map<SUMOVehicleClass, ConstEdgePairVector> myClassesViaSuccessorMap;
252 
254 
255 #ifdef HAVE_FOX
257  mutable FXMutex mySuccessorMutex;
258 #endif
259 
260 };
#define RailEdge_DEBUG_COND(obj)
Definition: RailEdge.h:29
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
the edge type representing backward edges
Definition: RailEdge.h:36
RailEdge(const E *orig)
Definition: RailEdge.h:41
const std::string myID
Definition: RailEdge.h:237
double myStartLength
length of the edge where this turn starts
Definition: RailEdge.h:248
void insertOriginalEdges(double length, std::vector< const E * > &into) const
Definition: RailEdge.h:152
bool myIsVirtual
Definition: RailEdge.h:240
int getNumericalID() const
Returns the index (numeric id) of the edge.
Definition: RailEdge.h:136
const E * getOriginal() const
Returns the original edge.
Definition: RailEdge.h:141
ConstEdgePairVector myViaSuccessors
Definition: RailEdge.h:253
std::vector< const E * > myReplacementEdges
actual edges to return when passing this (turnaround) edge - only forward
Definition: RailEdge.h:243
void addVirtualTurns(const E *forward, const E *backward, std::vector< _RailEdge * > &railEdges, int &numericalID, double dist, double maxTrainLength, const std::vector< const E * > &replacementEdges)
Definition: RailEdge.h:69
bool isVirtual() const
Definition: RailEdge.h:231
double getLength() const
Returns the length of the edge.
Definition: RailEdge.h:181
const E * myOriginal
Definition: RailEdge.h:238
const int myNumericalID
Definition: RailEdge.h:236
bool isInternal() const
Definition: RailEdge.h:189
double myMaxLength
maximum train length for passing this (turnaround) edge
Definition: RailEdge.h:246
bool prohibits(const V *const vehicle) const
Definition: RailEdge.h:193
RailEdge< E, V > _RailEdge
Definition: RailEdge.h:38
bool restricts(const V *const vehicle) const
Definition: RailEdge.h:202
std::map< SUMOVehicleClass, ConstEdgePairVector > myClassesViaSuccessorMap
The successors available for a given vClass.
Definition: RailEdge.h:251
std::vector< std::pair< const _RailEdge *, const _RailEdge * > > ConstEdgePairVector
Definition: RailEdge.h:39
void init(std::vector< _RailEdge * > &railEdges, int &numericalID, double maxTrainLength)
Definition: RailEdge.h:106
const ConstEdgePairVector & getViaSuccessors(SUMOVehicleClass vClass=SVC_IGNORING) const
Definition: RailEdge.h:206
_RailEdge * myTurnaround
Definition: RailEdge.h:239
RailEdge(const E *turnStart, const E *turnEnd, int numericalID)
Definition: RailEdge.h:48
void update(double maxTrainLength, const std::vector< const E * > &replacementEdges)
Definition: RailEdge.h:59
const std::string & getID() const
Returns the id of the edge.
Definition: RailEdge.h:148