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) {
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.");
300 double totalLength = 0.;
301 double bestDist = std::numeric_limits<double>::max();
304 totalLength +=
split->getLength();
305 double dist = fabs(totalLength - pos);
306 if (dist < bestDist) {
308 if (bestDist != std::numeric_limits<double>::max() &&
split == it->second.back()) {
321 const std::vector<_IntermodalEdge*>& splitList = it->second;
322 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
323 double totalLength = 0.;
324 while (splitIt + 1 != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
334 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myDepartLookup.find(e);
336 throw ProcessError(
"Depart edge '" + e->getID() +
"' not found in intermodal network.");
338 if (splitIndex >= (
int)it->second.size()) {
339 throw ProcessError(
"Split index " +
toString(splitIndex) +
" invalid for depart edge '" + e->getID() +
"' .");
341 return it->second[splitIndex];
346 typename std::map<const E*, std::vector<_IntermodalEdge*> >::const_iterator it =
myArrivalLookup.find(e);
348 throw ProcessError(
"Arrival edge '" + e->getID() +
"' not found in intermodal network.");
350 const std::vector<_IntermodalEdge*>& splitList = it->second;
351 typename std::vector<_IntermodalEdge*>::const_iterator splitIt = splitList.begin();
352 double totalLength = 0.;
353 while (splitIt != splitList.end() && totalLength + (*splitIt)->getLength() < pos) {
354 totalLength += (*splitIt)->getLength();
367 typename std::map<const N*, _IntermodalEdge*>::const_iterator it =
myWalkingConnectorLookup.find(e->getToJunction());
369 const L*
const sidewalk = getSidewalk<E, L>(e);
370 if (e->isInternal() || sidewalk == 0) {
373 for (
const auto& target : sidewalk->getOutgoingViaLanes()) {
374 if (target.first->getEdge().isWalkingArea()) {
384 for (
const E*
const edge : edges) {
392 for (
const auto& suc : edgePair.first->getViaSuccessors()) {
395 if (sucCarEdge !=
nullptr) {
405 for (
const E*
const out : edgePair.first->getToJunction()->getOutgoing()) {
406 if (!out->isInternal() && !out->isTazConnector() && getSidewalk<E, L>(out) != 0) {
410 for (
const E*
const in : edgePair.first->getToJunction()->getIncoming()) {
411 if (!in->isInternal() && !in->isTazConnector() && getSidewalk<E, L>(in) != 0) {
424 typename std::map<const E*, _IntermodalEdge*>::const_iterator it =
myCarLookup.find(e);
453 void addAccess(
const std::string& stopId,
const E* stopEdge,
const double pos,
const double length,
const SumoXMLTag category) {
454 assert(stopEdge !=
nullptr);
461 const L* lane = getSidewalk<E, L>(stopEdge);
462 if (lane !=
nullptr) {
463 const std::pair<_IntermodalEdge*, _IntermodalEdge*>& pair =
getBothDirections(stopEdge);
466 const int splitIndex =
findSplitIndex(pair.first, pos, relPos, needSplit);
468 splitEdge(pair.first, splitIndex, fwdSplit, relPos, length, needSplit, stopConn);
470 splitEdge(pair.second, splitIndex, backSplit, relPos, length, needSplit, stopConn,
false);
476 splitEdge(
myCarLookup[stopEdge], splitIndex, carSplit, relPos, length, needSplit, stopConn,
true,
false);
494 const std::vector<_IntermodalEdge*>& backSplitList =
myAccessSplits[pair.second];
495 _IntermodalEdge*
const backBeforeSplit = backSplitList[backSplitList.size() - 2 - splitIndex];
503 if (carSplit !=
nullptr) {
517 if (carSplit !=
nullptr) {
527 std::vector<_IntermodalEdge*>& splitList =
myDepartLookup[stopEdge];
528 assert(splitList.size() > 0);
529 typename std::vector<_IntermodalEdge*>::iterator splitIt = splitList.begin();
530 double totalLength = 0.;
532 while (splitIt != splitList.end() && totalLength < pos) {
538 const double newLength = pos - (totalLength - last->
getLength());
540 splitList.insert(splitIt - 1, stopConn);
548 std::vector<SUMOVehicleParameter::Stop> validStops;
549 if (addStops !=
nullptr) {
555 if (newUntil >= lastUntil) {
556 validStops.push_back(stop);
557 validStops.back().until = newUntil;
558 lastUntil = newUntil;
560 WRITE_WARNING(
"Ignoring unordered stop at '" + stop.busstop +
"' until " +
time2string(stop.until) +
" for vehicle '" + pars.
id +
"'.");
568 validStops.push_back(stop);
569 lastUntil = stop.
until;
574 if (validStops.size() < 2) {
575 WRITE_WARNING(
"Not using public transport line '" + pars.
line +
"' for routing persons. It has less than two usable stops.");
579 typename std::vector<_PTEdge*>& lineEdges =
myPTLines[pars.
line];
580 if (lineEdges.empty()) {
586 Position stopPos = E::getStopPosition(s);
587 if (lastStop !=
nullptr) {
593 lineEdges.push_back(newEdge);
600 if (validStops.size() != lineEdges.size() + 1) {
601 WRITE_WARNING(
"Number of stops for public transport line '" + pars.
line +
"' does not match earlier definitions, ignoring schedule.");
604 if (lineEdges.front()->getEntryStop() !=
myStopConnections[validStops.front().busstop]) {
605 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
608 typename std::vector<_PTEdge*>::const_iterator lineEdge = lineEdges.begin();
609 typename std::vector<SUMOVehicleParameter::Stop>::const_iterator s = validStops.begin() + 1;
610 for (; s != validStops.end(); ++s, ++lineEdge) {
612 WRITE_WARNING(
"Different stop for '" + pars.
line +
"' compared to earlier definitions, ignoring schedule.");
616 SUMOTime lastTime = validStops.front().until;
617 if (lineEdges.front()->hasSchedule(lastTime)) {
620 for (lineEdge = lineEdges.begin(), s = validStops.begin() + 1; lineEdge != lineEdges.end(); ++lineEdge, ++s) {
644 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
645 if (!splitList.empty()) {
650 relPos -=
split->getLength();
653 assert(splitIndex < (
int)splitList.size());
654 if (splitIndex + 1 < (
int)splitList.size() && fabs(relPos - splitList[splitIndex]->getLength()) <
POSITION_EPS) {
674 _IntermodalEdge* afterSplit,
const double relPos,
const double length,
const bool needSplit,
675 _IntermodalEdge*
const stopConn,
const bool forward =
true,
const bool addExit =
true) {
676 std::vector<_IntermodalEdge*>& splitList =
myAccessSplits[toSplit];
677 if (splitList.empty()) {
678 splitList.push_back(toSplit);
681 splitIndex = (int)splitList.size() - 1 - splitIndex;
698 const std::string newID = beforeSplit->
getID();
700 afterSplit->
setID(newID);
702 splitList.insert(splitList.begin() + splitIndex + 1, afterSplit);
705 afterSplit = splitList[splitIndex + 1];
742 std::map<std::string, std::vector<_PTEdge*> >
myPTLines;