43 #define DEBUGNODEID "gneJ34"
44 #define DEBUGNODEID2 "28842974"
45 #define DEBUGEDGEID "22820560#0"
46 #define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
48 #define SHARP_THRESHOLD_SAMEDIR 100
49 #define SHARP_THRESHOLD 80
66 const std::vector<NBRailwayTopologyAnalyzer::Track*>&
68 if ((minPermissions & svc) != 0) {
71 if (svcSuccessors.count(svc) == 0) {
72 std::vector<Track*> succ;
73 for (
Track* t : successors) {
74 if ((t->edge->getPermissions() & svc) != 0) {
78 svcSuccessors[svc] = succ;
80 return svcSuccessors[svc];
84 const std::vector<std::pair<const NBRailwayTopologyAnalyzer::Track*, const NBRailwayTopologyAnalyzer::Track*> >&
86 if ((minPermissions & svc) != 0) {
89 if (svcViaSuccessors.count(svc) == 0) {
90 std::vector<std::pair<const Track*, const Track*> >& succ = svcViaSuccessors[svc];
91 for (
const Track*
const t : successors) {
92 if ((t->edge->getPermissions() & svc) != 0) {
93 succ.push_back(std::make_pair(t,
nullptr));
97 return svcViaSuccessors[svc];
125 int numRailEdges = 0;
126 int numBidiEdges = 0;
127 int numNotCenterEdges = 0;
128 int numAddedBidiEdges = 0;
133 edge->invalidateConnections(
true);
134 if (!edge->isBidiRail()) {
148 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiEdges) +
" bidi-edges to ensure that all tracks are usable in both directions.");
149 if (numNotCenterEdges) {
150 WRITE_WARNING(
"Ignore " +
toString(numNotCenterEdges) +
" edges because they have the wrong spreadType");
158 const std::string id2 = (edge->
getID()[0] ==
'-'
159 ? edge->
getID().substr(1)
160 :
"-" + edge->
getID());
182 inEdges.push_back(e);
187 outEdges.push_back(e);
196 std::set<NBNode*> brokenNodes;;
202 std::set<NBNode*> railNodes =
getRailNodes(nb, verbose);
203 std::map<std::pair<int, int>, std::set<NBNode*, ComparatorIdLess> > types;
204 std::set<NBEdge*, ComparatorIdLess> bidiEdges;
205 std::set<NBEdge*, ComparatorIdLess> bufferStops;
206 for (
NBNode* node : railNodes) {
209 types[std::make_pair((
int)inEdges.size(), (int)outEdges.size())].insert(node);
210 for (
NBEdge* e : outEdges) {
211 if (e->isBidiRail() && bidiEdges.count(e->getTurnDestination(
true)) == 0) {
214 if (e->getID()[0] ==
'-') {
215 std::swap(primary, secondary);
216 }
else if (primary->
getID()[0] !=
'-' && secondary->
getID()[0] !=
'-' && secondary->
getID() < primary->
getID()) {
217 std::swap(primary, secondary);
219 if (bidiEdges.count(secondary) == 0) {
221 bidiEdges.insert(primary);
231 int numBufferStops = 0;
232 if (verbose && types.size() > 0) {
233 WRITE_MESSAGE(
"Railway nodes by number of incoming,outgoing edges:")
238 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are outgoing");
242 device.
writeAttr(
"meaning",
"edge pair angle supports driving but both are incoming");
246 device.
writeAttr(
"meaning",
"an incoming edge has a sharp angle to all outgoing edges");
250 device.
writeAttr(
"meaning",
"an outgoing edge has a sharp angle from all incoming edges");
254 for (
auto it : types) {
255 int numBrokenType = 0;
256 device.
openTag(
"railNodeType");
257 int in = it.first.first;
258 int out = it.first.second;
261 for (
NBNode* n : it.second) {
269 std::string broken =
"";
279 for (
NBEdge* e : inRail) {
290 for (
NBEdge* e : outRail) {
301 if (((in == 1 && out == 1) || (in == 2 && out == 2))
306 if (broken.size() > 0) {
308 brokenNodes.insert(n);
320 +
" count: " +
toString(it.second.size()) +
" broken: " +
toString(numBrokenType));
334 for (
NBEdge* e : bidiEdges) {
337 device.
writeAttr(
"bidi", e->getTurnDestination(
true)->getID());
351 std::set<NBNode*> railNodes;
354 int numRailEdges = 0;
355 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
356 if (
isRailway(it->second->getPermissions())) {
358 railNodes.
insert(it->second->getFromNode());
359 railNodes.insert(it->second->getToNode());
363 std::set<NBNode*> railSignals;
364 for (
NBNode* node : railNodes) {
366 railSignals.insert(node);
402 #ifdef DEBUG_SEQSTOREVERSE
407 for (
NBEdge* e1 : edges) {
408 for (
NBEdge* e2 : edges2) {
428 if (e != candOut &&
isStraight(node, e, candOut)) {
430 std::cout <<
" isStraight e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
436 if (e != candOut && !
isStraight(node, e, candOut)) {
438 std::cout <<
" isSharp e=" << e->getID() <<
" candOut=" << candOut->
getID() <<
"\n";
455 if (!e1->isBidiRail(
true)) {
461 return !
allBidi || countBidiAsSharp;
468 if (!e->isBidiRail()) {
481 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
499 if (bidiOut ==
nullptr) {
504 tmpBidiOut.push_back(bidiOut);
506 tmpBidiIn.push_back(bidiIn);
510 for (
NBEdge* cand : outRail) {
512 if (!cand->isBidiRail() &&
isStraight(node, bidiIn, cand)
514 &&
allSharp(node, inRail, tmpBidiOut,
true)) {
521 for (
NBEdge* cand : inRail) {
523 if (!cand->isBidiRail() &&
isStraight(node, cand, bidiOut)
525 &&
allSharp(node, outRail, tmpBidiIn,
true)) {
540 std::vector<EdgeVector> seqsToReverse;
541 for (
NBNode* n : brokenNodes) {
544 for (
NBEdge* start : outRail) {
546 tmp.push_back(start);
548 if (!
allBroken(n, start, inRail, outRail)
549 || (inRail.size() == 1 && outRail.size() == 1)) {
550 #ifdef DEBUG_SEQSTOREVERSE
552 std::cout <<
" abort at start n=" << n->getID() <<
" (not all broken)\n";
561 seq.push_back(start);
563 NBNode* n2 = start->getToNode();
566 if (brokenNodes.count(n2) != 0) {
568 tmp2.push_back(start);
569 if (
allBroken(n2, start, outRail2, inRail2)) {
570 seqsToReverse.push_back(seq);
572 #ifdef DEBUG_SEQSTOREVERSE
574 std::cout <<
" abort at n2=" << n2->
getID() <<
" (not all broken)\n";
580 if (outRail2.size() == 0) {
583 #ifdef DEBUG_SEQSTOREVERSE
585 std::cout <<
" abort at n2=" << n2->
getID() <<
" (border)\n";
588 }
else if (outRail2.size() > 1 || inRail2.size() > 1) {
591 #ifdef DEBUG_SEQSTOREVERSE
593 std::cout <<
" abort at n2=" << n2->
getID() <<
" (switch)\n";
597 start = outRail2.front();
604 if (seqsToReverse.size() > 0) {
605 WRITE_MESSAGE(
"Found " +
toString(seqsToReverse.size()) +
" reversible edge sequences between broken rail nodes");
607 std::sort(seqsToReverse.begin(), seqsToReverse.end(),
609 return a.size() < b.size();
612 std::set<NBNode*> affectedEndpoints;
613 std::set<std::string> reversedIDs;
614 std::map<int, int> seqLengths;
616 NBNode* seqStart = seq.front()->getFromNode();
617 NBNode* seqEnd = seq.back()->getToNode();
619 if (affectedEndpoints.count(seqStart) == 0
620 && affectedEndpoints.count(seqEnd) == 0) {
621 affectedEndpoints.insert(seqStart);
622 affectedEndpoints.insert(seqEnd);
625 e->reinitNodes(e->getToNode(), e->getFromNode());
626 e->setGeometry(e->getGeometry().reverse());
627 reversedIDs.insert(e->getID());
629 seqLengths[(int)seq.size()]++;
633 if (numReversed > 0) {
636 if (reversedIDs.count(item.second->getEdgeId())) {
637 item.second->findLaneAndComputeBusStopExtent(nb.
getEdgeCont());
649 int numBufferStops = 0;
650 int numAddedBidiTotal = 0;
651 for (
NBNode* node : railNodes) {
653 if (node->getEdges().size() != 1) {
654 WRITE_WARNING(
"Ignoring buffer stop junction '" + node->getID() +
"' with " +
toString(node->getEdges().size()) +
" edges\n");
657 int numAddedBidi = 0;
664 while (prev ==
nullptr || (inRail.size() + outRail.size()) == 3) {
666 if (prev ==
nullptr) {
667 assert(node->getEdges().size() == 1);
668 e = node->getEdges().front();
673 assert(inRail.size() == 2);
674 e = inRail.front() == prev2 ? inRail.back() : inRail.front();
677 assert(outRail.size() == 2);
678 e = outRail.front() == prev2 ? outRail.back() : outRail.front();
710 if (numAddedBidiTotal > 0) {
711 WRITE_MESSAGE(
"Added " +
toString(numAddedBidiTotal) +
" edges to connect " +
toString(numBufferStops) +
" buffer stops in both directions.");
719 if (inRail.size() == 2 && outRail.size() == 1 &&
isStraight(n, inRail.front(), inRail.back())) {
720 if (
isStraight(n, inRail.front(), outRail.front())) {
721 return inRail.front();
722 }
else if (
isStraight(n, inRail.back(), outRail.front())) {
723 return inRail.back();
726 if (inRail.size() == 1 && outRail.size() == 2 &&
isStraight(n, outRail.front(), outRail.back())) {
727 if (
isStraight(n, outRail.front(), inRail.front())) {
728 return outRail.front();
729 }
else if (
isStraight(n, outRail.back(), inRail.front())) {
730 return outRail.back();
740 std::map<int, int> seqLengths;
743 for (
NBNode* n : brokenNodes) {
745 if (edge !=
nullptr) {
746 std::vector<NBNode*> nodeSeq;
749 nodeSeq.push_back(prev);
750 edgeSeq.push_back(edge);
758 if (allRail.size() == 2 &&
isStraight(next, allRail.front(), allRail.back())) {
760 edge = allRail.front() == edge ? allRail.back() : allRail.front();
761 nodeSeq.push_back(prev);
762 edgeSeq.push_back(edge);
771 for (
NBEdge* e : edgeSeq) {
774 seqLengths[(int)edgeSeq.size()]++;
776 numAdded += (int)edgeSeq.size();
790 if (seqLengths.size() > 0) {
800 std::vector<Track*> tracks;
802 tracks.push_back(
new Track(edge));
804 const int numEdges = (int)tracks.
size();
806 tracks.push_back(
new Track(edge, (
int)tracks.size(), edge->getID() +
"_reverse"));
809 std::map<NBEdge*, std::pair<Track*, Track*> > stopTracks;
812 Track* start =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_start");
813 tracks.push_back(start);
814 Track* end =
new Track(edge, (
int)tracks.size(), edge->getID() +
"_end");
815 tracks.push_back(end);
816 stopTracks[edge] = std::make_pair(start, end);
823 for (
NBEdge* e1 : railEdges) {
824 for (
NBEdge* e2 : railEdges) {
826 int i = e1->getNumericalID();
827 int i2 = e2->getNumericalID();
828 if (e1->getToNode() == node) {
829 if (e2->getFromNode() == node) {
831 tracks[i]->addSuccessor(tracks[i2]);
833 tracks[i2 + numEdges]->addSuccessor(tracks[i + numEdges]);
836 tracks[i]->addSuccessor(tracks[i2 + numEdges]);
837 tracks[i2]->addSuccessor(tracks[i + numEdges]);
840 if (e2->getFromNode() == node) {
842 tracks[i + numEdges]->addSuccessor(tracks[i2]);
843 tracks[i2 + numEdges]->addSuccessor(tracks[i]);
854 for (
auto& item : stopTracks) {
855 const int index = item.first->getNumericalID();
857 item.second.first->addSuccessor(tracks[index]);
858 item.second.first->addSuccessor(tracks[index + numEdges]);
860 tracks[index]->addSuccessor(item.second.second);
861 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<NBPTStop*, NBPTStop*> > visited;
884 std::vector<NBPTStop*> stops = line->
getStops();
885 if (stops.size() < 2) {
888 for (
auto it = stops.begin(); it + 1 != stops.end(); ++it) {
889 std::pair<NBPTStop*, NBPTStop*> trip(*it, *(it + 1));
890 if (visited.count(trip) != 0) {
893 visited.insert(trip);
897 if (fromEdge ==
nullptr || toEdge ==
nullptr) {
900 if (stopTracks.count(fromEdge) == 0
901 || stopTracks.count(toEdge) == 0) {
905 std::vector<const Track*> route;
906 router->
compute(stopTracks[fromEdge].first, stopTracks[toEdge].second, &veh, 0, route);
910 if (route.size() > 0) {
911 assert(route.size() > 2);
912 for (
int i = 1; i < (int)route.size() - 1; ++i) {
913 if (route[i]->getNumericalID() >= numEdges) {
914 NBEdge* edge = route[i]->edge;
915 if (addBidiEdges.count(edge) == 0) {
917 bool isStop = i == 1 || i == (int)route.size() - 2;
919 addBidiEdges.insert(edge);
921 addBidiStops.insert(edge);
925 WRITE_WARNING(
"Stop on edge " + fromEdge->
getID() +
" can only be reached in reverse but edge has the wrong spreadType");
933 WRITE_WARNING(
"No connection found between stops on edge '" + fromEdge->
getID() +
"' and edge '" + toEdge->
getID() +
"'");
938 for (
NBEdge* edge : addBidiEdges) {
939 if (!edge->isBidiRail()) {
950 if (addBidiEdges.size() > 0 || numDisconnected > 0) {
951 WRITE_MESSAGE(
"Added " +
toString(addBidiStops.size()) +
" bidi-edges for public transport stops and a total of "
952 +
toString(added) +
" bidi-edges to ensure connectivity of stops ("
953 +
toString(numDisconnected) +
" stops remain disconnected)");
957 for (
Track* t : tracks) {
969 if (!
isRailway(e.second->getPermissions())) {
972 NBNode*
const from = e.second->getFromNode();
973 NBNode*
const to = e.second->getToNode();
974 if (brokenNodes.count(from) == 0 && brokenNodes.count(to) == 0) {
977 EdgeVector inRailFrom, outRailFrom, inRailTo, outRailTo;
980 bool haveReverse =
false;
981 for (
const NBEdge* cand : outRailTo) {
982 if (cand->getToNode() == from) {
990 bool haveStraightFrom =
false;
991 for (
const NBEdge* fromStraightCand : outRailFrom) {
992 if (fromStraightCand != e.second &&
isStraight(from, fromStraightCand, e.second)) {
993 haveStraightFrom =
true;
997 if (!haveStraightFrom) {
1000 for (
const NBEdge* toStraightCand : inRailTo) {
1001 if (toStraightCand != e.second &&
isStraight(to, toStraightCand, e.second)) {
1004 if (e2 !=
nullptr) {
1014 WRITE_MESSAGE(
"Added " +
toString(added) +
" bidi-edges to ensure connectivity of straight tracks.");