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()) {
161 for (
const E* in : edge->getPredecessors()) {
167 const L*
const sidewalk = getSidewalk<E, L>(edge);
168 if (sidewalk ==
nullptr) {
174 #ifdef IntermodalRouter_DEBUG_NETWORK
175 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
177 if (haveSeenWalkingArea) {
178 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
182 bool hasWalkingArea =
false;
183 for (
const auto& target : outgoing) {
184 if (target.first->getEdge().isWalkingArea()) {
185 hasWalkingArea =
true;
189 for (
const auto& target : outgoing) {
190 const E*
const targetEdge = &(target.first->getEdge());
191 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
192 && (!hasWalkingArea || targetEdge->isWalkingArea()));
193 #ifdef IntermodalRouter_DEBUG_NETWORK
194 const L* potTarget = getSidewalk<E, L>(targetEdge);
195 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
199 pair.first->addSuccessor(targetPair.first);
200 targetPair.second->addSuccessor(pair.second);
201 #ifdef IntermodalRouter_DEBUG_NETWORK
202 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
203 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
212 if (toNodeConn !=
nullptr) {
214 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
215 double minViaLength = std::numeric_limits<double>::max();
216 const E* minVia =
nullptr;
217 for (
const auto& target : outgoing) {
218 if (target.second !=
nullptr && target.second->getLength() < minViaLength) {
219 minViaLength = target.second->getLength();
220 minVia = target.second;
223 EdgePair interVia = std::make_pair(
nullptr,
nullptr);
224 if (minVia !=
nullptr) {
227 interVia = it->second;
230 if (!haveSeenWalkingArea) {
232 pair.first->addSuccessor(toNodeConn, interVia.first);
237 if (fromNodeConn !=
nullptr) {
238 if (!haveSeenWalkingArea) {
239 pair.second->addSuccessor(fromNodeConn);
243 if (!edge->isWalkingArea()) {
250 pair.first->addSuccessor(endConnector);
251 pair.second->addSuccessor(endConnector);
253 #ifdef IntermodalRouter_DEBUG_NETWORK
254 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.first->getID() <<
"\n";
255 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.second->getID() <<
"\n";
256 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->getID() <<
"\n";
257 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->getID() <<
"\n";
263 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
288 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
291 throw ProcessError(
"Edge '" + e->getID() +
"' not found in intermodal network.'");
298 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
300 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
304 double bestDist = std::numeric_limits<double>::max();
307 if (pos >=
split->getStartPos() - POSITION_EPS && pos <= split->getEndPos() + POSITION_EPS) {
308 const double dist =
split->getEndPos() -
split->getStartPos();
309 if (dist < bestDist) {
315 assert(best !=
nullptr);
319 const std::vector<_IntermodalEdge*>& splitList = it->second;
320 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
321 double totalLength = 0.;
322 while (splitIt + 1 != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
332 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
334 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
336 if (splitIndex >= (
int)it->second.size()) {
337 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
339 return it->second[splitIndex];
344 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
346 throw ProcessError(
"Arrival edge '" + e->getID() +
"' not found in intermodal network.");
348 const std::vector<_IntermodalEdge*>& splitList = it->second;
349 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
350 double totalLength = 0.;
351 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
352 totalLength += (*splitIt)->getLength();
365 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
367 const L*
const sidewalk = getSidewalk<E, L>(e);
368 if (e->isInternal() || sidewalk == 0) {
371 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
372 if (target.first->getEdge().isWalkingArea()) {
382 for (
const E*
const edge : edges) {
391 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
394 if (sucCarEdge !=
nullptr) {
408 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
409 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
413 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
414 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
427 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
428 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
432 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
433 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
500 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) {
501 assert(stopEdge !=
nullptr);
506 const double pos = (startPos + endPos) / 2.;
507 #ifdef IntermodalRouter_DEBUG_ACCESS
508 std::cout <<
"addAccess stopId=" << stopId <<
" stopEdge=" << stopEdge->getID() <<
" pos=" << pos <<
" length=" << length <<
" cat=" << category <<
"\n";
515 const L* lane = getSidewalk<E, L>(stopEdge);
516 if (lane !=
nullptr) {
517 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
520 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
522 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
524 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
530 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false, transferCarWalk);
533 if (carSplit !=
nullptr && (transferCarWalk || transferTaxiWalk)) {
539 if (transferCarWalk) {
549 if (carSplit !=
nullptr && transferWalkTaxi && !isAccess) {
558 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
559 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
567 if (carSplit !=
nullptr) {
581 if (carSplit !=
nullptr) {
592 std::vector<_IntermodalEdge*>& splitList =
myDepartLookup[stopEdge];
593 assert(splitList.size() > 0);
594 typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
595 while (splitIt != splitList.end() && startPos > (*splitIt)->getEndPos()) {
598 splitList.insert(splitIt, stopConn);
604 std::vector<SUMOVehicleParameter::Stop> validStops;
605 if (addStops !=
nullptr) {
611 if (newUntil >= lastUntil) {
612 validStops.push_back(stop);
613 validStops.back().until = newUntil;
614 lastUntil = newUntil;
616 WRITE_WARNING(
"Ignoring unordered stop at '" + stop.busstop +
"' until " +
time2string(stop.until) +
" for vehicle '" + pars.
id +
"'.");
624 validStops.push_back(stop);
625 lastUntil = stop.
until;
632 if (validStops.size() < 2 && pars.
line !=
"taxi") {
633 WRITE_WARNING(
"Not using public transport line '" + pars.
line +
"' for routing persons. It has less than two usable stops.");
637 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
638 if (lineEdges.empty()) {
644 Position stopPos = E::getStopPosition(s);
645 if (lastStop !=
nullptr) {
651 lineEdges.push_back(newEdge);
658 if (validStops.size() != lineEdges.size() + 1) {
659 WRITE_WARNINGF(
"Number of stops for public transport line '%' does not match earlier definitions, ignoring schedule.", pars.
line);
662 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
663 WRITE_WARNINGF(
"Different stop for '%' compared to earlier definitions, ignoring schedule.", pars.
line);
666 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
667 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
668 for (; s != validStops.end(); ++s, ++lineEdge) {
670 WRITE_WARNINGF(
"Different stop for '%' compared to earlier definitions, ignoring schedule.", pars.
line);
674 SUMOTime lastTime = validStops.front().until;
675 if (lineEdges.front()->hasSchedule(lastTime)) {
678 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
690 assert(edge !=
nullptr);
697 pedestrianEdges.first->addSuccessor(access);
698 pedestrianEdges.second->addSuccessor(access);
731 if (splitList !=
myAccessSplits.end() && !splitList->second.empty()) {
733 if (relPos < split->getLength() + POSITION_EPS) {
736 relPos -=
split->getLength();
739 assert(splitIndex < (
int)splitList->second.size());
740 if (splitIndex + 1 < (
int)splitList->second.size() && fabs(relPos - splitList->second[splitIndex]->getLength()) < POSITION_EPS) {
760 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
761 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true,
const bool addEntry =
true) {
762 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
763 if (splitList.empty()) {
764 splitList.push_back(toSplit);
767 splitIndex = (int)splitList.size() - 1 - splitIndex;
784 const std::string newID = beforeSplit->
getID();
786 afterSplit->
setID(newID);
788 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
791 afterSplit = splitList[splitIndex + 1];
827 std::map<const E*, _IntermodalEdge*, ComparatorNumericalIdLess>
myCarLookup;
830 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(...)
#define WRITE_WARNING(msg)
std::string time2string(SUMOTime t)
convert SUMOTime to string
const SVCPermissions SVCAll
all VClasses are allowed
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
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
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::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