19 #ifndef IntermodalNetwork_h 20 #define IntermodalNetwork_h 50 template <
class E,
class L>
52 if (edge ==
nullptr) {
56 const std::vector<L*>& lanes = edge->getLanes();
57 for (
const L*
const lane : lanes) {
62 for (
const L*
const lane : lanes) {
75 template<
class E,
class L,
class N,
class V>
82 typedef std::pair<_IntermodalEdge*, _IntermodalEdge*>
EdgePair;
100 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0)
102 #ifdef IntermodalRouter_DEBUG_NETWORK 103 std::cout <<
"initIntermodalNetwork\n";
106 bool haveSeenWalkingArea =
false;
107 for (
const E*
const edge : edges) {
108 if (edge->isTazConnector()) {
111 const L* lane = getSidewalk<E, L>(edge);
113 if (edge->isWalkingArea()) {
119 haveSeenWalkingArea =
true;
127 if (!edge->isWalkingArea()) {
136 for (
const E*
const edge : edges) {
137 if (edge->isTazConnector()) {
140 if (haveSeenWalkingArea) {
142 if (!pedestrianOnly && getSidewalk<E, L>(edge) ==
nullptr) {
143 const N*
const node = edge->getToJunction();
150 for (
const N*
const node : {
151 edge->getFromJunction(), edge->getToJunction()
161 for (
const E*
const edge : edges) {
162 const L*
const sidewalk = getSidewalk<E, L>(edge);
163 if (sidewalk ==
nullptr) {
169 #ifdef IntermodalRouter_DEBUG_NETWORK 170 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
172 if (haveSeenWalkingArea) {
173 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
177 bool hasWalkingArea =
false;
178 for (
const auto& target : outgoing) {
179 if (target.first->getEdge().isWalkingArea()) {
180 hasWalkingArea =
true;
184 for (
const auto& target : outgoing) {
185 const E*
const targetEdge = &(target.first->getEdge());
186 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
187 && (!hasWalkingArea || targetEdge->isWalkingArea()));
188 #ifdef IntermodalRouter_DEBUG_NETWORK 189 const L* potTarget = getSidewalk<E, L>(targetEdge);
190 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
194 pair.first->addSuccessor(targetPair.first);
195 targetPair.second->addSuccessor(pair.second);
196 #ifdef IntermodalRouter_DEBUG_NETWORK 197 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
198 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
207 if (toNodeConn !=
nullptr) {
208 if (!haveSeenWalkingArea) {
210 pair.first->addSuccessor(toNodeConn);
215 if (fromNodeConn !=
nullptr) {
216 if (!haveSeenWalkingArea) {
217 pair.second->addSuccessor(fromNodeConn);
221 if (!edge->isWalkingArea()) {
228 pair.first->addSuccessor(endConnector);
229 pair.second->addSuccessor(endConnector);
231 #ifdef IntermodalRouter_DEBUG_NETWORK 232 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.first->getID() <<
"\n";
233 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.second->getID() <<
"\n";
234 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->getID() <<
"\n";
235 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->getID() <<
"\n";
241 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
253 void addConnectors(_IntermodalEdge*
const depConn, _IntermodalEdge*
const arrConn,
const int index) {
266 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
269 throw ProcessError(
"Edge '" + e->getID() +
"' not found in intermodal network '");
276 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
278 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
280 const std::vector<_IntermodalEdge*>& splitList = it->second;
281 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
282 double totalLength = 0.;
283 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
284 totalLength += (*splitIt)->getLength();
292 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
294 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
296 if (splitIndex >= (
int)it->second.size()) {
297 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
299 return it->second[splitIndex];
304 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
306 throw ProcessError(
"Arrival edge '" + e->getID() +
"' not found in intermodal network.");
308 const std::vector<_IntermodalEdge*>& splitList = it->second;
309 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
310 double totalLength = 0.;
311 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
312 totalLength += (*splitIt)->getLength();
325 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
327 const L*
const sidewalk = getSidewalk<E, L>(e);
328 if (e->isInternal() || sidewalk == 0) {
331 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
332 if (target.first->getEdge().isWalkingArea()) {
342 for (
const E*
const edge : edges) {
349 _IntermodalEdge*
const carEdge = edgePair.second;
350 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
351 _IntermodalEdge*
const sucCarEdge =
getCarEdge(suc.first);
352 _IntermodalEdge*
const sucViaEdge =
getCarEdge(suc.second);
353 if (sucCarEdge !=
nullptr) {
363 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
364 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
368 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
369 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
382 typename std::map<const E*, _IntermodalEdge*>::const_iterator it =
myCarLookup.find(e);
411 void addAccess(
const std::string& stopId,
const E* stopEdge,
const double pos,
const double length,
const SumoXMLTag category) {
412 assert(stopEdge != 0);
418 const L* lane = getSidewalk<E, L>(stopEdge);
420 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
423 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
425 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
426 _IntermodalEdge*
const backSplit = needSplit ?
new PedestrianEdge<E, L, N, V>(myNumericalID++, stopEdge, lane,
false, pos) :
nullptr;
427 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
428 _IntermodalEdge* carSplit =
nullptr;
433 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false);
439 for (_IntermodalEdge* conn : {
442 _AccessEdge* access =
new _AccessEdge(myNumericalID++, beforeSplit, conn, length);
451 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
452 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
453 _IntermodalEdge*
const depConn =
new _IntermodalEdge(stopEdge->getID() +
"_depart_connector" +
toString(pos), myNumericalID++, stopEdge,
"!connector");
460 if (carSplit !=
nullptr) {
466 _IntermodalEdge*
const fwdBeforeSplit =
myAccessSplits[pair.first][splitIndex];
467 _IntermodalEdge*
const arrConn =
new _IntermodalEdge(stopEdge->getID() +
"_arrival_connector" +
toString(pos), myNumericalID++, stopEdge,
"!connector");
474 if (carSplit !=
nullptr) {
486 std::vector<SUMOVehicleParameter::Stop> validStops;
489 for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = addStops->begin(); s != addStops->end(); ++s) {
494 if (stop.
until >= lastUntil) {
495 validStops.push_back(stop);
496 lastUntil = stop.
until;
503 for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = pars.
stops.begin(); s != pars.
stops.end(); ++s) {
506 validStops.push_back(*s);
507 lastUntil = s->until;
510 if (validStops.size() < 2) {
511 WRITE_WARNING(
"Ignoring public transport line '" + pars.
line +
"' with less than two usable stops.");
515 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
516 if (lineEdges.empty()) {
517 _IntermodalEdge* lastStop = 0;
519 for (std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin(); s != validStops.end(); ++s) {
527 lineEdges.push_back(newEdge);
533 if (validStops.size() != lineEdges.size() + 1) {
534 WRITE_WARNING(
"Number of stops for public transport line '" + pars.
line +
"' does not match earlier definitions, ignoring schedule.");
537 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
538 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
541 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
542 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
543 for (; s != validStops.end(); ++s, ++lineEdge) {
545 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
549 SUMOTime lastTime = validStops.front().until;
550 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
570 int findSplitIndex(_IntermodalEdge*
const toSplit,
const double pos,
double& relPos,
bool& needSplit) {
574 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
575 if (!splitList.empty()) {
576 for (
const _IntermodalEdge*
const split : splitList) {
580 relPos -=
split->getLength();
583 assert(splitIndex < (
int)splitList.size());
584 if (splitIndex + 1 < (
int)splitList.size() && fabs(relPos - splitList[splitIndex]->getLength()) <
POSITION_EPS) {
603 void splitEdge(_IntermodalEdge*
const toSplit,
int splitIndex,
604 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
605 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true) {
606 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
607 if (splitList.empty()) {
608 splitList.push_back(toSplit);
611 splitIndex = (int)splitList.size() - 1 - splitIndex;
616 _IntermodalEdge* beforeSplit = splitList[splitIndex];
628 const std::string newID = beforeSplit->
getID();
630 afterSplit->
setID(newID);
632 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
635 afterSplit = splitList[splitIndex + 1];
672 std::map<std::string, std::vector<_PTEdge*> >
myPTLines;
const EdgePair & getBothDirections(const E *e) const
Returns the pair of forward and backward edge.
SumoXMLTag
Numbers representing SUMO-XML - element names.
_IntermodalEdge * getArrivalEdge(const E *e, const double pos) const
Returns the arriving intermodal edge.
public transport stops and access
void splitEdge(_IntermodalEdge *const toSplit, int splitIndex, _IntermodalEdge *afterSplit, const double relPos, const double length, const bool needSplit, _IntermodalEdge *const stopConn, const bool forward=true, const bool addExit=true)
Splits an edge (if necessary) and connects it to a stopping edge.
int repetitionNumber
The number of times the vehicle shall be repeatedly inserted.
ModeChangeOptions
where mode changes are possible
_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()
IntermodalNetwork(const std::vector< E *> &edges, const bool pedestrianOnly, const int carWalkTransfer=0)
std::map< const E *, EdgePair > myBidiLookup
retrieve the forward and backward edge for the given input edge E
void addEdge(_IntermodalEdge *edge)
const int myCarWalkTransfer
_IntermodalEdge * getStopEdge(const std::string &stopId) const
Returns the associated stop edge.
std::string time2string(SUMOTime t)
int getNumericalID() const
AccessEdge< E, L, N, V > _AccessEdge
the car edge type that is given to the internal router (SUMOAbstractRouter)
IntermodalNetwork & operator=(const IntermodalNetwork &s)
Invalidated assignment operator.
SUMOTime until
The time at which the vehicle may continue its journey.
IntermodalEdge< E, L, N, V > _IntermodalEdge
const std::string & getID() const
Returns the id.
#define WRITE_WARNING(msg)
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
void removeSuccessor(const IntermodalEdge *const edge)
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
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::string busstop
(Optional) bus stop if one is assigned to the stop
void transferSuccessors(IntermodalEdge *to)
PublicTransportEdge< E, L, N, V > _PTEdge
std::vector< _IntermodalEdge * > myEdges
the edge dictionary
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
PedestrianEdge< E, L, N, V > _PedestrianEdge
std::map< const E *, _IntermodalEdge * > myCarLookup
retrieve the car edge for the given input edge E
int findSplitIndex(_IntermodalEdge *const toSplit, const double pos, double &relPos, bool &needSplit)
Returns where to insert or use the split edge.
_IntermodalEdge * getArrivalConnector(const E *e, const int splitIndex=0) const
Returns the arriving intermodal connector at the given split offset.
SUMOTime depart
The vehicle's departure time.
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
std::pair< _IntermodalEdge *, _IntermodalEdge * > EdgePair
std::map< const E *, std::vector< _IntermodalEdge * > > myArrivalLookup
retrieve the arrival edges for the given input edge E
const L * getSidewalk(const E *edge)
the intermodal network storing edges, connections and the mappings to the "real" edges ...
std::string line
The vehicle's line (mainly for public transport)
the base edge type that is given to the internal router (SUMOAbstractRouter)
junctions with edges allowing the additional mode
_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< _IntermodalEdge *, std::vector< _IntermodalEdge * > > myAccessSplits
retrieve the splitted edges for the given "original"
void setID(const std::string &newID)
resets the id
Structure representing possible vehicle parameter.
std::map< const E *, std::vector< _IntermodalEdge * > > myDepartLookup
retrieve the depart edges for the given input edge E
Definition of vehicle stop (position and duration)
std::map< std::string, std::vector< _PTEdge * > > myPTLines
retrieve the public transport edges for the given line
void addCarEdges(const std::vector< E *> &edges)
the public transport edge type connecting the stop edges
std::map< std::string, _IntermodalEdge * > myStopConnections
retrieve the representing edge for the given stopping place
_IntermodalEdge * getCarEdge(const E *e) const
Returns the associated car edge.
void addConnectors(_IntermodalEdge *const depConn, _IntermodalEdge *const arrConn, const int index)
the pedestrian edge type that is given to the internal router (SUMOAbstractRouter) ...
void addSchedule(const std::string id, const SUMOTime begin, const SUMOTime end, const SUMOTime period, const double travelTimeSec)
the stop edge type representing bus and train stops
void addSchedule(const SUMOVehicleParameter &pars, const std::vector< SUMOVehicleParameter::Stop > *addStops=0)
void addSuccessor(IntermodalEdge *const s, IntermodalEdge *const via=nullptr)
vehicles ignoring classes
void addAccess(const std::string &stopId, const E *stopEdge, const double pos, const double length, const SumoXMLTag category)
Adds access edges for stopping places to the intermodal network.
the access edge connecting different modes that is given to the internal router (SUMOAbstractRouter) ...
std::string id
The vehicle's id.
void setLength(const double length)