60#define MAX_SLIPLANE_LENGTH 1000
70#define DEBUGNODEID2 ""
72#define DEBUGCOND(obj) ((obj) != 0 && ((obj)->getID() == DEBUGNODEID || (obj)->getID() == DEBUGNODEID2))
93 NodeCont::iterator i =
myNodes.find(
id);
99 const float pos[2] = {(float)position.
x(), (float)position.
y()};
107 std::string
id = node->
getID();
108 NodeCont::iterator i =
myNodes.find(
id);
121 NodeCont::const_iterator i =
myNodes.find(
id);
131 const double extOffset = offset + POSITION_EPS;
132 const float cmin[2] = {(float)(position.
x() - extOffset), (
float)(position.
y() - extOffset)};
133 const float cmax[2] = {(float)(position.
x() + extOffset), (
float)(position.
y() + extOffset)};
134 std::set<const Named*> into;
137 for (
const Named* namedNode : into) {
181 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
182 no += (*i).second->removeSelfLoops(dc, ec, tc);
193 const double distanceThreshold = 7.;
194 const double lengthThreshold = 0.10;
196 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
198 std::map<NBNode*, EdgeVector> connectionCount;
199 const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
200 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
201 connectionCount[(*j)->getToNode()].push_back(*j);
204 std::map<NBNode*, EdgeVector>::iterator k;
205 for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
207 if ((*k).second.size() < 2) {
213 const NBEdge*
const first = ev.front();
214 EdgeVector::const_iterator jci;
215 for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
218 (relativeLengthDifference > lengthThreshold) ||
219 (fabs(first->
getSpeed() - (*jci)->getSpeed()) >= 0.01) ||
227 if (jci == ev.end()) {
228 if (removeDuplicates) {
229 for (
int ei = 1; ei < (int)ev.size(); ei++) {
244 const std::vector<std::string>& edgeNames = ec.
getAllNames();
245 for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
254 if (outgoingEdges.size() != 1) {
259 if (incomingEdges.size() > 1) {
262 }
else if (incomingEdges.size() == 1) {
263 NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
264 NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
265 if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
273 bool hasJunction =
false;
285 adjacentNodes.clear();
286 for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
287 if ((*itOfOutgoings)->getToNode() != from
288 && (*itOfOutgoings)->getToNode() != to
292 adjacentNodes.insert((*itOfOutgoings)->getToNode());
294 for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
295 adjacentNodes.insert((*itOfIncomings)->getFromNode());
297 adjacentNodes.erase(to);
298 if (adjacentNodes.size() > 2) {
301 }
while (!hasJunction && eOld != e);
303 std::string warningString;
304 for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
305 if (roadIt == road.begin()) {
306 warningString += (*roadIt)->
getID();
308 warningString +=
"," + (*roadIt)->getID();
311 NBNode* fromNode = (*roadIt)->getFromNode();
312 NBNode* toNode = (*roadIt)->getToNode();
313 ec.
erase(dc, *roadIt);
332 std::vector<std::set<NBEdge*> > components;
334 std::set<std::string> edgesLeft;
335 for (std::map<std::string, NBEdge*>::const_iterator edgeIt = ec.
begin(); edgeIt != ec.
end(); ++edgeIt) {
336 edgesLeft.insert(edgeIt->first);
339 std::set<NBEdge*> toRemove;
340 int foundComponents = 0;
342 while (!edgesLeft.empty()) {
343 queue.push_back(ec.
getByID(*edgesLeft.begin()));
344 std::set<NBEdge*> component;
345 while (!queue.empty()) {
346 NBEdge*
const e = queue.back();
349 std::vector<EdgeVector> edgeLists;
354 for (std::vector<EdgeVector>::const_iterator listIt = edgeLists.begin(); listIt != edgeLists.end(); ++listIt) {
355 for (EdgeVector::const_iterator edgeIt = listIt->begin(); edgeIt != listIt->end(); ++edgeIt) {
356 std::set<std::string>::iterator leftIt = edgesLeft.find((*edgeIt)->getID());
357 if (leftIt != edgesLeft.end()) {
358 queue.push_back(*edgeIt);
359 edgesLeft.erase(leftIt);
365 std::vector<std::set<NBEdge*> >::iterator cIt;
366 for (cIt = components.begin(); cIt != components.end(); ++cIt) {
367 if (cIt->size() < component.size()) {
371 components.insert(cIt, component);
372 if ((
int)components.size() > numKeep) {
373 bool recheck =
false;
375 for (
NBEdge* e : components.back()) {
385 toRemove.insert(components.back().begin(), components.back().end());
388 std::vector<std::string> edgeIDs;
389 for (
NBEdge* e : components.back()) {
390 edgeIDs.push_back(e->getID());
394 components.pop_back();
398 for (
NBEdge* e : toRemove) {
399 NBNode*
const fromNode = e->getFromNode();
400 NBNode*
const toNode = e->getToNode();
409 if (foundComponents > 1) {
417 std::set<std::string> stopEdges;
418 for (
const auto& item : sc.
getStops()) {
419 stopEdges.insert(item.second->getEdgeId());
422 int numRemovedEdges = 0;
425 for (std::string edgeID : component) {
426 if (stopEdges.count(edgeID) != 0) {
433 numRemovedEdges += (int)component.size();
434 for (std::string edgeID : component) {
450 if (numRemoved > 0) {
461 bool removeGeometryNodes) {
463 std::set<std::string> edges2keep;
464 if (removeGeometryNodes) {
466 if (oc.
isSet(
"geometry.remove.keep-edges.input-file")) {
469 if (oc.
isSet(
"geometry.remove.keep-edges.explicit")) {
470 const std::vector<std::string> edges = oc.
getStringVector(
"geometry.remove.keep-edges.explicit");
471 edges2keep.insert(edges.begin(), edges.end());
476 if (oc.
exists(
"geometry.remove.keep-ptstops") && oc.
getBool(
"geometry.remove.keep-ptstops")) {
480 std::vector<NBNode*> toRemove;
482 std::map<NBEdge*, std::set<NBTrafficLightDefinition*> > tlsLookup;
483 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
492 for (
const auto& i :
myNodes) {
493 NBNode*
const current = i.second;
500 if (edges2keep.find(it_edge->getID()) != edges2keep.end()) {
510 for (
const std::pair<NBEdge*, NBEdge*>& j : current->
getEdgesToJoin()) {
512 NBEdge*
const continuation = j.second;
513 begin->append(continuation);
515 auto itTL = tlsLookup.find(continuation);
516 if (itTL != tlsLookup.end()) {
520 tlsLookup[
begin] = itTL->second;
524 ec.
extract(dc, continuation,
true);
526 toRemove.push_back(current);
529 for (
NBNode* n : toRemove) {
532 return (
int)toRemove.size();
538 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
539 (*i).second->avoidOverlap();
547 std::set<NBNode*> visited;
548 for (
const auto& i :
myNodes) {
549 if (visited.count(i.second) > 0) {
552 std::vector<NodeAndDist> toProc;
553 toProc.emplace_back(i.second, 0.);
555 while (!toProc.empty()) {
556 NBNode*
const n = toProc.back().first;
557 const double dist = toProc.back().second;
559 if (visited.count(n) > 0) {
563 bool pureRail =
true;
564 bool railAndPeds =
true;
582 const double length = e->getLoadedLength();
583#ifdef DEBUG_JOINJUNCTIONS
585 std::cout <<
"generateNodeClusters: consider s=" << s->
getID()
586 <<
" clusterNode=" << n->
getID() <<
" edge=" << e->getID() <<
" length=" << length <<
" with cluster " <<
joinNamedToString(c,
' ') <<
"\n";
590 bool railAndPeds2 =
true;
593 railAndPeds2 =
false;
604 const bool joinPedCrossings = bothCrossing && e->getPermissions() ==
SVC_PEDESTRIAN;
606 !joinPedCrossings && (
609 || (length > 3 * POSITION_EPS
618 bool foundRail =
false;
621 if ((e2->getPermissions() & railNoTram) != 0) {
634 if (visited.find(s) != visited.end()) {
637 if (length + dist < maxDist) {
639 toProc.emplace_back(s, dist + length);
641 toProc.emplace_back(s, 0.);
649#ifdef DEBUG_JOINJUNCTIONS
659 for (
const std::string& nodeID : ids) {
663 WRITE_WARNINGF(
TL(
"Ignoring join exclusion for junction '%' since it already occurred in a list of nodes to be joined."), nodeID);
675 maxIds = (int)cluster.size();
677 if ((
int)cluster.size() > maxIds) {
678 auto clusterIt = cluster.begin();
679 std::string result = prefix + *clusterIt;
680 for (
int i = 1; i < maxIds; i++) {
682 result +=
"_" + *clusterIt;
684 return result +
"_#" +
toString((
int)cluster.size() - maxIds) +
"more";
693 std::set<std::string> validCluster;
694 for (std::string nodeID : cluster) {
696 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' was already excluded from joining."), nodeID);
698 }
else if (
myJoined.count(nodeID) > 0) {
699 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' already occurred in another join-cluster."), nodeID);
703 validCluster.insert(nodeID);
705 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster.");
709 if (validCluster.size() > 1) {
710 myJoined.insert(validCluster.begin(), validCluster.end());
713 WRITE_WARNINGF(
TL(
"Ignoring join-cluster '%' because it has size '%'."), node->
getID(), validCluster.size());
724 for (std::string nodeID : item.first) {
726 if (node ==
nullptr) {
727 WRITE_ERROR(
"unknown junction '" + nodeID +
"' while joining.");
729 cluster.insert(node);
732 if (cluster.size() > 1) {
745#ifdef DEBUG_JOINJUNCTIONS
746 std::cout <<
"joinJunctions...\n";
750 std::map<const NBNode*, std::vector<NBNode*> > ptStopEnds;
752 for (
auto it = sc.
begin(); it != sc.
end(); it++) {
754 if (edge !=
nullptr) {
759 for (
NodeSet& cluster : cands) {
760#ifdef DEBUG_JOINJUNCTIONS
762 for (
NBNode* n : cluster) {
769 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
770 NodeSet::iterator check = j;
773 cluster.erase(check);
779 if (cluster.size() < 2) {
784 if (cluster.size() < 2) {
785 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
789 std::string origReason;
792 if (feasible && ((
int)cluster.size() -
pruneLongEdges(cluster, maxDist,
true) < 2)) {
793 origReason =
"long edge";
797#ifdef DEBUG_JOINJUNCTIONS
799 std::cout <<
" try to reduce to 4-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
805 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
810#ifdef DEBUG_JOINJUNCTIONS
812 std::cout <<
" try to reduce to 2-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
819 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
825 if (cluster.size() < 2) {
826 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
832 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster, origReason);
838 for (
NBNode* current : cluster) {
842 newComp.insert(current);
843 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
844 NodeClusters::iterator check = it_comp;
846 bool connected =
false;
847 for (
NBNode* k : *check) {
848 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
850 newComp.insert((*check).begin(), (*check).end());
851 it_comp = components.erase(check);
861 components.push_back(newComp);
863 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
864 if ((*it_comp).size() > 1) {
866 clusters.push_back(*it_comp);
869#ifdef DEBUG_JOINJUNCTIONS
874 return (
int)clusters.size();
880#ifdef DEBUG_JOINJUNCTIONS
881 std::cout <<
"joinSameJunctions...\n";
883 std::map<std::string, NodeSet> positions;
885 Position pos = item.second->getPosition();
889 positions[rounded].insert(item.second);
892 for (
auto& item : positions) {
893 if (item.second.size() > 1) {
894 for (
NBNode* n : item.second) {
896 item.second.erase(n);
899 if (item.second.size() > 1) {
900 clusters.push_back(item.second);
905 return (
int)clusters.size();
910#ifdef DEBUG_JOINJUNCTIONS
916 bool pruneFringe =
true;
919 while (pruneFringe) {
921 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
922 NodeSet::iterator check = j;
927 double clusterDist = std::numeric_limits<double>::max();
928 bool touchingCluster =
false;
930 NBNode* neighbor = (*it_edge)->getToNode();
931 if (cluster.count(neighbor) != 0) {
932 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
937 NBNode* neighbor = (*it_edge)->getFromNode();
938 if (cluster.count(neighbor) != 0) {
939 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
945 std::set<NBNode*> outsideNeighbors;
946 std::set<NBNode*> clusterNeighbors;
947 const double pedestrianFringeThreshold = 0.3;
949 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
950 if (cluster.count(neighbor) == 0) {
953 || clusterDist <= pedestrianFringeThreshold
954 || touchingCluster) {
955 outsideNeighbors.insert(neighbor);
958 clusterNeighbors.insert(neighbor);
961#ifdef DEBUG_JOINJUNCTIONS
963 <<
" clusterDist=" << clusterDist
964 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
965 <<
" touching=" << touchingCluster
970 if (clusterNeighbors.size() == 0
971 || (outsideNeighbors.size() <= 1
972 && clusterNeighbors.size() == 1
974 cluster.erase(check);
976#ifdef DEBUG_JOINJUNCTIONS
978 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
989 std::set<NBNode*> toRemove;
990 int maxPassengerLanes = 0;
991 for (
NBNode* n : cluster) {
992 for (
NBEdge* edge : n->getEdges()) {
993 maxPassengerLanes =
MAX2(maxPassengerLanes, edge->getNumLanesThatAllow(
SVC_PASSENGER));
996 for (
NBNode* n : cluster) {
997 for (
NBEdge* edge : n->getOutgoingEdges()) {
1001 std::vector<NBNode*> passed;
1004 NBNode* to = edge->getToNode();
1005 while (cluster.count(to) != 0) {
1007 bool goStraight = (std::find(passed.begin(), passed.end(), to) == passed.end()
1012 passed.push_back(to);
1015 if (cur !=
nullptr) {
1026#ifdef DEBUG_JOINJUNCTIONS
1028 std::cout <<
"check edge length " << edge->getID() <<
" (" << length <<
", passed=" << passed.size() <<
", max=" << longThreshold <<
")\n";
1031 if (length > longThreshold) {
1037#ifdef DEBUG_JOINJUNCTIONS
1039 std::cout <<
"node=" << n->getID() <<
" long edge " << edge->getID() <<
" (" << length <<
", passed=" <<
toString(passed) <<
", max=" << longThreshold <<
") keepStart=" << keepStart <<
" keepEnd=" << keepEnd <<
"\n";
1045 toRemove.insert(passed.begin(), passed.end() - 1);
1047 toRemove.insert(passed.back());
1054 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
1058 return (
int)toRemove.size();
1066 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1067 if (cluster.count(neighbor) != 0) {
1068 result.insert(neighbor);
1077#ifdef DEBUG_JOINJUNCTIONS
1079 std::cout <<
"pruning slip-lanes at cluster=" <<
joinNamedToString(cluster,
' ') <<
"\n";
1083 if (cluster.size() <= 2) {
1087 for (
NBNode* n : cluster) {
1093#ifdef DEBUG_JOINJUNCTIONS
1095 std::cout <<
" candidate slip-lane start=" << n->getID() <<
" outgoing=" <<
toString(outgoing) <<
"\n";
1098 for (
NBEdge* contEdge : outgoing) {
1102 double slipLength = contEdge->getLength();
1103 NBNode* cont = contEdge->getToNode();
1107 if (cands.count(cont) != 0) {
1111#ifdef DEBUG_JOINJUNCTIONS
1113 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1120#ifdef DEBUG_JOINJUNCTIONS
1122 std::cout <<
" candidate slip-lane end=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1129 const NBEdge*
const otherEdge = (contEdge == outgoing.front() ? outgoing.back() : outgoing.front());
1132 std::vector<NodeAndDist> toProc;
1135 while (!toProc.empty()) {
1137 NBNode* cont2 = nodeAndDist.first;
1138 double dist = nodeAndDist.second;
1139#ifdef DEBUG_JOINJUNCTIONS
1141 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1145 if (visited.find(cont2) != visited.end()) {
1148 visited.insert(cont2);
1149 if (cont2 == cont) {
1154 const double dist2 = dist + e->getLength();
1155 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1156 toProc.push_back(std::make_pair(e->getToNode(), dist2));
1163 toRemove.insert(cands.begin(), cands.end());
1164#ifdef DEBUG_JOINJUNCTIONS
1166 std::cout <<
" found slip-lane with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1179#ifdef DEBUG_JOINJUNCTIONS
1181 std::cout <<
" candidate slip-lane end=" << n->getID() <<
" incoming=" <<
toString(incoming) <<
"\n";
1184 for (
NBEdge* contEdge : incoming) {
1188 double slipLength = contEdge->getLength();
1189 NBNode* cont = contEdge->getFromNode();
1193 if (cands.count(cont) != 0) {
1197#ifdef DEBUG_JOINJUNCTIONS
1199 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1206#ifdef DEBUG_JOINJUNCTIONS
1208 std::cout <<
" candidate slip-lane start=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1215 const NBEdge*
const otherEdge = (contEdge == incoming.front() ? incoming.back() : incoming.front());
1218 std::vector<NodeAndDist> toProc;
1221 while (!toProc.empty()) {
1223 NBNode* cont2 = nodeAndDist.first;
1224 double dist = nodeAndDist.second;
1225#ifdef DEBUG_JOINJUNCTIONS
1227 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1231 if (visited.find(cont2) != visited.end()) {
1234 visited.insert(cont2);
1235 if (cont2 == cont) {
1240 const double dist2 = dist + e->getLength();
1241 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1242 toProc.push_back(std::make_pair(e->getFromNode(), dist2));
1249 toRemove.insert(cands.begin(), cands.end());
1250#ifdef DEBUG_JOINJUNCTIONS
1252 std::cout <<
" found slip-lane start with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1264 for (
NBNode* n : toRemove) {
1265 numRemoved += (int)cluster.erase(n);
1267 if (numRemoved > 0) {
1268#ifdef DEBUG_JOINJUNCTIONS
1270 std::cout <<
" removed " << numRemoved <<
" nodes from cluster: " <<
joinNamedToString(toRemove,
' ') <<
"\n";
1289 if (inRelAngle < 135) {
1296 const double outRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1297 if (outRelAngle <= 45) {
1298 straight.push_back(out);
1299 }
else if (outRelAngle >= 135) {
1303 if (straight.size() == 2 && numReverse == 1) {
1304 outgoing.insert(outgoing.begin(), straight.begin(), straight.end());
1305 inAngle = in->getAngleAtNode(n);
1325 if (outRelAngle < 135) {
1332 const double inRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1333 if (inRelAngle <= 45) {
1334 straight.push_back(in);
1335 }
else if (inRelAngle >= 135) {
1339 if (straight.size() == 2 && numReverse == 1) {
1340 incoming.insert(incoming.begin(), straight.begin(), straight.end());
1341 outAngle = out->getAngleAtNode(n);
1353 std::map<std::string, double> finalIncomingAngles;
1354 std::map<std::string, double> finalOutgoingAngles;
1355 for (NodeSet::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
1356 for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
1363 for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
1372#ifdef DEBUG_JOINJUNCTIONS
1373 for (
NBNode* n : cluster) {
1376 <<
"\n inAngles=" <<
joinToString(finalIncomingAngles,
' ',
':')
1377 <<
"\n outAngles=" <<
joinToString(finalOutgoingAngles,
' ',
':')
1382 if (finalIncomingAngles.size() > 4) {
1383 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
1387 const double PARALLEL_INCOMING_THRESHOLD = 10.0;
1388 bool foundParallel =
false;
1389 for (std::map<std::string, double>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
1390 std::map<std::string, double>::const_iterator k = j;
1391 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
1392 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
1393 reason =
"parallel incoming " + j->first +
"," + k->first;
1399 for (std::map<std::string, double>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
1400 std::map<std::string, double>::const_iterator k = j;
1401 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
1402 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
1403 reason =
"parallel outgoing " + j->first +
"," + k->first;
1409 bool hasTLS =
false;
1410 for (
NBNode* n : cluster) {
1411 if (n->isTLControlled()) {
1414 const auto& stopEnds = ptStopEnds.find(n);
1415 if (stopEnds != ptStopEnds.end()) {
1416 for (
NBNode*
const to : stopEnds->second) {
1417 if (cluster.count(to) != 0) {
1418 reason =
"it contains a pt stop edge";
1425 if (cluster.size() > 2) {
1427 double maxDist = -1;
1428 NBEdge* maxEdge =
nullptr;
1429 for (
NBNode* n1 : cluster) {
1430 for (
NBNode* n2 : cluster) {
1431 NBEdge* e1 = n1->getConnectionTo(n2);
1432 NBEdge* e2 = n2->getConnectionTo(n1);
1443#ifdef DEBUG_JOINJUNCTIONS
1444 for (
NBNode* n : cluster) {
1446 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxDist=" << maxDist <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
1450 if (!hasTLS && maxDist > 5) {
1452 std::vector<NBNode*> toCheck;
1453 std::set<NBNode*> visited;
1454 toCheck.push_back(maxEdge->
getToNode());
1455 bool foundCircle =
false;
1456 while (!toCheck.empty()) {
1457 NBNode* n = toCheck.back();
1466 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1467 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
1468 toCheck.push_back(cand);
1474 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxDist) +
")";
1480 if (!hasTLS && cluster.size() >= 2) {
1483 int outsideIncoming = 0;
1484 int outsideOutgoing = 0;
1485 int edgesWithin = 0;
1486 for (
NBNode* n : cluster) {
1487 bool foundOutsideIncoming =
false;
1489 if (cluster.count(e->getFromNode()) == 0) {
1492 foundOutsideIncoming =
true;
1497 if (foundOutsideIncoming) {
1500 bool foundOutsideOutgoing =
false;
1501 for (
NBEdge* e : n->getOutgoingEdges()) {
1502 if (cluster.count(e->getToNode()) == 0) {
1505 foundOutsideOutgoing =
true;
1508 if (foundOutsideOutgoing) {
1512 if (entryNodes < 2) {
1513 reason =
"only 1 entry node";
1516 if (exitNodes < 2) {
1517 reason =
"only 1 exit node";
1520 if (cluster.size() == 2) {
1521 if (edgesWithin == 1 && outsideIncoming < 3 && outsideOutgoing < 3) {
1522 reason =
"only 1 edge within and no cross-traffic";
1534 assert(circleSize >= 2);
1535 if ((
int)cands.size() == circleSize) {
1536 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1539 candCluster.insert(cands.begin(), cands.end());
1541 const bool feasible = (int)candCluster.size() == circleSize;
1544 cluster.insert(cands.begin(), cands.end());
1551 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1556 if (cands.size() == 0) {
1571 singleStart.insert(cands.back());
1574 std::vector<NBNode*> cands2(cands);
1588 double minDist = std::numeric_limits<double>::max();
1589 NBEdge* result =
nullptr;
1590 for (
NBNode* n : startNodes) {
1591 for (
NBEdge* e : n->getOutgoingEdges()) {
1592 NBNode* neigh = e->getToNode();
1593 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1596 if (dist < minDist) {
1610 for (
NodeSet cluster : clusters) {
1619 assert(cluster.size() > 1);
1620 std::string
id =
"cluster_";
1626 std::set<NBEdge*, ComparatorIdLess> allEdges;
1627 for (
NBNode* n : cluster) {
1629 allEdges.insert(edges.begin(), edges.end());
1632 std::set<NBEdge*, ComparatorIdLess> clusterIncoming;
1633 std::set<NBEdge*, ComparatorIdLess> inside;
1634 for (
NBEdge* e : allEdges) {
1635 if (cluster.count(e->getToNode()) > 0) {
1636 if (cluster.count(e->getFromNode()) > 0) {
1643 clusterIncoming.insert(e);
1647#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1649 <<
" resetConnections=" << resetConnections <<
"\n"
1654 NBNode* newNode =
nullptr;
1655 if (predefined !=
nullptr) {
1656 newNode = predefined;
1665 std::string tlID = id;
1666 if (predefined !=
nullptr) {
1668 nodeType = predefined->
getType();
1681 newNode->
reinit(pos, nodeType);
1687 if (!tlc.
insert(tlDef)) {
1690 throw ProcessError(
"Could not allocate tls '" +
id +
"'.");
1695 std::map<NBEdge*, EdgeSet> reachable;
1696 for (
NBEdge* e : clusterIncoming) {
1700 while (open.size() > 0) {
1701 NBEdge* cur = open.back();
1705 if (cluster.count(cur->
getToNode()) == 0) {
1713 if (seen.count(out) == 0
1714 && allEdges.count(out) != 0
1716 open.push_back(out);
1721 for (
const auto& con : cons) {
1722 if (con.toEdge !=
nullptr
1723 && seen.count(con.toEdge) == 0
1724 && allEdges.count(con.toEdge) != 0) {
1725 open.push_back(con.toEdge);
1731 for (
NBEdge* reached : seen) {
1733 if (inside.count(reached) == 0) {
1734 reachable[e].insert(reached);
1737#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1738 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1746 for (
NBEdge* e : inside) {
1747 for (
NBEdge* e2 : allEdges) {
1749 e2->replaceInConnections(e, e->getConnections());
1757 for (
NBEdge* e : allEdges) {
1758 std::vector<NBEdge::Connection> conns = e->getConnections();
1759 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1760 NBNode* from = outgoing ? newNode : e->getFromNode();
1761 NBNode* to = outgoing ? e->getToNode() : newNode;
1764 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1766 e->setParameter(
"origTo", e->getToNode()->getID());
1769 if (e->getTurnSignTarget() !=
"") {
1770 for (
NBNode* n : cluster) {
1771 if (e->getTurnSignTarget() == n->getID()) {
1772 e->setTurnSignTarget(to->
getID());
1777 e->reinitNodes(from, to);
1780 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1782 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1785#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1786 std::cout <<
" e=" << e->getID() <<
" declareConnectionsAsLoaded\n";
1791 if (!resetConnections) {
1797 in->removeFromConnections(out, -1, -1,
true,
false,
true);
1803 in->invalidateConnections(
true);
1809 for (
NBNode* n : cluster) {
1817 std::set<std::string> ids;
1818 for (
NBNode* n : cluster) {
1819 ids.insert(n->getID());
1829 bool ambiguousType =
false;
1830 for (
NBNode* j : cluster) {
1831 pos.
add(j->getPosition());
1833 if (j->isTLControlled()) {
1836 type = (*j->getControllingTLS().begin())->getType();
1837 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
1838 ambiguousType =
true;
1844 nodeType = otherType;
1845 }
else if (nodeType != otherType) {
1857 pos.
mul(1. / (
double)cluster.size());
1858 if (ambiguousType) {
1868 bool tooFast =
false;
1869 double laneSpeedSum = 0;
1870 std::set<NBEdge*> seen;
1873 for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
1874 if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
1877 if (j->hasIncoming(*k)) {
1878 laneSpeedSum += (double)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
1880 if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
1886 return !tooFast && laneSpeedSum >= laneSpeedThreshold && c.size() != 0;
1898 nonPedIncoming.push_back(e);
1901 for (
NBEdge* e : node->getOutgoingEdges()) {
1903 nonPedOutgoing.push_back(e);
1906 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
1922 if (node->isTLControlled()) {
1928 const std::string tlID = tl->
getID();
1929 if (tlID != node->getID()
1945 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
1946 if (oc.
isSet(
"tls.unset")) {
1947 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
1948 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
1951 throw ProcessError(
" The junction '" + *i +
"' to set as not-controlled is not known.");
1954 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
1955 (*j)->removeNode(n);
1965 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
1966 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1967 NBNode* cur = (*i).second;
1976 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
1978 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
1979 for (
const auto& item :
myNodes) {
1980 const NBNode* node = item.second;
1982#ifdef DEBUG_GUESSSIGNALS
1984 std::cout <<
" propagate TLS from " << node->
getID() <<
" downstream\n";
1990 edge->setSignalPosition(node->
getPosition(), node);
1995 std::set<NBEdge*> seen;
1996 std::set<NBEdge*> check;
1997 for (
const auto& item :
myNodes) {
1998 for (
NBEdge* edge : item.second->getOutgoingEdges()) {
2002#ifdef DEBUG_GUESSSIGNALS
2003 if (
DEBUGCOND(edge->getSignalNode()) ||
true) {
2004 std::cout <<
" primary signalPosition edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2011 while (check.size() > 0) {
2012 NBEdge*
const edge = *check.begin();
2013 check.erase(check.begin());
2018 if (seen.count(outEdge) == 0) {
2020#ifdef DEBUG_GUESSSIGNALS
2022 std::cout <<
" setSignalPosition edge=" << outEdge->
getID() <<
" pos=" << edge->
getSignalPosition() <<
"\n";
2025 check.insert(outEdge);
2032 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2033 NBNode* node = i->second;
2042 std::vector<const NBNode*> signals;
2045 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2046 const NBEdge* inEdge = *it_i;
2048#ifdef DEBUG_GUESSSIGNALS
2050 std::cout <<
" noTLS, edge=" << inEdge->
getID() <<
"\n";
2061 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2062 const NBEdge* inEdge = *it_i;
2065#ifdef DEBUG_GUESSSIGNALS
2074 if (signal !=
nullptr) {
2075 signals.push_back(signal);
2080 for (
const NBEdge* outEdge : outgoing) {
2081 NBNode* cand = outEdge->getToNode();
2083#ifdef DEBUG_GUESSSIGNALS
2085 std::cout <<
" node=" << node->
getID() <<
" outEdge=" << outEdge->getID() <<
" signalNode=" << cand->
getID() <<
" len=" << outEdge->getLength() <<
"\n";
2088 signals.push_back(cand);
2093 for (
const NBNode* s : signals) {
2094 std::set<NBTrafficLightDefinition*> tls = s->getControllingTLS();
2096 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
2103 if (!tlc.
insert(tlDef)) {
2115 if (oc.
getBool(
"tls.guess.joining")) {
2120 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
2124 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2125 if ((*j)->isTLControlled() ||
myUnsetTLS.count(*j) != 0) {
2140 for (
auto nodeSet : cands) {
2141 std::vector<NBNode*> nodes;
2142 for (
NBNode* node : nodeSet) {
2143 nodes.push_back(node);
2148 if (!tlc.
insert(tlDef)) {
2158 if (oc.
getBool(
"tls.guess")) {
2159 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2160 NBNode* cur = (*i).second;
2182 std::set<NBTrafficLightDefinition*> recompute;
2184 if (!node->hasConflict()) {
2185 const std::set<NBTrafficLightDefinition*>& tlDefs = node->getControllingTLS();
2186 recompute.insert(tlDefs.begin(), tlDefs.end());
2187 node->removeTrafficLights(
true);
2189 edge->clearControllingTLInformation();
2194 if (def->getNodes().size() == 0) {
2197 def->setParticipantsInformation();
2198 def->setTLControllingInformation();
2207 for (
const auto& item :
myNodes) {
2208 item.second->computeKeepClear();
2218 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2219 if (!(*j)->isTLControlled()) {
2230 bool dummySetTL =
false;
2231 std::string
id =
"joinedS_";
2236 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
2237 j->removeTrafficLights();
2242 std::vector<NBNode*> nodes;
2247 if (!tlc.
insert(tlDef)) {
2264 if (!tlc.
insert(tlDef)) {
2266 WRITE_WARNINGF(
TL(
"Building a tl-logic for junction '%' twice is not possible."),
id);
2276 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2277 (*i).second->computeLanes2Lanes();
2285 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2286 (*i).second->computeLogic(ec);
2293 std::set<NBNode*> roundaboutNodes;
2294 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
2295 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
2296 if (checkLaneFoesRoundabout) {
2298 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
2299 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
2300 roundaboutNodes.insert((*j)->getToNode());
2304 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2305 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
2306 (*i).second->computeLogic2(checkLaneFoes);
2313 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2314 delete ((*i).second);
2327 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
2329 while (
retrieve(freeID) !=
nullptr) {
2332 freeID =
"SUMOGenerated" + toString<int>(counter);
2340 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2341 (*i).second->computeNodeShape(mismatchThreshold);
2348 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2351 int numUnregulatedJunctions = 0;
2352 int numDeadEndJunctions = 0;
2353 int numTrafficLightJunctions = 0;
2354 int numPriorityJunctions = 0;
2355 int numRightBeforeLeftJunctions = 0;
2356 int numLeftBeforeRightJunctions = 0;
2357 int numAllWayStopJunctions = 0;
2358 int numZipperJunctions = 0;
2359 int numDistrictJunctions = 0;
2360 int numRailCrossing = 0;
2361 int numRailSignals = 0;
2362 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2363 switch ((*i).second->getType()) {
2365 ++numUnregulatedJunctions;
2368 ++numDeadEndJunctions;
2373 ++numTrafficLightJunctions;
2377 ++numPriorityJunctions;
2380 ++numRightBeforeLeftJunctions;
2383 ++numLeftBeforeRightJunctions;
2386 ++numAllWayStopJunctions;
2389 ++numZipperJunctions;
2392 ++numDistrictJunctions;
2409 if (numDeadEndJunctions > 0) {
2414 if (numLeftBeforeRightJunctions > 0) {
2417 if (numTrafficLightJunctions > 0) {
2420 if (numAllWayStopJunctions > 0) {
2423 if (numZipperJunctions > 0) {
2426 if (numRailCrossing > 0) {
2429 if (numRailSignals > 0) {
2432 if (numDistrictJunctions > 0) {
2440 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2444std::vector<std::string>
2446 std::vector<std::string> ret;
2447 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2448 ret.push_back((*i).first);
2456 if (
myNodes.count(newID) != 0) {
2457 throw ProcessError(
"Attempt to rename node using existing id '" + newID +
"'");
2467 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2468 NBNode* node = i->second;
2472 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
2479 edge->setSignalPosition(node->
getPosition(),
nullptr);
2480#ifdef DEBUG_GUESSSIGNALS
2481 std::cout <<
" discard-simple " << node->
getID() <<
" edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2485 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
2500 NBNode* node = item.second;
2511 if (!numericaIDs && !reservedIDs && prefix ==
"" && !startGiven) {
2514 std::vector<std::string> avoid;
2520 std::set<std::string> reserve;
2524 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
2528 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
2530 toChange.insert(it->second);
2537 toChange.insert(it->second);
2540 if (reservedIDs && reserve.count(it->first) > 0) {
2541 toChange.insert(it->second);
2545 for (
NBNode* node : toChange) {
2548 for (
NBNode* node : toChange) {
2552 node->setID(idSupplier.
getNext());
2553 myNodes[node->getID()] = node;
2555 if (prefix.empty()) {
2556 return (
int)toChange.size();
2561 for (
auto item : oldNodes) {
2563 rename(item.second, prefix + item.first);
2566 tlc.
rename(tlDef, prefix + tlDef->getID());
2584 for (
const auto& item :
myNodes) {
2587 paretoCheck(item.second, bottomRightFront, 1, -1);
2588 paretoCheck(item.second, bottomLeftFront, -1, -1);
2591 front.insert(topRightFront.begin(), topRightFront.end());
2592 front.insert(topLeftFront.begin(), topLeftFront.end());
2593 front.insert(bottomRightFront.begin(), bottomRightFront.end());
2594 front.insert(bottomLeftFront.begin(), bottomLeftFront.end());
2596 for (
NBNode* n : front) {
2597 const int in = (int)n->getIncomingEdges().size();
2598 const int out = (int)n->getOutgoingEdges().size();
2599 if ((in <= 1 && out <= 1) &&
2600 (in == 0 || out == 0
2601 || n->getIncomingEdges().front()->isTurningDirectionAt(n->getOutgoingEdges().front()))) {
2608 for (
const auto& item :
myNodes) {
2610 if (front.count(n) != 0) {
2613 if (n->
getEdges().size() == 1 && n->
getEdges().front()->getSpeed() > speedThreshold) {
2626 std::vector<NBNode*> dominated;
2628 const double x2 =
fn->getPosition().x() * xSign;
2629 const double y2 =
fn->getPosition().y() * ySign;
2630 if (x2 >= x && y2 >= y) {
2632 }
else if (x2 <= x && y2 <= y) {
2633 dominated.push_back(
fn);
2636 frontier.insert(node);
2637 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
const Boundary & getOrigBoundary() const
Returns the original boundary.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
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.
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 begin() const
Returns the pointer to the begin 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.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
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
const std::vector< Connection > & getConnections() const
Returns the connections.
const Position & getSignalPosition() const
Returns the position of a traffic signal on this edge.
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
NBNode * getToNode() const
Returns the destination node of the edge.
static EdgeVector filterByPermissions(const EdgeVector &edges, SVCPermissions permissions)
return only those edges that permit at least one of the give permissions
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...
bool isNearEnough2BeJoined2(NBEdge *e, double threshold) const
Check if edge is near enought to be joined to another edge.
@ INIT
The edge has been loaded, nothing is computed yet.
double getSpeed() const
Returns the speed allowed on this edge.
const std::string & getID() const
static const double UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
const NBNode * getSignalNode() const
Returns the node that (possibly) represents a traffic signal controlling at the end of this edge.
@ USER
The connection was given by the user.
NBNode * getFromNode() const
Returns the origin node of the edge.
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.
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
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)
std::string createClusterId(const NodeSet &cluster, const std::string &prefix="cluster_")
generate id from cluster node ids
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
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.
void registerJoinedCluster(const NodeSet &cluster)
gets all joined clusters (see doc for myClusters2Join)
std::string getFreeID()
generates a new node ID
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
void addJoinExclusion(const std::vector< std::string > &ids)
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.
std::set< const NBNode * > myUnsetTLS
nodes that are excluded from tls-guessing
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string &prefix, NBTrafficLightLogicCont &tlc)
remap node IDs accoring to options –numerical-ids and –reserved-ids
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 feasibleCluster(const NodeSet &cluster, const std::map< const NBNode *, std::vector< NBNode * > > &ptStopEnds, std::string &reason) const
determine wether the cluster is not too complex for joining
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)
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)
void addCluster2Join(const std::set< std::string > &cluster, NBNode *node)
add ids of nodes which shall be joined into a single node
bool customTLID(const NodeSet &c) const
check wheter the set of nodes contains traffic lights with custom id
static int pruneLongEdges(NodeSet &cluster, double maxDist, const bool dryRun=false)
avoid removal of long edges when joining junction clusters
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.
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 reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
SumoXMLNodeType getType() const
Returns the type of this node.
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
void removeTrafficLights(bool setAsPriority=false)
Removes all references to traffic lights that control this tls.
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 Position & getPosition() const
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
void updateSurroundingGeometry()
update geometry of node and surrounding edges
bool checkIsRemovable() const
check if node is removable
void setFringeType(FringeType fringeType)
set method for computing right-of-way
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
void replaceEdge(const std::string &edgeID, const EdgeVector &replacement)
replace the edge with the closes edge on the given edge list in all stops
std::map< std::string, NBPTStop * >::const_iterator begin() const
Returns the pointer to the begin of the stored pt stops.
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
std::map< std::string, NBPTStop * >::const_iterator end() const
Returns the pointer to the end of the stored pt stops.
const std::map< std::string, NBPTStop * > & getStops() const
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.
void rename(NBTrafficLightDefinition *tlDef, const std::string &newID)
rename traffic light
bool computeSingleLogic(OptionsCont &oc, NBTrafficLightDefinition *def)
Computes a specific traffic light logic (using by NETEDIT)
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)
int getInt(const std::string &name) const
Returns the int-value of the named option (only for Option_Integer)
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
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.