18 #ifndef IntermodalNetwork_h
19 #define IntermodalNetwork_h
50 template <
class E,
class L>
52 if (edge ==
nullptr) {
56 const std::vector<L*>& lanes = edge->getLanes();
57 for (
const L*
const lane : lanes) {
62 for (
const L*
const lane : lanes) {
75 template<
class E,
class L,
class N,
class V>
82 typedef std::pair<_IntermodalEdge*, _IntermodalEdge*>
EdgePair;
100 IntermodalNetwork(
const std::vector<E*>& edges,
const bool pedestrianOnly,
const int carWalkTransfer = 0)
102 #ifdef IntermodalRouter_DEBUG_NETWORK
103 std::cout <<
"initIntermodalNetwork\n";
106 bool haveSeenWalkingArea =
false;
107 for (
const E*
const edge : edges) {
108 if (edge->isTazConnector()) {
111 const L* lane = getSidewalk<E, L>(edge);
113 if (edge->isWalkingArea()) {
119 haveSeenWalkingArea =
true;
127 if (!edge->isWalkingArea()) {
136 for (
const E*
const edge : edges) {
137 if (edge->isTazConnector() || edge->isInternal()) {
140 if (haveSeenWalkingArea) {
142 if (!pedestrianOnly && getSidewalk<E, L>(edge) ==
nullptr) {
143 const N*
const node = edge->getToJunction();
150 for (
const N*
const node : {
151 edge->getFromJunction(), edge->getToJunction()
161 for (
const E*
const edge : edges) {
162 if (edge->isTazConnector()) {
165 const L*
const sidewalk = getSidewalk<E, L>(edge);
166 if (sidewalk ==
nullptr) {
172 #ifdef IntermodalRouter_DEBUG_NETWORK
173 std::cout <<
" building connections from " << sidewalk->getID() <<
"\n";
175 if (haveSeenWalkingArea) {
176 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
180 bool hasWalkingArea =
false;
181 for (
const auto& target : outgoing) {
182 if (target.first->getEdge().isWalkingArea()) {
183 hasWalkingArea =
true;
187 for (
const auto& target : outgoing) {
188 const E*
const targetEdge = &(target.first->getEdge());
189 const bool used = (target.first == getSidewalk<E, L>(targetEdge)
190 && (!hasWalkingArea || targetEdge->isWalkingArea()));
191 #ifdef IntermodalRouter_DEBUG_NETWORK
192 const L* potTarget = getSidewalk<E, L>(targetEdge);
193 std::cout <<
" lane=" << (potTarget == 0 ?
"NULL" : potTarget->getID()) << (used ?
"(used)" :
"") <<
"\n";
197 pair.first->addSuccessor(targetPair.first);
198 targetPair.second->addSuccessor(pair.second);
199 #ifdef IntermodalRouter_DEBUG_NETWORK
200 std::cout <<
" " << pair.first->getID() <<
" -> " << targetPair.first->getID() <<
"\n";
201 std::cout <<
" " << targetPair.second->getID() <<
" -> " << pair.second->getID() <<
"\n";
210 if (toNodeConn !=
nullptr) {
212 const std::vector<std::pair<const L*, const E*> > outgoing = sidewalk->getOutgoingViaLanes();
213 double minViaLength = std::numeric_limits<double>::max();
214 const E* minVia =
nullptr;
215 for (
const auto& target : outgoing) {
216 if (target.second !=
nullptr && target.second->getLength() < minViaLength) {
217 minViaLength = target.second->getLength();
218 minVia = target.second;
221 EdgePair interVia = std::make_pair(
nullptr,
nullptr);
222 if (minVia !=
nullptr) {
225 interVia = it->second;
228 if (!haveSeenWalkingArea) {
230 pair.first->addSuccessor(toNodeConn, interVia.first);
235 if (fromNodeConn !=
nullptr) {
236 if (!haveSeenWalkingArea) {
237 pair.second->addSuccessor(fromNodeConn);
241 if (!edge->isWalkingArea()) {
248 pair.first->addSuccessor(endConnector);
249 pair.second->addSuccessor(endConnector);
251 #ifdef IntermodalRouter_DEBUG_NETWORK
252 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.first->getID() <<
"\n";
253 std::cout <<
" " << startConnector->getID() <<
" -> " << pair.second->getID() <<
"\n";
254 std::cout <<
" " << pair.first->getID() <<
" -> " << endConnector->getID() <<
"\n";
255 std::cout <<
" " << pair.second->getID() <<
" -> " << endConnector->getID() <<
"\n";
261 for (
typename std::vector<_IntermodalEdge*>::iterator it =
myEdges.begin(); it !=
myEdges.end(); ++it) {
286 typename std::map<const E*, EdgePair>::const_iterator it =
myBidiLookup.find(e);
289 throw ProcessError(
"Edge '" + e->getID() +
"' not found in intermodal network.'");
296 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
298 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
302 double totalLength = 0.;
303 double bestDist = std::numeric_limits<double>::max();
306 totalLength +=
split->getLength();
307 double dist = fabs(totalLength - pos);
308 if (dist < bestDist) {
310 if (bestDist != std::numeric_limits<double>::max() &&
split == it->second.back()) {
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(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
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(
"Arrival edge '" + e->getID() +
"' not found in intermodal network.");
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) {
394 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
397 if (sucCarEdge !=
nullptr) {
407 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
408 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
412 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
413 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
426 typename std::map<const E*, _IntermodalEdge*>::const_iterator it =
myCarLookup.find(e);
455 void addAccess(
const std::string& stopId,
const E* stopEdge,
const double pos,
const double length,
const SumoXMLTag category) {
456 assert(stopEdge !=
nullptr);
465 const L* lane = getSidewalk<E, L>(stopEdge);
466 if (lane !=
nullptr) {
467 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
470 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
472 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
474 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
480 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false, transferCarWalk);
483 if (carSplit !=
nullptr && transferCarWalk) {
498 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
499 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
507 if (carSplit !=
nullptr) {
521 if (carSplit !=
nullptr) {
531 std::vector<_IntermodalEdge*>& splitList =
myDepartLookup[stopEdge];
532 assert(splitList.size() > 0);
533 typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
534 double totalLength = 0.;
536 while (splitIt != splitList.end() && totalLength < pos) {
542 const double newLength = pos - (totalLength - last->
getLength());
544 splitList.insert(splitIt - 1, stopConn);
552 std::vector<SUMOVehicleParameter::Stop> validStops;
553 if (addStops !=
nullptr) {
559 if (newUntil >= lastUntil) {
560 validStops.push_back(stop);
561 validStops.back().until = newUntil;
562 lastUntil = newUntil;
564 WRITE_WARNING(
"Ignoring unordered stop at '" + stop.busstop +
"' until " +
time2string(stop.until) +
" for vehicle '" + pars.
id +
"'.");
572 validStops.push_back(stop);
573 lastUntil = stop.
until;
578 if (validStops.size() < 2) {
579 WRITE_WARNING(
"Not using public transport line '" + pars.
line +
"' for routing persons. It has less than two usable stops.");
583 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
584 if (lineEdges.empty()) {
590 Position stopPos = E::getStopPosition(s);
591 if (lastStop !=
nullptr) {
597 lineEdges.push_back(newEdge);
604 if (validStops.size() != lineEdges.size() + 1) {
605 WRITE_WARNING(
"Number of stops for public transport line '" + pars.
line +
"' does not match earlier definitions, ignoring schedule.");
608 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
609 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
612 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
613 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
614 for (; s != validStops.end(); ++s, ++lineEdge) {
616 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
620 SUMOTime lastTime = validStops.front().until;
621 if (lineEdges.front()->hasSchedule(lastTime)) {
624 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
648 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
649 if (!splitList.empty()) {
654 relPos -=
split->getLength();
657 assert(splitIndex < (
int)splitList.size());
658 if (splitIndex + 1 < (
int)splitList.size() && fabs(relPos - splitList[splitIndex]->getLength()) <
POSITION_EPS) {
678 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
679 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true,
const bool addEntry =
true) {
680 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
681 if (splitList.empty()) {
682 splitList.push_back(toSplit);
685 splitIndex = (int)splitList.size() - 1 - splitIndex;
702 const std::string newID = beforeSplit->
getID();
704 afterSplit->
setID(newID);
706 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
709 afterSplit = splitList[splitIndex + 1];
748 std::map<std::string, std::vector<_PTEdge*> >
myPTLines;