19 #ifndef IntermodalNetwork_h 20 #define IntermodalNetwork_h 51 template <
class E,
class L>
53 if (edge ==
nullptr) {
57 const std::vector<L*>& lanes = edge->getLanes();
58 for (
const L*
const lane : lanes) {
63 for (
const L*
const lane : lanes) {
76 template<
class E,
class L,
class N,
class V>
83 typedef std::pair<_IntermodalEdge*, _IntermodalEdge*>
EdgePair;
101 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0)
103 #ifdef IntermodalRouter_DEBUG_NETWORK 104 std::cout <<
"initIntermodalNetwork\n";
107 bool haveSeenWalkingArea =
false;
108 for (
const E*
const edge : edges) {
109 if (edge->isTazConnector()) {
112 const L* lane = getSidewalk<E, L>(edge);
114 if (edge->isWalkingArea()) {
120 haveSeenWalkingArea =
true;
128 if (!edge->isWalkingArea()) {
137 for (
const E*
const edge : edges) {
138 if (edge->isTazConnector() || edge->isInternal()) {
141 if (haveSeenWalkingArea) {
143 if (!pedestrianOnly && getSidewalk<E, L>(edge) ==
nullptr) {
144 const N*
const node = edge->getToJunction();
151 for (
const N*
const node : {
152 edge->getFromJunction(), edge->getToJunction()
162 for (
const E*
const edge : edges) {
163 const L*
const sidewalk = getSidewalk<E, L>(edge);
164 if (sidewalk ==
nullptr) {
170 #ifdef IntermodalRouter_DEBUG_NETWORK 171 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
173 if (haveSeenWalkingArea) {
174 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
178 bool hasWalkingArea =
false;
179 for (
const auto& target : outgoing) {
180 if (target.first->getEdge().isWalkingArea()) {
181 hasWalkingArea =
true;
185 for (
const auto& target : outgoing) {
186 const E*
const targetEdge = &(target.first->getEdge());
187 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
188 && (!hasWalkingArea || targetEdge->isWalkingArea()));
189 #ifdef IntermodalRouter_DEBUG_NETWORK 190 const L* potTarget = getSidewalk<E, L>(targetEdge);
191 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
195 pair.first->addSuccessor(targetPair.first);
196 targetPair.second->addSuccessor(pair.second);
197 #ifdef IntermodalRouter_DEBUG_NETWORK 198 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
199 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
208 if (toNodeConn !=
nullptr) {
210 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
211 double minViaLength = std::numeric_limits<double>::max();
212 const E* minVia =
nullptr;
213 for (
const auto& target : outgoing) {
214 if (target.second !=
nullptr && target.second->getLength() < minViaLength) {
215 minViaLength = target.second->getLength();
216 minVia = target.second;
219 EdgePair interVia = std::make_pair(
nullptr,
nullptr);
220 if (minVia !=
nullptr) {
223 interVia = it->second;
226 if (!haveSeenWalkingArea) {
228 pair.first->addSuccessor(toNodeConn, interVia.first);
233 if (fromNodeConn !=
nullptr) {
234 if (!haveSeenWalkingArea) {
235 pair.second->addSuccessor(fromNodeConn);
239 if (!edge->isWalkingArea()) {
246 pair.first->addSuccessor(endConnector);
247 pair.second->addSuccessor(endConnector);
249 #ifdef IntermodalRouter_DEBUG_NETWORK 250 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.first->getID() <<
"\n";
251 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.second->getID() <<
"\n";
252 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->getID() <<
"\n";
253 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->getID() <<
"\n";
259 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
271 void addConnectors(_IntermodalEdge*
const depConn, _IntermodalEdge*
const arrConn,
const int index) {
284 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
287 throw ProcessError(
"Edge '" + e->getID() +
"' not found in intermodal network.'");
294 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
296 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
298 const std::vector<_IntermodalEdge*>& splitList = it->second;
299 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
300 double totalLength = 0.;
301 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
302 totalLength += (*splitIt)->getLength();
310 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
312 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
314 if (splitIndex >= (
int)it->second.size()) {
315 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
317 return it->second[splitIndex];
322 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
324 throw ProcessError(
"Arrival edge '" + e->getID() +
"' not found in intermodal network.");
326 const std::vector<_IntermodalEdge*>& splitList = it->second;
327 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
328 double totalLength = 0.;
329 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
330 totalLength += (*splitIt)->getLength();
343 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
345 const L*
const sidewalk = getSidewalk<E, L>(e);
346 if (e->isInternal() || sidewalk == 0) {
349 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
350 if (target.first->getEdge().isWalkingArea()) {
360 for (
const E*
const edge : edges) {
367 _IntermodalEdge*
const carEdge = edgePair.second;
368 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
369 _IntermodalEdge*
const sucCarEdge =
getCarEdge(suc.first);
370 _IntermodalEdge*
const sucViaEdge =
getCarEdge(suc.second);
371 if (sucCarEdge !=
nullptr) {
381 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
382 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
386 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
387 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
400 typename std::map<const E*, _IntermodalEdge*>::const_iterator it =
myCarLookup.find(e);
429 void addAccess(
const std::string& stopId,
const E* stopEdge,
const double pos,
const double length,
const SumoXMLTag category) {
430 assert(stopEdge != 0);
436 const L* lane = getSidewalk<E, L>(stopEdge);
438 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
441 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
443 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
444 _IntermodalEdge*
const backSplit = needSplit ?
new PedestrianEdge<E, L, N, V>(myNumericalID++, stopEdge, lane,
false, pos) :
nullptr;
445 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
446 _IntermodalEdge* carSplit =
nullptr;
451 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false);
457 for (_IntermodalEdge* conn : {
460 _AccessEdge* access =
new _AccessEdge(myNumericalID++, beforeSplit, conn, length);
469 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
470 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
471 _IntermodalEdge*
const depConn =
new _IntermodalEdge(stopEdge->getID() +
"_depart_connector" +
toString(pos), myNumericalID++, stopEdge,
"!connector");
478 if (carSplit !=
nullptr) {
484 _IntermodalEdge*
const fwdBeforeSplit =
myAccessSplits[pair.first][splitIndex];
485 _IntermodalEdge*
const arrConn =
new _IntermodalEdge(stopEdge->getID() +
"_arrival_connector" +
toString(pos), myNumericalID++, stopEdge,
"!connector");
492 if (carSplit !=
nullptr) {
504 std::vector<SUMOVehicleParameter::Stop> validStops;
505 if (addStops !=
nullptr) {
511 if (newUntil >= lastUntil) {
512 validStops.push_back(stop);
513 validStops.back().until = newUntil;
514 lastUntil = newUntil;
516 WRITE_WARNING(
"Ignoring unordered stop at '" + stop.busstop +
"' until " +
time2string(stop.until) +
" for vehicle '" + pars.
id +
"'.");
524 validStops.push_back(stop);
525 lastUntil = stop.
until;
530 if (validStops.size() < 2) {
531 WRITE_WARNING(
"Not using public transport line '" + pars.
line +
"' for routing persons. It has less than two usable stops.");
535 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
536 if (lineEdges.empty()) {
537 _IntermodalEdge* lastStop =
nullptr;
542 Position stopPos = E::getStopPosition(s);
543 if (lastStop !=
nullptr) {
549 lineEdges.push_back(newEdge);
556 if (validStops.size() != lineEdges.size() + 1) {
557 WRITE_WARNING(
"Number of stops for public transport line '" + pars.
line +
"' does not match earlier definitions, ignoring schedule.");
560 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
561 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
564 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
565 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
566 for (; s != validStops.end(); ++s, ++lineEdge) {
568 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
572 SUMOTime lastTime = validStops.front().until;
573 if (lineEdges.front()->hasSchedule(lastTime)) {
576 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
596 int findSplitIndex(_IntermodalEdge*
const toSplit,
const double pos,
double& relPos,
bool& needSplit) {
600 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
601 if (!splitList.empty()) {
602 for (
const _IntermodalEdge*
const split : splitList) {
606 relPos -=
split->getLength();
609 assert(splitIndex < (
int)splitList.size());
610 if (splitIndex + 1 < (
int)splitList.size() && fabs(relPos - splitList[splitIndex]->getLength()) <
POSITION_EPS) {
629 void splitEdge(_IntermodalEdge*
const toSplit,
int splitIndex,
630 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
631 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true) {
632 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
633 if (splitList.empty()) {
634 splitList.push_back(toSplit);
637 splitIndex = (int)splitList.size() - 1 - splitIndex;
642 _IntermodalEdge* beforeSplit = splitList[splitIndex];
654 const std::string newID = beforeSplit->
getID();
656 afterSplit->
setID(newID);
658 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
661 afterSplit = splitList[splitIndex + 1];
698 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
void addSchedule(const std::string id, const SUMOTime begin, const int repetitionNumber, const SUMOTime period, const SUMOTime travelTime)
A point in 2D or 3D with translation and scaling methods.
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.
void addSchedule(const SUMOVehicleParameter &pars, const std::vector< SUMOVehicleParameter::Stop > *addStops=nullptr)
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
double distanceTo(const Position &p2) const
returns the euclidean distance in 3 dimension
_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) ...
the stop edge type representing bus and train stops
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)