60 #define MAX_SLIPLANE_LENGTH 1000
68 #define DEBUGNODEID "3513423881"
69 #define DEBUGNODEID2 ""
71 #define DEBUGCOND(obj) ((obj) != 0 && ((obj)->getID() == DEBUGNODEID || (obj)->getID() == DEBUGNODEID2))
92 NodeCont::iterator i =
myNodes.find(
id);
98 const float pos[2] = {(float)position.
x(), (float)position.
y()};
106 std::string
id = node->
getID();
107 NodeCont::iterator i =
myNodes.find(
id);
120 NodeCont::const_iterator i =
myNodes.find(
id);
130 const double extOffset = offset + POSITION_EPS;
131 const float cmin[2] = {(float)(position.
x() - extOffset), (
float)(position.
y() - extOffset)};
132 const float cmax[2] = {(float)(position.
x() + extOffset), (
float)(position.
y() + extOffset)};
133 std::set<const Named*> into;
136 for (
const Named* namedNode : into) {
180 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
181 no += (*i).second->removeSelfLoops(dc, ec, tc);
192 const double distanceThreshold = 7.;
193 const double lengthThreshold = 0.10;
195 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
197 std::map<NBNode*, EdgeVector> connectionCount;
198 const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
199 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
200 connectionCount[(*j)->getToNode()].push_back(*j);
203 std::map<NBNode*, EdgeVector>::iterator k;
204 for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
206 if ((*k).second.size() < 2) {
212 const NBEdge*
const first = ev.front();
213 EdgeVector::const_iterator jci;
214 for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
217 (relativeLengthDifference > lengthThreshold) ||
218 (fabs(first->
getSpeed() - (*jci)->getSpeed()) >= 0.01) ||
226 if (jci == ev.end()) {
237 const std::vector<std::string>& edgeNames = ec.
getAllNames();
238 for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
247 if (outgoingEdges.size() != 1) {
252 if (incomingEdges.size() > 1) {
255 }
else if (incomingEdges.size() == 1) {
256 NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
257 NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
258 if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
266 bool hasJunction =
false;
278 adjacentNodes.clear();
279 for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
280 if ((*itOfOutgoings)->getToNode() != from
281 && (*itOfOutgoings)->getToNode() != to
285 adjacentNodes.insert((*itOfOutgoings)->getToNode());
287 for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
288 adjacentNodes.insert((*itOfIncomings)->getFromNode());
290 adjacentNodes.erase(to);
291 if (adjacentNodes.size() > 2) {
294 }
while (!hasJunction && eOld != e);
296 std::string warningString;
297 for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
298 if (roadIt == road.begin()) {
299 warningString += (*roadIt)->
getID();
301 warningString +=
"," + (*roadIt)->getID();
304 NBNode* fromNode = (*roadIt)->getFromNode();
305 NBNode* toNode = (*roadIt)->getToNode();
306 ec.
erase(dc, *roadIt);
316 WRITE_WARNINGF(
"Removed a road without junctions: %.", warningString);
324 std::vector<std::set<NBEdge*> > components;
326 std::set<std::string> edgesLeft;
327 for (std::map<std::string, NBEdge*>::const_iterator edgeIt = ec.
begin(); edgeIt != ec.
end(); ++edgeIt) {
328 edgesLeft.insert(edgeIt->first);
331 std::set<NBEdge*> toRemove;
332 while (!edgesLeft.empty()) {
333 queue.push_back(ec.
getByID(*edgesLeft.begin()));
334 std::set<NBEdge*> component;
335 while (!queue.empty()) {
336 NBEdge*
const e = queue.back();
339 std::vector<EdgeVector> edgeLists;
344 for (std::vector<EdgeVector>::const_iterator listIt = edgeLists.begin(); listIt != edgeLists.end(); ++listIt) {
345 for (EdgeVector::const_iterator edgeIt = listIt->begin(); edgeIt != listIt->end(); ++edgeIt) {
346 std::set<std::string>::iterator leftIt = edgesLeft.find((*edgeIt)->getID());
347 if (leftIt != edgesLeft.end()) {
348 queue.push_back(*edgeIt);
349 edgesLeft.erase(leftIt);
354 std::vector<std::set<NBEdge*> >::iterator cIt;
355 for (cIt = components.begin(); cIt != components.end(); ++cIt) {
356 if (cIt->size() < component.size()) {
360 components.insert(cIt, component);
361 if ((
int)components.size() > numKeep) {
362 toRemove.insert(components.back().begin(), components.back().end());
363 components.pop_back();
366 for (std::set<NBEdge*>::iterator edgeIt = toRemove.begin(); edgeIt != toRemove.end(); ++edgeIt) {
367 NBNode*
const fromNode = (*edgeIt)->getFromNode();
368 NBNode*
const toNode = (*edgeIt)->getToNode();
369 ec.
erase(dc, *edgeIt);
384 bool removeGeometryNodes) {
386 std::set<std::string> edges2keep;
387 if (removeGeometryNodes) {
389 if (oc.
isSet(
"geometry.remove.keep-edges.input-file")) {
392 if (oc.
isSet(
"geometry.remove.keep-edges.explicit")) {
393 const std::vector<std::string> edges = oc.
getStringVector(
"geometry.remove.keep-edges.explicit");
394 edges2keep.insert(edges.begin(), edges.end());
401 std::vector<NBNode*> toRemove;
402 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
403 NBNode* current = (*i).second;
405 std::vector<std::pair<NBEdge*, NBEdge*> > toJoin;
412 if (removeGeometryNodes &&
mySplit.count(current) == 0) {
420 for (EdgeVector::const_iterator it_edge = current->
getEdges().begin(); it_edge != current->
getEdges().end(); ++it_edge) {
421 if (edges2keep.find((*it_edge)->getID()) != edges2keep.end()) {
435 for (std::vector<std::pair<NBEdge*, NBEdge*> >::iterator j = toJoin.begin(); j != toJoin.end(); j++) {
437 NBEdge* continuation = (*j).second;
438 begin->append(continuation);
441 ec.
extract(dc, continuation,
true);
443 toRemove.push_back(current);
447 for (std::vector<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
456 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
457 (*i).second->avoidOverlap();
464 std::set<NBNode*> visited;
465 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
466 std::vector<NodeAndDist> toProc;
467 if (visited.find((*i).second) != visited.end()) {
470 toProc.push_back(std::make_pair((*i).second, 0));
472 while (!toProc.empty()) {
474 NBNode* n = nodeAndDist.first;
475 double dist = nodeAndDist.second;
477 if (visited.find(n) != visited.end()) {
481 bool pureRail =
true;
482 bool railAndPeds =
true;
500 const double length = e->getLoadedLength();
501 #ifdef DEBUG_JOINJUNCTIONS
503 std::cout <<
"generateNodeClusters: consider s=" << s->
getID()
504 <<
" clusterNode=" << n->
getID() <<
" edge=" << e->getID() <<
" length=" << length <<
" with cluster " <<
joinNamedToString(c,
' ') <<
"\n";
508 bool railAndPeds2 =
true;
511 railAndPeds2 =
false;
522 const bool joinPedCrossings = bothCrossing && e->getPermissions() ==
SVC_PEDESTRIAN;
524 !joinPedCrossings && (
527 || (length > 3 * POSITION_EPS
536 bool foundRail =
false;
539 if ((e2->getPermissions() & railNoTram) != 0) {
552 if (visited.find(s) != visited.end()) {
555 if (length + dist < maxDist) {
557 toProc.push_back(std::make_pair(s, dist + length));
559 toProc.push_back(std::make_pair(s, 0));
567 #ifdef DEBUG_JOINJUNCTIONS
577 for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
581 WRITE_WARNINGF(
"Ignoring join exclusion for junction '%' since it already occurred in a list of nodes to be joined.", *it);
582 }
else if (check &&
retrieve(*it) ==
nullptr) {
583 WRITE_WARNINGF(
"Ignoring join exclusion for unknown junction '%'.", *it);
594 std::set<std::string> validCluster;
595 for (std::string nodeID : cluster) {
597 WRITE_WARNINGF(
"Ignoring join-cluster because junction '%' was already excluded from joining.", nodeID);
599 }
else if (
myJoined.count(nodeID) > 0) {
600 WRITE_WARNINGF(
"Ignoring join-cluster because junction '%' already occurred in another join-cluster.", nodeID);
604 if (node !=
nullptr) {
605 validCluster.insert(nodeID);
609 std::set<std::string> subIDs;
612 validCluster.insert(nID);
614 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster (componentID).");
618 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster.");
623 if (validCluster.size() > 1) {
624 myJoined.insert(validCluster.begin(), validCluster.end());
627 WRITE_WARNINGF(
"Ignoring join-cluster '%s' because it has size '%'.", node->
getID(), validCluster.size());
638 for (std::string nodeID : item.first) {
640 if (node ==
nullptr) {
641 WRITE_ERROR(
"unknown junction '" + nodeID +
"' while joining.");
643 cluster.insert(node);
646 if (cluster.size() > 1) {
659 #ifdef DEBUG_JOINJUNCTIONS
660 std::cout <<
"joinJunctions...\n";
665 for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
667 #ifdef DEBUG_JOINJUNCTIONS
669 for (
NBNode* n : cluster) {
676 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
677 NodeSet::iterator check = j;
680 cluster.erase(check);
689 if (cluster.size() < 2) {
693 std::string origReason;
694 std::string origCluster;
697 #ifdef DEBUG_JOINJUNCTIONS
699 std::cout <<
" try to reduce to 4-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
706 WRITE_WARNINGF(
"Reducing junction cluster % (%).", origCluster, origReason);
711 #ifdef DEBUG_JOINJUNCTIONS
713 std::cout <<
" try to reduce to 2-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
720 WRITE_WARNINGF(
"Reducing junction cluster % (%).", origCluster, origReason);
725 WRITE_WARNINGF(
"Not joining junctions % (%).", origCluster, origReason);
731 for (
NBNode* current : cluster) {
735 newComp.insert(current);
736 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
737 NodeClusters::iterator check = it_comp;
739 bool connected =
false;
740 for (
NBNode* k : *check) {
741 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
743 newComp.insert((*check).begin(), (*check).end());
744 it_comp = components.erase(check);
754 components.push_back(newComp);
756 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
757 if ((*it_comp).size() > 1) {
759 clusters.push_back(*it_comp);
762 #ifdef DEBUG_JOINJUNCTIONS
767 return (
int)clusters.size();
772 #ifdef DEBUG_JOINJUNCTIONS
773 std::cout <<
"joinSameJunctions...\n";
775 std::map<Position, NodeSet> positions;
777 positions[item.second->getPosition()].insert(item.second);
780 for (
auto& item : positions) {
781 if (item.second.size() > 1) {
782 for (
NBNode* n : item.second) {
784 item.second.erase(n);
787 if (item.second.size() > 1) {
788 clusters.push_back(item.second);
793 return (
int)clusters.size();
798 #ifdef DEBUG_JOINJUNCTIONS
804 bool pruneFringe =
true;
807 while (pruneFringe) {
809 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
810 NodeSet::iterator check = j;
815 double clusterDist = std::numeric_limits<double>::max();
816 bool touchingCluster =
false;
818 NBNode* neighbor = (*it_edge)->getToNode();
819 if (cluster.count(neighbor) != 0) {
820 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
825 NBNode* neighbor = (*it_edge)->getFromNode();
826 if (cluster.count(neighbor) != 0) {
827 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
833 std::set<NBNode*> outsideNeighbors;
834 std::set<NBNode*> clusterNeighbors;
835 const double pedestrianFringeThreshold = 0.3;
837 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
838 if (cluster.count(neighbor) == 0) {
841 || clusterDist <= pedestrianFringeThreshold
842 || touchingCluster) {
843 outsideNeighbors.insert(neighbor);
846 clusterNeighbors.insert(neighbor);
849 #ifdef DEBUG_JOINJUNCTIONS
851 <<
" clusterDist=" << clusterDist
852 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
853 <<
" touching=" << touchingCluster
858 if (clusterNeighbors.size() == 0
859 || (outsideNeighbors.size() <= 1
860 && clusterNeighbors.size() == 1
862 cluster.erase(check);
864 #ifdef DEBUG_JOINJUNCTIONS
866 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
877 std::set<NBNode*> toRemove;
878 int maxPassengerLanes = 0;
879 for (
NBNode* n : cluster) {
880 for (
NBEdge* edge : n->getEdges()) {
881 maxPassengerLanes =
MAX2(maxPassengerLanes, edge->getNumLanesThatAllow(
SVC_PASSENGER));
884 for (
NBNode* n : cluster) {
885 for (
NBEdge* edge : n->getOutgoingEdges()) {
889 std::vector<NBNode*> passed;
892 NBNode* to = edge->getToNode();
893 while (cluster.count(to) != 0) {
895 bool goStraight = (std::find(passed.begin(), passed.end(), to) == passed.end()
900 passed.push_back(to);
903 if (cur !=
nullptr) {
914 #ifdef DEBUG_JOINJUNCTIONS
916 std::cout <<
"check edge length " << edge->getID() <<
" (" << length <<
", passed=" << passed.size() <<
", max=" << longThreshold <<
")\n";
919 if (length > longThreshold) {
925 #ifdef DEBUG_JOINJUNCTIONS
927 std::cout <<
"node=" << n->getID() <<
" long edge " << edge->getID() <<
" (" << length <<
", passed=" <<
toString(passed) <<
", max=" << longThreshold <<
") keepStart=" << keepStart <<
" keepEnd=" << keepEnd <<
"\n";
933 toRemove.insert(passed.begin(), passed.end() - 1);
935 toRemove.insert(passed.back());
941 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
951 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
952 if (cluster.count(neighbor) != 0) {
953 result.insert(neighbor);
962 #ifdef DEBUG_JOINJUNCTIONS
964 std::cout <<
"pruning slip-lanes at cluster=" <<
joinNamedToString(cluster,
' ') <<
"\n";
968 if (cluster.size() <= 2) {
972 for (
NBNode* n : cluster) {
978 #ifdef DEBUG_JOINJUNCTIONS
980 std::cout <<
" candidate slip-lane start=" << n->getID() <<
" outgoing=" <<
toString(outgoing) <<
"\n";
983 for (
NBEdge* contEdge : outgoing) {
987 double slipLength = contEdge->getLength();
988 NBNode* cont = contEdge->getToNode();
992 if (cands.count(cont) != 0) {
996 #ifdef DEBUG_JOINJUNCTIONS
998 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1005 #ifdef DEBUG_JOINJUNCTIONS
1007 std::cout <<
" candidate slip-lane end=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1014 NBEdge* otherEdge = (contEdge == outgoing.front() ? outgoing.back() : outgoing.front());
1015 double otherLength = otherEdge->
getLength();
1020 std::vector<NodeAndDist> toProc;
1021 toProc.push_back(std::make_pair(cont2, otherLength));
1023 while (!toProc.empty()) {
1025 NBNode* cont2 = nodeAndDist.first;
1026 double dist = nodeAndDist.second;
1027 #ifdef DEBUG_JOINJUNCTIONS
1029 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1033 if (visited.find(cont2) != visited.end()) {
1036 visited.insert(cont2);
1037 if (cont2 == cont) {
1042 const double dist2 = dist + e->getLength();
1043 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1044 toProc.push_back(std::make_pair(e->getToNode(), dist2));
1051 toRemove.insert(cands.begin(), cands.end());
1052 #ifdef DEBUG_JOINJUNCTIONS
1054 std::cout <<
" found slip-lane with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1067 #ifdef DEBUG_JOINJUNCTIONS
1069 std::cout <<
" candidate slip-lane end=" << n->getID() <<
" incoming=" <<
toString(incoming) <<
"\n";
1072 for (
NBEdge* contEdge : incoming) {
1076 double slipLength = contEdge->getLength();
1077 NBNode* cont = contEdge->getFromNode();
1081 if (cands.count(cont) != 0) {
1085 #ifdef DEBUG_JOINJUNCTIONS
1087 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1094 #ifdef DEBUG_JOINJUNCTIONS
1096 std::cout <<
" candidate slip-lane start=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1103 NBEdge* otherEdge = (contEdge == incoming.front() ? incoming.back() : incoming.front());
1104 double otherLength = otherEdge->
getLength();
1109 std::vector<NodeAndDist> toProc;
1110 toProc.push_back(std::make_pair(cont2, otherLength));
1112 while (!toProc.empty()) {
1114 NBNode* cont2 = nodeAndDist.first;
1115 double dist = nodeAndDist.second;
1116 #ifdef DEBUG_JOINJUNCTIONS
1118 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1122 if (visited.find(cont2) != visited.end()) {
1125 visited.insert(cont2);
1126 if (cont2 == cont) {
1131 const double dist2 = dist + e->getLength();
1132 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1133 toProc.push_back(std::make_pair(e->getFromNode(), dist2));
1140 toRemove.insert(cands.begin(), cands.end());
1141 #ifdef DEBUG_JOINJUNCTIONS
1143 std::cout <<
" found slip-lane start with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1155 for (
NBNode* n : toRemove) {
1156 numRemoved += (int)cluster.erase(n);
1158 if (numRemoved > 0) {
1159 #ifdef DEBUG_JOINJUNCTIONS
1161 std::cout <<
" removed " << numRemoved <<
" nodes from cluster: " <<
joinNamedToString(toRemove,
' ') <<
"\n";
1180 if (inRelAngle < 135) {
1187 const double outRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1188 if (outRelAngle <= 45) {
1189 straight.push_back(out);
1190 }
else if (outRelAngle >= 135) {
1194 if (straight.size() == 2 && numReverse == 1) {
1195 outgoing.insert(outgoing.begin(), straight.begin(), straight.end());
1196 inAngle = in->getAngleAtNode(n);
1216 if (outRelAngle < 135) {
1223 const double inRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1224 if (inRelAngle <= 45) {
1225 straight.push_back(in);
1226 }
else if (inRelAngle >= 135) {
1230 if (straight.size() == 2 && numReverse == 1) {
1231 incoming.insert(incoming.begin(), straight.begin(), straight.end());
1232 outAngle = out->getAngleAtNode(n);
1244 std::map<std::string, double> finalIncomingAngles;
1245 std::map<std::string, double> finalOutgoingAngles;
1246 for (NodeSet::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
1247 for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
1254 for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
1263 #ifdef DEBUG_JOINJUNCTIONS
1264 for (
NBNode* n : cluster) {
1267 <<
"\n inAngles=" <<
joinToString(finalIncomingAngles,
' ',
':')
1268 <<
"\n outAngles=" <<
joinToString(finalOutgoingAngles,
' ',
':')
1273 if (finalIncomingAngles.size() > 4) {
1274 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
1278 const double PARALLEL_INCOMING_THRESHOLD = 10.0;
1279 bool foundParallel =
false;
1280 for (std::map<std::string, double>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
1281 std::map<std::string, double>::const_iterator k = j;
1282 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
1283 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
1284 reason =
"parallel incoming " + j->first +
"," + k->first;
1290 for (std::map<std::string, double>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
1291 std::map<std::string, double>::const_iterator k = j;
1292 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
1293 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
1294 reason =
"parallel outgoing " + j->first +
"," + k->first;
1301 for (
auto it = sc.
begin(); it != sc.
end(); it++) {
1303 if (edge !=
nullptr && cluster.count(edge->
getFromNode()) != 0 && cluster.count(edge->
getToNode()) != 0) {
1304 reason =
"it contains stop '" + it->first +
"'";
1310 for (
NBNode* n : cluster) {
1311 if (n->isTLControlled()) {
1315 const bool hasTLS = numTLS > 0;
1317 if (cluster.size() > 2) {
1319 double maxDist = -1;
1320 NBEdge* maxEdge =
nullptr;
1321 for (
NBNode* n1 : cluster) {
1322 for (
NBNode* n2 : cluster) {
1323 NBEdge* e1 = n1->getConnectionTo(n2);
1324 NBEdge* e2 = n2->getConnectionTo(n1);
1335 #ifdef DEBUG_JOINJUNCTIONS
1336 for (
NBNode* n : cluster) {
1338 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxDist=" << maxDist <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
1342 if (!hasTLS && maxDist > 5) {
1344 std::vector<NBNode*> toCheck;
1345 std::set<NBNode*> visited;
1346 toCheck.push_back(maxEdge->
getToNode());
1347 bool foundCircle =
false;
1348 while (!toCheck.empty()) {
1349 NBNode* n = toCheck.back();
1358 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1359 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
1360 toCheck.push_back(cand);
1366 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxDist) +
")";
1372 if (!hasTLS && cluster.size() >= 2) {
1375 int outsideIncoming = 0;
1376 int outsideOutgoing = 0;
1377 int edgesWithin = 0;
1378 for (
NBNode* n : cluster) {
1379 bool foundOutsideIncoming =
false;
1381 if (cluster.count(e->getFromNode()) == 0) {
1384 foundOutsideIncoming =
true;
1389 if (foundOutsideIncoming) {
1392 bool foundOutsideOutgoing =
false;
1393 for (
NBEdge* e : n->getOutgoingEdges()) {
1394 if (cluster.count(e->getToNode()) == 0) {
1397 foundOutsideOutgoing =
true;
1400 if (foundOutsideOutgoing) {
1404 if (entryNodes < 2) {
1405 reason =
"only 1 entry node";
1408 if (exitNodes < 2) {
1409 reason =
"only 1 exit node";
1412 if (cluster.size() == 2) {
1413 if (edgesWithin == 1 && outsideIncoming < 3 && outsideOutgoing < 3) {
1414 reason =
"only 1 edge within and no cross-traffic";
1426 assert(circleSize >= 2);
1427 if ((
int)cands.size() == circleSize) {
1428 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1431 candCluster.insert(cands.begin(), cands.end());
1433 const bool feasible = (int)candCluster.size() == circleSize;
1436 cluster.insert(cands.begin(), cands.end());
1443 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1448 if (cands.size() == 0) {
1463 singleStart.insert(cands.back());
1466 std::vector<NBNode*> cands2(cands);
1480 double minDist = std::numeric_limits<double>::max();
1481 NBEdge* result =
nullptr;
1482 for (
NBNode* n : startNodes) {
1483 for (
NBEdge* e : n->getOutgoingEdges()) {
1484 NBNode* neigh = e->getToNode();
1485 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1488 if (dist < minDist) {
1502 for (
NodeSet cluster : clusters) {
1511 assert(cluster.size() > 1);
1514 std::string
id =
"cluster";
1518 NBNode* newNode =
nullptr;
1519 if (predefined !=
nullptr) {
1520 newNode = predefined;
1529 std::string tlID = id;
1530 if (predefined !=
nullptr) {
1532 nodeType = predefined->
getType();
1545 newNode->
reinit(pos, nodeType);
1548 if (!tlc.
insert(tlDef)) {
1551 throw ProcessError(
"Could not allocate tls '" +
id +
"'.");
1555 std::set<NBEdge*, ComparatorIdLess> allEdges;
1556 for (
NBNode* n : cluster) {
1558 allEdges.insert(edges.begin(), edges.end());
1561 std::set<NBEdge*, ComparatorIdLess> clusterIncoming;
1562 std::set<NBEdge*, ComparatorIdLess> inside;
1563 for (
NBEdge* e : allEdges) {
1564 if (cluster.count(e->getToNode()) > 0) {
1565 if (cluster.count(e->getFromNode()) > 0) {
1568 clusterIncoming.insert(e);
1572 #ifdef DEBUG_JOINJUNCTIONS
1574 <<
" incoming=" <<
toString(clusterIncoming) <<
"\n"
1575 <<
" inside=" <<
toString(inside) <<
"\n";
1579 std::map<NBEdge*, EdgeSet> reachable;
1580 for (
NBEdge* e : clusterIncoming) {
1584 while (open.size() > 0) {
1585 NBEdge* cur = open.back();
1589 if (cluster.count(cur->
getToNode()) == 0) {
1597 if (seen.count(out) == 0
1598 && allEdges.count(out) != 0
1600 open.push_back(out);
1605 for (
const auto& con : cons) {
1606 if (con.toEdge !=
nullptr
1607 && seen.count(con.toEdge) == 0
1608 && allEdges.count(con.toEdge) != 0) {
1609 open.push_back(con.toEdge);
1615 for (
NBEdge* reached : seen) {
1617 if (inside.count(reached) == 0) {
1618 reachable[e].insert(reached);
1621 #ifdef DEBUG_JOINJUNCTIONS
1622 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1627 for (
NBEdge* e : inside) {
1628 for (
NBEdge* e2 : allEdges) {
1630 e2->replaceInConnections(e, e->getConnections());
1638 for (
NBEdge* e : allEdges) {
1639 std::vector<NBEdge::Connection> conns = e->getConnections();
1640 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1641 NBNode* from = outgoing ? newNode : e->getFromNode();
1642 NBNode* to = outgoing ? e->getToNode() : newNode;
1645 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1647 e->setParameter(
"origTo", e->getToNode()->getID());
1650 e->reinitNodes(from, to);
1653 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1655 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1661 if (!resetConnections) {
1667 in->removeFromConnections(out, -1, -1,
true,
false,
true);
1673 in->invalidateConnections(
true);
1679 for (
NBNode* n : cluster) {
1687 std::set<std::string> ids;
1688 for (
NBNode* n : cluster) {
1689 ids.insert(n->getID());
1700 bool ambiguousType =
false;
1701 for (
NBNode* j : cluster) {
1702 pos.
add(j->getPosition());
1704 if (j->isTLControlled()) {
1707 type = (*j->getControllingTLS().begin())->getType();
1708 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
1709 ambiguousType =
true;
1715 nodeType = otherType;
1716 }
else if (nodeType != otherType) {
1728 pos.
mul(1.0 / cluster.size());
1729 if (ambiguousType) {
1731 WRITE_WARNINGF(
"Ambiguous traffic light type for node cluster '%', setting to '%'.",
id,
toString(type));
1739 bool tooFast =
false;
1740 double laneSpeedSum = 0;
1741 std::set<NBEdge*> seen;
1744 for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
1745 if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
1748 if (j->hasIncoming(*k)) {
1749 laneSpeedSum += (double)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
1751 if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
1757 return !tooFast && laneSpeedSum >= laneSpeedThreshold && c.size() != 0;
1769 nonPedIncoming.push_back(e);
1772 for (
NBEdge* e : node->getOutgoingEdges()) {
1774 nonPedOutgoing.push_back(e);
1777 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
1793 if (node->isTLControlled()) {
1794 const std::string tlID = (*node->getControllingTLS().begin())->getID();
1795 if (tlID != node->getID()
1811 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
1812 std::vector<NBNode*> ncontrolled;
1813 if (oc.
isSet(
"tls.unset")) {
1814 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
1815 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
1818 throw ProcessError(
" The junction '" + *i +
"' to set as not-controlled is not known.");
1821 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
1822 (*j)->removeNode(n);
1825 ncontrolled.push_back(n);
1832 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
1833 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1834 NBNode* cur = (*i).second;
1835 if (cur->
isNearDistrict() && std::find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
1843 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
1845 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
1846 for (
const auto& item :
myNodes) {
1847 const NBNode* node = item.second;
1849 #ifdef DEBUG_GUESSSIGNALS
1851 std::cout <<
" propagate TLS from " << node->
getID() <<
" downstream\n";
1857 edge->setSignalPosition(node->
getPosition(), node);
1862 std::set<NBEdge*> seen;
1863 std::set<NBEdge*> check;
1864 for (
const auto& item :
myNodes) {
1865 for (
NBEdge* edge : item.second->getOutgoingEdges()) {
1869 #ifdef DEBUG_GUESSSIGNALS
1870 if (
DEBUGCOND(edge->getSignalNode()) ||
true) {
1871 std::cout <<
" primary signalPosition edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
1878 while (check.size() > 0) {
1879 NBEdge*
const edge = *check.begin();
1880 check.erase(check.begin());
1885 if (seen.count(outEdge) == 0) {
1887 #ifdef DEBUG_GUESSSIGNALS
1889 std::cout <<
" setSignalPosition edge=" << outEdge->
getID() <<
" pos=" << edge->
getSignalPosition() <<
"\n";
1892 check.insert(outEdge);
1899 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1900 NBNode* node = i->second;
1901 if (find(ncontrolled.begin(), ncontrolled.end(), node) != ncontrolled.end()) {
1909 std::vector<const NBNode*> signals;
1912 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
1913 const NBEdge* inEdge = *it_i;
1915 #ifdef DEBUG_GUESSSIGNALS
1917 std::cout <<
" noTLS, edge=" << inEdge->
getID() <<
"\n";
1928 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
1929 const NBEdge* inEdge = *it_i;
1932 #ifdef DEBUG_GUESSSIGNALS
1941 if (signal !=
nullptr) {
1942 signals.push_back(signal);
1947 for (
const NBEdge* outEdge : outgoing) {
1948 NBNode* cand = outEdge->getToNode();
1950 #ifdef DEBUG_GUESSSIGNALS
1952 std::cout <<
" node=" << node->
getID() <<
" outEdge=" << outEdge->getID() <<
" signalNode=" << cand->
getID() <<
" len=" << outEdge->getLength() <<
"\n";
1955 signals.push_back(cand);
1960 for (
const NBNode* s : signals) {
1961 std::set<NBTrafficLightDefinition*> tls = s->getControllingTLS();
1963 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
1970 if (!tlc.
insert(tlDef)) {
1982 if (oc.
getBool(
"tls.guess.joining")) {
1987 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
1991 for (NodeSet::iterator j = c.begin(); j != c.end();) {
1992 if ((*j)->isTLControlled() || std::find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
2008 for (
auto nodeSet : cands) {
2009 std::vector<NBNode*> nodes;
2010 for (
NBNode* node : nodeSet) {
2011 nodes.push_back(node);
2014 std::string
id =
"joinedG_" +
toString(index++);
2016 if (!tlc.
insert(tlDef)) {
2026 if (oc.
getBool(
"tls.guess")) {
2027 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2028 NBNode* cur = (*i).second;
2034 if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
2049 std::set<NBTrafficLightDefinition*> recompute;
2051 if (!node->hasConflict()) {
2052 const std::set<NBTrafficLightDefinition*>& tlDefs = node->getControllingTLS();
2053 recompute.insert(tlDefs.begin(), tlDefs.end());
2054 node->removeTrafficLights(
true);
2056 edge->clearControllingTLInformation();
2061 if (def->getNodes().size() == 0) {
2064 def->setParticipantsInformation();
2065 def->setTLControllingInformation();
2074 for (
const auto& item :
myNodes) {
2075 item.second->computeKeepClear();
2086 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2087 if (!(*j)->isTLControlled()) {
2099 std::string
id =
"joined";
2104 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
2105 j->removeTrafficLights();
2106 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
2110 std::vector<NBNode*> nodes;
2119 if (!tlc.
insert(tlDef)) {
2136 if (!tlc.
insert(tlDef)) {
2138 WRITE_WARNINGF(
"Building a tl-logic for junction '%' twice is not possible.",
id);
2148 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2149 (*i).second->computeLanes2Lanes();
2157 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2158 (*i).second->computeLogic(ec);
2165 std::set<NBNode*> roundaboutNodes;
2166 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
2167 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
2168 if (checkLaneFoesRoundabout) {
2170 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
2171 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
2172 roundaboutNodes.insert((*j)->getToNode());
2176 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2177 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
2178 (*i).second->computeLogic2(checkLaneFoes);
2185 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2186 delete ((*i).second);
2199 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
2201 while (
retrieve(freeID) !=
nullptr) {
2204 freeID =
"SUMOGenerated" + toString<int>(counter);
2212 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2213 (*i).second->computeNodeShape(mismatchThreshold);
2220 int numUnregulatedJunctions = 0;
2221 int numDeadEndJunctions = 0;
2222 int numTrafficLightJunctions = 0;
2223 int numPriorityJunctions = 0;
2224 int numRightBeforeLeftJunctions = 0;
2225 int numAllWayStopJunctions = 0;
2226 int numZipperJunctions = 0;
2227 int numDistrictJunctions = 0;
2228 int numRailCrossing = 0;
2229 int numRailSignals = 0;
2230 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2231 switch ((*i).second->getType()) {
2233 ++numUnregulatedJunctions;
2236 ++numDeadEndJunctions;
2241 ++numTrafficLightJunctions;
2245 ++numPriorityJunctions;
2248 ++numRightBeforeLeftJunctions;
2251 ++numAllWayStopJunctions;
2254 ++numZipperJunctions;
2257 ++numDistrictJunctions;
2274 if (numDeadEndJunctions > 0) {
2279 if (numTrafficLightJunctions > 0) {
2282 if (numAllWayStopJunctions > 0) {
2285 if (numZipperJunctions > 0) {
2288 if (numRailCrossing > 0) {
2291 if (numRailSignals > 0) {
2294 if (numDistrictJunctions > 0) {
2300 std::vector<std::string>
2302 std::vector<std::string> ret;
2303 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2304 ret.push_back((*i).first);
2312 if (
myNodes.count(newID) != 0) {
2313 throw ProcessError(
"Attempt to rename node using existing id '" + newID +
"'");
2323 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2324 NBNode* node = i->second;
2328 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
2335 edge->setSignalPosition(node->
getPosition(),
nullptr);
2336 #ifdef DEBUG_GUESSSIGNALS
2337 std::cout <<
" discard-simple " << node->
getID() <<
" edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2341 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
2356 NBNode* node = item.second;
2367 std::vector<std::string> avoid;
2373 std::set<std::string> reserve;
2377 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
2381 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
2383 toChange.insert(it->second);
2390 toChange.insert(it->second);
2393 if (reservedIDs && reserve.count(it->first) > 0) {
2394 toChange.insert(it->second);
2398 for (
NBNode* node : toChange) {
2401 for (
NBNode* node : toChange) {
2405 node->setID(idSupplier.
getNext());
2406 myNodes[node->getID()] = node;
2408 if (prefix.empty()) {
2409 return (
int)toChange.size();
2414 for (
auto item : oldNodes) {
2416 rename(item.second, prefix + item.first);
2431 for (
const auto& item :
myNodes) {
2434 paretoCheck(item.second, bottomRightFront, 1, -1);
2435 paretoCheck(item.second, bottomLeftFront, -1, -1);
2438 front.insert(topRightFront.begin(), topRightFront.end());
2439 front.insert(topLeftFront.begin(), topLeftFront.end());
2440 front.insert(bottomRightFront.begin(), bottomRightFront.end());
2441 front.insert(bottomLeftFront.begin(), bottomLeftFront.end());
2443 for (
NBNode* n : front) {
2444 const int in = (int)n->getIncomingEdges().size();
2445 const int out = (int)n->getOutgoingEdges().size();
2446 if ((in <= 1 && out <= 1) &&
2447 (in == 0 || out == 0
2448 || n->getIncomingEdges().front()->isTurningDirectionAt(n->getOutgoingEdges().front()))) {
2461 std::vector<NBNode*> dominated;
2463 const double x2 =
fn->getPosition().x() * xSign;
2464 const double y2 =
fn->getPosition().y() * ySign;
2465 if (x2 >= x && y2 >= y) {
2467 }
else if (x2 <= x && y2 <= y) {
2468 dominated.push_back(
fn);
2471 frontier.insert(node);
2472 for (
NBNode* r : dominated) {
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGE(msg)
#define WRITE_WARNING(msg)
std::set< NBNode *, ComparatorIdLess > NodeSet
std::set< NBEdge * > EdgeSet
container for unique edges
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
#define MAX_SLIPLANE_LENGTH
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_TRAM
vehicle is a light rail
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
const std::string SUMO_PARAM_ORIGID
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
@ TRAFFIC_LIGHT_RIGHT_ON_RED
@ TRAFFIC_LIGHT_NOJUNCTION
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
#define UNUSED_PARAMETER(x)
std::string joinNamedToString(const std::set< T *, C > &ns, const T_BETWEEN &between)
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)
std::string getNext()
Returns the next id.
A container for districts.
A class representing a single district.
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.
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
void extract(NBDistrictCont &dc, NBEdge *edge, bool remember=false)
Removes the given edge from the container like erase but does not delete it.
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
bool hasPostProcessConnection(const std::string &from, const std::string &to="")
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
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.
static EdgeVector filterByPermissions(const EdgeVector &edges, SVCPermissions permissions)
return only those edges that permit at least one of the give permissions
const Position & getSignalPosition() const
Returns the position of a traffic signal on this edge.
EdgeBuildingStep getStep() const
The building step of this edge.
NBEdge * getStraightContinuation(SVCPermissions permissions) const
return the straightest follower edge for the given permissions or nullptr (never returns turn-arounds...
const NBNode * getSignalNode() const
Returns the node that (possibly) represents a traffic signal controlling at the end of this edge.
const std::string & getID() const
bool isNearEnough2BeJoined2(NBEdge *e, double threshold) const
Check if edge is near enought to be joined to another edge.
NBNode * getToNode() const
Returns the destination node of the edge.
@ INIT
The edge has been loaded, nothing is computed yet.
double getSpeed() const
Returns the speed allowed on this edge.
static const double UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
@ USER
The connection was given by the user.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
double getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
const std::vector< Connection > & getConnections() const
Returns the connections.
NBNode * getFromNode() const
Returns the origin node of the edge.
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
static void loadPrefixedIDsFomFile(const std::string &file, const std::string prefix, std::set< std::string > &into)
Add prefixed ids defined in file.
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
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.
void clear()
deletes all nodes
std::set< std::string > myJoinExclusions
set of node ids which should not be joined
NamedRTree myRTree
node positions for faster lookup
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
void avoidOverlap()
fix overlap
bool onlyCrossings(const NodeSet &c) const
check wheter the set of nodes only contains pedestrian crossings
std::vector< std::pair< std::set< std::string >, NBNode * > > myClusters2Join
loaded sets of node ids to join (cleared after use)
void addCluster2Join(std::set< std::string > cluster, NBNode *node)
add ids of nodes which shall be joined into a single node
void recheckGuessedTLS(NBTrafficLightLogicCont &tlc)
recheck myGuessedTLS after node logics are computed
std::vector< NodeSet > NodeClusters
Definition of a node cluster container.
void computeKeepClear()
compute keepClear status for all connections
NodeCont myNodes
The map of names to nodes.
static void pruneLongEdges(NodeSet &cluster, double maxDist)
avoid removal of long edges when joinining junction clusters
void registerJoinedCluster(const NodeSet &cluster)
gets all joined clusters (see doc for myClusters2Join)
std::string getFreeID()
generates a new node ID
void addJoinExclusion(const std::vector< std::string > &ids, bool check=false)
void paretoCheck(NBNode *node, NodeSet &frontier, int xSign, int ySign)
update pareto frontier with the given node
bool maybeSlipLaneStart(const NBNode *n, EdgeVector &outgoing, double &inAngle) const
check whether the given node maybe the start of a slip lane
bool erase(NBNode *node)
Removes the given node, deleting it.
int joinLoadedClusters(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins loaded junction clusters (see NIXMLNodesHandler)
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
NodeCont myExtractedNodes
The extracted nodes which are kept for reference.
void joinTLS(NBTrafficLightLogicCont &tlc, double maxdist)
Builds clusters of tls-controlled junctions and joins the control if possible.
int removeUnwishedNodes(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, NBPTStopCont &sc, NBPTLineCont &lc, NBParkingCont &pc, bool removeGeometryNodes)
Removes "unwished" nodes.
bool reduceToCircle(NodeSet &cluster, int circleSize, NodeSet startNodes, std::vector< NBNode * > cands=std::vector< NBNode * >()) const
try to find a joinable subset (recursively)
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
void removeComponents(NBDistrictCont &dc, NBEdgeCont &ec, const int numKeep)
Checks the network for weak connectivity and removes all but the largest components....
std::vector< std::string > getAllNames() const
get all node names
void computeLogics2(const NBEdgeCont &ec, OptionsCont &oc)
compute right-of-way logic for all lane-to-lane connections
void rename(NBNode *node, const std::string &newID)
Renames the node. Throws exception if newID already exists.
void joinNodeClusters(NodeClusters clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, bool resetConnections=false)
joins the given node clusters
void discardRailSignals()
void printBuiltNodesStatistics() const
Prints statistics about built nodes.
void removeIsolatedRoads(NBDistrictCont &dc, NBEdgeCont &ec)
Removes sequences of edges that are not connected with a junction. Simple roads without junctions som...
void setAsTLControlled(NBNode *node, NBTrafficLightLogicCont &tlc, TrafficLightType type, std::string id="")
Sets the given node as being controlled by a tls.
std::set< const NBNode * > mySplit
nodes that were created when splitting an edge
void joinSimilarEdges(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins edges connecting the same nodes.
void computeLogics(const NBEdgeCont &ec)
build the list of outgoing edges and lanes
void joinNodeCluster(NodeSet clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, NBNode *predefined=nullptr, bool resetConnections=false)
void generateNodeClusters(double maxDist, NodeClusters &into) const
Builds node clusters.
void computeNodeShapes(double mismatchThreshold=-1)
Compute the junction shape for this node.
std::vector< std::set< std::string > > myJoinedClusters
sets of node ids which were joined
void pruneClusterFringe(NodeSet &cluster) const
remove geometry-like fringe nodes from cluster
NBEdge * shortestEdge(const NodeSet &cluster, const NodeSet &startNodes, const std::vector< NBNode * > &exclude) const
find closest neighbor for building circle
std::pair< NBNode *, double > NodeAndDist
void guessTLs(OptionsCont &oc, NBTrafficLightLogicCont &tlc)
Guesses which junctions or junction clusters shall be controlled by tls.
int guessFringe()
guess and mark fringe nodes
std::set< NBNode * > myGuessedTLS
nodes that received a traffic light due to guessing (–tls.guess)
int joinJunctions(double maxDist, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, NBPTStopCont &sc)
Joins junctions that are very close together.
void computeLanes2Lanes()
divides the incoming lanes on outgoing lanes
void discardTrafficLights(NBTrafficLightLogicCont &tlc, bool geometryLike, bool guessSignals)
bool feasibleCluster(const NodeSet &cluster, const NBEdgeCont &ec, const NBPTStopCont &sc, std::string &reason) const
determine wether the cluster is not too complex for joining
static NodeSet getClusterNeighbors(const NBNode *n, NodeSet &cluster)
return all cluster neighbors for the given node
void removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes self-loop edges (edges where the source and the destination node are the same)
std::set< std::string > myJoined
ids found in loaded join clusters used for error checking
bool shouldBeTLSControlled(const NodeSet &c, double laneSpeedThreshold) const
Returns whethe the given node cluster should be controlled by a tls.
int joinSameJunctions(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins junctions with the same coordinates regardless of topology.
void analyzeCluster(NodeSet cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type, SumoXMLNodeType &nodeType)
bool customTLID(const NodeSet &c) const
check wheter the set of nodes contains traffic lights with custom id
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string &prefix)
remap node IDs accoring to options –numerical-ids and –reserved-ids
bool maybeSlipLaneEnd(const NBNode *n, EdgeVector &incoming, double &outAngle) const
check whether the given node maybe the end of a slip lane
void pruneSlipLaneNodes(NodeSet &cluster) const
remove nodes that form a slip lane from cluster
Represents a single node (junction) during network building.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
SumoXMLNodeType getType() const
Returns the type of this node.
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
void removeTrafficLights(bool setAsPriority=false)
Removes all references to traffic lights that control this tls.
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
void updateSurroundingGeometry()
update geometry of node and surrounding edges
const Position & getPosition() const
bool checkIsRemovable() const
check if node is removable
bool geometryLike() const
whether this is structurally similar to a geometry node
bool isNearDistrict() const
@chech if node is near district
bool isTLControlled() const
Returns whether this node is controlled by any tls.
static bool isRailwayNode(const NBNode *n)
whether the given node only has rail edges
A traffic light logics which must be computed (only nodes/edges are given)
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
std::map< std::string, NBPTStop * >::const_iterator begin() const
Returns the pointer to the begin of the stored pt stops.
std::map< std::string, NBPTStop * >::const_iterator end() const
Returns the pointer to the end of the stored pt stops.
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
The base class for traffic light logic definitions.
A container for traffic light definitions and built programs.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
bool computeSingleLogic(OptionsCont &oc, NBTrafficLightDefinition *def)
Computes a specific traffic light logic (using by NETEDIT)
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
bool removeFully(const std::string id)
Removes a logic definition (and all programs) from the dictionary.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
Allows to store the object; used as context while traveling the rtree in TraCI.
Base class for objects which have an id.
virtual void setID(const std::string &newID)
resets the id
const std::string & getID() const
Returns the id.
void Remove(const float a_min[2], const float a_max[2], Named *const &a_data)
Remove entry.
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
A storage for options typed value containers)
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
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 isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
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)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
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.
void setx(double x)
set position x
static const Position INVALID
used to indicate that a position is valid
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
double x() const
Returns the x-position.
void add(const Position &pos)
Adds the given position to this one.
void setz(double z)
set position z
void mul(double val)
Multiplies both positions with the given value.
double z() const
Returns the z-position.
void sety(double y)
set position y
double y() const
Returns the y-position.
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
T get(const std::string &str) const
std::vector< std::string > getVector()
return vector of strings
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.