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());
211 incoming->invalidateConnections(
true);
228 inEdges.push_back(e);
233 outEdges.push_back(e);
241 std::set<NBNode*> brokenNodes;
247 std::set<NBNode*> railNodes =
getRailNodes(ec, verbose);
248 std::map<std::pair<int, int>, std::set<NBNode*, ComparatorIdLess> > types;
249 std::set<NBEdge*, ComparatorIdLess> bidiEdges;
250 std::set<NBEdge*, ComparatorIdLess> bufferStops;
251 for (
NBNode* node : railNodes) {
254 types[std::make_pair((
int)inEdges.size(), (
int)outEdges.size())].insert(node);
255 for (
NBEdge* e : outEdges) {
256 if (e->isBidiRail() && bidiEdges.count(e->getTurnDestination(
true)) == 0) {
259 if (e->getID()[0] ==
'-') {
261 }
else if (primary->
getID()[0] !=
'-' && secondary->
getID()[0] !=
'-' && secondary->
getID() < primary->
getID()) {
264 if (bidiEdges.count(secondary) == 0) {
266 bidiEdges.insert(primary);
276 int numBufferStops = 0;
277 if (verbose && types.size() > 0) {
278 WRITE_MESSAGE(
TL(
"Railway nodes by number of incoming,outgoing edges:"))
283 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are outgoing");
287 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are incoming");
291 device.
writeAttr(
"meaning",
"an incoming edge has a sharp angle to all outgoing edges");
295 device.
writeAttr(
"meaning",
"an outgoing edge has a sharp angle from all incoming edges");
299 for (
auto it : types) {
300 int numBrokenType = 0;
301 device.
openTag(
"railNodeType");
302 int in = it.first.first;
303 int out = it.first.second;
306 for (
NBNode* n : it.second) {
314 std::string broken =
"";
324 for (
NBEdge* e : inRail) {
335 for (
NBEdge* e : outRail) {
346 if (((in == 1 && out == 1) || (in == 2 && out == 2))
351 if (broken.size() > 0) {
353 brokenNodes.insert(n);
365 +
" count: " +
toString(it.second.size()) +
" broken: " +
toString(numBrokenType));
379 for (
NBEdge* e : bidiEdges) {
382 device.
writeAttr(
"bidi", e->getTurnDestination(
true)->getID());
396 std::set<NBNode*> railNodes;
397 int numRailEdges = 0;
398 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
399 if (
hasRailway(it->second->getPermissions())) {
401 railNodes.insert(it->second->getFromNode());
402 railNodes.insert(it->second->getToNode());
405 int numRailSignals = 0;
406 for (
const NBNode*
const node : railNodes) {
444#ifdef DEBUG_SEQSTOREVERSE
449 for (
NBEdge* e1 : edges) {
450 for (
NBEdge* e2 : edges2) {
470 if (e != candOut &&
isStraight(node, e, candOut)) {
472 std::cout <<
" isStraight e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
478 if (e != candOut && !
isStraight(node, e, candOut)) {
480 std::cout <<
" isSharp e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
497 if (!e1->isBidiRail(
true)) {
503 return !
allBidi || countBidiAsSharp;
510 if (!e->isBidiRail()) {
521 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
539 if (bidiOut ==
nullptr) {
544 tmpBidiOut.push_back(bidiOut);
546 tmpBidiIn.push_back(bidiIn);
550 for (
NBEdge* cand : outRail) {
552 if (!cand->isBidiRail() &&
isStraight(node, bidiIn, cand)
554 &&
allSharp(node, inRail, tmpBidiOut,
true)) {
561 for (
NBEdge* cand : inRail) {
563 if (!cand->isBidiRail() &&
isStraight(node, cand, bidiOut)
565 &&
allSharp(node, outRail, tmpBidiIn,
true)) {
580 std::vector<EdgeVector> seqsToReverse;
583 const EdgeVector& route = item.second->getEdges();
584 lineEdges.insert(route.begin(), route.end());
586 for (
NBNode* n : brokenNodes) {
589 for (
NBEdge* start : outRail) {
590 if (lineEdges.count(start)) {
595 tmp.push_back(start);
597 if (!
allBroken(n, start, inRail, outRail)
598 || (inRail.size() == 1 && outRail.size() == 1)) {
599#ifdef DEBUG_SEQSTOREVERSE
601 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
610 seq.push_back(start);
612 NBNode* n2 = start->getToNode();
615 if (brokenNodes.count(n2) != 0) {
617 tmp2.push_back(start);
618 if (
allBroken(n2, start, outRail2, inRail2)) {
619 seqsToReverse.push_back(seq);
621#ifdef DEBUG_SEQSTOREVERSE
623 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
629 if (outRail2.size() == 0) {
632#ifdef DEBUG_SEQSTOREVERSE
634 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
637 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
640#ifdef DEBUG_SEQSTOREVERSE
642 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
646 start = outRail2.front();
653 if (seqsToReverse.size() > 0) {
656 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
658 return a.size() < b.size();
661 std::set<NBNode*> affectedEndpoints;
662 std::set<std::string> reversedIDs;
663 std::map<int, int> seqLengths;
665 NBNode* seqStart = seq.front()->getFromNode();
666 NBNode* seqEnd = seq.back()->getToNode();
668 if (affectedEndpoints.count(seqStart) == 0
669 && affectedEndpoints.count(seqEnd) == 0) {
670 affectedEndpoints.insert(seqStart);
671 affectedEndpoints.insert(seqEnd);
675 reversedIDs.insert(e->getID());
677 seqLengths[(int)seq.size()]++;
681 if (numReversed > 0) {
684 if (reversedIDs.count(item.second->getEdgeId())) {
685 item.second->findLaneAndComputeBusStopExtent(ec);
708 int numBufferStops = 0;
709 int numAddedBidiTotal = 0;
710 for (
NBNode* node : railNodes) {
712 if (node->getEdges().size() != 1) {
713 WRITE_WARNINGF(
TL(
"Ignoring buffer stop junction '%' with % edges."), node->getID(), node->getEdges().size());
723 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
725 if (prev ==
nullptr) {
726 assert(node->getEdges().size() == 1);
727 e = node->getEdges().front();
732 assert(inRail.size() == 2);
733 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
736 assert(outRail.size() == 2);
737 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
769 if (numAddedBidiTotal > 0) {
772 return numAddedBidiTotal;
779 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
780 if (
isStraight(n, inRail.front(), outRail.front())) {
781 return inRail.front();
782 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
783 return inRail.back();
786 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
787 if (
isStraight(n, outRail.front(), inRail.front())) {
788 return outRail.front();
789 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
790 return outRail.back();
800 std::map<int, int> seqLengths;
803 for (
NBNode* n : brokenNodes) {
806 std::vector<NBNode*> nodeSeq;
809 nodeSeq.push_back(prev);
810 edgeSeq.push_back(edge);
818 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
820 edge = allRail.front() == edge ? allRail.back() : allRail.front();
821 nodeSeq.push_back(prev);
822 edgeSeq.push_back(edge);
831 for (
NBEdge* e : edgeSeq) {
834 seqLengths[(int)edgeSeq.size()]++;
836 numAdded += (int)edgeSeq.size();
850 if (seqLengths.size() > 0) {
859 std::set<NBPTLine*> result;
860 std::set<std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > > visited;
861 for (
const auto& item : lc.
getLines()) {
862 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
863 if (stops.size() > 1) {
864 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
865 std::shared_ptr<NBPTStop> fromStop = *it;
866 std::shared_ptr<NBPTStop> toStop = *(it + 1);
867 visited.insert({fromStop, toStop});
871 for (
const auto& item : lc.
getLines()) {
872 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
873 if (stops.size() > 1) {
874 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
875 std::shared_ptr<NBPTStop> fromStop = *it;
876 std::shared_ptr<NBPTStop> toStop = *(it + 1);
877 std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > reverseTrip({toStop, fromStop});
878 if (visited.count(reverseTrip)) {
879 result.insert(item.second);
892 std::vector<Track*> tracks;
894 tracks.push_back(
new Track(edge));
896 const int numEdges = (int)tracks.size();
898 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse", penalty));
901 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
904 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
905 tracks.push_back(start);
906 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
907 tracks.push_back(end);
908 stopTracks[edge] = {start, end};
915 for (
NBEdge* e1 : railEdges) {
916 for (
NBEdge* e2 : railEdges) {
918 int i = e1->getNumericalID();
919 int i2 = e2->getNumericalID();
920 if (e1->getToNode() == node) {
921 if (e2->getFromNode() == node) {
923 tracks[i]->addSuccessor(tracks[i2]);
925 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
928 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
929 tracks[i2]->addSuccessor(tracks[i + numEdges]);
932 if (e2->getFromNode() == node) {
934 tracks[i + numEdges]->addSuccessor(tracks[i2]);
935 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
946 for (
auto& item : stopTracks) {
947 const int index = item.first->getNumericalID();
949 item.second.first->addSuccessor(tracks[index]);
950 item.second.first->addSuccessor(tracks[index + numEdges]);
952 tracks[index]->addSuccessor(item.second.second);
953 tracks[index + numEdges]->addSuccessor(item.second.second);
969 int numDisconnected = 0;
970 std::set<std::shared_ptr<NBPTStop>> addBidiStops;
971 std::set<NBEdge*, ComparatorIdLess> addBidiStopEdges;
972 std::set<NBEdge*, ComparatorIdLess> addBidiEdges;
973 std::set<std::pair<std::string, std::string> > visited;
980 for (
const auto& item : lc.
getLines()) {
982 std::vector<NBPTLine::PTStopInfo> stops = line->
getStopEdges(ec);
983 std::vector<NBEdge*> stopEdges;
984 for (
auto it : stops) {
985 stopEdges.push_back(it.edge);
989 if (routeStart !=
nullptr && (stopEdges.empty() || routeStart != stopEdges.front())) {
992 if (routeEnd !=
nullptr && (stopEdges.empty() || routeEnd != stopEdges.back())) {
995 if (stops.size() < 2) {
998 if (!line->
isConsistent(stopEdges) && requireBidi.count(line) == 0) {
999 WRITE_WARNINGF(
TL(
"Edge sequence is not consistent with stop sequence in line '%', not adding bidi edges."), item.first);
1002 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
1003 NBEdge* fromEdge = it->edge;
1004 NBEdge* toEdge = (it + 1)->edge;
1005 const std::string fromStop = it->stopID;
1006 const std::string toStop = (it + 1)->stopID;
1007 const double fromPos = it->pos;
1008 const double toPos = (it + 1)->pos;
1009 bool fromRevised = it->revised;
1010 bool toRevised = (it + 1)->revised;
1011 std::pair<std::string, std::string> trip(fromStop, toStop);
1012 std::pair<std::string, std::string> reverseTrip(toStop, fromStop);
1016 if (visited.count(trip) != 0) {
1019 visited.insert(trip);
1021 if (stopTracks.count(fromEdge) == 0
1022 || stopTracks.count(toEdge) == 0) {
1025 bool needBidi = visited.count(reverseTrip) != 0;
1027 std::vector<const Track*> route;
1028 Track* from = fromRevised ? tracks[fromEdge->
getNumericalID()] : stopTracks[fromEdge].first;
1030 int iStart = fromRevised ? 0 : 1;
1031 int iDeltaEnd = toRevised ? 0 : 1;
1032 if (fromEdge == toEdge && fromPos > toPos) {
1039 router->
compute(from, to, &veh, 0, route);
1044 if (route.size() > 0) {
1045 assert((
int)route.size() > iStart + iDeltaEnd);
1046 for (
int i = iStart; i < (int)route.size() - iDeltaEnd; ++i) {
1047 const bool isBidi = route[i]->getNumericalID() >= numEdges;
1048 bool isStop = i == iStart || i == (int)route.size() - 1 - iDeltaEnd;
1049 if (isBidi || needBidi) {
1050 NBEdge* edge = route[i]->edge;
1051 if (addBidiEdges.count(edge) == 0) {
1054 addBidiEdges.insert(edge);
1056 addBidiStopEdges.insert(edge);
1060 WRITE_WARNINGF(
TL(
"Stop on edge '%' can only be reached in reverse but edge has the wrong spreadType."), fromEdge->
getID());
1066 if (isStop && isBidi) {
1067 std::shared_ptr<NBPTStop> fs = sc.
get(fromStop);
1069 addBidiStops.insert(fs);
1071 std::shared_ptr<NBPTStop> ts = sc.
get(toStop);
1073 addBidiStops.insert(ts);
1083 for (
NBEdge* edge : addBidiEdges) {
1084 if (!edge->isBidiRail()) {
1085 if (edge->getFromNode()->getIncomingEdges().size() == 0
1086 && edge->getToNode()->getOutgoingEdges().size() == 0) {
1092 if (e2 !=
nullptr) {
1102 for (std::shared_ptr<NBPTStop> stop : addBidiStops) {
1103 std::shared_ptr<NBPTStop> fromReverse = sc.
getReverseStop(stop, ec);
1106 stop->setBidiStop(fromReverse);
1109 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
1110 WRITE_MESSAGE(
"Added " +
toString(addBidiStopEdges.size()) +
" bidi-edges for public transport stops and a total of "
1111 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
1112 +
toString(numDisconnected) +
" stops remain disconnected)");
1116 for (
Track* t : tracks) {
1120 return (
int)addBidiEdges.size();
1128 for (
const auto& e : ec) {
1129 if (!
hasRailway(e.second->getPermissions())) {
1132 NBNode*
const from = e.second->getFromNode();
1133 NBNode*
const to = e.second->getToNode();
1134 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
1137 if (e.second->isBidiRail()) {
1140 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
1145 bool haveStraight =
false;
1146 bool haveStraightReverse =
false;
1147 if (!geometryLike || outRailFrom.size() + inRailFrom.size() == 2) {
1148 for (
const NBEdge* fromStraightCand : outRailFrom) {
1149 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1150 haveStraightReverse =
true;
1155 if (haveStraightReverse) {
1156 for (
const NBEdge* fromStraightCand : inRailFrom) {
1157 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1158 haveStraight =
true;
1165 if ((!haveStraightReverse || haveStraight) && (!geometryLike || outRailTo.size() + inRailTo.size() == 2)) {
1168 haveStraight =
false;
1169 haveStraightReverse =
false;
1170 for (
const NBEdge* toStraightCand : inRailTo) {
1171 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1172 haveStraightReverse =
true;
1177 if (haveStraightReverse) {
1178 for (
const NBEdge* toStraightCand : outRailTo) {
1179 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1180 haveStraight =
true;
1188 if (haveStraightReverse && !haveStraight) {
1191 if (e2 !=
nullptr) {
1200 WRITE_MESSAGEF(
TL(
"Added % bidi-edges to ensure connectivity of straight tracks at geometry-like nodes."),
toString(added));
1226 if (
isRailway(p) && (p & vClasses) != 0) {
1227 if (edge->getRoutingType() ==
"") {
1228 edge->setPriority(-1);
1234 for (
const auto& item : lc.
getLines()) {
1235 if ((item.second->getVClass() & vClasses) == 0) {
1238 for (
NBEdge* edge : item.second->getEdges()) {
1239 if (edge->getRoutingType() ==
"") {
1240 edge->setPriority(4);
1241 edge->setRoutingType(
"4");
1265 std::set<NBEdge*, ComparatorIdLess> bidi;
1270 if (!edge->isBidiRail()) {
1271 edge->setPriority(4);
1272 edge->setRoutingType(
"4");
1278 if (edge->getPriority() >= 0) {
1287 if (uni.size() == 0) {
1288 if (bidi.size() != 0) {
1289 WRITE_WARNING(
TL(
"Cannot extend track direction priority because there are no track edges with positive priority"));
1296 while (!check.empty()) {
1297 NBEdge* edge = *check.begin();
1299 if (seen.count(edge) != 0) {
1305 forward.insert(straightOut);
1306 check.insert(straightOut);
1310 forward.insert(straightIn);
1311 check.insert(straightIn);
1313#ifdef DEBUG_DIRECTION_PRIORITY
1321 for (
NBEdge* edge : bidi) {
1322 NBEdge* bidiEdge =
const_cast<NBEdge*
>(edge->getBidiEdge());
1325 if (forward.count(edge) != 0) {
1326 if (forward.count(bidiEdge) == 0) {
1335 if (forward.count(bidiEdge) != 0) {
1344 if (bidiEdge ==
nullptr) {
1345 WRITE_WARNINGF(
TL(
"Edge '%' was loaded with undefined priority (%) but has unambiguous main direction (no bidi edge)"), edge->getID(), edge->getPriority());
1347 if (edge->getPriority() >= 0) {
1350 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() >= 0) {
1353 if (edge->getPriority() < 0) {
1354 edge->setPriority(prio);
1355 edge->setRoutingType(
toString(prio));
1357 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() < 0) {
1362 std::map<int, int> numPrios;
1363 for (
NBEdge* edge : bidi) {
1364 numPrios[edge->getPriority()]++;
1380 int addedSignals = 0;
1381 if (oc.
exists(
"railway.signal.guess.by-stops")) {
1382 if (oc.
getBool(
"railway.signal.guess.by-stops")) {
1384 const double minLength = oc.
getFloat(
"osm.stop-output.length.train");
1385 addedSignals += guessByStops(ec, sc, minLength);
1388 return addedSignals;
1399 int addedSignals = 0;
1404 if (canBeSignal(to)) {
1411 if (canBeSignal(from)) {
1419 if (in->getFromNode() != stopEdge->
getToNode()) {
1433 if (searchDist <= 0 && canBeSignal(from)) {
1441 return addedSignals;
1448 int numCorridors = 0;
1450 std::set<NBNode*> railGeomNodes;
1451 for (
NBNode* n : railNodes) {
1452 if (n->geometryLike()) {
1453 railGeomNodes.insert(n);
1456 std::set<NBNode*, ComparatorIdLess> kinkNodes;;
1457 for (
NBNode* n : railGeomNodes) {
1459 NBEdge* out = n->getOutgoingEdges().size() == 1 || n->getOutgoingEdges()[1]->
isTurningDirectionAt(in) ? n->getOutgoingEdges().front() : n->getOutgoingEdges().back();
1461 if (maxAngle > 0 && relAngle > maxAngle) {
1462 kinkNodes.insert(n);
1465 while (!kinkNodes.empty()) {
1466 std::vector<NBNode*> corridor;
1467 std::vector<NBEdge*> corridorEdges;
1470 NBNode* n = *kinkNodes.begin();
1471 kinkNodes.erase(kinkNodes.begin());
1476 NBEdge*
const centerIn = in;
1477 NBEdge*
const centerOut = out;
1480 corridor.push_back(up);
1481 corridor.push_back(n);
1482 corridor.push_back(down);
1485 corridorEdges.push_back(in);
1486 corridorEdges.push_back(out);
1490 while (kinkNodes.count(up) != 0) {
1495 corridor.insert(corridor.begin(), up);
1496 corridorEdges.insert(corridorEdges.begin(), in2);
1497 kinkNodes.erase(up);
1502 delta = cEnd - cBeg;
1503 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(up) != 0) {
1508 corridor.insert(corridor.begin(), up);
1509 corridorEdges.insert(corridorEdges.begin(), in2);
1510 kinkNodes.erase(up);
1514 delta = cEnd - cBeg;
1518 while (kinkNodes.count(down) != 0) {
1523 corridor.push_back(down);
1524 corridorEdges.push_back(out2);
1525 kinkNodes.erase(down);
1530 delta = cEnd - cBeg;
1531 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(down) != 0) {
1536 corridor.push_back(down);
1537 corridorEdges.push_back(out2);
1538 kinkNodes.erase(down);
1542 delta = cEnd - cBeg;
1545 std::set<NBNode*> corridorNodes(corridor.begin(), corridor.end());
1546 for (
NBNode* n2 : corridorNodes) {
1547 for (
NBEdge* e : n2->getEdges()) {
1548 if (corridorNodes.count(e->getFromNode()) != 0
1549 && corridorNodes.count(e->getToNode()) != 0) {
1551 simpleGeom.push_back(e->getFromNode()->getPosition());
1552 simpleGeom.push_back(e->getToNode()->getPosition());
1553 e->setGeometry(simpleGeom);
1558 double currLength = 0;
1559 for (
int i = 1; i < (int)corridor.size() - 1; i++) {
1560 currLength += corridorEdges[i - 1]->getLoadedLength();
1561 const Position newPos = cBeg + delta * (currLength / length);
1562 NBNode*
const n2 = corridor[i];
1563 n2->
reinit(newPos, n2->getType());
1564 for (
NBEdge* e : n2->getEdges()) {
1565 e->resetEndpointAtNode(n2);
1576 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 (exclusive) railway edge.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
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.
double getLength() const
Returns the computed length of the edge.
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.
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
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...
int getNumericalID() const
Returns the index (numeric id) of the edge.
void setDistance(double distance)
set kilometrage at start of edge (negative value implies couting down along the edge)
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
double getDistance() const
get distance
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.
void setRoutingType(const std::string &routingType)
set the routingType for this edge
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
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.
Container for nodes during the netbuilding process.
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< PTStopInfo > getStopEdges(const NBEdgeCont &ec) const
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(NBNodeCont &nc, 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 int reverseEdges(NBEdgeCont &ec, NBPTStopCont &sc, NBPTLineCont &lc)
reverse edges sequences that are to broken nodes on both sides
static void analyzeTopology(NBEdgeCont &ec)
static void setPTLinePriority(NBEdgeCont &ec, NBPTLineCont &lc, SVCPermissions vClasses)
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 void reverseEdge(NBEdge *e)
reverse a single edge
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 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 computeTurnDirections(NBNodeCont &nc, bool warn=true)
Computes turnaround destinations for all edges (if exist)
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.
void close()
Closes the device and removes it from the dictionary.
OutputDevice & openTag(const std::string &xmlElement)
Opens an XML tag.
OutputDevice & writeAttr(const ATTR_TYPE &attr, const T &val, const bool isNull=false)
writes a named attribute
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 int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool isInt(const std::string &sData)
check if the given sData can be converted to int
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
get stop edges and stop ids and directional validity