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);
670 reversedIDs.insert(e->getID());
672 seqLengths[(int)seq.size()]++;
676 if (numReversed > 0) {
679 if (reversedIDs.count(item.second->getEdgeId())) {
680 item.second->findLaneAndComputeBusStopExtent(ec);
703 int numBufferStops = 0;
704 int numAddedBidiTotal = 0;
705 for (
NBNode* node : railNodes) {
707 if (node->getEdges().size() != 1) {
708 WRITE_WARNINGF(
TL(
"Ignoring buffer stop junction '%' with % edges."), node->getID(), node->getEdges().size());
718 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
720 if (prev ==
nullptr) {
721 assert(node->getEdges().size() == 1);
722 e = node->getEdges().front();
727 assert(inRail.size() == 2);
728 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
731 assert(outRail.size() == 2);
732 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
764 if (numAddedBidiTotal > 0) {
767 return numAddedBidiTotal;
774 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
775 if (
isStraight(n, inRail.front(), outRail.front())) {
776 return inRail.front();
777 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
778 return inRail.back();
781 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
782 if (
isStraight(n, outRail.front(), inRail.front())) {
783 return outRail.front();
784 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
785 return outRail.back();
795 std::map<int, int> seqLengths;
798 for (
NBNode* n : brokenNodes) {
801 std::vector<NBNode*> nodeSeq;
804 nodeSeq.push_back(prev);
805 edgeSeq.push_back(edge);
813 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
815 edge = allRail.front() == edge ? allRail.back() : allRail.front();
816 nodeSeq.push_back(prev);
817 edgeSeq.push_back(edge);
826 for (
NBEdge* e : edgeSeq) {
829 seqLengths[(int)edgeSeq.size()]++;
831 numAdded += (int)edgeSeq.size();
845 if (seqLengths.size() > 0) {
854 std::set<NBPTLine*> result;
855 std::set<std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > > visited;
856 for (
const auto& item : lc.
getLines()) {
857 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
858 if (stops.size() > 1) {
859 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
860 std::shared_ptr<NBPTStop> fromStop = *it;
861 std::shared_ptr<NBPTStop> toStop = *(it + 1);
862 visited.insert({fromStop, toStop});
866 for (
const auto& item : lc.
getLines()) {
867 const std::vector<std::shared_ptr<NBPTStop> >& stops = item.second->getStops();
868 if (stops.size() > 1) {
869 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
870 std::shared_ptr<NBPTStop> fromStop = *it;
871 std::shared_ptr<NBPTStop> toStop = *(it + 1);
872 std::pair<std::shared_ptr<NBPTStop>, std::shared_ptr<NBPTStop> > reverseTrip({toStop, fromStop});
873 if (visited.count(reverseTrip)) {
874 result.insert(item.second);
887 std::vector<Track*> tracks;
889 tracks.push_back(
new Track(edge));
891 const int numEdges = (int)tracks.size();
893 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse", penalty));
896 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
899 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
900 tracks.push_back(start);
901 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
902 tracks.push_back(end);
903 stopTracks[edge] = {start, end};
910 for (
NBEdge* e1 : railEdges) {
911 for (
NBEdge* e2 : railEdges) {
913 int i = e1->getNumericalID();
914 int i2 = e2->getNumericalID();
915 if (e1->getToNode() == node) {
916 if (e2->getFromNode() == node) {
918 tracks[i]->addSuccessor(tracks[i2]);
920 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
923 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
924 tracks[i2]->addSuccessor(tracks[i + numEdges]);
927 if (e2->getFromNode() == node) {
929 tracks[i + numEdges]->addSuccessor(tracks[i2]);
930 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
941 for (
auto& item : stopTracks) {
942 const int index = item.first->getNumericalID();
944 item.second.first->addSuccessor(tracks[index]);
945 item.second.first->addSuccessor(tracks[index + numEdges]);
947 tracks[index]->addSuccessor(item.second.second);
948 tracks[index + numEdges]->addSuccessor(item.second.second);
964 int numDisconnected = 0;
965 std::set<std::shared_ptr<NBPTStop>> addBidiStops;
966 std::set<NBEdge*, ComparatorIdLess> addBidiStopEdges;
967 std::set<NBEdge*, ComparatorIdLess> addBidiEdges;
968 std::set<std::pair<std::string, std::string> > visited;
975 for (
const auto& item : lc.
getLines()) {
977 std::vector<NBPTLine::PTStopInfo> stops = line->
getStopEdges(ec);
978 std::vector<NBEdge*> stopEdges;
979 for (
auto it : stops) {
980 stopEdges.push_back(it.edge);
984 if (routeStart !=
nullptr && (stopEdges.empty() || routeStart != stopEdges.front())) {
987 if (routeEnd !=
nullptr && (stopEdges.empty() || routeEnd != stopEdges.back())) {
990 if (stops.size() < 2) {
993 if (!line->
isConsistent(stopEdges) && requireBidi.count(line) == 0) {
994 WRITE_WARNINGF(
TL(
"Edge sequence is not consistent with stop sequence in line '%', not adding bidi edges."), item.first);
997 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
998 NBEdge* fromEdge = it->edge;
999 NBEdge* toEdge = (it + 1)->edge;
1000 const std::string fromStop = it->stopID;
1001 const std::string toStop = (it + 1)->stopID;
1002 const double fromPos = it->pos;
1003 const double toPos = (it + 1)->pos;
1004 bool fromRevised = it->revised;
1005 bool toRevised = (it + 1)->revised;
1006 std::pair<std::string, std::string> trip(fromStop, toStop);
1007 std::pair<std::string, std::string> reverseTrip(toStop, fromStop);
1011 if (visited.count(trip) != 0) {
1014 visited.insert(trip);
1016 if (stopTracks.count(fromEdge) == 0
1017 || stopTracks.count(toEdge) == 0) {
1020 bool needBidi = visited.count(reverseTrip) != 0;
1022 std::vector<const Track*> route;
1023 Track* from = fromRevised ? tracks[fromEdge->
getNumericalID()] : stopTracks[fromEdge].first;
1025 int iStart = fromRevised ? 0 : 1;
1026 int iDeltaEnd = toRevised ? 0 : 1;
1027 if (fromEdge == toEdge && fromPos > toPos) {
1034 router->
compute(from, to, &veh, 0, route);
1039 if (route.size() > 0) {
1040 assert((
int)route.size() > iStart + iDeltaEnd);
1041 for (
int i = iStart; i < (int)route.size() - iDeltaEnd; ++i) {
1042 const bool isBidi = route[i]->getNumericalID() >= numEdges;
1043 bool isStop = i == iStart || i == (int)route.size() - 1 - iDeltaEnd;
1044 if (isBidi || needBidi) {
1045 NBEdge* edge = route[i]->edge;
1046 if (addBidiEdges.count(edge) == 0) {
1049 addBidiEdges.insert(edge);
1051 addBidiStopEdges.insert(edge);
1055 WRITE_WARNINGF(
TL(
"Stop on edge '%' can only be reached in reverse but edge has the wrong spreadType."), fromEdge->
getID());
1061 if (isStop && isBidi) {
1062 std::shared_ptr<NBPTStop> fs = sc.
get(fromStop);
1064 addBidiStops.insert(fs);
1066 std::shared_ptr<NBPTStop> ts = sc.
get(toStop);
1068 addBidiStops.insert(ts);
1078 for (
NBEdge* edge : addBidiEdges) {
1079 if (!edge->isBidiRail()) {
1080 if (edge->getFromNode()->getIncomingEdges().size() == 0
1081 && edge->getToNode()->getOutgoingEdges().size() == 0) {
1087 if (e2 !=
nullptr) {
1097 for (std::shared_ptr<NBPTStop> stop : addBidiStops) {
1098 std::shared_ptr<NBPTStop> fromReverse = sc.
getReverseStop(stop, ec);
1101 stop->setBidiStop(fromReverse);
1104 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
1105 WRITE_MESSAGE(
"Added " +
toString(addBidiStopEdges.size()) +
" bidi-edges for public transport stops and a total of "
1106 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
1107 +
toString(numDisconnected) +
" stops remain disconnected)");
1111 for (
Track* t : tracks) {
1115 return (
int)addBidiEdges.size();
1123 for (
const auto& e : ec) {
1124 if (!
hasRailway(e.second->getPermissions())) {
1127 NBNode*
const from = e.second->getFromNode();
1128 NBNode*
const to = e.second->getToNode();
1129 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
1132 if (e.second->isBidiRail()) {
1135 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
1140 bool haveStraight =
false;
1141 bool haveStraightReverse =
false;
1142 if (!geometryLike || outRailFrom.size() + inRailFrom.size() == 2) {
1143 for (
const NBEdge* fromStraightCand : outRailFrom) {
1144 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1145 haveStraightReverse =
true;
1150 if (haveStraightReverse) {
1151 for (
const NBEdge* fromStraightCand : inRailFrom) {
1152 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1153 haveStraight =
true;
1160 if ((!haveStraightReverse || haveStraight) && (!geometryLike || outRailTo.size() + inRailTo.size() == 2)) {
1163 haveStraight =
false;
1164 haveStraightReverse =
false;
1165 for (
const NBEdge* toStraightCand : inRailTo) {
1166 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1167 haveStraightReverse =
true;
1172 if (haveStraightReverse) {
1173 for (
const NBEdge* toStraightCand : outRailTo) {
1174 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1175 haveStraight =
true;
1183 if (haveStraightReverse && !haveStraight) {
1186 if (e2 !=
nullptr) {
1195 WRITE_MESSAGEF(
TL(
"Added % bidi-edges to ensure connectivity of straight tracks at geometry-like nodes."),
toString(added));
1221 if (
isRailway(p) && (p & vClasses) != 0) {
1222 if (edge->getRoutingType() ==
"") {
1223 edge->setPriority(-1);
1227 for (
const auto& item : lc.
getLines()) {
1228 if ((item.second->getVClass() & vClasses) == 0) {
1231 for (
NBEdge* edge : item.second->getEdges()) {
1232 if (edge->getRoutingType() ==
"") {
1233 edge->setPriority(4);
1234 edge->setRoutingType(
"4");
1258 std::set<NBEdge*, ComparatorIdLess> bidi;
1263 if (!edge->isBidiRail()) {
1264 edge->setPriority(4);
1265 edge->setRoutingType(
"4");
1271 if (edge->getPriority() >= 0) {
1280 if (uni.size() == 0) {
1281 if (bidi.size() != 0) {
1282 WRITE_WARNING(
TL(
"Cannot extend track direction priority because there are no track edges with positive priority"));
1289 while (!check.empty()) {
1290 NBEdge* edge = *check.begin();
1292 if (seen.count(edge) != 0) {
1298 forward.insert(straightOut);
1299 check.insert(straightOut);
1303 forward.insert(straightIn);
1304 check.insert(straightIn);
1306#ifdef DEBUG_DIRECTION_PRIORITY
1314 for (
NBEdge* edge : bidi) {
1315 NBEdge* bidiEdge =
const_cast<NBEdge*
>(edge->getBidiEdge());
1318 if (forward.count(edge) != 0) {
1319 if (forward.count(bidiEdge) == 0) {
1328 if (forward.count(bidiEdge) != 0) {
1337 if (bidiEdge ==
nullptr) {
1338 WRITE_WARNINGF(
TL(
"Edge '%' was loaded with undefined priority (%) but has unambiguous main direction (no bidi edge)"), edge->getID(), edge->getPriority());
1340 if (edge->getPriority() >= 0) {
1343 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() >= 0) {
1346 if (edge->getPriority() < 0) {
1347 edge->setPriority(prio);
1348 edge->setRoutingType(
toString(prio));
1350 if (bidiEdge !=
nullptr && bidiEdge->
getPriority() < 0) {
1355 std::map<int, int> numPrios;
1356 for (
NBEdge* edge : bidi) {
1357 numPrios[edge->getPriority()]++;
1373 int addedSignals = 0;
1374 if (oc.
exists(
"railway.signal.guess.by-stops")) {
1375 if (oc.
getBool(
"railway.signal.guess.by-stops")) {
1376 const double minLength = oc.
getFloat(
"osm.stop-output.length.train");
1377 addedSignals += guessByStops(ec, sc, minLength);
1380 return addedSignals;
1391 int addedSignals = 0;
1396 if (canBeSignal(to)) {
1403 if (canBeSignal(from)) {
1411 if (in->getFromNode() != stopEdge->
getToNode()) {
1425 if (searchDist <= 0 && canBeSignal(from)) {
1433 return addedSignals;
1440 int numCorridors = 0;
1442 std::set<NBNode*> railGeomNodes;
1443 for (
NBNode* n : railNodes) {
1444 if (n->geometryLike()) {
1445 railGeomNodes.insert(n);
1448 std::set<NBNode*, ComparatorIdLess> kinkNodes;;
1449 for (
NBNode* n : railGeomNodes) {
1451 NBEdge* out = n->getOutgoingEdges().size() == 1 || n->getOutgoingEdges()[1]->
isTurningDirectionAt(in) ? n->getOutgoingEdges().front() : n->getOutgoingEdges().back();
1453 if (maxAngle > 0 && relAngle > maxAngle) {
1454 kinkNodes.insert(n);
1457 while (!kinkNodes.empty()) {
1458 std::vector<NBNode*> corridor;
1459 std::vector<NBEdge*> corridorEdges;
1462 NBNode* n = *kinkNodes.begin();
1463 kinkNodes.erase(kinkNodes.begin());
1468 NBEdge*
const centerIn = in;
1469 NBEdge*
const centerOut = out;
1472 corridor.push_back(up);
1473 corridor.push_back(n);
1474 corridor.push_back(down);
1477 corridorEdges.push_back(in);
1478 corridorEdges.push_back(out);
1482 while (kinkNodes.count(up) != 0) {
1487 corridor.insert(corridor.begin(), up);
1488 corridorEdges.insert(corridorEdges.begin(), in2);
1489 kinkNodes.erase(up);
1494 delta = cEnd - cBeg;
1495 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(up) != 0) {
1500 corridor.insert(corridor.begin(), up);
1501 corridorEdges.insert(corridorEdges.begin(), in2);
1502 kinkNodes.erase(up);
1506 delta = cEnd - cBeg;
1510 while (kinkNodes.count(down) != 0) {
1515 corridor.push_back(down);
1516 corridorEdges.push_back(out2);
1517 kinkNodes.erase(down);
1522 delta = cEnd - cBeg;
1523 while (delta.
length2D() <= POSITION_EPS * (
double)corridor.size() && railGeomNodes.count(down) != 0) {
1528 corridor.push_back(down);
1529 corridorEdges.push_back(out2);
1530 kinkNodes.erase(down);
1534 delta = cEnd - cBeg;
1537 std::set<NBNode*> corridorNodes(corridor.begin(), corridor.end());
1538 for (
NBNode* n2 : corridorNodes) {
1539 for (
NBEdge* e : n2->getEdges()) {
1540 if (corridorNodes.count(e->getFromNode()) != 0
1541 && corridorNodes.count(e->getToNode()) != 0) {
1543 simpleGeom.push_back(e->getFromNode()->getPosition());
1544 simpleGeom.push_back(e->getToNode()->getPosition());
1545 e->setGeometry(simpleGeom);
1550 double currLength = 0;
1551 for (
int i = 1; i < (int)corridor.size() - 1; i++) {
1552 currLength += corridorEdges[i - 1]->getLoadedLength();
1553 const Position newPos = cBeg + delta * (currLength / length);
1554 NBNode*
const n2 = corridor[i];
1555 n2->
reinit(newPos, n2->getType());
1556 for (
NBEdge* e : n2->getEdges()) {
1557 e->resetEndpointAtNode(n2);
1568 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.
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)
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.
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 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 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 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