49 template <
class E,
class L>
51 if (edge ==
nullptr) {
55 const std::vector<L*>& lanes = edge->getLanes();
56 for (
const L*
const lane : lanes) {
61 for (
const L*
const lane : lanes) {
74 template<
class E,
class L,
class N,
class V>
81 typedef std::pair<_IntermodalEdge*, _IntermodalEdge*>
EdgePair;
107 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0)
109 #ifdef IntermodalRouter_DEBUG_NETWORK
110 std::cout <<
"initIntermodalNetwork\n";
113 bool haveSeenWalkingArea =
false;
114 for (
const E*
const edge : edges) {
115 if (edge->isTazConnector()) {
122 const L* lane = getSidewalk<E, L>(edge);
124 if (edge->isWalkingArea()) {
130 haveSeenWalkingArea =
true;
138 if (!edge->isWalkingArea()) {
148 for (
const E*
const edge : edges) {
149 if (edge->isTazConnector() || edge->isInternal()) {
152 if (haveSeenWalkingArea) {
154 if (!pedestrianOnly && getSidewalk<E, L>(edge) ==
nullptr) {
155 const N*
const node = edge->getToJunction();
162 for (
const N*
const node : {
163 edge->getFromJunction(), edge->getToJunction()
173 for (
const E*
const edge : edges) {
174 if (edge->isTazConnector()) {
178 const E* other = edge->getOtherTazConnector();
181 for (
const E* out : edge->getSuccessors()) {
185 for (
const E* in : edge->getPredecessors()) {
191 const L*
const sidewalk = getSidewalk<E, L>(edge);
192 if (sidewalk ==
nullptr) {
198 #ifdef IntermodalRouter_DEBUG_NETWORK
199 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
201 if (haveSeenWalkingArea) {
202 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
206 bool hasWalkingArea =
false;
207 for (
const auto& target : outgoing) {
208 if (target.first->getEdge().isWalkingArea()) {
209 hasWalkingArea =
true;
213 for (
const auto& target : outgoing) {
214 const E*
const targetEdge = &(target.first->getEdge());
215 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
216 && (!hasWalkingArea || targetEdge->isWalkingArea()));
217 #ifdef IntermodalRouter_DEBUG_NETWORK
218 const L* potTarget = getSidewalk<E, L>(targetEdge);
219 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
223 pair.first->addSuccessor(targetPair.first);
224 targetPair.second->addSuccessor(pair.second);
225 #ifdef IntermodalRouter_DEBUG_NETWORK
226 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
227 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
236 if (toNodeConn !=
nullptr) {
238 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
239 double minViaLength = std::numeric_limits<double>::max();
240 const E* minVia =
nullptr;
241 for (
const auto& target : outgoing) {
242 if (target.second !=
nullptr && target.second->getLength() < minViaLength) {
243 minViaLength = target.second->getLength();
244 minVia = target.second;
247 EdgePair interVia = std::make_pair(
nullptr,
nullptr);
248 if (minVia !=
nullptr) {
251 interVia = it->second;
254 if (!haveSeenWalkingArea) {
256 pair.first->addSuccessor(toNodeConn, interVia.first);
261 if (fromNodeConn !=
nullptr) {
262 if (!haveSeenWalkingArea) {
263 pair.second->addSuccessor(fromNodeConn);
267 if (!edge->isWalkingArea()) {
274 pair.first->addSuccessor(endConnector);
275 pair.second->addSuccessor(endConnector);
277 #ifdef IntermodalRouter_DEBUG_NETWORK
278 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.first->getID() <<
"\n";
279 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.second->getID() <<
"\n";
280 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->getID() <<
"\n";
281 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->getID() <<
"\n";
287 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
312 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
315 throw ProcessError(
"Edge '" + e->getID() +
"' not found in intermodal network.'");
322 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
324 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
328 double totalLength = 0.;
329 double bestDist = std::numeric_limits<double>::max();
332 totalLength +=
split->getLength();
333 double dist = fabs(totalLength - pos);
334 if (dist < bestDist) {
336 if (bestDist != std::numeric_limits<double>::max() &&
split == it->second.back()) {
349 const std::vector<_IntermodalEdge*>& splitList = it->second;
350 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
351 double totalLength = 0.;
352 while (splitIt + 1 != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
362 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
364 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
366 if (splitIndex >= (
int)it->second.size()) {
367 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
369 return it->second[splitIndex];
374 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
376 throw ProcessError(
"Arrival edge '" + e->getID() +
"' not found in intermodal network.");
378 const std::vector<_IntermodalEdge*>& splitList = it->second;
379 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
380 double totalLength = 0.;
381 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
382 totalLength += (*splitIt)->getLength();
395 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
397 const L*
const sidewalk = getSidewalk<E, L>(e);
398 if (e->isInternal() || sidewalk == 0) {
401 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
402 if (target.first->getEdge().isWalkingArea()) {
412 for (
const E*
const edge : edges) {
421 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
424 if (sucCarEdge !=
nullptr) {
438 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
439 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
443 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
444 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
457 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
458 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
462 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
463 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
528 void addAccess(
const std::string& stopId,
const E* stopEdge,
const double pos,
const double length,
const SumoXMLTag category,
bool isAccess,
double taxiWait) {
529 assert(stopEdge !=
nullptr);
534 #ifdef IntermodalRouter_DEBUG_ACCESS
535 std::cout <<
"addAccess stopId=" << stopId <<
" stopEdge=" << stopEdge->getID() <<
" pos=" << pos <<
" length=" << length <<
" cat=" << category <<
"\n";
542 const L* lane = getSidewalk<E, L>(stopEdge);
543 if (lane !=
nullptr) {
544 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
547 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
549 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
551 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
557 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false, transferCarWalk);
560 if (carSplit !=
nullptr && (transferCarWalk || transferTaxiWalk)) {
566 if (transferCarWalk) {
576 if (carSplit !=
nullptr && transferWalkTaxi && !isAccess) {
585 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
586 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
594 if (carSplit !=
nullptr) {
608 if (carSplit !=
nullptr) {
619 std::vector<_IntermodalEdge*>& splitList =
myDepartLookup[stopEdge];
620 assert(splitList.size() > 0);
621 typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
622 double totalLength = 0.;
624 while (splitIt != splitList.end() && totalLength < pos) {
630 const double newLength = pos - (totalLength - last->
getLength());
632 splitList.insert(splitIt - 1, stopConn);
635 #ifdef IntermodalRouter_DEBUG_ACCESS
636 std::cout <<
" splitList:\n";
637 for (
auto conEdge : splitList) {
638 std::cout <<
" " << conEdge->getID() <<
" length=" << conEdge->getLength() <<
"\n";
646 std::vector<SUMOVehicleParameter::Stop> validStops;
647 if (addStops !=
nullptr) {
653 if (newUntil >= lastUntil) {
654 validStops.push_back(stop);
655 validStops.back().until = newUntil;
656 lastUntil = newUntil;
658 WRITE_WARNING(
"Ignoring unordered stop at '" + stop.busstop +
"' until " +
time2string(stop.until) +
" for vehicle '" + pars.
id +
"'.");
666 validStops.push_back(stop);
667 lastUntil = stop.
until;
674 if (validStops.size() < 2 && pars.
line !=
"taxi") {
675 WRITE_WARNING(
"Not using public transport line '" + pars.
line +
"' for routing persons. It has less than two usable stops.");
679 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
680 if (lineEdges.empty()) {
686 Position stopPos = E::getStopPosition(s);
687 if (lastStop !=
nullptr) {
693 lineEdges.push_back(newEdge);
700 if (validStops.size() != lineEdges.size() + 1) {
701 WRITE_WARNING(
"Number of stops for public transport line '" + pars.
line +
"' does not match earlier definitions, ignoring schedule.");
704 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
705 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
708 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
709 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
710 for (; s != validStops.end(); ++s, ++lineEdge) {
712 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
716 SUMOTime lastTime = validStops.front().until;
717 if (lineEdges.front()->hasSchedule(lastTime)) {
720 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
732 assert(edge !=
nullptr);
739 pedestrianEdges.first->addSuccessor(access);
740 pedestrianEdges.second->addSuccessor(access);
772 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
773 if (!splitList.empty()) {
775 if (relPos < split->getLength() + POSITION_EPS) {
778 relPos -=
split->getLength();
781 assert(splitIndex < (
int)splitList.size());
782 if (splitIndex + 1 < (
int)splitList.size() && fabs(relPos - splitList[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;
const L * getSidewalk(const E *edge)
std::vector< std::string > & split(const std::string &s, char delim, std::vector< std::string > &elems)
#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 pos, 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)
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
int findSplitIndex(_IntermodalEdge *const toSplit, const double pos, double &relPos, bool &needSplit)
Returns where to insert or use the split edge.
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