42 #define DEBUGNODEID "gneJ34"
43 #define DEBUGNODEID2 "28842974"
44 #define DEBUGEDGEID "22820560#0"
45 #define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
47 #define SHARP_THRESHOLD_SAMEDIR 100
48 #define SHARP_THRESHOLD 80
65 const std::vector<NBRailwayTopologyAnalyzer::Track*>&
67 if ((minPermissions & svc) != 0) {
70 if (svcSuccessors.count(svc) == 0) {
71 std::vector<Track*> succ;
72 for (
Track* t : successors) {
73 if ((t->edge->getPermissions() & svc) != 0) {
77 svcSuccessors[svc] = succ;
79 return svcSuccessors[svc];
83 const std::vector<std::pair<const NBRailwayTopologyAnalyzer::Track*, const NBRailwayTopologyAnalyzer::Track*> >&
85 if ((minPermissions & svc) != 0) {
88 if (svcViaSuccessors.count(svc) == 0) {
89 std::vector<std::pair<const Track*, const Track*> >& succ = svcViaSuccessors[svc];
90 for (
const Track*
const t : successors) {
91 if ((t->edge->getPermissions() & svc) != 0) {
92 succ.push_back(std::make_pair(t,
nullptr));
96 return svcViaSuccessors[svc];
126 int numRailEdges = 0;
127 int numBidiEdges = 0;
128 int numNotCenterEdges = 0;
129 int numAddedBidiEdges = 0;
134 edge->invalidateConnections(
true);
135 if (!edge->isBidiRail()) {
149 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiEdges) +
" bidi-edges to ensure that all tracks are usable in both directions.");
150 if (numNotCenterEdges) {
151 WRITE_WARNING(
"Ignore " +
toString(numNotCenterEdges) +
" edges because they have the wrong spreadType");
159 const std::string id2 = (edge->
getID()[0] ==
'-'
160 ? edge->
getID().substr(1)
161 :
"-" + edge->
getID());
183 inEdges.push_back(e);
188 outEdges.push_back(e);
197 std::set<NBNode*> brokenNodes;
203 std::set<NBNode*> railNodes =
getRailNodes(nb, verbose);
204 std::map<std::pair<int, int>, std::set<NBNode*, ComparatorIdLess> > types;
205 std::set<NBEdge*, ComparatorIdLess> bidiEdges;
206 std::set<NBEdge*, ComparatorIdLess> bufferStops;
207 for (
NBNode* node : railNodes) {
210 types[std::make_pair((
int)inEdges.size(), (
int)outEdges.size())].insert(node);
211 for (
NBEdge* e : outEdges) {
212 if (e->isBidiRail() && bidiEdges.count(e->getTurnDestination(
true)) == 0) {
215 if (e->getID()[0] ==
'-') {
216 std::swap(primary, secondary);
217 }
else if (primary->
getID()[0] !=
'-' && secondary->
getID()[0] !=
'-' && secondary->
getID() < primary->
getID()) {
218 std::swap(primary, secondary);
220 if (bidiEdges.count(secondary) == 0) {
222 bidiEdges.insert(primary);
232 int numBufferStops = 0;
233 if (verbose && types.size() > 0) {
234 WRITE_MESSAGE(
"Railway nodes by number of incoming,outgoing edges:")
239 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are outgoing");
243 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are incoming");
247 device.
writeAttr(
"meaning",
"an incoming edge has a sharp angle to all outgoing edges");
251 device.
writeAttr(
"meaning",
"an outgoing edge has a sharp angle from all incoming edges");
255 for (
auto it : types) {
256 int numBrokenType = 0;
257 device.
openTag(
"railNodeType");
258 int in = it.first.first;
259 int out = it.first.second;
262 for (
NBNode* n : it.second) {
270 std::string broken =
"";
280 for (
NBEdge* e : inRail) {
291 for (
NBEdge* e : outRail) {
302 if (((in == 1 && out == 1) || (in == 2 && out == 2))
307 if (broken.size() > 0) {
309 brokenNodes.insert(n);
321 +
" count: " +
toString(it.second.size()) +
" broken: " +
toString(numBrokenType));
335 for (
NBEdge* e : bidiEdges) {
338 device.
writeAttr(
"bidi", e->getTurnDestination(
true)->getID());
352 std::set<NBNode*> railNodes;
355 int numRailEdges = 0;
356 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
357 if (
isRailway(it->second->getPermissions())) {
359 railNodes.
insert(it->second->getFromNode());
360 railNodes.insert(it->second->getToNode());
364 std::set<NBNode*> railSignals;
365 for (
NBNode* node : railNodes) {
367 railSignals.insert(node);
403 #ifdef DEBUG_SEQSTOREVERSE
408 for (
NBEdge* e1 : edges) {
409 for (
NBEdge* e2 : edges2) {
429 if (e != candOut &&
isStraight(node, e, candOut)) {
431 std::cout <<
" isStraight e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
437 if (e != candOut && !
isStraight(node, e, candOut)) {
439 std::cout <<
" isSharp e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
456 if (!e1->isBidiRail(
true)) {
462 return !
allBidi || countBidiAsSharp;
469 if (!e->isBidiRail()) {
482 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
500 if (bidiOut ==
nullptr) {
505 tmpBidiOut.push_back(bidiOut);
507 tmpBidiIn.push_back(bidiIn);
511 for (
NBEdge* cand : outRail) {
513 if (!cand->isBidiRail() &&
isStraight(node, bidiIn, cand)
515 &&
allSharp(node, inRail, tmpBidiOut,
true)) {
522 for (
NBEdge* cand : inRail) {
524 if (!cand->isBidiRail() &&
isStraight(node, cand, bidiOut)
526 &&
allSharp(node, outRail, tmpBidiIn,
true)) {
541 std::vector<EdgeVector> seqsToReverse;
542 for (
NBNode* n : brokenNodes) {
545 for (
NBEdge* start : outRail) {
547 tmp.push_back(start);
549 if (!
allBroken(n, start, inRail, outRail)
550 || (inRail.size() == 1 && outRail.size() == 1)) {
551 #ifdef DEBUG_SEQSTOREVERSE
553 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
562 seq.push_back(start);
564 NBNode* n2 = start->getToNode();
567 if (brokenNodes.count(n2) != 0) {
569 tmp2.push_back(start);
570 if (
allBroken(n2, start, outRail2, inRail2)) {
571 seqsToReverse.push_back(seq);
573 #ifdef DEBUG_SEQSTOREVERSE
575 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
581 if (outRail2.size() == 0) {
584 #ifdef DEBUG_SEQSTOREVERSE
586 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
589 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
592 #ifdef DEBUG_SEQSTOREVERSE
594 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
598 start = outRail2.front();
605 if (seqsToReverse.size() > 0) {
606 WRITE_MESSAGE(
"Found " +
toString(seqsToReverse.size()) +
" reversible edge sequences between broken rail nodes");
608 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
610 return a.size() < b.size();
613 std::set<NBNode*> affectedEndpoints;
614 std::set<std::string> reversedIDs;
615 std::map<int, int> seqLengths;
617 NBNode* seqStart = seq.front()->getFromNode();
618 NBNode* seqEnd = seq.back()->getToNode();
620 if (affectedEndpoints.count(seqStart) == 0
621 && affectedEndpoints.count(seqEnd) == 0) {
622 affectedEndpoints.insert(seqStart);
623 affectedEndpoints.insert(seqEnd);
626 e->reinitNodes(e->getToNode(), e->getFromNode());
627 e->setGeometry(e->getGeometry().reverse());
628 reversedIDs.insert(e->getID());
630 seqLengths[(int)seq.size()]++;
634 if (numReversed > 0) {
637 if (reversedIDs.count(item.second->getEdgeId())) {
638 item.second->findLaneAndComputeBusStopExtent(nb.
getEdgeCont());
650 int numBufferStops = 0;
651 int numAddedBidiTotal = 0;
652 for (
NBNode* node : railNodes) {
654 if (node->getEdges().size() != 1) {
655 WRITE_WARNING(
"Ignoring buffer stop junction '" + node->getID() +
"' with " +
toString(node->getEdges().size()) +
" edges\n");
658 int numAddedBidi = 0;
665 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
667 if (prev ==
nullptr) {
668 assert(node->getEdges().size() == 1);
669 e = node->getEdges().front();
674 assert(inRail.size() == 2);
675 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
678 assert(outRail.size() == 2);
679 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
711 if (numAddedBidiTotal > 0) {
712 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiTotal) +
" edges to connect " +
toString(numBufferStops) +
" buffer stops in both directions.");
720 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
721 if (
isStraight(n, inRail.front(), outRail.front())) {
722 return inRail.front();
723 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
724 return inRail.back();
727 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
728 if (
isStraight(n, outRail.front(), inRail.front())) {
729 return outRail.front();
730 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
731 return outRail.back();
741 std::map<int, int> seqLengths;
744 for (
NBNode* n : brokenNodes) {
746 if (edge !=
nullptr) {
747 std::vector<NBNode*> nodeSeq;
750 nodeSeq.push_back(prev);
751 edgeSeq.push_back(edge);
759 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
761 edge = allRail.front() == edge ? allRail.back() : allRail.front();
762 nodeSeq.push_back(prev);
763 edgeSeq.push_back(edge);
772 for (
NBEdge* e : edgeSeq) {
775 seqLengths[(int)edgeSeq.size()]++;
777 numAdded += (int)edgeSeq.size();
791 if (seqLengths.size() > 0) {
801 std::vector<Track*> tracks;
803 tracks.push_back(
new Track(edge));
805 const int numEdges = (int)tracks.
size();
807 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse"));
810 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
813 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
814 tracks.push_back(start);
815 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
816 tracks.push_back(end);
817 stopTracks[edge] = std::make_pair(start, end);
824 for (
NBEdge* e1 : railEdges) {
825 for (
NBEdge* e2 : railEdges) {
827 int i = e1->getNumericalID();
828 int i2 = e2->getNumericalID();
829 if (e1->getToNode() == node) {
830 if (e2->getFromNode() == node) {
832 tracks[i]->addSuccessor(tracks[i2]);
834 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
837 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
838 tracks[i2]->addSuccessor(tracks[i + numEdges]);
841 if (e2->getFromNode() == node) {
843 tracks[i + numEdges]->addSuccessor(tracks[i2]);
844 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
855 for (
auto& item : stopTracks) {
856 const int index = item.first->getNumericalID();
858 item.second.first->addSuccessor(tracks[index]);
859 item.second.first->addSuccessor(tracks[index + numEdges]);
861 tracks[index]->addSuccessor(item.second.second);
862 tracks[index + numEdges]->addSuccessor(item.second.second);
878 int numDisconnected = 0;
879 std::set<NBEdge*> addBidiStops;
880 std::set<NBEdge*> addBidiEdges;
881 std::set<std::pair<NBEdge*, NBEdge*> > visited;
887 if (routeStart !=
nullptr) {
888 stops.insert(stops.begin(), routeStart);
890 if (routeEnd !=
nullptr) {
891 stops.push_back(routeEnd);
893 if (stops.size() < 2) {
896 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
898 NBEdge* toEdge = *(it + 1);
899 std::pair<NBEdge*, NBEdge*> trip(fromEdge, toEdge);
901 if (visited.count(trip) != 0) {
904 visited.insert(trip);
906 if (stopTracks.count(fromEdge) == 0
907 || stopTracks.count(toEdge) == 0) {
911 std::vector<const Track*> route;
912 router->
compute(stopTracks[fromEdge].first, stopTracks[toEdge].second, &veh, 0, route);
916 if (route.size() > 0) {
917 assert(route.size() > 2);
918 for (
int i = 1; i < (int)route.size() - 1; ++i) {
919 if (route[i]->getNumericalID() >= numEdges) {
920 NBEdge* edge = route[i]->edge;
921 if (addBidiEdges.count(edge) == 0) {
923 bool isStop = i == 1 || i == (int)route.size() - 2;
925 addBidiEdges.insert(edge);
927 addBidiStops.insert(edge);
931 WRITE_WARNING(
"Stop on edge " + fromEdge->
getID() +
" can only be reached in reverse but edge has the wrong spreadType");
939 WRITE_WARNING(
"No connection found between stops on edge '" + fromEdge->
getID() +
"' and edge '" + toEdge->
getID() +
"'");
944 for (
NBEdge* edge : addBidiEdges) {
945 if (!edge->isBidiRail()) {
956 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
957 WRITE_MESSAGE(
"Added " +
toString(addBidiStops.size()) +
" bidi-edges for public transport stops and a total of "
958 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
959 +
toString(numDisconnected) +
" stops remain disconnected)");
963 for (
Track* t : tracks) {
975 if (!
isRailway(e.second->getPermissions())) {
978 NBNode*
const from = e.second->getFromNode();
979 NBNode*
const to = e.second->getToNode();
980 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
983 if (e.second->isBidiRail()) {
986 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
991 bool haveStraight =
false;
992 bool haveStraightReverse =
false;
993 if (!geometryLike || outRailFrom.size() + inRailFrom.size() == 2) {
994 for (
const NBEdge* fromStraightCand : outRailFrom) {
995 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
996 haveStraightReverse =
true;
1001 if (haveStraightReverse) {
1002 for (
const NBEdge* fromStraightCand : inRailFrom) {
1003 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
1004 haveStraight =
true;
1011 if ((!haveStraightReverse || haveStraight) && (!geometryLike || outRailTo.size() + inRailTo.size() == 2)) {
1014 haveStraight =
false;
1015 haveStraightReverse =
false;
1016 for (
const NBEdge* toStraightCand : inRailTo) {
1017 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1018 haveStraightReverse =
true;
1023 if (haveStraightReverse) {
1024 for (
const NBEdge* toStraightCand : outRailTo) {
1025 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1026 haveStraight =
true;
1034 if (haveStraightReverse && !haveStraight) {
1037 if (e2 !=
nullptr) {
1046 WRITE_MESSAGE(
"Added " +
toString(added) +
" bidi-edges to ensure connectivity of straight tracks at geometry-like nodes.");
1048 WRITE_MESSAGE(
"Added " +
toString(added) +
" bidi-edges to ensure connectivity of straight tracks at switches.");