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;
578 const EdgeVector& route = item.second->getEdges();
579 lineEdges.insert(route.begin(), route.end());
581 for (
NBNode* n : brokenNodes) {
584 for (
NBEdge* start : outRail) {
585 if (lineEdges.count(start)) {
590 tmp.push_back(start);
592 if (!
allBroken(n, start, inRail, outRail)
593 || (inRail.size() == 1 && outRail.size() == 1)) {
594#ifdef DEBUG_SEQSTOREVERSE
596 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
605 seq.push_back(start);
607 NBNode* n2 = start->getToNode();
610 if (brokenNodes.count(n2) != 0) {
612 tmp2.push_back(start);
613 if (
allBroken(n2, start, outRail2, inRail2)) {
614 seqsToReverse.push_back(seq);
616#ifdef DEBUG_SEQSTOREVERSE
618 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
624 if (outRail2.size() == 0) {
627#ifdef DEBUG_SEQSTOREVERSE
629 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
632 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
635#ifdef DEBUG_SEQSTOREVERSE
637 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
641 start = outRail2.front();
648 if (seqsToReverse.size() > 0) {
651 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
653 return a.size() < b.size();
656 std::set<NBNode*> affectedEndpoints;
657 std::set<std::string> reversedIDs;
658 std::map<int, int> seqLengths;
660 NBNode* seqStart = seq.front()->getFromNode();
661 NBNode* seqEnd = seq.back()->getToNode();
663 if (affectedEndpoints.count(seqStart) == 0
664 && affectedEndpoints.count(seqEnd) == 0) {
665 affectedEndpoints.insert(seqStart);
666 affectedEndpoints.insert(seqEnd);
669 e->reinitNodes(e->getToNode(), e->getFromNode());
670 e->setGeometry(e->getGeometry().reverse());
671 reversedIDs.insert(e->getID());
676 seqLengths[(int)seq.size()]++;
680 if (numReversed > 0) {
683 if (reversedIDs.count(item.second->getEdgeId())) {
684 item.second->findLaneAndComputeBusStopExtent(ec);
697 int numBufferStops = 0;
698 int numAddedBidiTotal = 0;
699 for (
NBNode* node : railNodes) {
701 if (node->getEdges().size() != 1) {
702 WRITE_WARNINGF(
TL(
"Ignoring buffer stop junction '%' with % edges."), node->getID(), node->getEdges().size());
712 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
714 if (prev ==
nullptr) {
715 assert(node->getEdges().size() == 1);
716 e = node->getEdges().front();
721 assert(inRail.size() == 2);
722 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
725 assert(outRail.size() == 2);
726 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
758 if (numAddedBidiTotal > 0) {
761 return numAddedBidiTotal;
768 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
769 if (
isStraight(n, inRail.front(), outRail.front())) {
770 return inRail.front();
771 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
772 return inRail.back();
775 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
776 if (
isStraight(n, outRail.front(), inRail.front())) {
777 return outRail.front();
778 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
779 return outRail.back();
789 std::map<int, int> seqLengths;
792 for (
NBNode* n : brokenNodes) {
795 std::vector<NBNode*> nodeSeq;
798 nodeSeq.push_back(prev);
799 edgeSeq.push_back(edge);
807 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
809 edge = allRail.front() == edge ? allRail.back() : allRail.front();
810 nodeSeq.push_back(prev);
811 edgeSeq.push_back(edge);
820 for (
NBEdge* e : edgeSeq) {
823 seqLengths[(int)edgeSeq.size()]++;
825 numAdded += (int)edgeSeq.size();
839 if (seqLengths.size() > 0) {
848 std::set<NBPTLine*> result;
849 std::set<std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > > visited;
850 for (
const auto& item : lc.
getLines()) {
851 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
852 if (stops.size() > 1) {
853 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
854 std::shared_ptr<NBPTStop> fromStop = *it;
855 std::shared_ptr<NBPTStop> toStop = *(it + 1);
856 visited.insert({fromStop, toStop});
860 for (
const auto& item : lc.
getLines()) {
861 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
862 if (stops.size() > 1) {
863 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
864 std::shared_ptr<NBPTStop> fromStop = *it;
865 std::shared_ptr<NBPTStop> toStop = *(it + 1);
866 std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > reverseTrip({toStop, fromStop});
867 if (visited.count(reverseTrip)) {
868 result.insert(item.second);
881 std::vector<Track*> tracks;
883 tracks.push_back(
new Track(edge));
885 const int numEdges = (int)tracks.size();
887 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse", penalty));
890 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
893 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
894 tracks.push_back(start);
895 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
896 tracks.push_back(end);
897 stopTracks[edge] = {start, end};
904 for (
NBEdge* e1 : railEdges) {
905 for (
NBEdge* e2 : railEdges) {
907 int i = e1->getNumericalID();
908 int i2 = e2->getNumericalID();
909 if (e1->getToNode() == node) {
910 if (e2->getFromNode() == node) {
912 tracks[i]->addSuccessor(tracks[i2]);
914 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
917 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
918 tracks[i2]->addSuccessor(tracks[i + numEdges]);
921 if (e2->getFromNode() == node) {
923 tracks[i + numEdges]->addSuccessor(tracks[i2]);
924 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
935 for (
auto& item : stopTracks) {
936 const int index = item.first->getNumericalID();
938 item.second.first->addSuccessor(tracks[index]);
939 item.second.first->addSuccessor(tracks[index + numEdges]);
941 tracks[index]->addSuccessor(item.second.second);
942 tracks[index + numEdges]->addSuccessor(item.second.second);
958 int numDisconnected = 0;
959 std::set<std::shared_ptr<NBPTStop>> addBidiStops;
960 std::set<NBEdge*, ComparatorIdLess> addBidiStopEdges;
961 std::set<NBEdge*, ComparatorIdLess> addBidiEdges;
962 std::set<std::pair<std::string, std::string> > visited;
969 for (
const auto& item : lc.
getLines()) {
971 std::vector<NBPTLine::PTStopInfo> stops = line->
getStopEdges(ec);
972 std::vector<NBEdge*> stopEdges;
973 for (
auto it : stops) {
974 stopEdges.push_back(it.edge);
978 if (routeStart !=
nullptr && (stopEdges.empty() || routeStart != stopEdges.front())) {
981 if (routeEnd !=
nullptr && (stopEdges.empty() || routeEnd != stopEdges.back())) {
984 if (stops.size() < 2) {
987 if (!line->
isConsistent(stopEdges) && requireBidi.count(line) == 0) {
988 WRITE_WARNINGF(
TL(
"Edge sequence is not consistent with stop sequence in line '%', not adding bidi edges."), item.first);
991 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
992 NBEdge* fromEdge = it->edge;
993 NBEdge* toEdge = (it + 1)->edge;
994 const std::string fromStop = it->stopID;
995 const std::string toStop = (it + 1)->stopID;
996 const double fromPos = it->pos;
997 const double toPos = (it + 1)->pos;
998 bool fromRevised = it->revised;
999 bool toRevised = (it + 1)->revised;
1000 std::pair<std::string, std::string> trip(fromStop, toStop);
1001 std::pair<std::string, std::string> reverseTrip(toStop, fromStop);
1005 if (visited.count(trip) != 0) {
1008 visited.insert(trip);
1010 if (stopTracks.count(fromEdge) == 0
1011 || stopTracks.count(toEdge) == 0) {
1014 bool needBidi = visited.count(reverseTrip) != 0;
1016 std::vector<const Track*> route;
1017 Track* from = fromRevised ? tracks[fromEdge->
getNumericalID()] : stopTracks[fromEdge].first;
1019 int iStart = fromRevised ? 0 : 1;
1020 int iDeltaEnd = toRevised ? 0 : 1;
1021 if (fromEdge == toEdge && fromPos > toPos) {
1028 router->
compute(from, to, &veh, 0, route);
1033 if (route.size() > 0) {
1034 assert((
int)route.size() > iStart + iDeltaEnd);
1035 for (
int i = iStart; i < (int)route.size() - iDeltaEnd; ++i) {
1036 const bool isBidi = route[i]->getNumericalID() >= numEdges;
1037 bool isStop = i == iStart || i == (int)route.size() - 1 - iDeltaEnd;
1038 if (isBidi || needBidi) {
1039 NBEdge* edge = route[i]->edge;
1040 if (addBidiEdges.count(edge) == 0) {
1043 addBidiEdges.insert(edge);
1045 addBidiStopEdges.insert(edge);
1049 WRITE_WARNINGF(
TL(
"Stop on edge '%' can only be reached in reverse but edge has the wrong spreadType."), fromEdge->
getID());
1055 if (isStop && isBidi) {
1056 std::shared_ptr<NBPTStop> fs = sc.
get(fromStop);
1058 addBidiStops.insert(fs);
1060 std::shared_ptr<NBPTStop> ts = sc.
get(toStop);
1062 addBidiStops.insert(ts);
1072 for (
NBEdge* edge : addBidiEdges) {
1073 if (!edge->isBidiRail()) {
1076 if (e2 !=
nullptr) {
1085 for (std::shared_ptr<NBPTStop> stop : addBidiStops) {
1086 std::shared_ptr<NBPTStop> fromReverse = sc.
getReverseStop(stop, ec);
1089 stop->setBidiStop(fromReverse);
1092 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
1093 WRITE_MESSAGE(
"Added " +
toString(addBidiStopEdges.size()) +
" bidi-edges for public transport stops and a total of "
1094 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
1095 +
toString(numDisconnected) +
" stops remain disconnected)");
1099 for (
Track* t : tracks) {
1103 return (
int)addBidiEdges.size();
1111 for (
const auto& e : ec) {
1112 if (!
hasRailway(e.second->getPermissions())) {
1115 NBNode*
const from = e.second->getFromNode();
1116 NBNode*
const to = e.second->getToNode();
1117 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
1120 if (e.second->isBidiRail()) {
1123 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
1128 bool haveStraight =
false;
1129 bool haveStraightReverse =
false;
1130 if (!geometryLike || outRailFrom.size() + inRailFrom.size() == 2) {
1131 for (
const NBEdge* fromStraightCand : outRailFrom) {
1132 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1133 haveStraightReverse =
true;
1138 if (haveStraightReverse) {
1139 for (
const NBEdge* fromStraightCand : inRailFrom) {
1140 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1141 haveStraight =
true;
1148 if ((!haveStraightReverse || haveStraight) && (!geometryLike || outRailTo.size() + inRailTo.size() == 2)) {
1151 haveStraight =
false;
1152 haveStraightReverse =
false;
1153 for (
const NBEdge* toStraightCand : inRailTo) {
1154 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1155 haveStraightReverse =
true;
1160 if (haveStraightReverse) {
1161 for (
const NBEdge* toStraightCand : outRailTo) {
1162 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1163 haveStraight =
true;
1171 if (haveStraightReverse && !haveStraight) {
1174 if (e2 !=
nullptr) {
1183 WRITE_MESSAGEF(
TL(
"Added % bidi-edges to ensure connectivity of straight tracks at geometry-like nodes."),
toString(added));
1222 std::set<NBEdge*, ComparatorIdLess> bidi;
1227 if (!edge->isBidiRail()) {
1228 edge->setPriority(4);
1229 edge->setRoutingType(
"4");
1235 if (edge->getPriority() >= 0) {
1244 if (uni.size() == 0) {
1245 if (bidi.size() != 0) {
1246 WRITE_WARNING(
TL(
"Cannot extend track direction priority because there are no track edges with positive priority"));
1253 while (!check.empty()) {
1254 NBEdge* edge = *check.begin();
1256 if (seen.count(edge) != 0) {
1262 forward.insert(straightOut);
1263 check.insert(straightOut);
1267 forward.insert(straightIn);
1268 check.insert(straightIn);
1270#ifdef DEBUG_DIRECTION_PRIORITY
1278 for (
NBEdge* edge : bidi) {
1279 NBEdge* bidiEdge =
const_cast<NBEdge*
>(edge->getBidiEdge());
1282 if (forward.count(edge) != 0) {
1283 if (forward.count(bidiEdge) == 0) {
1292 if (forward.count(bidiEdge) != 0) {
1301 if (bidiEdge ==
nullptr) {
1302 WRITE_WARNINGF(
TL(
"Edge '%' was loaded with undefined priority (%) but has unambiguous main direction (no bidi edge)"), edge->getID(), edge->getPriority());
1304 if (edge->getPriority() >= 0) {
1307 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() >= 0) {
1310 if (edge->getPriority() < 0) {
1311 edge->setPriority(prio);
1312 edge->setRoutingType(
toString(prio));
1314 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() < 0) {
1319 std::map<int, int> numPrios;
1320 for (
NBEdge* edge : bidi) {
1321 numPrios[edge->getPriority()]++;
1337 int addedSignals = 0;
1338 if (oc.
exists(
"railway.signal.guess.by-stops")) {
1339 if (oc.
getBool(
"railway.signal.guess.by-stops")) {
1340 const double minLength = oc.
getFloat(
"osm.stop-output.length.train");
1341 addedSignals += guessByStops(ec, sc, minLength);
1344 return addedSignals;
1355 int addedSignals = 0;
1360 if (canBeSignal(to)) {
1367 if (canBeSignal(from)) {
1375 if (in->getFromNode() != stopEdge->
getToNode()) {
1389 if (searchDist <= 0 && canBeSignal(from)) {
1397 return addedSignals;
1404 int numCorridors = 0;
1406 std::set<NBNode*> railGeomNodes;
1407 for (
NBNode* n : railNodes) {
1408 if (n->geometryLike()) {
1409 railGeomNodes.insert(n);
1412 std::set<NBNode*, ComparatorIdLess> kinkNodes;;
1413 for (
NBNode* n : railGeomNodes) {
1415 NBEdge* out = n->getOutgoingEdges().size() == 1 || n->getOutgoingEdges()[1]->
isTurningDirectionAt(in) ? n->getOutgoingEdges().front() : n->getOutgoingEdges().back();
1417 if (maxAngle > 0 && relAngle > maxAngle) {
1418 kinkNodes.insert(n);
1421 while (!kinkNodes.empty()) {
1422 std::vector<NBNode*> corridor;
1423 std::vector<NBEdge*> corridorEdges;
1426 NBNode* n = *kinkNodes.begin();
1427 kinkNodes.erase(kinkNodes.begin());
1432 NBEdge*
const centerIn = in;
1433 NBEdge*
const centerOut = out;
1436 corridor.push_back(up);
1437 corridor.push_back(n);
1438 corridor.push_back(down);
1441 corridorEdges.push_back(in);
1442 corridorEdges.push_back(out);
1446 while (kinkNodes.count(up) != 0) {
1451 corridor.insert(corridor.begin(), up);
1452 corridorEdges.insert(corridorEdges.begin(), in2);
1453 kinkNodes.erase(up);
1458 delta = cEnd - cBeg;
1459 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(up) != 0) {
1464 corridor.insert(corridor.begin(), up);
1465 corridorEdges.insert(corridorEdges.begin(), in2);
1466 kinkNodes.erase(up);
1470 delta = cEnd - cBeg;
1474 while (kinkNodes.count(down) != 0) {
1479 corridor.push_back(down);
1480 corridorEdges.push_back(out2);
1481 kinkNodes.erase(down);
1486 delta = cEnd - cBeg;
1487 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(down) != 0) {
1492 corridor.push_back(down);
1493 corridorEdges.push_back(out2);
1494 kinkNodes.erase(down);
1498 delta = cEnd - cBeg;
1501 std::set<NBNode*> corridorNodes(corridor.begin(), corridor.end());
1502 for (
NBNode* n2 : corridorNodes) {
1503 for (
NBEdge* e : n2->getEdges()) {
1504 if (corridorNodes.count(e->getFromNode()) != 0
1505 && corridorNodes.count(e->getToNode()) != 0) {
1507 simpleGeom.push_back(e->getFromNode()->getPosition());
1508 simpleGeom.push_back(e->getToNode()->getPosition());
1509 e->setGeometry(simpleGeom);
1514 double currLength = 0;
1515 for (
int i = 1; i < (int)corridor.size() - 1; i++) {
1516 currLength += corridorEdges[i - 1]->getLoadedLength();
1517 const Position newPos = cBeg + delta * (currLength / length);
1518 NBNode*
const n2 = corridor[i];
1519 n2->
reinit(newPos, n2->getType());
1520 for (
NBEdge* e : n2->getEdges()) {
1521 e->resetEndpointAtNode(n2);
1532 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.
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.
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.
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.
void setRoutingType(const std::string &routingType)
mark this edge as a bidi 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< 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(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 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 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
get stop edges and stop ids and directional validity