75template<
class E,
class L,
class N,
class V>
82 typedef std::pair<_IntermodalEdge*, _IntermodalEdge*>
EdgePair;
89 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0)
91#ifdef IntermodalRouter_DEBUG_NETWORK
92 std::cout <<
"initIntermodalNetwork\n";
95 bool haveSeenWalkingArea =
false;
96 for (
const E*
const edge : edges) {
97 if (edge->isTazConnector()) {
104 const L* lane = getSidewalk<E, L>(edge);
106 if (edge->isWalkingArea()) {
112 haveSeenWalkingArea =
true;
120 if (!edge->isWalkingArea()) {
130 for (
const E*
const edge : edges) {
131 if (edge->isTazConnector() || edge->isInternal()) {
134 if (haveSeenWalkingArea) {
136 if (!pedestrianOnly && getSidewalk<E, L>(edge) ==
nullptr) {
137 const N*
const node = edge->getToJunction();
144 for (
const N*
const node : {
145 edge->getFromJunction(), edge->getToJunction()
155 for (
const E*
const edge : edges) {
156 if (edge->isTazConnector()) {
160 const E* other = edge->getOtherTazConnector();
163 for (
const E* out : edge->getSuccessors()) {
164 if (out->isNormal()) {
169 for (
const E* in : edge->getPredecessors()) {
170 if (in->isNormal()) {
177 const L*
const sidewalk = getSidewalk<E, L>(edge);
178 if (sidewalk ==
nullptr) {
184#ifdef IntermodalRouter_DEBUG_NETWORK
185 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
187 if (haveSeenWalkingArea) {
188 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
192 bool hasWalkingArea =
false;
193 for (
const auto& target : outgoing) {
194 if (target.first->getEdge().isWalkingArea()) {
195 hasWalkingArea =
true;
199 for (
const auto& target : outgoing) {
200 const E*
const targetEdge = &(target.first->getEdge());
201 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
202 && (!hasWalkingArea || targetEdge->isWalkingArea()));
203#ifdef IntermodalRouter_DEBUG_NETWORK
204 const L* potTarget = getSidewalk<E, L>(targetEdge);
205 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
209 pair.first->addSuccessor(targetPair.first);
210 targetPair.second->addSuccessor(pair.second);
211#ifdef IntermodalRouter_DEBUG_NETWORK
212 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
213 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
222 if (toNodeConn !=
nullptr) {
224 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
225 double minViaLength = std::numeric_limits<double>::max();
226 const E* minVia =
nullptr;
227 for (
const auto& target : outgoing) {
228 if (target.second !=
nullptr && target.second->getLength() < minViaLength) {
229 minViaLength = target.second->getLength();
230 minVia = target.second;
233 EdgePair interVia = std::make_pair(
nullptr,
nullptr);
234 if (minVia !=
nullptr) {
237 interVia = it->second;
240 if (!haveSeenWalkingArea) {
242 pair.first->addSuccessor(toNodeConn, interVia.first);
247 if (fromNodeConn !=
nullptr) {
248 if (!haveSeenWalkingArea) {
253 if (!edge->isWalkingArea()) {
260 pair.first->addSuccessor(endConnector);
261 pair.second->addSuccessor(endConnector);
262#ifdef IntermodalRouter_DEBUG_NETWORK
263 std::cout <<
" " << startConnector->
getID() <<
" -> " << pair.first->getID() <<
"\n";
264 std::cout <<
" " << startConnector->
getID() <<
" -> " << pair.second->getID() <<
"\n";
265 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->
getID() <<
"\n";
266 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->
getID() <<
"\n";
89 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0) {
…}
273 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
298 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
301 throw ProcessError(
TLF(
"Edge '%' not found in intermodal network.'", e->getID()));
308 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
310 throw ProcessError(
TLF(
"Depart edge '%' not found in intermodal network.", e->getID()));
314 double bestDist = std::numeric_limits<double>::max();
317 if (pos >=
split->getStartPos() - POSITION_EPS && pos <=
split->getEndPos() + POSITION_EPS) {
319 if (dist < bestDist) {
325 assert(best !=
nullptr);
329 const std::vector<_IntermodalEdge*>& splitList = it->second;
330 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
331 double totalLength = 0.;
332 while (splitIt + 1 != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
342 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
344 throw ProcessError(
TLF(
"Depart edge '%' not found in intermodal network.", e->getID()));
346 if (splitIndex >= (
int)it->second.size()) {
347 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
349 return it->second[splitIndex];
354 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
356 throw ProcessError(
TLF(
"Arrival edge '%' not found in intermodal network.", e->getID()));
358 const std::vector<_IntermodalEdge*>& splitList = it->second;
359 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
360 double totalLength = 0.;
361 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
362 totalLength += (*splitIt)->getLength();
365 if (splitIt != splitList.end()) {
368 return splitList.back();
379 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
381 const L*
const sidewalk = getSidewalk<E, L>(e);
382 if (e->isInternal() || sidewalk == 0) {
385 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
386 if (target.first->getEdge().isWalkingArea()) {
396 for (
const E*
const edge : edges) {
405 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
408 if (sucCarEdge !=
nullptr) {
422 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
423 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
427 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
428 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
441 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
442 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
446 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
447 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
514 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) {
515 assert(stopEdge !=
nullptr);
520 const double pos = (startPos + endPos) / 2.;
521#ifdef IntermodalRouter_DEBUG_ACCESS
522 std::cout <<
"addAccess stopId=" << stopId <<
" stopEdge=" << stopEdge->getID() <<
" pos=" << pos <<
" length=" << length <<
" tag=" <<
toString(category)
523 <<
" access=" << isAccess <<
" tWait=" << taxiWait <<
"\n";
530 const L* lane = getSidewalk<E, L>(stopEdge);
531 if (lane !=
nullptr) {
532 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
535 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
537 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
539 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
545 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false, transferCarWalk);
548 if (carSplit !=
nullptr && (transferCarWalk || transferTaxiWalk)) {
554 if (transferCarWalk) {
559 }
else if (transferTaxiWalk) {
564 if (carSplit !=
nullptr && transferWalkTaxi && !isAccess) {
573 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
574 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
582 if (carSplit !=
nullptr) {
596 if (carSplit !=
nullptr) {
607 std::vector<_IntermodalEdge*>& splitList =
myDepartLookup[stopEdge];
608 assert(splitList.size() > 0);
609 typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
610 while (splitIt != splitList.end() && startPos > (*splitIt)->getEndPos()) {
613 splitList.insert(splitIt, stopConn);
615 if (!isAccess && (transferWalkTaxi || transferCarWalk || transferTaxiWalk)) {
619 const int splitIndex =
findSplitIndex(carEdge, pos, relPos, needSplit);
622 splitEdge(carEdge, splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false,
false);
624 if (transferCarWalk || transferTaxiWalk) {
627 if (transferCarWalk) {
632 }
else if (transferTaxiWalk) {
636 if (transferWalkTaxi) {
514 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) {
…}
649 std::vector<SUMOVehicleParameter::Stop> validStops;
650 if (addStops !=
nullptr) {
656 if (newUntil >= lastUntil) {
657 validStops.push_back(stop);
658 validStops.back().until = newUntil;
659 lastUntil = newUntil;
669 validStops.push_back(stop);
670 lastUntil = stop.until;
672 if (stop.busstop !=
"" && stop.until >= 0) {
677 if (validStops.size() < 2 && pars.
line !=
"taxi") {
678 WRITE_WARNINGF(
TL(
"Not using public transport line '%' for routing persons. It has less than two usable stops."), pars.
line);
682 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
683 if (lineEdges.empty()) {
689 Position stopPos = E::getStopPosition(s);
690 if (lastStop !=
nullptr) {
696 lineEdges.push_back(newEdge);
702 if (pars.
line !=
"taxi" && validStops.front().busstop == validStops.back().busstop) {
706 if (validStops.size() != lineEdges.size() + 1) {
707 WRITE_WARNINGF(
"Number of stops for public transport line '%' does not match earlier definitions, ignoring schedule.", pars.
line);
710 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
711 WRITE_WARNINGF(
"Different stop for '%' compared to earlier definitions, ignoring schedule.", pars.
line);
714 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
715 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
716 for (; s != validStops.end(); ++s, ++lineEdge) {
718 WRITE_WARNINGF(
"Different stop for '%' compared to earlier definitions, ignoring schedule.", pars.
line);
722 SUMOTime lastTime = validStops.front().until;
723 if (lineEdges.front()->hasSchedule(lastTime)) {
726 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
738 assert(edge !=
nullptr);
745 pedestrianEdges.first->addSuccessor(access);
746 pedestrianEdges.second->addSuccessor(access);
783 if (splitList !=
myAccessSplits.end() && !splitList->second.empty()) {
785 if (relPos < split->getLength() + POSITION_EPS) {
788 relPos -=
split->getLength();
791 assert(splitIndex < (
int)splitList->second.size());
792 if (splitIndex + 1 < (
int)splitList->second.size() && fabs(relPos - splitList->second[splitIndex]->getLength()) < POSITION_EPS) {
812 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
813 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true,
const bool addEntry =
true) {
814 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
815 if (splitList.empty()) {
816 splitList.push_back(toSplit);
819 splitIndex = (int)splitList.size() - 1 - splitIndex;
836 const std::string newID = beforeSplit->
getID();
838 afterSplit->
setID(newID);
840 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
843 afterSplit = splitList[splitIndex + 1];
879 std::map<const E*, _IntermodalEdge*, ComparatorNumericalIdLess>
myCarLookup;
882 std::map<std::string, std::vector<_PTEdge*> >
myPTLines;
ModeChangeOptions
where mode changes are possible
@ TAXI_DROPOFF_ANYWHERE
taxi customer may exit anywhere
@ PT_STOPS
public transport stops and access
@ TAXI_PICKUP_ANYWHERE
taxi customer may be picked up anywhere
@ TAXI_PICKUP_PARKING_AREAS
taxi customer may be picked up at parking areas
@ TAXI_DROPOFF_PT
taxi customer may exit at public transport stops
@ TAXI_DROPOFF_PARKING_AREAS
taxi customer may exit at parking areas
@ ALL_JUNCTIONS
junctions with edges allowing the additional mode
@ TAXI_PICKUP_PT
taxi customer may be picked up at public transport stops
@ PARKING_AREAS
parking areas
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)
const E * getEdge() const
void setLength(const double length)
void transferSuccessors(IntermodalEdge *to)
bool removeSuccessor(const IntermodalEdge *const edge)
void addSuccessor(IntermodalEdge *const s, IntermodalEdge *const via=nullptr)
double getLength() const
required by DijkstraRouter et al for external effort computation
int getNumericalID() const
virtual double getEndPos() 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.
const std::vector< _IntermodalEdge * > & getAllEdges()
_IntermodalEdge * getArrivalConnector(const E *e, const int splitIndex=0) const
Returns the arriving intermodal connector at the given split offset.
PublicTransportEdge< E, L, N, V > _PTEdge
_IntermodalEdge * getCarEdge(const E *e) const
Returns the associated car edge.
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 * getStopEdge(const std::string &stopId) const
Returns the associated stop edge.
const int myCarWalkTransfer
void addEdge(_IntermodalEdge *edge)
std::vector< _IntermodalEdge * > myEdges
the edge dictionary
AccessEdge< E, L, N, V > _AccessEdge
IntermodalNetwork & operator=(const IntermodalNetwork &s)
Invalidated assignment operator.
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)
const EdgePair & getBothDirections(const E *e) const
Returns the pair of forward and backward edge.
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 * getArrivalEdge(const E *e, const double pos) const
Returns the arriving intermodal edge.
IntermodalEdge< E, L, N, V > _IntermodalEdge
std::map< const E *, std::vector< _IntermodalEdge * > > myDepartLookup
retrieve the depart edges for the given input edge E
_IntermodalEdge * getDepartConnector(const E *e, const int splitIndex=0) const
Returns the departing intermodal connector at the given split offset.
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 dimensions
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)
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