50 template<
class E,
class L,
class N,
class V>
57 typedef std::pair<_IntermodalEdge*, _IntermodalEdge*>
EdgePair;
83 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0)
85 #ifdef IntermodalRouter_DEBUG_NETWORK
86 std::cout <<
"initIntermodalNetwork\n";
89 bool haveSeenWalkingArea =
false;
90 for (
const E*
const edge : edges) {
91 if (edge->isTazConnector()) {
98 const L* lane = getSidewalk<E, L>(edge);
100 if (edge->isWalkingArea()) {
106 haveSeenWalkingArea =
true;
114 if (!edge->isWalkingArea()) {
124 for (
const E*
const edge : edges) {
125 if (edge->isTazConnector() || edge->isInternal()) {
128 if (haveSeenWalkingArea) {
130 if (!pedestrianOnly && getSidewalk<E, L>(edge) ==
nullptr) {
131 const N*
const node = edge->getToJunction();
138 for (
const N*
const node : {
139 edge->getFromJunction(), edge->getToJunction()
149 for (
const E*
const edge : edges) {
150 if (edge->isTazConnector()) {
154 const E* other = edge->getOtherTazConnector();
157 for (
const E* out : edge->getSuccessors()) {
158 if (out->isNormal()) {
163 for (
const E* in : edge->getPredecessors()) {
164 if (in->isNormal()) {
171 const L*
const sidewalk = getSidewalk<E, L>(edge);
172 if (sidewalk ==
nullptr) {
178 #ifdef IntermodalRouter_DEBUG_NETWORK
179 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
181 if (haveSeenWalkingArea) {
182 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
186 bool hasWalkingArea =
false;
187 for (
const auto& target : outgoing) {
188 if (target.first->getEdge().isWalkingArea()) {
189 hasWalkingArea =
true;
193 for (
const auto& target : outgoing) {
194 const E*
const targetEdge = &(target.first->getEdge());
195 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
196 && (!hasWalkingArea || targetEdge->isWalkingArea()));
197 #ifdef IntermodalRouter_DEBUG_NETWORK
198 const L* potTarget = getSidewalk<E, L>(targetEdge);
199 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
203 pair.first->addSuccessor(targetPair.first);
204 targetPair.second->addSuccessor(pair.second);
205 #ifdef IntermodalRouter_DEBUG_NETWORK
206 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
207 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
216 if (toNodeConn !=
nullptr) {
218 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
219 double minViaLength = std::numeric_limits<double>::max();
220 const E* minVia =
nullptr;
221 for (
const auto& target : outgoing) {
222 if (target.second !=
nullptr && target.second->getLength() < minViaLength) {
223 minViaLength = target.second->getLength();
224 minVia = target.second;
227 EdgePair interVia = std::make_pair(
nullptr,
nullptr);
228 if (minVia !=
nullptr) {
231 interVia = it->second;
234 if (!haveSeenWalkingArea) {
236 pair.first->addSuccessor(toNodeConn, interVia.first);
241 if (fromNodeConn !=
nullptr) {
242 if (!haveSeenWalkingArea) {
243 pair.second->addSuccessor(fromNodeConn);
247 if (!edge->isWalkingArea()) {
254 pair.first->addSuccessor(endConnector);
255 pair.second->addSuccessor(endConnector);
256 #ifdef IntermodalRouter_DEBUG_NETWORK
257 std::cout <<
" " << startConnector->
getID() <<
" -> " << pair.first->getID() <<
"\n";
258 std::cout <<
" " << startConnector->
getID() <<
" -> " << pair.second->getID() <<
"\n";
259 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->
getID() <<
"\n";
260 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->
getID() <<
"\n";
267 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
292 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
295 throw ProcessError(
TLF(
"Edge '%' not found in intermodal network.'", e->getID()));
302 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
304 throw ProcessError(
TLF(
"Depart edge '%' not found in intermodal network.", e->getID()));
308 double bestDist = std::numeric_limits<double>::max();
311 if (pos >=
split->getStartPos() - POSITION_EPS && pos <= split->getEndPos() + POSITION_EPS) {
312 const double dist =
split->getEndPos() -
split->getStartPos();
313 if (dist < bestDist) {
319 assert(best !=
nullptr);
323 const std::vector<_IntermodalEdge*>& splitList = it->second;
324 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
325 double totalLength = 0.;
326 while (splitIt + 1 != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
336 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
338 throw ProcessError(
TLF(
"Depart edge '%' not found in intermodal network.", e->getID()));
340 if (splitIndex >= (
int)it->second.size()) {
341 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
343 return it->second[splitIndex];
348 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
350 throw ProcessError(
TLF(
"Arrival edge '%' not found in intermodal network.", e->getID()));
352 const std::vector<_IntermodalEdge*>& splitList = it->second;
353 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
354 double totalLength = 0.;
355 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
356 totalLength += (*splitIt)->getLength();
369 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
371 const L*
const sidewalk = getSidewalk<E, L>(e);
372 if (e->isInternal() || sidewalk == 0) {
375 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
376 if (target.first->getEdge().isWalkingArea()) {
386 for (
const E*
const edge : edges) {
395 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
398 if (sucCarEdge !=
nullptr) {
412 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
413 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
417 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
418 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
431 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
432 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
436 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
437 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
504 void addAccess(
const std::string& stopId,
const E* stopEdge,
const double startPos,
const double endPos,
const double length,
const SumoXMLTag category,
bool isAccess,
double taxiWait) {
505 assert(stopEdge !=
nullptr);
510 const double pos = (startPos + endPos) / 2.;
511 #ifdef IntermodalRouter_DEBUG_ACCESS
512 std::cout <<
"addAccess stopId=" << stopId <<
" stopEdge=" << stopEdge->getID() <<
" pos=" << pos <<
" length=" << length <<
" tag=" <<
toString(category)
513 <<
" access=" << isAccess <<
" tWait=" << taxiWait <<
"\n";
520 const L* lane = getSidewalk<E, L>(stopEdge);
521 if (lane !=
nullptr) {
522 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
525 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
527 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
529 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
535 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false, transferCarWalk);
538 if (carSplit !=
nullptr && (transferCarWalk || transferTaxiWalk)) {
544 if (transferCarWalk) {
549 }
else if (transferTaxiWalk) {
554 if (carSplit !=
nullptr && transferWalkTaxi && !isAccess) {
563 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
564 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
572 if (carSplit !=
nullptr) {
586 if (carSplit !=
nullptr) {
597 std::vector<_IntermodalEdge*>& splitList =
myDepartLookup[stopEdge];
598 assert(splitList.size() > 0);
599 typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
600 while (splitIt != splitList.end() && startPos > (*splitIt)->getEndPos()) {
603 splitList.insert(splitIt, stopConn);
605 if (!isAccess && (transferWalkTaxi || transferCarWalk || transferTaxiWalk)) {
609 const int splitIndex =
findSplitIndex(carEdge, pos, relPos, needSplit);
612 splitEdge(carEdge, splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false,
false);
614 if (transferCarWalk || transferTaxiWalk) {
617 if (transferCarWalk) {
622 }
else if (transferTaxiWalk) {
626 if (transferWalkTaxi) {
639 std::vector<SUMOVehicleParameter::Stop> validStops;
640 if (addStops !=
nullptr) {
646 if (newUntil >= lastUntil) {
647 validStops.push_back(stop);
648 validStops.back().until = newUntil;
649 lastUntil = newUntil;
659 validStops.push_back(stop);
660 lastUntil = stop.
until;
667 if (validStops.size() < 2 && pars.
line !=
"taxi") {
668 WRITE_WARNINGF(
TL(
"Not using public transport line '%' for routing persons. It has less than two usable stops."), pars.
line);
672 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
673 if (lineEdges.empty()) {
679 Position stopPos = E::getStopPosition(s);
680 if (lastStop !=
nullptr) {
686 lineEdges.push_back(newEdge);
692 if (pars.
line !=
"taxi" && validStops.front().busstop == validStops.back().busstop) {
696 if (validStops.size() != lineEdges.size() + 1) {
697 WRITE_WARNINGF(
"Number of stops for public transport line '%' does not match earlier definitions, ignoring schedule.", pars.
line);
700 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
701 WRITE_WARNINGF(
"Different stop for '%' compared to earlier definitions, ignoring schedule.", pars.
line);
704 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
705 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
706 for (; s != validStops.end(); ++s, ++lineEdge) {
708 WRITE_WARNINGF(
"Different stop for '%' compared to earlier definitions, ignoring schedule.", pars.
line);
712 SUMOTime lastTime = validStops.front().until;
713 if (lineEdges.front()->hasSchedule(lastTime)) {
716 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
728 assert(edge !=
nullptr);
735 pedestrianEdges.first->addSuccessor(access);
736 pedestrianEdges.second->addSuccessor(access);
773 if (splitList !=
myAccessSplits.end() && !splitList->second.empty()) {
775 if (relPos < split->getLength() + POSITION_EPS) {
778 relPos -=
split->getLength();
781 assert(splitIndex < (
int)splitList->second.size());
782 if (splitIndex + 1 < (
int)splitList->second.size() && fabs(relPos - splitList->second[splitIndex]->getLength()) < POSITION_EPS) {
802 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
803 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true,
const bool addEntry =
true) {
804 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
805 if (splitList.empty()) {
806 splitList.push_back(toSplit);
809 splitIndex = (int)splitList.size() - 1 - splitIndex;
826 const std::string newID = beforeSplit->
getID();
828 afterSplit->
setID(newID);
830 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
833 afterSplit = splitList[splitIndex + 1];
869 std::map<const E*, _IntermodalEdge*, ComparatorNumericalIdLess>
myCarLookup;
872 std::map<std::string, std::vector<_PTEdge*> >
myPTLines;
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#define WRITE_WARNINGF(...)
std::string time2string(SUMOTime t, bool humanReadable)
convert SUMOTime to string (independently of global format setting)
const SVCPermissions SVCAll
all VClasses are allowed
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_IGNORING
vehicles ignoring classes
@ SVC_TAXI
vehicle is a taxi
@ SVC_PEDESTRIAN
pedestrian
SumoXMLTag
Numbers representing SUMO-XML - element names.
@ SUMO_TAG_BUS_STOP
A bus stop.
@ SUMO_TAG_PARKING_AREA
A parking area.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
the access edge connecting different modes that is given to the internal router (SUMOAbstractRouter)
the car edge type that is given to the internal router (SUMOAbstractRouter)
the base edge type that is given to the internal router (SUMOAbstractRouter)
void setLength(const double length)
void transferSuccessors(IntermodalEdge *to)
bool removeSuccessor(const IntermodalEdge *const edge)
void addSuccessor(IntermodalEdge *const s, IntermodalEdge *const via=nullptr)
const E * getEdge() const
double getLength() const
required by DijkstraRouter et al for external effort computation
int getNumericalID() const
the intermodal network storing edges, connections and the mappings to the "real" edges
_IntermodalEdge * getWalkingConnector(const E *e) const
Returns the outgoing pedestrian edge, which is either a walking area or a walking connector.
PublicTransportEdge< E, L, N, V > _PTEdge
std::map< const E *, _IntermodalEdge *, ComparatorNumericalIdLess > myCarLookup
retrieve the car edge for the given input edge E
void addCarAccess(const E *edge, SUMOVehicleClass svc, double traveltime)
Adds access edges for transfering from walking to vehicle use.
void addAccess(const std::string &stopId, const E *stopEdge, const double startPos, const double endPos, const double length, const SumoXMLTag category, bool isAccess, double taxiWait)
Adds access edges for stopping places to the intermodal network.
std::map< const E *, std::vector< _IntermodalEdge * > > myArrivalLookup
retrieve the arrival edges for the given input edge E
std::map< const N *, _IntermodalEdge * > myWalkingConnectorLookup
the walking connector edge (fake walking area)
std::map< std::string, _IntermodalEdge * > myStopConnections
retrieve the representing edge for the given stopping place
std::map< _IntermodalEdge *, std::vector< _IntermodalEdge * > > myAccessSplits
retrieve the splitted edges for the given "original"
_IntermodalEdge * getArrivalConnector(const E *e, const int splitIndex=0) const
Returns the arriving intermodal connector at the given split offset.
const EdgePair & getBothDirections(const E *e) const
Returns the pair of forward and backward edge.
const std::vector< _IntermodalEdge * > & getAllEdges()
_IntermodalEdge * getArrivalEdge(const E *e, const double pos) const
Returns the arriving intermodal edge.
const int myCarWalkTransfer
_IntermodalEdge * getStopEdge(const std::string &stopId) const
Returns the associated stop edge.
void addEdge(_IntermodalEdge *edge)
std::vector< _IntermodalEdge * > myEdges
the edge dictionary
IntermodalNetwork & operator=(const IntermodalNetwork &s)
Invalidated assignment operator.
AccessEdge< E, L, N, V > _AccessEdge
ModeChangeOptions
where mode changes are possible
@ TAXI_PICKUP_ANYWHERE
taxi customer may be picked up anywhere
@ TAXI_DROPOFF_ANYWHERE
taxi customer may exit anywhere
@ PARKING_AREAS
parking areas
@ ALL_JUNCTIONS
junctions with edges allowing the additional mode
@ TAXI_PICKUP_PT
taxi customer may be picked up at public transport stop
@ PT_STOPS
public transport stops and access
@ TAXI_DROPOFF_PT
taxi customer may be picked up at public transport stop
std::map< const E *, EdgePair > myBidiLookup
retrieve the forward and backward edge for the given input edge E
std::set< std::string > myLoopedLines
looped lines need extra checking when building itineraries
bool isLooped(const std::string lineID) const
std::map< std::string, std::vector< _PTEdge * > > myPTLines
retrieve the public transport edges for the given line
void addRestrictedCarExit(_IntermodalEdge *from, _IntermodalEdge *to, SVCPermissions vehicleRestriction)
Adds access edges for transfering from driving to walking that are only usable by a particular vehicl...
void addConnectors(_IntermodalEdge *const depConn, _IntermodalEdge *const arrConn, const int index)
int findSplitIndex(_IntermodalEdge *const toSplit, const double pos, double &relPos, bool &needSplit) const
Returns where to insert or use the split edge.
void addCarEdges(const std::vector< E * > &edges, double taxiWait)
PedestrianEdge< E, L, N, V > _PedestrianEdge
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, const bool addEntry=true)
Splits an edge (if necessary) and connects it to a stopping edge.
IntermodalNetwork(const std::vector< E * > &edges, const bool pedestrianOnly, const int carWalkTransfer=0)
IntermodalEdge< E, L, N, V > _IntermodalEdge
_IntermodalEdge * getDepartConnector(const E *e, const int splitIndex=0) const
Returns the departing intermodal connector at the given split offset.
std::map< const E *, std::vector< _IntermodalEdge * > > myDepartLookup
retrieve the depart edges for the given input edge E
_IntermodalEdge * getCarEdge(const E *e) const
Returns the associated car edge.
void addSchedule(const SUMOVehicleParameter &pars, const std::vector< SUMOVehicleParameter::Stop > *addStops=nullptr)
std::pair< _IntermodalEdge *, _IntermodalEdge * > EdgePair
const _IntermodalEdge * getDepartEdge(const E *e, const double pos) const
Returns the departing intermodal edge.
virtual void setID(const std::string &newID)
resets the id
const std::string & getID() const
Returns the id.
the pedestrian edge type that is given to the internal router (SUMOAbstractRouter)
A point in 2D or 3D with translation and scaling methods.
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
the public transport edge type connecting the stop edges
void addSchedule(const std::string id, const SUMOTime begin, const int repetitionNumber, const SUMOTime period, const SUMOTime travelTime)
Definition of vehicle stop (position and duration)
SUMOTime until
The time at which the vehicle may continue its journey.
std::string busstop
(Optional) bus stop if one is assigned to the stop
Structure representing possible vehicle parameter.
SUMOTime repetitionOffset
The time offset between vehicle reinsertions.
std::string id
The vehicle's id.
std::vector< Stop > stops
List of the stops the vehicle will make, TraCI may add entries here.
std::string line
The vehicle's line (mainly for public transport)
the stop edge type representing bus and train stops