60 #define MAX_SLIPLANE_LENGTH 1000
68 #define DEBUGNODEID ""
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()) {
227 if (removeDuplicates) {
228 for (
int ei = 1; ei < (int)ev.size(); ei++) {
243 const std::vector<std::string>& edgeNames = ec.
getAllNames();
244 for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
253 if (outgoingEdges.size() != 1) {
258 if (incomingEdges.size() > 1) {
261 }
else if (incomingEdges.size() == 1) {
262 NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
263 NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
264 if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
272 bool hasJunction =
false;
284 adjacentNodes.clear();
285 for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
286 if ((*itOfOutgoings)->getToNode() != from
287 && (*itOfOutgoings)->getToNode() != to
291 adjacentNodes.insert((*itOfOutgoings)->getToNode());
293 for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
294 adjacentNodes.insert((*itOfIncomings)->getFromNode());
296 adjacentNodes.erase(to);
297 if (adjacentNodes.size() > 2) {
300 }
while (!hasJunction && eOld != e);
302 std::string warningString;
303 for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
304 if (roadIt == road.begin()) {
305 warningString += (*roadIt)->
getID();
307 warningString +=
"," + (*roadIt)->getID();
310 NBNode* fromNode = (*roadIt)->getFromNode();
311 NBNode* toNode = (*roadIt)->getToNode();
312 ec.
erase(dc, *roadIt);
322 WRITE_WARNINGF(
"Removed a road without junctions: %.", warningString);
331 std::vector<std::set<NBEdge*> > components;
333 std::set<std::string> edgesLeft;
334 for (std::map<std::string, NBEdge*>::const_iterator edgeIt = ec.
begin(); edgeIt != ec.
end(); ++edgeIt) {
335 edgesLeft.insert(edgeIt->first);
338 std::set<NBEdge*> toRemove;
339 int foundComponents = 0;
341 while (!edgesLeft.empty()) {
342 queue.push_back(ec.
getByID(*edgesLeft.begin()));
343 std::set<NBEdge*> component;
344 while (!queue.empty()) {
345 NBEdge*
const e = queue.back();
348 std::vector<EdgeVector> edgeLists;
353 for (std::vector<EdgeVector>::const_iterator listIt = edgeLists.begin(); listIt != edgeLists.end(); ++listIt) {
354 for (EdgeVector::const_iterator edgeIt = listIt->begin(); edgeIt != listIt->end(); ++edgeIt) {
355 std::set<std::string>::iterator leftIt = edgesLeft.find((*edgeIt)->getID());
356 if (leftIt != edgesLeft.end()) {
357 queue.push_back(*edgeIt);
358 edgesLeft.erase(leftIt);
364 std::vector<std::set<NBEdge*> >::iterator cIt;
365 for (cIt = components.begin(); cIt != components.end(); ++cIt) {
366 if (cIt->size() < component.size()) {
370 components.insert(cIt, component);
371 if ((
int)components.size() > numKeep) {
372 bool recheck =
false;
374 for (
NBEdge* e : components.back()) {
384 toRemove.insert(components.back().begin(), components.back().end());
387 std::vector<std::string> edgeIDs;
388 for (
NBEdge* e : components.back()) {
389 edgeIDs.push_back(e->getID());
393 components.pop_back();
397 for (
NBEdge* e : toRemove) {
398 NBNode*
const fromNode = e->getFromNode();
399 NBNode*
const toNode = e->getToNode();
408 if (foundComponents > 1) {
416 std::set<std::string> stopEdges;
417 for (
const auto& item : sc.
getStops()) {
418 stopEdges.insert(item.second->getEdgeId());
421 int numRemovedEdges = 0;
424 for (std::string edgeID : component) {
425 if (stopEdges.count(edgeID) != 0) {
432 numRemovedEdges += (int)component.size();
433 for (std::string edgeID : component) {
449 if (numRemoved > 0) {
460 bool removeGeometryNodes) {
462 std::set<std::string> edges2keep;
463 if (removeGeometryNodes) {
465 if (oc.
isSet(
"geometry.remove.keep-edges.input-file")) {
468 if (oc.
isSet(
"geometry.remove.keep-edges.explicit")) {
469 const std::vector<std::string> edges = oc.
getStringVector(
"geometry.remove.keep-edges.explicit");
470 edges2keep.insert(edges.begin(), edges.end());
475 if (oc.
getBool(
"geometry.remove.keep-ptstops")) {
479 std::vector<NBNode*> toRemove;
481 std::map<NBEdge*, std::set<NBTrafficLightDefinition*> > tlsLookup;
482 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
491 for (
const auto& i :
myNodes) {
492 NBNode*
const current = i.second;
499 if (edges2keep.find(it_edge->getID()) != edges2keep.end()) {
509 for (
const std::pair<NBEdge*, NBEdge*>& j : current->
getEdgesToJoin()) {
511 NBEdge*
const continuation = j.second;
512 begin->append(continuation);
514 auto itTL = tlsLookup.find(continuation);
515 if (itTL != tlsLookup.end()) {
519 tlsLookup[
begin] = itTL->second;
523 ec.
extract(dc, continuation,
true);
525 toRemove.push_back(current);
528 for (
NBNode* n : toRemove) {
531 return (
int)toRemove.size();
537 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
538 (*i).second->avoidOverlap();
545 std::set<NBNode*> visited;
546 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
547 std::vector<NodeAndDist> toProc;
548 if (visited.find((*i).second) != visited.end()) {
551 toProc.push_back(std::make_pair((*i).second, 0));
553 while (!toProc.empty()) {
555 NBNode* n = nodeAndDist.first;
556 double dist = nodeAndDist.second;
558 if (visited.find(n) != visited.end()) {
562 bool pureRail =
true;
563 bool railAndPeds =
true;
581 const double length = e->getLoadedLength();
582 #ifdef DEBUG_JOINJUNCTIONS
584 std::cout <<
"generateNodeClusters: consider s=" << s->
getID()
585 <<
" clusterNode=" << n->
getID() <<
" edge=" << e->getID() <<
" length=" << length <<
" with cluster " <<
joinNamedToString(c,
' ') <<
"\n";
589 bool railAndPeds2 =
true;
592 railAndPeds2 =
false;
603 const bool joinPedCrossings = bothCrossing && e->getPermissions() ==
SVC_PEDESTRIAN;
605 !joinPedCrossings && (
608 || (length > 3 * POSITION_EPS
617 bool foundRail =
false;
620 if ((e2->getPermissions() & railNoTram) != 0) {
633 if (visited.find(s) != visited.end()) {
636 if (length + dist < maxDist) {
638 toProc.push_back(std::make_pair(s, dist + length));
640 toProc.push_back(std::make_pair(s, 0));
648 #ifdef DEBUG_JOINJUNCTIONS
658 for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
662 WRITE_WARNINGF(
"Ignoring join exclusion for junction '%' since it already occurred in a list of nodes to be joined.", *it);
663 }
else if (check &&
retrieve(*it) ==
nullptr) {
664 WRITE_WARNINGF(
"Ignoring join exclusion for unknown junction '%'.", *it);
675 std::set<std::string> validCluster;
676 for (std::string nodeID : cluster) {
678 WRITE_WARNINGF(
"Ignoring join-cluster because junction '%' was already excluded from joining.", nodeID);
680 }
else if (
myJoined.count(nodeID) > 0) {
681 WRITE_WARNINGF(
"Ignoring join-cluster because junction '%' already occurred in another join-cluster.", nodeID);
685 validCluster.insert(nodeID);
689 std::set<std::string> subIDs;
692 validCluster.insert(nID);
694 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster (componentID).");
698 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster.");
703 if (validCluster.size() > 1) {
704 myJoined.insert(validCluster.begin(), validCluster.end());
707 WRITE_WARNINGF(
"Ignoring join-cluster '%s' because it has size '%'.", node->
getID(), validCluster.size());
718 for (std::string nodeID : item.first) {
720 if (node ==
nullptr) {
721 WRITE_ERROR(
"unknown junction '" + nodeID +
"' while joining.");
723 cluster.insert(node);
726 if (cluster.size() > 1) {
739 #ifdef DEBUG_JOINJUNCTIONS
740 std::cout <<
"joinJunctions...\n";
745 for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
747 #ifdef DEBUG_JOINJUNCTIONS
749 for (
NBNode* n : cluster) {
756 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
757 NodeSet::iterator check = j;
760 cluster.erase(check);
767 if (cluster.size() < 2) {
771 std::string origReason;
772 std::string origCluster;
775 #ifdef DEBUG_JOINJUNCTIONS
777 std::cout <<
" try to reduce to 4-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
784 WRITE_WARNINGF(
"Reducing junction cluster % (%).", origCluster, origReason);
789 #ifdef DEBUG_JOINJUNCTIONS
791 std::cout <<
" try to reduce to 2-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
798 WRITE_WARNINGF(
"Reducing junction cluster % (%).", origCluster, origReason);
804 if (cluster.size() < 2) {
810 WRITE_WARNINGF(
"Not joining junctions % (%).", origCluster, origReason);
816 for (
NBNode* current : cluster) {
820 newComp.insert(current);
821 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
822 NodeClusters::iterator check = it_comp;
824 bool connected =
false;
825 for (
NBNode* k : *check) {
826 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
828 newComp.insert((*check).begin(), (*check).end());
829 it_comp = components.erase(check);
839 components.push_back(newComp);
841 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
842 if ((*it_comp).size() > 1) {
844 clusters.push_back(*it_comp);
847 #ifdef DEBUG_JOINJUNCTIONS
852 return (
int)clusters.size();
857 #ifdef DEBUG_JOINJUNCTIONS
858 std::cout <<
"joinSameJunctions...\n";
860 std::map<std::string, NodeSet> positions;
862 Position pos = item.second->getPosition();
866 positions[rounded].insert(item.second);
869 for (
auto& item : positions) {
870 if (item.second.size() > 1) {
871 for (
NBNode* n : item.second) {
873 item.second.erase(n);
876 if (item.second.size() > 1) {
877 clusters.push_back(item.second);
882 return (
int)clusters.size();
887 #ifdef DEBUG_JOINJUNCTIONS
893 bool pruneFringe =
true;
896 while (pruneFringe) {
898 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
899 NodeSet::iterator check = j;
904 double clusterDist = std::numeric_limits<double>::max();
905 bool touchingCluster =
false;
907 NBNode* neighbor = (*it_edge)->getToNode();
908 if (cluster.count(neighbor) != 0) {
909 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
914 NBNode* neighbor = (*it_edge)->getFromNode();
915 if (cluster.count(neighbor) != 0) {
916 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
922 std::set<NBNode*> outsideNeighbors;
923 std::set<NBNode*> clusterNeighbors;
924 const double pedestrianFringeThreshold = 0.3;
926 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
927 if (cluster.count(neighbor) == 0) {
930 || clusterDist <= pedestrianFringeThreshold
931 || touchingCluster) {
932 outsideNeighbors.insert(neighbor);
935 clusterNeighbors.insert(neighbor);
938 #ifdef DEBUG_JOINJUNCTIONS
940 <<
" clusterDist=" << clusterDist
941 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
942 <<
" touching=" << touchingCluster
947 if (clusterNeighbors.size() == 0
948 || (outsideNeighbors.size() <= 1
949 && clusterNeighbors.size() == 1
951 cluster.erase(check);
953 #ifdef DEBUG_JOINJUNCTIONS
955 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
966 std::set<NBNode*> toRemove;
967 int maxPassengerLanes = 0;
968 for (
NBNode* n : cluster) {
969 for (
NBEdge* edge : n->getEdges()) {
970 maxPassengerLanes =
MAX2(maxPassengerLanes, edge->getNumLanesThatAllow(
SVC_PASSENGER));
973 for (
NBNode* n : cluster) {
974 for (
NBEdge* edge : n->getOutgoingEdges()) {
978 std::vector<NBNode*> passed;
981 NBNode* to = edge->getToNode();
982 while (cluster.count(to) != 0) {
984 bool goStraight = (std::find(passed.begin(), passed.end(), to) == passed.end()
989 passed.push_back(to);
992 if (cur !=
nullptr) {
1003 #ifdef DEBUG_JOINJUNCTIONS
1005 std::cout <<
"check edge length " << edge->getID() <<
" (" << length <<
", passed=" << passed.size() <<
", max=" << longThreshold <<
")\n";
1008 if (length > longThreshold) {
1014 #ifdef DEBUG_JOINJUNCTIONS
1016 std::cout <<
"node=" << n->getID() <<
" long edge " << edge->getID() <<
" (" << length <<
", passed=" <<
toString(passed) <<
", max=" << longThreshold <<
") keepStart=" << keepStart <<
" keepEnd=" << keepEnd <<
"\n";
1022 toRemove.insert(passed.begin(), passed.end() - 1);
1024 toRemove.insert(passed.back());
1030 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
1040 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1041 if (cluster.count(neighbor) != 0) {
1042 result.insert(neighbor);
1051 #ifdef DEBUG_JOINJUNCTIONS
1053 std::cout <<
"pruning slip-lanes at cluster=" <<
joinNamedToString(cluster,
' ') <<
"\n";
1057 if (cluster.size() <= 2) {
1061 for (
NBNode* n : cluster) {
1067 #ifdef DEBUG_JOINJUNCTIONS
1069 std::cout <<
" candidate slip-lane start=" << n->getID() <<
" outgoing=" <<
toString(outgoing) <<
"\n";
1072 for (
NBEdge* contEdge : outgoing) {
1076 double slipLength = contEdge->getLength();
1077 NBNode* cont = contEdge->getToNode();
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 end=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1103 const NBEdge*
const otherEdge = (contEdge == outgoing.front() ? outgoing.back() : outgoing.front());
1106 std::vector<NodeAndDist> toProc;
1109 while (!toProc.empty()) {
1111 NBNode* cont2 = nodeAndDist.first;
1112 double dist = nodeAndDist.second;
1113 #ifdef DEBUG_JOINJUNCTIONS
1115 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1119 if (visited.find(cont2) != visited.end()) {
1122 visited.insert(cont2);
1123 if (cont2 == cont) {
1128 const double dist2 = dist + e->getLength();
1129 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1130 toProc.push_back(std::make_pair(e->getToNode(), dist2));
1137 toRemove.insert(cands.begin(), cands.end());
1138 #ifdef DEBUG_JOINJUNCTIONS
1140 std::cout <<
" found slip-lane with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1153 #ifdef DEBUG_JOINJUNCTIONS
1155 std::cout <<
" candidate slip-lane end=" << n->getID() <<
" incoming=" <<
toString(incoming) <<
"\n";
1158 for (
NBEdge* contEdge : incoming) {
1162 double slipLength = contEdge->getLength();
1163 NBNode* cont = contEdge->getFromNode();
1167 if (cands.count(cont) != 0) {
1171 #ifdef DEBUG_JOINJUNCTIONS
1173 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1180 #ifdef DEBUG_JOINJUNCTIONS
1182 std::cout <<
" candidate slip-lane start=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1189 const NBEdge*
const otherEdge = (contEdge == incoming.front() ? incoming.back() : incoming.front());
1192 std::vector<NodeAndDist> toProc;
1195 while (!toProc.empty()) {
1197 NBNode* cont2 = nodeAndDist.first;
1198 double dist = nodeAndDist.second;
1199 #ifdef DEBUG_JOINJUNCTIONS
1201 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1205 if (visited.find(cont2) != visited.end()) {
1208 visited.insert(cont2);
1209 if (cont2 == cont) {
1214 const double dist2 = dist + e->getLength();
1215 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1216 toProc.push_back(std::make_pair(e->getFromNode(), dist2));
1223 toRemove.insert(cands.begin(), cands.end());
1224 #ifdef DEBUG_JOINJUNCTIONS
1226 std::cout <<
" found slip-lane start with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1238 for (
NBNode* n : toRemove) {
1239 numRemoved += (int)cluster.erase(n);
1241 if (numRemoved > 0) {
1242 #ifdef DEBUG_JOINJUNCTIONS
1244 std::cout <<
" removed " << numRemoved <<
" nodes from cluster: " <<
joinNamedToString(toRemove,
' ') <<
"\n";
1263 if (inRelAngle < 135) {
1270 const double outRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1271 if (outRelAngle <= 45) {
1272 straight.push_back(out);
1273 }
else if (outRelAngle >= 135) {
1277 if (straight.size() == 2 && numReverse == 1) {
1278 outgoing.insert(outgoing.begin(), straight.begin(), straight.end());
1279 inAngle = in->getAngleAtNode(n);
1299 if (outRelAngle < 135) {
1306 const double inRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1307 if (inRelAngle <= 45) {
1308 straight.push_back(in);
1309 }
else if (inRelAngle >= 135) {
1313 if (straight.size() == 2 && numReverse == 1) {
1314 incoming.insert(incoming.begin(), straight.begin(), straight.end());
1315 outAngle = out->getAngleAtNode(n);
1327 std::map<std::string, double> finalIncomingAngles;
1328 std::map<std::string, double> finalOutgoingAngles;
1329 for (NodeSet::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
1330 for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
1337 for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
1346 #ifdef DEBUG_JOINJUNCTIONS
1347 for (
NBNode* n : cluster) {
1350 <<
"\n inAngles=" <<
joinToString(finalIncomingAngles,
' ',
':')
1351 <<
"\n outAngles=" <<
joinToString(finalOutgoingAngles,
' ',
':')
1356 if (finalIncomingAngles.size() > 4) {
1357 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
1361 const double PARALLEL_INCOMING_THRESHOLD = 10.0;
1362 bool foundParallel =
false;
1363 for (std::map<std::string, double>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
1364 std::map<std::string, double>::const_iterator k = j;
1365 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
1366 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
1367 reason =
"parallel incoming " + j->first +
"," + k->first;
1373 for (std::map<std::string, double>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
1374 std::map<std::string, double>::const_iterator k = j;
1375 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
1376 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
1377 reason =
"parallel outgoing " + j->first +
"," + k->first;
1384 for (
auto it = sc.
begin(); it != sc.
end(); it++) {
1386 if (edge !=
nullptr && cluster.count(edge->
getFromNode()) != 0 && cluster.count(edge->
getToNode()) != 0) {
1387 reason =
"it contains stop '" + it->first +
"'";
1393 for (
NBNode* n : cluster) {
1394 if (n->isTLControlled()) {
1398 const bool hasTLS = numTLS > 0;
1400 if (cluster.size() > 2) {
1402 double maxDist = -1;
1403 NBEdge* maxEdge =
nullptr;
1404 for (
NBNode* n1 : cluster) {
1405 for (
NBNode* n2 : cluster) {
1406 NBEdge* e1 = n1->getConnectionTo(n2);
1407 NBEdge* e2 = n2->getConnectionTo(n1);
1418 #ifdef DEBUG_JOINJUNCTIONS
1419 for (
NBNode* n : cluster) {
1421 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxDist=" << maxDist <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
1425 if (!hasTLS && maxDist > 5) {
1427 std::vector<NBNode*> toCheck;
1428 std::set<NBNode*> visited;
1429 toCheck.push_back(maxEdge->
getToNode());
1430 bool foundCircle =
false;
1431 while (!toCheck.empty()) {
1432 NBNode* n = toCheck.back();
1441 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1442 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
1443 toCheck.push_back(cand);
1449 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxDist) +
")";
1455 if (!hasTLS && cluster.size() >= 2) {
1458 int outsideIncoming = 0;
1459 int outsideOutgoing = 0;
1460 int edgesWithin = 0;
1461 for (
NBNode* n : cluster) {
1462 bool foundOutsideIncoming =
false;
1464 if (cluster.count(e->getFromNode()) == 0) {
1467 foundOutsideIncoming =
true;
1472 if (foundOutsideIncoming) {
1475 bool foundOutsideOutgoing =
false;
1476 for (
NBEdge* e : n->getOutgoingEdges()) {
1477 if (cluster.count(e->getToNode()) == 0) {
1480 foundOutsideOutgoing =
true;
1483 if (foundOutsideOutgoing) {
1487 if (entryNodes < 2) {
1488 reason =
"only 1 entry node";
1491 if (exitNodes < 2) {
1492 reason =
"only 1 exit node";
1495 if (cluster.size() == 2) {
1496 if (edgesWithin == 1 && outsideIncoming < 3 && outsideOutgoing < 3) {
1497 reason =
"only 1 edge within and no cross-traffic";
1509 assert(circleSize >= 2);
1510 if ((
int)cands.size() == circleSize) {
1511 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1514 candCluster.insert(cands.begin(), cands.end());
1516 const bool feasible = (int)candCluster.size() == circleSize;
1519 cluster.insert(cands.begin(), cands.end());
1526 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1531 if (cands.size() == 0) {
1546 singleStart.insert(cands.back());
1549 std::vector<NBNode*> cands2(cands);
1563 double minDist = std::numeric_limits<double>::max();
1564 NBEdge* result =
nullptr;
1565 for (
NBNode* n : startNodes) {
1566 for (
NBEdge* e : n->getOutgoingEdges()) {
1567 NBNode* neigh = e->getToNode();
1568 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1571 if (dist < minDist) {
1585 for (
NodeSet cluster : clusters) {
1594 assert(cluster.size() > 1);
1595 std::string
id =
"cluster";
1601 std::set<NBEdge*, ComparatorIdLess> allEdges;
1602 for (
NBNode* n : cluster) {
1604 allEdges.insert(edges.begin(), edges.end());
1607 std::set<NBEdge*, ComparatorIdLess> clusterIncoming;
1608 std::set<NBEdge*, ComparatorIdLess> inside;
1609 for (
NBEdge* e : allEdges) {
1610 if (cluster.count(e->getToNode()) > 0) {
1611 if (cluster.count(e->getFromNode()) > 0) {
1618 clusterIncoming.insert(e);
1622 #ifdef DEBUG_JOINJUNCTIONS
1628 NBNode* newNode =
nullptr;
1629 if (predefined !=
nullptr) {
1630 newNode = predefined;
1639 std::string tlID = id;
1640 if (predefined !=
nullptr) {
1642 nodeType = predefined->
getType();
1655 newNode->
reinit(pos, nodeType);
1658 if (!tlc.
insert(tlDef)) {
1661 throw ProcessError(
"Could not allocate tls '" +
id +
"'.");
1666 std::map<NBEdge*, EdgeSet> reachable;
1667 for (
NBEdge* e : clusterIncoming) {
1671 while (open.size() > 0) {
1672 NBEdge* cur = open.back();
1676 if (cluster.count(cur->
getToNode()) == 0) {
1684 if (seen.count(out) == 0
1685 && allEdges.count(out) != 0
1687 open.push_back(out);
1692 for (
const auto& con : cons) {
1693 if (con.toEdge !=
nullptr
1694 && seen.count(con.toEdge) == 0
1695 && allEdges.count(con.toEdge) != 0) {
1696 open.push_back(con.toEdge);
1702 for (
NBEdge* reached : seen) {
1704 if (inside.count(reached) == 0) {
1705 reachable[e].insert(reached);
1708 #ifdef DEBUG_JOINJUNCTIONS
1709 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1714 for (
NBEdge* e : inside) {
1715 for (
NBEdge* e2 : allEdges) {
1717 e2->replaceInConnections(e, e->getConnections());
1725 for (
NBEdge* e : allEdges) {
1726 std::vector<NBEdge::Connection> conns = e->getConnections();
1727 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1728 NBNode* from = outgoing ? newNode : e->getFromNode();
1729 NBNode* to = outgoing ? e->getToNode() : newNode;
1732 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1734 e->setParameter(
"origTo", e->getToNode()->getID());
1737 if (e->getTurnSignTarget() !=
"") {
1738 for (
NBNode* n : cluster) {
1739 if (e->getTurnSignTarget() == n->getID()) {
1740 e->setTurnSignTarget(to->
getID());
1745 e->reinitNodes(from, to);
1748 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1750 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1756 if (!resetConnections) {
1762 in->removeFromConnections(out, -1, -1,
true,
false,
true);
1768 in->invalidateConnections(
true);
1774 for (
NBNode* n : cluster) {
1782 std::set<std::string> ids;
1783 for (
NBNode* n : cluster) {
1784 ids.insert(n->getID());
1794 bool ambiguousType =
false;
1795 for (
NBNode* j : cluster) {
1796 pos.
add(j->getPosition());
1798 if (j->isTLControlled()) {
1801 type = (*j->getControllingTLS().begin())->getType();
1802 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
1803 ambiguousType =
true;
1809 nodeType = otherType;
1810 }
else if (nodeType != otherType) {
1822 pos.
mul(1.0 / cluster.size());
1823 if (ambiguousType) {
1825 WRITE_WARNINGF(
"Ambiguous traffic light type for node cluster '%', setting to '%'.",
id,
toString(type));
1833 bool tooFast =
false;
1834 double laneSpeedSum = 0;
1835 std::set<NBEdge*> seen;
1838 for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
1839 if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
1842 if (j->hasIncoming(*k)) {
1843 laneSpeedSum += (double)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
1845 if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
1851 return !tooFast && laneSpeedSum >= laneSpeedThreshold && c.size() != 0;
1863 nonPedIncoming.push_back(e);
1866 for (
NBEdge* e : node->getOutgoingEdges()) {
1868 nonPedOutgoing.push_back(e);
1871 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
1887 if (node->isTLControlled()) {
1893 const std::string tlID = tl->
getID();
1894 if (tlID != node->getID()
1910 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
1911 std::vector<NBNode*> ncontrolled;
1912 if (oc.
isSet(
"tls.unset")) {
1913 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
1914 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
1917 throw ProcessError(
" The junction '" + *i +
"' to set as not-controlled is not known.");
1920 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
1921 (*j)->removeNode(n);
1924 ncontrolled.push_back(n);
1931 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
1932 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1933 NBNode* cur = (*i).second;
1934 if (cur->
isNearDistrict() && std::find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
1942 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
1944 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
1945 for (
const auto& item :
myNodes) {
1946 const NBNode* node = item.second;
1948 #ifdef DEBUG_GUESSSIGNALS
1950 std::cout <<
" propagate TLS from " << node->
getID() <<
" downstream\n";
1956 edge->setSignalPosition(node->
getPosition(), node);
1961 std::set<NBEdge*> seen;
1962 std::set<NBEdge*> check;
1963 for (
const auto& item :
myNodes) {
1964 for (
NBEdge* edge : item.second->getOutgoingEdges()) {
1968 #ifdef DEBUG_GUESSSIGNALS
1969 if (
DEBUGCOND(edge->getSignalNode()) ||
true) {
1970 std::cout <<
" primary signalPosition edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
1977 while (check.size() > 0) {
1978 NBEdge*
const edge = *check.begin();
1979 check.erase(check.begin());
1984 if (seen.count(outEdge) == 0) {
1986 #ifdef DEBUG_GUESSSIGNALS
1988 std::cout <<
" setSignalPosition edge=" << outEdge->
getID() <<
" pos=" << edge->
getSignalPosition() <<
"\n";
1991 check.insert(outEdge);
1998 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1999 NBNode* node = i->second;
2000 if (find(ncontrolled.begin(), ncontrolled.end(), node) != ncontrolled.end()) {
2008 std::vector<const NBNode*> signals;
2011 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2012 const NBEdge* inEdge = *it_i;
2014 #ifdef DEBUG_GUESSSIGNALS
2016 std::cout <<
" noTLS, edge=" << inEdge->
getID() <<
"\n";
2027 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2028 const NBEdge* inEdge = *it_i;
2031 #ifdef DEBUG_GUESSSIGNALS
2040 if (signal !=
nullptr) {
2041 signals.push_back(signal);
2046 for (
const NBEdge* outEdge : outgoing) {
2047 NBNode* cand = outEdge->getToNode();
2049 #ifdef DEBUG_GUESSSIGNALS
2051 std::cout <<
" node=" << node->
getID() <<
" outEdge=" << outEdge->getID() <<
" signalNode=" << cand->
getID() <<
" len=" << outEdge->getLength() <<
"\n";
2054 signals.push_back(cand);
2059 for (
const NBNode* s : signals) {
2060 std::set<NBTrafficLightDefinition*> tls = s->getControllingTLS();
2062 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
2069 if (!tlc.
insert(tlDef)) {
2081 if (oc.
getBool(
"tls.guess.joining")) {
2086 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
2090 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2091 if ((*j)->isTLControlled() || std::find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
2107 for (
auto nodeSet : cands) {
2108 std::vector<NBNode*> nodes;
2109 for (
NBNode* node : nodeSet) {
2110 nodes.push_back(node);
2113 std::string
id =
"joinedG_" +
toString(index++);
2115 if (!tlc.
insert(tlDef)) {
2125 if (oc.
getBool(
"tls.guess")) {
2126 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2127 NBNode* cur = (*i).second;
2133 if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
2148 std::set<NBTrafficLightDefinition*> recompute;
2150 if (!node->hasConflict()) {
2151 const std::set<NBTrafficLightDefinition*>& tlDefs = node->getControllingTLS();
2152 recompute.insert(tlDefs.begin(), tlDefs.end());
2153 node->removeTrafficLights(
true);
2155 edge->clearControllingTLInformation();
2160 if (def->getNodes().size() == 0) {
2163 def->setParticipantsInformation();
2164 def->setTLControllingInformation();
2173 for (
const auto& item :
myNodes) {
2174 item.second->computeKeepClear();
2185 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2186 if (!(*j)->isTLControlled()) {
2197 bool dummySetTL =
false;
2198 std::string
id =
"joined";
2203 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
2204 j->removeTrafficLights();
2209 std::vector<NBNode*> nodes;
2218 if (!tlc.
insert(tlDef)) {
2235 if (!tlc.
insert(tlDef)) {
2237 WRITE_WARNINGF(
"Building a tl-logic for junction '%' twice is not possible.",
id);
2247 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2248 (*i).second->computeLanes2Lanes();
2256 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2257 (*i).second->computeLogic(ec);
2264 std::set<NBNode*> roundaboutNodes;
2265 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
2266 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
2267 if (checkLaneFoesRoundabout) {
2269 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
2270 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
2271 roundaboutNodes.insert((*j)->getToNode());
2275 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2276 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
2277 (*i).second->computeLogic2(checkLaneFoes);
2284 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2285 delete ((*i).second);
2298 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
2300 while (
retrieve(freeID) !=
nullptr) {
2303 freeID =
"SUMOGenerated" + toString<int>(counter);
2311 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2312 (*i).second->computeNodeShape(mismatchThreshold);
2319 WRITE_MESSAGE(
"-----------------------------------------------------");
2322 int numUnregulatedJunctions = 0;
2323 int numDeadEndJunctions = 0;
2324 int numTrafficLightJunctions = 0;
2325 int numPriorityJunctions = 0;
2326 int numRightBeforeLeftJunctions = 0;
2327 int numAllWayStopJunctions = 0;
2328 int numZipperJunctions = 0;
2329 int numDistrictJunctions = 0;
2330 int numRailCrossing = 0;
2331 int numRailSignals = 0;
2332 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2333 switch ((*i).second->getType()) {
2335 ++numUnregulatedJunctions;
2338 ++numDeadEndJunctions;
2343 ++numTrafficLightJunctions;
2347 ++numPriorityJunctions;
2350 ++numRightBeforeLeftJunctions;
2353 ++numAllWayStopJunctions;
2356 ++numZipperJunctions;
2359 ++numDistrictJunctions;
2376 if (numDeadEndJunctions > 0) {
2381 if (numTrafficLightJunctions > 0) {
2384 if (numAllWayStopJunctions > 0) {
2387 if (numZipperJunctions > 0) {
2390 if (numRailCrossing > 0) {
2393 if (numRailSignals > 0) {
2396 if (numDistrictJunctions > 0) {
2404 WRITE_MESSAGE(
"-----------------------------------------------------");
2408 std::vector<std::string>
2410 std::vector<std::string> ret;
2411 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2412 ret.push_back((*i).first);
2420 if (
myNodes.count(newID) != 0) {
2421 throw ProcessError(
"Attempt to rename node using existing id '" + newID +
"'");
2431 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2432 NBNode* node = i->second;
2436 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
2443 edge->setSignalPosition(node->
getPosition(),
nullptr);
2444 #ifdef DEBUG_GUESSSIGNALS
2445 std::cout <<
" discard-simple " << node->
getID() <<
" edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2449 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
2464 NBNode* node = item.second;
2475 std::vector<std::string> avoid;
2481 std::set<std::string> reserve;
2485 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
2489 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
2491 toChange.insert(it->second);
2498 toChange.insert(it->second);
2501 if (reservedIDs && reserve.count(it->first) > 0) {
2502 toChange.insert(it->second);
2506 for (
NBNode* node : toChange) {
2509 for (
NBNode* node : toChange) {
2513 node->setID(idSupplier.
getNext());
2514 myNodes[node->getID()] = node;
2516 if (prefix.empty()) {
2517 return (
int)toChange.size();
2522 for (
auto item : oldNodes) {
2524 rename(item.second, prefix + item.first);
2539 for (
const auto& item :
myNodes) {
2542 paretoCheck(item.second, bottomRightFront, 1, -1);
2543 paretoCheck(item.second, bottomLeftFront, -1, -1);
2546 front.insert(topRightFront.begin(), topRightFront.end());
2547 front.insert(topLeftFront.begin(), topLeftFront.end());
2548 front.insert(bottomRightFront.begin(), bottomRightFront.end());
2549 front.insert(bottomLeftFront.begin(), bottomLeftFront.end());
2551 for (
NBNode* n : front) {
2552 const int in = (int)n->getIncomingEdges().size();
2553 const int out = (int)n->getOutgoingEdges().size();
2554 if ((in <= 1 && out <= 1) &&
2555 (in == 0 || out == 0
2556 || n->getIncomingEdges().front()->isTurningDirectionAt(n->getOutgoingEdges().front()))) {
2569 std::vector<NBNode*> dominated;
2571 const double x2 =
fn->getPosition().x() * xSign;
2572 const double y2 =
fn->getPosition().y() * ySign;
2573 if (x2 >= x && y2 >= y) {
2575 }
else if (x2 <= x && y2 <= y) {
2576 dominated.push_back(
fn);
2579 frontier.insert(node);
2580 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.
bool isWaterway(SVCPermissions permissions)
Returns whether an edge with the given permission is a waterway 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
int gPrecision
the precision for floating point outputs
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
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)
static methods for processing the coordinates conversion for the current net
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
const Boundary & getOrigBoundary() const
Returns the original boundary.
const Position getOffsetBase() const
Returns the network base.
const Boundary & getConvBoundary() const
Returns the converted boundary.
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 removeRoundaboutEdges(const EdgeSet &toRemove)
remove edges from all stored roundabouts
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
std::vector< std::vector< std::string > > myRailComponents
network components that must be removed if not connected to the road network via stop access
NamedRTree myRTree
node positions for faster lookup
void removeRailComponents(NBDistrictCont &dc, NBEdgeCont &ec, NBPTStopCont &sc)
remove rail components after ptstops are built
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.
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 joinSimilarEdges(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, bool removeDuplicates)
Joins edges connecting the same nodes.
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 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 removeComponents(NBDistrictCont &dc, NBEdgeCont &ec, const int numKeep, bool hasPTStops)
Checks the network for weak connectivity and removes all but the largest components....
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 replaceEdge(const std::string &edgeID, const EdgeVector &replacement)
replace the edge with the given edge list in all lines
const std::map< std::string, NBPTStop * > & getStops() const
void replaceEdge(const std::string &edgeID, const EdgeVector &replacement)
replace the edge with the closes edge on the given edge list in all stops
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.
const std::vector< NBNode * > & getNodes() const
Returns the list of controlled nodes.
virtual void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane, bool incoming)=0
Replaces a removed edge/lane.
A container for traffic light definitions and built programs.
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.
static std::string realString(const double v, const int precision=gPrecision)
Helper method for string formatting.
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.