44#define DEBUGNODEID "gneJ34"
45#define DEBUGNODEID2 "28842974"
46#define DEBUGEDGEID "22820560#0"
47#define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
49#define SHARP_THRESHOLD_SAMEDIR 100
50#define SHARP_THRESHOLD 80
67const std::vector<NBRailwayTopologyAnalyzer::Track*>&
69 if ((minPermissions & svc) != 0) {
72 if (svcSuccessors.count(svc) == 0) {
73 std::vector<Track*> succ;
74 for (
Track* t : successors) {
75 if ((t->edge->getPermissions() & svc) != 0) {
79 svcSuccessors[svc] = succ;
81 return svcSuccessors[svc];
86const std::vector<std::pair<const NBRailwayTopologyAnalyzer::Track*, const NBRailwayTopologyAnalyzer::Track*> >&
88 if ((minPermissions & svc) != 0) {
91 if (svcViaSuccessors.count(svc) == 0) {
92 std::vector<std::pair<const Track*, const Track*> >& succ = svcViaSuccessors[svc];
93 for (
const Track*
const t : successors) {
94 if ((t->edge->getPermissions() & svc) != 0) {
95 succ.push_back(std::make_pair(t,
nullptr));
99 return svcViaSuccessors[svc];
137 int numNotCenterEdges = 0;
138 int numAddedBidiEdges = 0;
140 std::vector<NBEdge*> edges;
141 if (inputfile ==
"") {
143 edges.push_back(edge);
146 std::set<std::string> edgeIDs;
148 for (
const std::string& edgeID : edgeIDs) {
150 if (edge !=
nullptr) {
151 edges.push_back(edge);
155 for (
NBEdge* edge : edges) {
159 if (!edge->isBidiRail()) {
171 WRITE_MESSAGEF(
TL(
"Added % bidi-edges to ensure that all tracks are usable in both directions."),
toString(numAddedBidiEdges));
172 if (numNotCenterEdges) {
175 return numAddedBidiEdges;
183 const std::string id2 = (edge->
getID()[0] ==
'-'
184 ? edge->
getID().substr(1)
185 :
"-" + edge->
getID());
206 incoming->invalidateConnections(
true);
223 inEdges.push_back(e);
228 outEdges.push_back(e);
236 std::set<NBNode*> brokenNodes;
242 std::set<NBNode*> railNodes =
getRailNodes(ec, verbose);
243 std::map<std::pair<int, int>, std::set<NBNode*, ComparatorIdLess> > types;
244 std::set<NBEdge*, ComparatorIdLess> bidiEdges;
245 std::set<NBEdge*, ComparatorIdLess> bufferStops;
246 for (
NBNode* node : railNodes) {
249 types[std::make_pair((
int)inEdges.size(), (
int)outEdges.size())].insert(node);
250 for (
NBEdge* e : outEdges) {
251 if (e->isBidiRail() && bidiEdges.count(e->getTurnDestination(
true)) == 0) {
254 if (e->getID()[0] ==
'-') {
256 }
else if (primary->
getID()[0] !=
'-' && secondary->
getID()[0] !=
'-' && secondary->
getID() < primary->
getID()) {
259 if (bidiEdges.count(secondary) == 0) {
261 bidiEdges.insert(primary);
271 int numBufferStops = 0;
272 if (verbose && types.size() > 0) {
273 WRITE_MESSAGE(
TL(
"Railway nodes by number of incoming,outgoing edges:"))
278 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are outgoing");
282 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are incoming");
286 device.
writeAttr(
"meaning",
"an incoming edge has a sharp angle to all outgoing edges");
290 device.
writeAttr(
"meaning",
"an outgoing edge has a sharp angle from all incoming edges");
294 for (
auto it : types) {
295 int numBrokenType = 0;
296 device.
openTag(
"railNodeType");
297 int in = it.first.first;
298 int out = it.first.second;
301 for (
NBNode* n : it.second) {
309 std::string broken =
"";
319 for (
NBEdge* e : inRail) {
330 for (
NBEdge* e : outRail) {
341 if (((in == 1 && out == 1) || (in == 2 && out == 2))
346 if (broken.size() > 0) {
348 brokenNodes.insert(n);
360 +
" count: " +
toString(it.second.size()) +
" broken: " +
toString(numBrokenType));
374 for (
NBEdge* e : bidiEdges) {
377 device.
writeAttr(
"bidi", e->getTurnDestination(
true)->getID());
391 std::set<NBNode*> railNodes;
392 int numRailEdges = 0;
393 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
394 if (
hasRailway(it->second->getPermissions())) {
396 railNodes.insert(it->second->getFromNode());
397 railNodes.insert(it->second->getToNode());
400 int numRailSignals = 0;
401 for (
const NBNode*
const node : railNodes) {
439#ifdef DEBUG_SEQSTOREVERSE
444 for (
NBEdge* e1 : edges) {
445 for (
NBEdge* e2 : edges2) {
465 if (e != candOut &&
isStraight(node, e, candOut)) {
467 std::cout <<
" isStraight e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
473 if (e != candOut && !
isStraight(node, e, candOut)) {
475 std::cout <<
" isSharp e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
492 if (!e1->isBidiRail(
true)) {
498 return !
allBidi || countBidiAsSharp;
505 if (!e->isBidiRail()) {
516 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
534 if (bidiOut ==
nullptr) {
539 tmpBidiOut.push_back(bidiOut);
541 tmpBidiIn.push_back(bidiIn);
545 for (
NBEdge* cand : outRail) {
547 if (!cand->isBidiRail() &&
isStraight(node, bidiIn, cand)
549 &&
allSharp(node, inRail, tmpBidiOut,
true)) {
556 for (
NBEdge* cand : inRail) {
558 if (!cand->isBidiRail() &&
isStraight(node, cand, bidiOut)
560 &&
allSharp(node, outRail, tmpBidiIn,
true)) {
575 std::vector<EdgeVector> seqsToReverse;
576 for (
NBNode* n : brokenNodes) {
579 for (
NBEdge* start : outRail) {
581 tmp.push_back(start);
583 if (!
allBroken(n, start, inRail, outRail)
584 || (inRail.size() == 1 && outRail.size() == 1)) {
585#ifdef DEBUG_SEQSTOREVERSE
587 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
596 seq.push_back(start);
598 NBNode* n2 = start->getToNode();
601 if (brokenNodes.count(n2) != 0) {
603 tmp2.push_back(start);
604 if (
allBroken(n2, start, outRail2, inRail2)) {
605 seqsToReverse.push_back(seq);
607#ifdef DEBUG_SEQSTOREVERSE
609 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
615 if (outRail2.size() == 0) {
618#ifdef DEBUG_SEQSTOREVERSE
620 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
623 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
626#ifdef DEBUG_SEQSTOREVERSE
628 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
632 start = outRail2.front();
639 if (seqsToReverse.size() > 0) {
642 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
644 return a.size() < b.size();
647 std::set<NBNode*> affectedEndpoints;
648 std::set<std::string> reversedIDs;
649 std::map<int, int> seqLengths;
651 NBNode* seqStart = seq.front()->getFromNode();
652 NBNode* seqEnd = seq.back()->getToNode();
654 if (affectedEndpoints.count(seqStart) == 0
655 && affectedEndpoints.count(seqEnd) == 0) {
656 affectedEndpoints.insert(seqStart);
657 affectedEndpoints.insert(seqEnd);
660 e->reinitNodes(e->getToNode(), e->getFromNode());
661 e->setGeometry(e->getGeometry().reverse());
662 reversedIDs.insert(e->getID());
667 seqLengths[(int)seq.size()]++;
671 if (numReversed > 0) {
674 if (reversedIDs.count(item.second->getEdgeId())) {
675 item.second->findLaneAndComputeBusStopExtent(ec);
688 int numBufferStops = 0;
689 int numAddedBidiTotal = 0;
690 for (
NBNode* node : railNodes) {
692 if (node->getEdges().size() != 1) {
693 WRITE_WARNINGF(
TL(
"Ignoring buffer stop junction '%' with % edges."), node->getID(), node->getEdges().size());
703 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
705 if (prev ==
nullptr) {
706 assert(node->getEdges().size() == 1);
707 e = node->getEdges().front();
712 assert(inRail.size() == 2);
713 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
716 assert(outRail.size() == 2);
717 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
749 if (numAddedBidiTotal > 0) {
752 return numAddedBidiTotal;
759 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
760 if (
isStraight(n, inRail.front(), outRail.front())) {
761 return inRail.front();
762 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
763 return inRail.back();
766 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
767 if (
isStraight(n, outRail.front(), inRail.front())) {
768 return outRail.front();
769 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
770 return outRail.back();
780 std::map<int, int> seqLengths;
783 for (
NBNode* n : brokenNodes) {
786 std::vector<NBNode*> nodeSeq;
789 nodeSeq.push_back(prev);
790 edgeSeq.push_back(edge);
798 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
800 edge = allRail.front() == edge ? allRail.back() : allRail.front();
801 nodeSeq.push_back(prev);
802 edgeSeq.push_back(edge);
811 for (
NBEdge* e : edgeSeq) {
814 seqLengths[(int)edgeSeq.size()]++;
816 numAdded += (int)edgeSeq.size();
830 if (seqLengths.size() > 0) {
839 std::set<NBPTLine*> result;
840 std::set<std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > > visited;
841 for (
const auto& item : lc.
getLines()) {
842 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
843 if (stops.size() > 1) {
844 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
845 std::shared_ptr<NBPTStop> fromStop = *it;
846 std::shared_ptr<NBPTStop> toStop = *(it + 1);
847 visited.insert({fromStop, toStop});
851 for (
const auto& item : lc.
getLines()) {
852 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
853 if (stops.size() > 1) {
854 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
855 std::shared_ptr<NBPTStop> fromStop = *it;
856 std::shared_ptr<NBPTStop> toStop = *(it + 1);
857 std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > reverseTrip({toStop, fromStop});
858 if (visited.count(reverseTrip)) {
859 result.insert(item.second);
872 std::vector<Track*> tracks;
874 tracks.push_back(
new Track(edge));
876 const int numEdges = (int)tracks.size();
878 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse", penalty));
881 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
884 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
885 tracks.push_back(start);
886 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
887 tracks.push_back(end);
888 stopTracks[edge] = {start, end};
895 for (
NBEdge* e1 : railEdges) {
896 for (
NBEdge* e2 : railEdges) {
898 int i = e1->getNumericalID();
899 int i2 = e2->getNumericalID();
900 if (e1->getToNode() == node) {
901 if (e2->getFromNode() == node) {
903 tracks[i]->addSuccessor(tracks[i2]);
905 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
908 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
909 tracks[i2]->addSuccessor(tracks[i + numEdges]);
912 if (e2->getFromNode() == node) {
914 tracks[i + numEdges]->addSuccessor(tracks[i2]);
915 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
926 for (
auto& item : stopTracks) {
927 const int index = item.first->getNumericalID();
929 item.second.first->addSuccessor(tracks[index]);
930 item.second.first->addSuccessor(tracks[index + numEdges]);
932 tracks[index]->addSuccessor(item.second.second);
933 tracks[index + numEdges]->addSuccessor(item.second.second);
949 int numDisconnected = 0;
950 std::set<NBEdge*, ComparatorIdLess> addBidiStops;
951 std::set<NBEdge*, ComparatorIdLess> addBidiEdges;
952 std::set<std::pair<std::string, std::string> > visited;
959 for (
const auto& item : lc.
getLines()) {
961 std::vector<std::pair<NBEdge*, std::string> > stops = line->
getStopEdges(ec);
962 std::vector<NBEdge*> stopEdges;
963 for (
auto it : stops) {
964 stopEdges.push_back(it.first);
968 if (routeStart !=
nullptr) {
969 stops.insert(stops.begin(), {routeStart, routeStart->
getID()});
971 if (routeEnd !=
nullptr) {
972 stops.push_back({routeEnd, routeEnd->
getID()});
974 if (stops.size() < 2) {
977 if (!line->
isConsistent(stopEdges) && requireBidi.count(line) == 0) {
978 WRITE_WARNINGF(
TL(
"Edge sequence is not consistent with stop sequence in line '%', not adding bidi edges."), item.first);
981 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
982 NBEdge* fromEdge = it->first;
983 NBEdge* toEdge = (it + 1)->first;
984 const std::string fromStop = it->second;
985 const std::string toStop = (it + 1)->second;
986 std::pair<std::string, std::string> trip(fromStop, toStop);
987 std::pair<std::string, std::string> reverseTrip(toStop, fromStop);
989 if (visited.count(trip) != 0) {
992 visited.insert(trip);
994 if (stopTracks.count(fromEdge) == 0
995 || stopTracks.count(toEdge) == 0) {
998 const bool needBidi = visited.count(reverseTrip) != 0;
1000 std::vector<const Track*> route;
1001 router->
compute(stopTracks[fromEdge].first, stopTracks[toEdge].second, &veh, 0, route);
1005 if (route.size() > 0) {
1006 assert(route.size() > 2);
1007 for (
int i = 1; i < (int)route.size() - 1; ++i) {
1008 if (route[i]->getNumericalID() >= numEdges || needBidi) {
1009 NBEdge* edge = route[i]->edge;
1010 if (addBidiEdges.count(edge) == 0) {
1011 bool isStop = i == 1 || i == (int)route.size() - 2;
1014 addBidiEdges.insert(edge);
1016 addBidiStops.insert(edge);
1020 WRITE_WARNINGF(
TL(
"Stop on edge '%' can only be reached in reverse but edge has the wrong spreadType."), fromEdge->
getID());
1023 }
else if (isStop && needBidi) {
1024 std::shared_ptr<NBPTStop> fs = sc.
get(fromStop);
1026 std::shared_ptr<NBPTStop> fromReverse = sc.
getReverseStop(fs, ec);
1029 fs->setBidiStop(fromReverse);
1032 std::shared_ptr<NBPTStop> ts = sc.
get(toStop);
1037 ts->setBidiStop(toReverse);
1050 for (
NBEdge* edge : addBidiEdges) {
1051 if (!edge->isBidiRail()) {
1054 if (e2 !=
nullptr) {
1064 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
1065 WRITE_MESSAGE(
"Added " +
toString(addBidiStops.size()) +
" bidi-edges for public transport stops and a total of "
1066 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
1067 +
toString(numDisconnected) +
" stops remain disconnected)");
1071 for (
Track* t : tracks) {
1075 return (
int)addBidiEdges.size();
1083 for (
const auto& e : ec) {
1084 if (!
hasRailway(e.second->getPermissions())) {
1087 NBNode*
const from = e.second->getFromNode();
1088 NBNode*
const to = e.second->getToNode();
1089 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
1092 if (e.second->isBidiRail()) {
1095 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
1100 bool haveStraight =
false;
1101 bool haveStraightReverse =
false;
1102 if (!geometryLike || outRailFrom.size() + inRailFrom.size() == 2) {
1103 for (
const NBEdge* fromStraightCand : outRailFrom) {
1104 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1105 haveStraightReverse =
true;
1110 if (haveStraightReverse) {
1111 for (
const NBEdge* fromStraightCand : inRailFrom) {
1112 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1113 haveStraight =
true;
1120 if ((!haveStraightReverse || haveStraight) && (!geometryLike || outRailTo.size() + inRailTo.size() == 2)) {
1123 haveStraight =
false;
1124 haveStraightReverse =
false;
1125 for (
const NBEdge* toStraightCand : inRailTo) {
1126 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1127 haveStraightReverse =
true;
1132 if (haveStraightReverse) {
1133 for (
const NBEdge* toStraightCand : outRailTo) {
1134 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1135 haveStraight =
true;
1143 if (haveStraightReverse && !haveStraight) {
1146 if (e2 !=
nullptr) {
1155 WRITE_MESSAGEF(
TL(
"Added % bidi-edges to ensure connectivity of straight tracks at geometry-like nodes."),
toString(added));
1194 std::set<NBEdge*, ComparatorIdLess> bidi;
1199 if (!edge->isBidiRail()) {
1200 edge->setPriority(4);
1206 if (edge->getPriority() >= 0) {
1215 if (uni.size() == 0) {
1216 if (bidi.size() != 0) {
1217 WRITE_WARNING(
TL(
"Cannot extend track direction priority because there are no track edges with positive priority"));
1224 while (!check.empty()) {
1225 NBEdge* edge = *check.begin();
1227 if (seen.count(edge) != 0) {
1233 forward.insert(straightOut);
1234 check.insert(straightOut);
1238 forward.insert(straightIn);
1239 check.insert(straightIn);
1241#ifdef DEBUG_DIRECTION_PRIORITY
1249 for (
NBEdge* edge : bidi) {
1250 NBEdge* bidiEdge =
const_cast<NBEdge*
>(edge->getBidiEdge());
1253 if (forward.count(edge) != 0) {
1254 if (forward.count(bidiEdge) == 0) {
1263 if (forward.count(bidiEdge) != 0) {
1272 if (bidiEdge ==
nullptr) {
1273 WRITE_WARNINGF(
TL(
"Edge '%' was loaded with undefined priority (%) but has unambiguous main direction (no bidi edge)"), edge->getID(), edge->getPriority());
1275 if (edge->getPriority() >= 0) {
1278 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() >= 0) {
1281 if (edge->getPriority() < 0) {
1282 edge->setPriority(prio);
1284 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() < 0) {
1288 std::map<int, int> numPrios;
1289 for (
NBEdge* edge : bidi) {
1290 numPrios[edge->getPriority()]++;
1306 int addedSignals = 0;
1307 if (oc.
exists(
"railway.signal.guess.by-stops")) {
1308 if (oc.
getBool(
"railway.signal.guess.by-stops")) {
1309 const double minLength = oc.
getFloat(
"osm.stop-output.length.train");
1310 addedSignals += guessByStops(ec, sc, minLength);
1313 return addedSignals;
1324 int addedSignals = 0;
1329 if (canBeSignal(to)) {
1336 if (canBeSignal(from)) {
1344 if (in->getFromNode() != stopEdge->
getToNode()) {
1358 if (searchDist <= 0 && canBeSignal(from)) {
1366 return addedSignals;
1373 int numCorridors = 0;
1375 std::set<NBNode*> railGeomNodes;
1376 for (
NBNode* n : railNodes) {
1377 if (n->geometryLike()) {
1378 railGeomNodes.insert(n);
1381 std::set<NBNode*, ComparatorIdLess> kinkNodes;;
1382 for (
NBNode* n : railGeomNodes) {
1384 NBEdge* out = n->getOutgoingEdges().size() == 1 || n->getOutgoingEdges()[1]->
isTurningDirectionAt(in) ? n->getOutgoingEdges().front() : n->getOutgoingEdges().back();
1386 if (maxAngle > 0 && relAngle > maxAngle) {
1387 kinkNodes.insert(n);
1390 while (!kinkNodes.empty()) {
1391 std::vector<NBNode*> corridor;
1392 std::vector<NBEdge*> corridorEdges;
1395 NBNode* n = *kinkNodes.begin();
1396 kinkNodes.erase(kinkNodes.begin());
1401 NBEdge*
const centerIn = in;
1402 NBEdge*
const centerOut = out;
1405 corridor.push_back(up);
1406 corridor.push_back(n);
1407 corridor.push_back(down);
1410 corridorEdges.push_back(in);
1411 corridorEdges.push_back(out);
1415 while (kinkNodes.count(up) != 0) {
1420 corridor.insert(corridor.begin(), up);
1421 corridorEdges.insert(corridorEdges.begin(), in2);
1422 kinkNodes.erase(up);
1427 delta = cEnd - cBeg;
1428 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(up) != 0) {
1433 corridor.insert(corridor.begin(), up);
1434 corridorEdges.insert(corridorEdges.begin(), in2);
1435 kinkNodes.erase(up);
1439 delta = cEnd - cBeg;
1443 while (kinkNodes.count(down) != 0) {
1448 corridor.push_back(down);
1449 corridorEdges.push_back(out2);
1450 kinkNodes.erase(down);
1455 delta = cEnd - cBeg;
1456 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(down) != 0) {
1461 corridor.push_back(down);
1462 corridorEdges.push_back(out2);
1463 kinkNodes.erase(down);
1467 delta = cEnd - cBeg;
1470 std::set<NBNode*> corridorNodes(corridor.begin(), corridor.end());
1471 for (
NBNode* n2 : corridorNodes) {
1472 for (
NBEdge* e : n2->getEdges()) {
1473 if (corridorNodes.count(e->getFromNode()) != 0
1474 && corridorNodes.count(e->getToNode()) != 0) {
1476 simpleGeom.push_back(e->getFromNode()->getPosition());
1477 simpleGeom.push_back(e->getToNode()->getPosition());
1478 e->setGeometry(simpleGeom);
1483 double currLength = 0;
1484 for (
int i = 1; i < (int)corridor.size() - 1; i++) {
1485 currLength += corridorEdges[i - 1]->getLoadedLength();
1486 const Position newPos = cBeg + delta * (currLength / length);
1487 NBNode*
const n2 = corridor[i];
1488 n2->
reinit(newPos, n2->getType());
1489 for (
NBEdge* e : n2->getEdges()) {
1490 e->resetEndpointAtNode(n2);
1501 WRITE_MESSAGEF(
TL(
"Moved % rail junctions for straightening % corridors."), moved, numCorridors);
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGEF(...)
#define WRITE_MESSAGE(msg)
#define WRITE_WARNING(msg)
#define SHARP_THRESHOLD_SAMEDIR
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a railway edge.
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SUMO_TAG_NODE
alternative definition for junction
bool gDebugFlag1
global utility flags for debugging
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
A class that stores a 2D geometrical boundary.
void add(double x, double y, double z=0)
Makes the boundary include the given coordinate.
Computes the shortest path through a network using the Dijkstra algorithm.
static double angleDiff(const double angle1, const double angle2)
Returns the difference of the second angle to the first angle in radiants.
Storage for edges, including some functionality operating on multiple edges.
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
EdgeVector getAllEdges() const
return all edges
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
bool wasIgnored(std::string id) const
Returns whether the edge with the id was ignored during parsing.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
The representation of a single edge during network building.
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
NBNode * getToNode() const
Returns the destination node of the edge.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
NBEdge * getStraightContinuation(SVCPermissions permissions) const
return the straightest follower edge for the given permissions or nullptr (never returns turn-arounds...
static double getTravelTimeStatic(const NBEdge *const edge, const NBVehicle *const, double)
NBEdge * getStraightPredecessor(SVCPermissions permissions) const
return the straightest predecessor edge for the given permissions or nullptr (never returns turn-arou...
const std::string & getID() const
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
NBNode * getFromNode() const
Returns the origin node of the edge.
NBEdge * getTurnDestination(bool possibleDestination=false) const
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
void setPriority(int priority)
Sets the priority of the edge.
int getPriority() const
Returns the priority of the edge.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
static void loadEdgesFromFile(const std::string &file, std::set< std::string > &into)
Add edge ids defined in file (either ID or edge:ID per line) into the given set.
Represents a single node (junction) during network building.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
SumoXMLNodeType getType() const
Returns the type of this node.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
const Position & getPosition() const
bool geometryLike() const
whether this is structurally similar to a geometry node
const std::map< std::string, NBPTLine * > & getLines() const
bool isConsistent(std::vector< NBEdge * > stops) const
return whether the mentioned edges appear in that order in the route
std::vector< std::pair< NBEdge *, std::string > > getStopEdges(const NBEdgeCont &ec) const
get stop edges and stop ids
const std::string & getRef() const
get line reference (not unique)
NBEdge * getRouteEnd(const NBEdgeCont &ec) const
return last valid edge of myRoute (if it doest not lie before the last stop)
NBEdge * getRouteStart(const NBEdgeCont &ec) const
return first valid edge of myRoute (if it doest not lie after the first stop)
Container for public transport stops during the net building process.
const std::map< std::string, std::shared_ptr< NBPTStop > > & getStops() const
Returns an unmodifiable reference to the stored pt stops.
std::shared_ptr< NBPTStop > get(std::string id) const
Retrieve a previously inserted pt stop.
std::shared_ptr< NBPTStop > getReverseStop(std::shared_ptr< NBPTStop > pStop, const NBEdgeCont &ec)
bool insert(std::shared_ptr< NBPTStop > ptStop, bool floating=false)
Inserts a node into the map.
static int straigthenCorrdidor(NBEdgeCont &ec, double maxAngle)
static bool canBeSignal(const NBNode *node)
static int guessByStops(NBEdgeCont &ec, NBPTStopCont &sc, double minLength)
static int guessRailSignals(NBEdgeCont &ec, NBPTStopCont &sc)
SVCPermissions minPermissions
const std::vector< std::pair< const Track *, const Track * > > & getViaSuccessors(SUMOVehicleClass svc=SVC_IGNORING, bool ignoreTransientPermissions=false) const
const std::vector< Track * > & getSuccessors(SUMOVehicleClass svc=SVC_IGNORING) const
std::vector< Track * > successors
void addSuccessor(Track *track)
std::vector< std::pair< const Track *, const Track * > > viaSuccessors
static NBEdge * isBidiSwitch(const NBNode *n)
static int repairTopology(NBEdgeCont &ec, NBPTStopCont &sc, NBPTLineCont &lc)
static void getRailEdges(const NBNode *node, EdgeVector &inEdges, EdgeVector &outEdges)
filter out rail edges among all edges of a the given node
static void extendDirectionPriority(NBEdgeCont &ec, bool fromUniDir)
static std::set< NBNode * > getRailNodes(NBEdgeCont &ec, bool verbose=false)
static void updateTurns(NBEdge *edge)
recompute turning directions for both nodes of the given edge
static bool isStraight(const NBNode *node, const NBEdge *e1, const NBEdge *e2)
static void analyzeTopology(NBEdgeCont &ec)
static int addBidiEdgesForStops(NBEdgeCont &ec, NBPTLineCont &lc, NBPTStopCont &sc, bool minimal)
add bidi-edges to connect successive public transport stops
static std::set< NBPTLine * > findBidiCandidates(NBPTLineCont &lc)
identify lines that are likely to require bidirectional tracks
static int addBidiEdgesForStraightConnectivity(NBEdgeCont &ec, bool geometryLike)
add bidi-edges to connect straight tracks
static bool allSharp(const NBNode *node, const EdgeVector &in, const EdgeVector &out, bool countBidiAsSharp=false)
static bool allBroken(const NBNode *node, NBEdge *candOut, const EdgeVector &in, const EdgeVector &out)
static std::set< NBNode * > getBrokenRailNodes(NBEdgeCont &ec, bool verbose=false)
static int addBidiEdgesBetweenSwitches(NBEdgeCont &ec)
add bidi-edges to connect switches that are approached in both directions
static bool allBidi(const EdgeVector &edges)
static int makeAllBidi(NBEdgeCont &ec)
static double getTravelTimeStatic(const Track *const track, const NBVehicle *const veh, double time)
static bool hasRailway(SVCPermissions permissions)
filter for rail edges but do not return (legacy) all purpose edges
static int reverseEdges(NBEdgeCont &ec, NBPTStopCont &sc)
reverse edges sequences that are to broken nodes on both sides
static bool hasStraightPair(const NBNode *node, const EdgeVector &edges, const EdgeVector &edges2)
static int addBidiEdgesForBufferStops(NBEdgeCont &ec)
add bidi-edges to connect buffers stops in both directions
static NBEdge * addBidiEdge(NBEdgeCont &ec, NBEdge *edge, bool update=true)
add bidi-edge for the given edge
static int extendBidiEdges(NBEdgeCont &ec)
add further bidi-edges near existing bidi-edges
static const std::string OSM_DIRECTION
processing parameter for rail signal edges and nodes
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
A vehicle as used by router.
static std::string getIDSecure(const T *obj, const std::string &fallBack="NULL")
get an identifier for Named-like object which may be Null
const std::string & getID() const
Returns the id.
A storage for options typed value containers)
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool exists(const std::string &name) const
Returns the information whether the named option is known.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Static storage of an output device and its base (abstract) implementation.
OutputDevice & writeAttr(const SumoXMLAttr attr, const T &val)
writes a named attribute
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
bool closeTag(const std::string &comment="")
Closes the most recently opened tag and optionally adds a comment.
static OutputDevice & getDevice(const std::string &name, bool usePrefix=true)
Returns the described OutputDevice.
bool writeXMLHeader(const std::string &rootElement, const std::string &schemaFile, std::map< SumoXMLAttr, std::string > attrs=std::map< SumoXMLAttr, std::string >(), bool includeConfig=true)
Writes an XML header with optional configuration.
virtual const std::string getParameter(const std::string &key, const std::string defaultValue="") const
Returns the value for a given key.
virtual void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
A point in 2D or 3D with translation and scaling methods.
double length2D() const
Computes the length of the given vector neglecting the z coordinate.
PositionVector reverse() const
reverse position vector
virtual bool compute(const E *from, const E *to, const V *const vehicle, SUMOTime msTime, std::vector< const E * > &into, bool silent=false)=0
Builds the route between the given edges using the minimum effort at the given time The definition of...
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects