61#define MAX_SLIPLANE_LENGTH 1000
72#define DEBUGNODEID2 ""
74#define DEBUGCOND(obj) ((obj) != 0 && ((obj)->getID() == DEBUGNODEID || (obj)->getID() == DEBUGNODEID2))
90 NodeCont::iterator i =
myNodes.find(
id);
96 const float pos[2] = {(float)position.
x(), (float)position.
y()};
104 std::string
id = node->
getID();
105 NodeCont::iterator i =
myNodes.find(
id);
118 NodeCont::const_iterator i =
myNodes.find(
id);
128 std::vector<NBNode*> result;
129 const double extOffset = offset + POSITION_EPS;
130 const float cmin[2] = {(float)(position.
x() - extOffset), (
float)(position.
y() - extOffset)};
131 const float cmax[2] = {(float)(position.
x() + extOffset), (
float)(position.
y() + extOffset)};
132 std::set<const Named*> into;
135 for (
const Named* namedNode : into) {
140 result.push_back(node);
179 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
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++) {
242 int numRemovedEdges = 0;
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);
327 return numRemovedEdges;
334 std::vector<std::set<NBEdge*> > components;
336 std::set<std::string> edgesLeft;
337 for (std::map<std::string, NBEdge*>::const_iterator edgeIt = ec.
begin(); edgeIt != ec.
end(); ++edgeIt) {
338 edgesLeft.insert(edgeIt->first);
341 std::set<NBEdge*> toRemove;
342 int foundComponents = 0;
344 while (!edgesLeft.empty()) {
345 queue.push_back(ec.
getByID(*edgesLeft.begin()));
346 std::set<NBEdge*> component;
347 while (!queue.empty()) {
348 NBEdge*
const e = queue.back();
351 std::vector<EdgeVector> edgeLists;
356 for (std::vector<EdgeVector>::const_iterator listIt = edgeLists.begin(); listIt != edgeLists.end(); ++listIt) {
357 for (EdgeVector::const_iterator edgeIt = listIt->begin(); edgeIt != listIt->end(); ++edgeIt) {
358 std::set<std::string>::iterator leftIt = edgesLeft.find((*edgeIt)->getID());
359 if (leftIt != edgesLeft.end()) {
360 queue.push_back(*edgeIt);
361 edgesLeft.erase(leftIt);
367 std::vector<std::set<NBEdge*> >::iterator cIt;
368 for (cIt = components.begin(); cIt != components.end(); ++cIt) {
369 if (cIt->size() < component.size()) {
373 components.insert(cIt, component);
374 if ((
int)components.size() > numKeep) {
375 bool recheck =
false;
377 for (
NBEdge* e : components.back()) {
387 toRemove.insert(components.back().begin(), components.back().end());
390 std::vector<std::string> edgeIDs;
391 for (
NBEdge* e : components.back()) {
392 edgeIDs.push_back(e->getID());
396 components.pop_back();
400 for (
NBEdge* e : toRemove) {
401 NBNode*
const fromNode = e->getFromNode();
402 NBNode*
const toNode = e->getToNode();
411 if (foundComponents > 1) {
414 return (
int)toRemove.size();
420 std::set<std::string> stopEdges;
421 for (
const auto& item : sc.
getStops()) {
422 stopEdges.insert(item.second->getEdgeId());
425 int numRemovedEdges = 0;
428 for (std::string edgeID : component) {
429 if (stopEdges.count(edgeID) != 0) {
436 numRemovedEdges += (int)component.size();
437 for (std::string edgeID : component) {
453 if (numRemoved > 0) {
465 bool removeGeometryNodes) {
468 std::set<std::string> edges2keep;
469 if (removeGeometryNodes) {
470 if (oc.
isSet(
"geometry.remove.keep-edges.input-file")) {
473 if (oc.
isSet(
"geometry.remove.keep-edges.explicit")) {
474 const std::vector<std::string> edges = oc.
getStringVector(
"geometry.remove.keep-edges.explicit");
475 edges2keep.insert(edges.begin(), edges.end());
480 if (oc.
exists(
"geometry.remove.keep-ptstops") && oc.
getBool(
"geometry.remove.keep-ptstops")) {
485 std::map<NBEdge*, std::set<NBTrafficLightDefinition*> > tlsLookup;
486 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
493 const bool outputRemoved = oc.
getBool(
"output.removed-nodes");
494 std::vector<NBNode*> toRemove;
495 for (
const auto& i :
myNodes) {
496 NBNode*
const current = i.second;
503 if (edges2keep.find(it_edge->getID()) != edges2keep.end()) {
513 for (
const std::pair<NBEdge*, NBEdge*>& j : current->
getEdgesToJoin()) {
515 NBEdge*
const continuation = j.second;
518 auto itTL = tlsLookup.find(continuation);
519 if (itTL != tlsLookup.end()) {
521 tls->replaceRemoved(continuation, -1,
begin, -1,
true);
523 tlsLookup[
begin] = itTL->second;
527 ec.
extract(dc, continuation,
true);
532 toRemove.push_back(current);
535 for (
NBNode* n : toRemove) {
538 return (
int)toRemove.size();
544 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
545 (*i).second->avoidOverlap();
553 std::set<NBNode*> visited;
554 for (
const auto& i :
myNodes) {
555 if (visited.count(i.second) > 0) {
558 std::vector<NodeAndDist> toProc;
559 toProc.emplace_back(i.second, 0.);
561 while (!toProc.empty()) {
562 NBNode*
const n = toProc.back().first;
563 const double dist = toProc.back().second;
565 if (visited.count(n) > 0) {
569 bool pureRail =
true;
570 bool railAndPeds =
true;
588 const double length = e->getLoadedLength();
589#ifdef DEBUG_JOINJUNCTIONS
591 std::cout <<
"generateNodeClusters: consider s=" << s->
getID()
592 <<
" clusterNode=" << n->
getID() <<
" edge=" << e->getID() <<
" dist=" << dist <<
" length=" << length <<
" with cluster " <<
joinNamedToString(c,
' ') <<
"\n";
596 bool railAndPeds2 =
true;
599 railAndPeds2 =
false;
610 const bool joinPedCrossings = bothCrossing && e->getPermissions() ==
SVC_PEDESTRIAN;
612 !joinPedCrossings && (
615 || (length > 3 * POSITION_EPS
618#ifdef DEBUG_JOINJUNCTIONS
629 bool foundRail =
false;
632 if ((e2->getPermissions() & railNoTram) != 0) {
645 if (visited.find(s) != visited.end()) {
648 if (length + dist < maxDist) {
653 const double fullLength = e->getGeometry().length2D();
654 const double length2 = bothCrossing || hasTLS || trueGeomLike ? length : fullLength;
655 toProc.emplace_back(s, dist + length2);
657 toProc.emplace_back(s, 0.);
665#ifdef DEBUG_JOINJUNCTIONS
678 if ((e->getPermissions() & ~ignored) != 0) {
679 allowedIn.push_back(e);
683 if ((e->getPermissions() & ~ignored) != 0) {
684 allowedOut.push_back(e);
687 if (allowedIn.size() > 0 && allowedOut.size() > 0) {
697 for (
const std::string& nodeID : ids) {
701 WRITE_WARNINGF(
TL(
"Ignoring join exclusion for junction '%' since it already occurred in a list of nodes to be joined."), nodeID);
713 maxIds = (int)cluster.size();
715 if ((
int)cluster.size() > maxIds) {
716 auto clusterIt = cluster.begin();
717 std::string result = prefix + *clusterIt;
718 for (
int i = 1; i < maxIds; i++) {
720 result +=
"_" + *clusterIt;
722 return result +
"_#" +
toString((
int)cluster.size() - maxIds) +
"more";
731 std::set<std::string> validCluster;
732 for (std::string nodeID : cluster) {
734 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' was already excluded from joining."), nodeID);
736 }
else if (
myJoined.count(nodeID) > 0) {
737 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' already occurred in another join-cluster."), nodeID);
741 validCluster.insert(nodeID);
743 WRITE_ERRORF(
TL(
"Unknown junction '%' in join-cluster."), nodeID);
747 if (validCluster.size() > 1) {
748 myJoined.insert(validCluster.begin(), validCluster.end());
751 WRITE_WARNINGF(
TL(
"Ignoring join-cluster '%' because it has size '%'."), node->
getID(), validCluster.size());
762 for (std::string nodeID : item.first) {
764 if (node ==
nullptr) {
767 cluster.insert(node);
770 if (cluster.size() > 1) {
783#ifdef DEBUG_JOINJUNCTIONS
784 std::cout <<
"joinJunctions...\n";
788 std::map<const NBNode*, std::vector<NBNode*> > ptStopEnds;
790 for (
const auto& stopIt : sc.
getStops()) {
792 if (edge !=
nullptr) {
797 for (
NodeSet& cluster : cands) {
798#ifdef DEBUG_JOINJUNCTIONS
800 for (
NBNode* n : cluster) {
807 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
808 NodeSet::iterator check = j;
811 cluster.erase(check);
817 if (cluster.size() < 2) {
822 if (cluster.size() < 2) {
823 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
827 NBNode* tryRemove =
nullptr;
829 std::string origReason;
831 bool feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, origReason, tryRemove);
832 if (feasible && ((
int)cluster.size() -
pruneLongEdges(cluster, maxDist,
true) < 2)) {
833 origReason =
"long edge";
837#ifdef DEBUG_JOINJUNCTIONS
839 std::cout <<
" try to reduce to 4-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
843 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
845 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
850#ifdef DEBUG_JOINJUNCTIONS
852 std::cout <<
" try to reduce to 2-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
856 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
858 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
862 while (!feasible && tryRemove !=
nullptr) {
863 cluster.erase(tryRemove);
866 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
868 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
871 if (cluster.size() < 2) {
872 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"after reduction");
877 if (cluster.size() < 2) {
878 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
884 if (cluster.size() < 2) {
885 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
889 if (cluster.size() < 2) {
890 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
894 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, origReason, tryRemove);
896 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster, origReason);
902 for (
NBNode* current : cluster) {
906 newComp.insert(current);
907 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
908 NodeClusters::iterator check = it_comp;
910 bool connected =
false;
911 for (
NBNode* k : *check) {
912 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
914 newComp.insert((*check).begin(), (*check).end());
915 it_comp = components.erase(check);
925 components.push_back(newComp);
927 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
928 if ((*it_comp).size() > 1) {
930 clusters.push_back(*it_comp);
933#ifdef DEBUG_JOINJUNCTIONS
938 return (
int)clusters.size();
944#ifdef DEBUG_JOINJUNCTIONS
945 std::cout <<
"joinSameJunctions...\n";
947 std::set<NBNode*> checked;
956 for (
NBNode* n2 : nearby) {
961 if (cluster.size() > 1) {
962 checked.insert(cluster.begin(), cluster.end());
963 clusters.push_back(cluster);
967 return (
int)clusters.size();
972#ifdef DEBUG_JOINJUNCTIONS
979 bool pruneFringe =
true;
980 bool pruneNoisyFringe =
false;
983 while (pruneFringe) {
985 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
986 NodeSet::iterator check = j;
991 double clusterDist = std::numeric_limits<double>::max();
992 bool touchingCluster =
false;
994 NBNode* neighbor = (*it_edge)->getToNode();
995 if (cluster.count(neighbor) != 0) {
996 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
1001 NBNode* neighbor = (*it_edge)->getFromNode();
1002 if (cluster.count(neighbor) != 0) {
1003 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
1009 std::set<NBNode*> outsideNeighbors;
1010 std::set<NBNode*> clusterNeighbors;
1011 const double pedestrianFringeThreshold = 0.3;
1013 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1014 if (cluster.count(neighbor) == 0) {
1017 || (clusterDist <= pedestrianFringeThreshold
1018 && (!pruneNoisyFringe
1022 || cluster.size() == 2))
1023 || touchingCluster) {
1024 outsideNeighbors.insert(neighbor);
1027 clusterNeighbors.insert(neighbor);
1030#ifdef DEBUG_JOINJUNCTIONS
1032 <<
" clusterDist=" << clusterDist
1033 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
1034 <<
" touching=" << touchingCluster
1040 if (clusterNeighbors.size() == 0
1041 || (outsideNeighbors.size() <= 1
1042 && clusterNeighbors.size() == 1
1044 cluster.erase(check);
1046#ifdef DEBUG_JOINJUNCTIONS
1048 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
1051 }
else if (outsideNeighbors.size() <= 1 && clusterNeighbors.size() == 1) {
1052 geometryLikeTLS.insert(n);
1055 if (!pruneFringe && !pruneNoisyFringe) {
1058 pruneNoisyFringe =
true;
1062 if (remove2TLS && geometryLikeTLS.size() == cluster.size()) {
1070 for (
const NBNode* n1 : cluster) {
1071 for (
const NBNode* n2 : cluster) {
1072 result =
MAX2(result, n1->getPosition().distanceTo2D(n2->getPosition()));
1080 std::set<NBNode*> toRemove;
1081 int maxPassengerLanes = 0;
1082 for (
NBNode* n : cluster) {
1083 for (
NBEdge* edge : n->getEdges()) {
1084 maxPassengerLanes =
MAX2(maxPassengerLanes, edge->getNumLanesThatAllow(
SVC_PASSENGER));
1087 for (
NBNode* n : cluster) {
1088 for (
NBEdge* edge : n->getOutgoingEdges()) {
1092 std::vector<NBNode*> passed;
1095 NBNode* to = edge->getToNode();
1096 while (cluster.count(to) != 0) {
1098 bool goStraight = (std::find(passed.begin(), passed.end(), to) == passed.end()
1103 passed.push_back(to);
1106 if (cur !=
nullptr) {
1117#ifdef DEBUG_JOINJUNCTIONS
1119 std::cout <<
"check edge length " << edge->getID() <<
" (" << length <<
", passed=" << passed.size() <<
", max=" << longThreshold <<
")\n";
1122 if (length > longThreshold) {
1126 const bool keepStart =
getClusterNeighbors(passed.back(), longThreshold, cluster).size() == 1;
1127 const bool keepEnd = !keepStart &&
getClusterNeighbors(n, longThreshold, cluster).size() == 1;
1128#ifdef DEBUG_JOINJUNCTIONS
1130 std::cout <<
"node=" << n->getID() <<
" long edge " << edge->getID() <<
" (" << length <<
", passed=" <<
toString(passed) <<
", max=" << longThreshold <<
") keepStart=" << keepStart <<
" keepEnd=" << keepEnd <<
"\n";
1136 toRemove.insert(passed.begin(), passed.end() - 1);
1138 toRemove.insert(passed.back());
1145 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
1149 return (
int)toRemove.size();
1157 if (e->getLength() > longThreshold) {
1160 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1161 if (cluster.count(neighbor) != 0) {
1162 result.insert(neighbor);
1171#ifdef DEBUG_JOINJUNCTIONS
1173 std::cout <<
"pruning slip-lanes at cluster=" <<
joinNamedToString(cluster,
' ') <<
"\n";
1177 if (cluster.size() <= 2) {
1181 for (
NBNode* n : cluster) {
1187#ifdef DEBUG_JOINJUNCTIONS
1189 std::cout <<
" candidate slip-lane start=" << n->
getID() <<
" outgoing=" <<
toString(outgoing) <<
"\n";
1192 for (
NBEdge* contEdge : outgoing) {
1196 double slipLength = contEdge->getLength();
1197 NBNode* cont = contEdge->getToNode();
1201 if (cands.count(cont) != 0) {
1205#ifdef DEBUG_JOINJUNCTIONS
1207 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1214#ifdef DEBUG_JOINJUNCTIONS
1216 std::cout <<
" candidate slip-lane end=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1223 const NBEdge*
const otherEdge = (contEdge == outgoing.front() ? outgoing.back() : outgoing.front());
1226 std::vector<NodeAndDist> toProc;
1229 while (!toProc.empty()) {
1231 NBNode* cont2 = nodeAndDist.first;
1232 double dist = nodeAndDist.second;
1233#ifdef DEBUG_JOINJUNCTIONS
1235 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1239 if (visited.find(cont2) != visited.end()) {
1242 visited.insert(cont2);
1243 if (cont2 == cont) {
1248 const double dist2 = dist + e->getLength();
1249 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1250 toProc.push_back(std::make_pair(e->getToNode(), dist2));
1257 toRemove.insert(cands.begin(), cands.end());
1258#ifdef DEBUG_JOINJUNCTIONS
1260 std::cout <<
" found slip-lane with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1273#ifdef DEBUG_JOINJUNCTIONS
1275 std::cout <<
" candidate slip-lane end=" << n->getID() <<
" incoming=" <<
toString(incoming) <<
"\n";
1278 for (
NBEdge* contEdge : incoming) {
1282 double slipLength = contEdge->getLength();
1283 NBNode* cont = contEdge->getFromNode();
1287 if (cands.count(cont) != 0) {
1291#ifdef DEBUG_JOINJUNCTIONS
1293 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1300#ifdef DEBUG_JOINJUNCTIONS
1302 std::cout <<
" candidate slip-lane start=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1309 const NBEdge*
const otherEdge = (contEdge == incoming.front() ? incoming.back() : incoming.front());
1312 std::vector<NodeAndDist> toProc;
1315 while (!toProc.empty()) {
1317 NBNode* cont2 = nodeAndDist.first;
1318 double dist = nodeAndDist.second;
1319#ifdef DEBUG_JOINJUNCTIONS
1321 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1325 if (visited.find(cont2) != visited.end()) {
1328 visited.insert(cont2);
1329 if (cont2 == cont) {
1334 const double dist2 = dist + e->getLength();
1335 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1336 toProc.push_back(std::make_pair(e->getFromNode(), dist2));
1343 toRemove.insert(cands.begin(), cands.end());
1344#ifdef DEBUG_JOINJUNCTIONS
1346 std::cout <<
" found slip-lane start with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1358 for (
NBNode* n : toRemove) {
1359 numRemoved += (int)cluster.erase(n);
1361 if (numRemoved > 0) {
1362#ifdef DEBUG_JOINJUNCTIONS
1364 std::cout <<
" removed " << numRemoved <<
" nodes from cluster: " <<
joinNamedToString(toRemove,
' ') <<
"\n";
1382 if (inPE.size() == 1 && outPE.size() == 2) {
1383 outgoing.insert(outgoing.begin(), outPE.begin(), outPE.end());
1384 inAngle = inPE.front()->getAngleAtNode(n);
1386 }
else if (inPE.size() >= 2 && outPE.size() == 3) {
1389 const double inRelAngle = fabs(
NBHelpers::relAngle(inPE.front()->getAngleAtNode(n), inPE.back()->getAngleAtNode(n)));
1391 if (inRelAngle < 135) {
1394 for (
NBEdge* in : inPE) {
1397 for (
NBEdge* out : outPE) {
1398 const double outRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1399 if (outRelAngle <= 45) {
1400 straight.push_back(out);
1401 }
else if (outRelAngle >= 135) {
1405 if (straight.size() == 2 && numReverse == 1) {
1406 outgoing.insert(outgoing.begin(), straight.begin(), straight.end());
1407 inAngle = in->getAngleAtNode(n);
1420 if (inPE.size() == 2 && outPE.size() == 1) {
1421 incoming.insert(incoming.begin(), inPE.begin(), inPE.end());
1422 outAngle = outPE.front()->getAngleAtNode(n);
1424 }
else if (inPE.size() == 3 && outPE.size() >= 2) {
1427 const double outRelAngle = fabs(
NBHelpers::relAngle(outPE.front()->getAngleAtNode(n), outPE.back()->getAngleAtNode(n)));
1429 if (outRelAngle < 135) {
1432 for (
NBEdge* out : outPE) {
1435 for (
NBEdge* in : inPE) {
1436 const double inRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1437 if (inRelAngle <= 45) {
1438 straight.push_back(in);
1439 }
else if (inRelAngle >= 135) {
1443 if (straight.size() == 2 && numReverse == 1) {
1444 incoming.insert(incoming.begin(), straight.begin(), straight.end());
1445 outAngle = out->getAngleAtNode(n);
1455 double maxDist, std::string& reason,
NBNode*& tryRemove)
const {
1458 std::map<NBEdge*, double, ComparatorIdLess> finalIncomingAngles;
1459 std::map<NBEdge*, double, ComparatorIdLess> finalOutgoingAngles;
1460 for (
NBNode* n : cluster) {
1461 for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
1468 for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
1477#ifdef DEBUG_JOINJUNCTIONS
1478 for (
NBNode* n : cluster) {
1487 if (finalIncomingAngles.size() > 5) {
1488 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
1493 const double PARALLEL_THRESHOLD_SAME_NODE = PARALLEL_THRESHOLD_DIFF_NODE / 3;
1494 bool foundParallel =
false;
1495 for (
auto j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
1497 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
1498 const double angleDiff = fabs(j->second - k->second);
1499 if (angleDiff < PARALLEL_THRESHOLD_DIFF_NODE) {
1504#ifdef DEBUG_JOINJUNCTIONS
1506 std::cout <<
" angleDiff=" << angleDiff <<
" shapeDist=" << edgeDist <<
"\n";
1509 if (angleDiff >= PARALLEL_THRESHOLD_SAME_NODE && (
1511 || (edgeDist < maxDist)))) {
1514 reason =
"parallel incoming " + e1->
getID() +
"," + e2->
getID();
1529 for (
auto j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
1531 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
1532 const double angleDiff = fabs(j->second - k->second);
1533 if (angleDiff < PARALLEL_THRESHOLD_DIFF_NODE) {
1538#ifdef DEBUG_JOINJUNCTIONS
1540 std::cout <<
" angleDiff=" << angleDiff <<
" shapeDist=" << edgeDist <<
"\n";
1543 if (angleDiff >= PARALLEL_THRESHOLD_SAME_NODE && (
1545 || (edgeDist < maxDist)))) {
1548 reason =
"parallel outgoing " + e1->
getID() +
"," + e2->
getID();
1563 bool hasTLS =
false;
1564 for (
NBNode* n : cluster) {
1565 if (n->isTLControlled() || n->hadSignal()) {
1568 const auto& stopEnds = ptStopEnds.find(n);
1569 if (stopEnds != ptStopEnds.end()) {
1570 for (
NBNode*
const to : stopEnds->second) {
1571 if (cluster.count(to) != 0) {
1572 reason =
"it contains a pt stop edge";
1579 if (cluster.size() > 2) {
1581 double maxLength = -1;
1582 NBEdge* maxEdge =
nullptr;
1583 for (
NBNode* n1 : cluster) {
1584 for (
NBNode* n2 : cluster) {
1585 NBEdge* e1 = n1->getConnectionTo(n2);
1586 NBEdge* e2 = n2->getConnectionTo(n1);
1597#ifdef DEBUG_JOINJUNCTIONS
1598 for (
NBNode* n : cluster) {
1600 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxLength=" << maxLength <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
1604 if (!hasTLS && maxLength > 5) {
1606 std::vector<NBNode*> toCheck;
1607 std::set<NBNode*> visited;
1608 toCheck.push_back(maxEdge->
getToNode());
1609 bool foundCircle =
false;
1610 while (!toCheck.empty()) {
1611 NBNode* n = toCheck.back();
1620 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1621 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
1622 toCheck.push_back(cand);
1628 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxLength) +
")";
1634 if (cluster.size() >= 2) {
1639 int edgesWithin = 0;
1640 for (
NBNode* n : cluster) {
1641 bool foundOutsideIncoming =
false;
1642 for (
NBEdge* e : n->getIncomingEdges()) {
1643 if (cluster.count(e->getFromNode()) == 0) {
1645 outsideIncoming.push_back(e);
1646 foundOutsideIncoming =
true;
1651 if (foundOutsideIncoming) {
1654 bool foundOutsideOutgoing =
false;
1655 for (
NBEdge* e : n->getOutgoingEdges()) {
1656 if (cluster.count(e->getToNode()) == 0) {
1658 outsideOutgoing.push_back(e);
1659 foundOutsideOutgoing =
true;
1662 if (foundOutsideOutgoing) {
1667 if (entryNodes < 2) {
1668 reason =
"only 1 entry node";
1671 if (exitNodes < 2) {
1672 reason =
"only 1 exit node";
1675 if (cluster.size() == 2) {
1676 if (edgesWithin == 1 && outsideIncoming.size() < 3 && outsideOutgoing.size() < 3) {
1677 reason =
"only 1 edge within and no cross-traffic";
1696 std::cout <<
"reduceToCircle cs=" << circleSize <<
" cands=" <<
toString(cands,
',') <<
" startNodes=" <<
joinNamedToString(startNodes,
',') <<
"\n";
1698 assert(circleSize >= 2);
1699 if ((
int)cands.size() == circleSize) {
1700 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1703 candCluster.insert(cands.begin(), cands.end());
1705 bool feasible = (int)candCluster.size() == circleSize;
1708 cluster.insert(cands.begin(), cands.end());
1715 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1718 std::cout <<
" abort\n";
1722 if (cands.size() == 0) {
1728 if (
reduceToCircle(cluster, circleSize, startNodes, maxDist, cands)) {
1737 singleStart.insert(cands.back());
1740 std::vector<NBNode*> cands2(cands);
1742 if (
reduceToCircle(cluster, circleSize, startNodes, maxDist, cands2)) {
1748 std::cout <<
" abort2\n";
1756 double minDist = std::numeric_limits<double>::max();
1757 NBEdge* result =
nullptr;
1758 for (
NBNode* n : startNodes) {
1759 for (
NBEdge* e : n->getOutgoingEdges()) {
1760 NBNode* neigh = e->getToNode();
1761 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1764 if (dist < minDist) {
1778 for (
NodeSet cluster : clusters) {
1787 assert(cluster.size() > 1);
1788 std::string
id =
"cluster_";
1794 std::set<NBEdge*, ComparatorIdLess> allEdges;
1795 for (
NBNode* n : cluster) {
1797 allEdges.insert(edges.begin(), edges.end());
1800 std::set<NBEdge*, ComparatorIdLess> clusterIncoming;
1801 std::set<NBEdge*, ComparatorIdLess> inside;
1802 for (
NBEdge* e : allEdges) {
1803 if (cluster.count(e->getToNode()) > 0) {
1804 if (cluster.count(e->getFromNode()) > 0) {
1811 clusterIncoming.insert(e);
1815#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1817 <<
" resetConnections=" << resetConnections <<
"\n"
1822 NBNode* newNode =
nullptr;
1823 if (predefined !=
nullptr) {
1824 newNode = predefined;
1833 std::string tlID = id;
1834 if (predefined !=
nullptr) {
1836 nodeType = predefined->
getType();
1849 newNode->
reinit(pos, nodeType);
1855 if (!tlc.
insert(tlDef)) {
1863 std::map<NBEdge*, EdgeSet> reachable;
1864 std::map<std::pair<NBEdge*, NBEdge*>,
SVCPermissions> conPermissions;
1866 for (
NBEdge*
const e : clusterIncoming) {
1870 while (open.size() > 0) {
1871 NBEdge*
const cur = open.back();
1873#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1874 std::cout <<
"e=" << e->getID() <<
" cur=" << cur->
getID() <<
" open=" <<
toString(open) <<
"\n";
1875 std::cout <<
"e=" << e->getID() <<
" cur=" << cur->
getID() <<
" open=" <<
toString(open) <<
"\n";
1879 if (cluster.count(cur->
getToNode()) == 0) {
1887 if (allEdges.count(out) != 0) {
1889 if (seen.count(out) == 0 || (~conPermissions[ {e, out}] & p) != 0) {
1891 open.push_back(out);
1892 conPermissions[ {e, out}] |= p;
1893#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1902 for (
const auto& con : cons) {
1903 if (con.toEdge !=
nullptr && allEdges.count(con.toEdge) != 0) {
1906 p &= con.permissions;
1908 if (seen.count(con.toEdge) == 0 || (~conPermissions[ {e, con.toEdge}] & p) != 0) {
1909 open.push_back(con.toEdge);
1910 conPermissions[ {e, con.toEdge}] |= p;
1918 for (
NBEdge* reached : seen) {
1920 if (inside.count(reached) == 0) {
1925 reachable[e].insert(reached);
1926 const SVCPermissions pDefault = e->getPermissions() & reached->getPermissions();
1927 if (conPermissions[ {e, reached}] != pDefault) {
1928 specialPermissions.insert(e);
1929#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1930 std::cout <<
"e=" << e->getID() <<
" out=" << reached->getID() <<
" special=" <<
getVehicleClassNames(conPermissions[ {e, reached}]) <<
"\n";
1935#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1936 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1944 for (
NBEdge* e : inside) {
1945 for (
NBEdge* e2 : allEdges) {
1947 e2->replaceInConnections(e, e->getConnections());
1955 for (
NBEdge* e : allEdges) {
1956 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1957 NBNode* from = outgoing ? newNode : e->getFromNode();
1958 NBNode* to = outgoing ? e->getToNode() : newNode;
1961 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1963 e->setParameter(
"origTo", e->getToNode()->getID());
1966 if (e->getTurnSignTarget() !=
"") {
1967 for (
NBNode* n : cluster) {
1968 if (e->getTurnSignTarget() == n->getID()) {
1969 e->setTurnSignTarget(to->
getID());
1974 e->reinitNodes(from, to);
1977 std::vector<NBEdge::Connection> conns = e->getConnections();
1978 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1979 if ((*k).toEdge ==
nullptr) {
1984 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1987#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1988 std::cout <<
" e=" << e->getID() <<
" declareConnectionsAsLoaded\n";
1993 if (!resetConnections) {
1998 if (reachable[in].count(out) == 0) {
2001 in->removeFromConnections(out, -1, -1,
true,
false,
true);
2005 }
else if (specialPermissions.count(in) != 0) {
2006 SVCPermissions pDefault = in->getPermissions() & out->getPermissions();
2007 SVCPermissions p = conPermissions[ {in, out}] == 0 ? pDefault : conPermissions[ {in, out}];
2008 in->addEdge2EdgeConnection(out,
true, p == pDefault ?
SVC_UNSPECIFIED : p);
2015 in->invalidateConnections(
true);
2021 for (
NBNode* n : cluster) {
2029 std::set<std::string> ids;
2030 for (
NBNode* n : cluster) {
2031 ids.insert(n->getID());
2054 bool ambiguousType =
false;
2055 for (
NBNode* j : cluster) {
2056 pos.
add(j->getPosition());
2058 if (j->isTLControlled()) {
2061 type = (*j->getControllingTLS().begin())->getType();
2062 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
2063 ambiguousType =
true;
2069 nodeType = otherType;
2070 }
else if (nodeType != otherType) {
2082 pos.
mul(1. / (
double)cluster.size());
2083 if (ambiguousType) {
2093 bool tooFast =
false;
2094 double laneSpeedSum = 0;
2095 std::set<NBEdge*> seen;
2097 for (
const NBEdge* e : j->getEdges()) {
2098 if (c.find(e->getFromNode()) != c.end() && c.find(e->getToNode()) != c.end()) {
2102 if (j->hasIncoming(e)) {
2103 if (recheck && !j->hasConflict(e)) {
2108 laneSpeedSum += (double)e->getNumLanes() * e->getLaneSpeed(0);
2110 if (e->getLaneSpeed(0) * 3.6 > 79) {
2116 return !tooFast && laneSpeedSum >= laneSpeedThreshold && c.size() != 0;
2126 for (
NBEdge* e : node->getIncomingEdges()) {
2128 nonPedIncoming.push_back(e);
2131 for (
NBEdge* e : node->getOutgoingEdges()) {
2133 nonPedOutgoing.push_back(e);
2136 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
2152 if (node->isTLControlled()) {
2158 const std::string tlID = tl->
getID();
2159 if (tlID != node->getID()
2175 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
2176 if (oc.
isSet(
"tls.unset")) {
2177 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
2178 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
2181 throw ProcessError(
TLF(
" The junction '%' to set as not-controlled is not known.", *i));
2184 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
2185 (*j)->removeNode(n);
2195 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
2196 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2197 NBNode* cur = (*i).second;
2206 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
2208 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
2209 for (
const auto& item :
myNodes) {
2210 const NBNode* node = item.second;
2212#ifdef DEBUG_GUESSSIGNALS
2214 std::cout <<
" propagate TLS from " << node->
getID() <<
" downstream\n";
2220 edge->setSignalPosition(node->
getPosition(), node);
2225 std::set<NBEdge*> seen;
2226 std::set<NBEdge*> check;
2227 for (
const auto& item :
myNodes) {
2228 for (
NBEdge* edge : item.second->getOutgoingEdges()) {
2232#ifdef DEBUG_GUESSSIGNALS
2233 if (
DEBUGCOND(edge->getSignalNode()) ||
true) {
2234 std::cout <<
" primary signalPosition edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2241 while (check.size() > 0) {
2242 NBEdge*
const edge = *check.begin();
2243 check.erase(check.begin());
2248 if (seen.count(outEdge) == 0) {
2250#ifdef DEBUG_GUESSSIGNALS
2252 std::cout <<
" setSignalPosition edge=" << outEdge->
getID() <<
" pos=" << edge->
getSignalPosition() <<
"\n";
2255 check.insert(outEdge);
2262 const int slack = oc.
getInt(
"tls.guess-signals.slack");
2263 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2264 NBNode* node = i->second;
2273 std::vector<const NBNode*> signals;
2274 int foundSignals = 0;
2275 int missingSignals = 0;
2277 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2278 const NBEdge* inEdge = *it_i;
2281#ifdef DEBUG_GUESSSIGNALS
2283 std::cout <<
" noTLS, edge=" << inEdge->
getID() <<
"\n";
2287 if (missingSignals > slack) {
2296 int foundSignalsAtDist = 0;
2297 if (foundSignals > 1 && missingSignals <= slack && missingSignals < foundSignals) {
2301 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2302 const NBEdge* inEdge = *it_i;
2305#ifdef DEBUG_GUESSSIGNALS
2311 if (missingSignals > slack) {
2316 foundSignalsAtDist++;
2319 if (signal !=
nullptr) {
2320 signals.push_back(signal);
2325 for (
const NBEdge* outEdge : outgoing) {
2326 NBNode* cand = outEdge->getToNode();
2328#ifdef DEBUG_GUESSSIGNALS
2330 std::cout <<
" node=" << node->
getID() <<
" outEdge=" << outEdge->getID() <<
" signalNode=" << cand->
getID() <<
" len=" << outEdge->getLength() <<
"\n";
2333 signals.push_back(cand);
2337 if (foundSignalsAtDist > 1 && missingSignals <= slack && missingSignals < foundSignalsAtDist) {
2338 for (
const NBNode* s : signals) {
2339 std::set<NBTrafficLightDefinition*> tls = s->getControllingTLS();
2341 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
2348 if (!tlc.
insert(tlDef)) {
2360 if (oc.
getBool(
"tls.guess.joining")) {
2365 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
2369 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2370 if ((*j)->isTLControlled() ||
myUnsetTLS.count(*j) != 0) {
2385 for (
auto nodeSet : cands) {
2386 std::vector<NBNode*> nodes;
2387 for (
NBNode* node : nodeSet) {
2388 nodes.push_back(node);
2393 if (!tlc.
insert(tlDef)) {
2403 if (oc.
getBool(
"tls.guess")) {
2404 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2405 NBNode* cur = (*i).second;
2428 std::set<NBTrafficLightDefinition*> recompute;
2431 const std::set<NBTrafficLightDefinition*>& tlDefs = node->getControllingTLS();
2432 recompute.insert(tlDefs.begin(), tlDefs.end());
2433 node->removeTrafficLights(
true);
2434 for (
NBEdge* edge : node->getIncomingEdges()) {
2435 edge->clearControllingTLInformation();
2440 if (def->getNodes().size() == 0) {
2443 def->setParticipantsInformation();
2444 def->setTLControllingInformation();
2469 for (
const auto& item :
myNodes) {
2470 item.second->computeKeepClear();
2478 for (
const std::string& tlsID : excludeList) {
2479 if (!tlc.
exist(tlsID,
false)) {
2480 WRITE_WARNINGF(
"Unknown tls ID '%' in option tls.join-exclude", tlsID);
2483 std::set<std::string> exclude(excludeList.begin(), excludeList.end());
2487 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2488 if (!(*j)->isTLControlled() || exclude.count((*(*j)->getControllingTLS().begin())->getID()) != 0) {
2499 bool dummySetTL =
false;
2500 std::string
id =
"joinedS_";
2505 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
2506 j->removeTrafficLights();
2511 std::vector<NBNode*> nodes;
2516 if (!tlc.
insert(tlDef)) {
2533 if (!tlc.
insert(tlDef)) {
2535 WRITE_WARNINGF(
TL(
"Building a tl-logic for junction '%' twice is not possible."),
id);
2545 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2546 (*i).second->computeLanes2Lanes();
2554 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2555 (*i).second->computeLogic(ec);
2562 std::set<NBNode*> roundaboutNodes;
2563 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
2564 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
2565 if (checkLaneFoesRoundabout) {
2567 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
2568 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
2569 roundaboutNodes.insert((*j)->getToNode());
2573 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2574 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
2575 (*i).second->computeLogic2(checkLaneFoes);
2582 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2583 delete ((*i).second);
2596 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
2598 while (
retrieve(freeID) !=
nullptr) {
2601 freeID =
"SUMOGenerated" + toString<int>(counter);
2609 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2610 (*i).second->computeNodeShape(mismatchThreshold);
2617 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2620 int numUnregulatedJunctions = 0;
2621 int numDeadEndJunctions = 0;
2622 int numTrafficLightJunctions = 0;
2623 int numPriorityJunctions = 0;
2624 int numRightBeforeLeftJunctions = 0;
2625 int numLeftBeforeRightJunctions = 0;
2626 int numAllWayStopJunctions = 0;
2627 int numZipperJunctions = 0;
2628 int numDistrictJunctions = 0;
2629 int numRailCrossing = 0;
2630 int numRailSignals = 0;
2631 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2632 switch ((*i).second->getType()) {
2634 ++numUnregulatedJunctions;
2637 ++numDeadEndJunctions;
2642 ++numTrafficLightJunctions;
2646 ++numPriorityJunctions;
2649 ++numRightBeforeLeftJunctions;
2652 ++numLeftBeforeRightJunctions;
2655 ++numAllWayStopJunctions;
2658 ++numZipperJunctions;
2661 ++numDistrictJunctions;
2678 if (numDeadEndJunctions > 0) {
2683 if (numLeftBeforeRightJunctions > 0) {
2686 if (numTrafficLightJunctions > 0) {
2689 if (numAllWayStopJunctions > 0) {
2692 if (numZipperJunctions > 0) {
2695 if (numRailCrossing > 0) {
2698 if (numRailSignals > 0) {
2701 if (numDistrictJunctions > 0) {
2709 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2713std::vector<std::string>
2715 std::vector<std::string> ret;
2716 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2717 ret.push_back((*i).first);
2726 const auto nodeContainerCopy =
myNodes;
2728 for (
const auto& node : nodeContainerCopy) {
2729 node.second->setID(prefix + node.second->getID());
2730 myNodes[node.second->getID()] = node.second;
2737 if (
myNodes.count(newID) != 0) {
2738 throw ProcessError(
TLF(
"Attempt to rename node using existing id '%'", newID));
2748 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2749 NBNode* node = i->second;
2753 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
2763 edge->setSignalPosition(node->
getPosition(),
nullptr);
2764#ifdef DEBUG_GUESSSIGNALS
2765 std::cout <<
" discard-simple " << node->
getID() <<
" edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2768 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
2783 NBNode* node = item.second;
2794 if (!numericaIDs && !reservedIDs && prefix ==
"" && !startGiven) {
2797 std::vector<std::string> avoid;
2803 std::set<std::string> reserve;
2807 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
2811 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
2813 toChange.insert(it->second);
2820 toChange.insert(it->second);
2823 if (reservedIDs && reserve.count(it->first) > 0) {
2824 toChange.insert(it->second);
2827 std::set<std::string> keep;
2831 for (
auto it = toChange.begin(); it != toChange.end();) {
2832 if (keep.count((*it)->getID()) != 0) {
2833 it = toChange.erase(it++);
2840 for (
NBNode* node : toChange) {
2843 for (
NBNode* node : toChange) {
2847 node->setID(idSupplier.
getNext());
2849 tlc.
rename(tlDef, node->getID());
2851 myNodes[node->getID()] = node;
2853 if (prefix.empty()) {
2854 return (
int)toChange.size();
2859 for (
auto item : oldNodes) {
2861 rename(item.second, prefix + item.first);
2864 tlc.
rename(tlDef, prefix + tlDef->getID());
2882 for (
const auto& item :
myNodes) {
2885 paretoCheck(item.second, bottomRightFront, 1, -1);
2886 paretoCheck(item.second, bottomLeftFront, -1, -1);
2889 front.insert(topRightFront.begin(), topRightFront.end());
2890 front.insert(topLeftFront.begin(), topLeftFront.end());
2891 front.insert(bottomRightFront.begin(), bottomRightFront.end());
2892 front.insert(bottomLeftFront.begin(), bottomLeftFront.end());
2894 for (
NBNode* n : front) {
2895 const int in = (int)n->getIncomingEdges().size();
2896 const int out = (int)n->getOutgoingEdges().size();
2897 if ((in <= 1 && out <= 1) &&
2898 (in == 0 || out == 0
2899 || n->getIncomingEdges().front()->isTurningDirectionAt(n->getOutgoingEdges().front()))) {
2906 for (
const auto& item :
myNodes) {
2908 if (front.count(n) != 0) {
2911 if (n->
getEdges().size() == 1 && n->
getEdges().front()->getSpeed() > speedThreshold) {
2924 std::vector<NBNode*> dominated;
2926 const double x2 =
fn->getPosition().x() * xSign;
2927 const double y2 =
fn->getPosition().y() * ySign;
2928 if (x2 >= x && y2 >= y) {
2930 }
else if (x2 <= x && y2 <= y) {
2931 dominated.push_back(
fn);
2934 frontier.insert(node);
2935 for (
NBNode* r : dominated) {
2943 for (
const auto& item :
myNodes) {
2946 bool hasNEMA =
false;
2964 bool hadShapes =
false;
2965 for (
const auto& item :
myNodes) {
2966 if (item.second->getShape().size() > 0 && !item.second->hasCustomShape()) {
2968 item.second->resetShape();
#define WRITE_WARNINGF(...)
#define WRITE_MESSAGEF(...)
#define WRITE_ERRORF(...)
#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 isForVulnerableModes(SVCPermissions permissions)
Returns whether an edge with the given permissions allows only vulnerable road users.
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a (exclusive) railway edge.
const SVCPermissions SVC_UNSPECIFIED
permissions not specified
bool isWaterway(SVCPermissions permissions)
Returns whether an edge with the given permissions is a waterway edge.
const std::string & getVehicleClassNames(SVCPermissions permissions, bool expand)
Returns the ids of the given classes, divided using a ' '.
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_DELIVERY
vehicle is a small delivery vehicle
@ SVC_TRAM
vehicle is a light rail
@ SVC_PEDESTRIAN
pedestrian
const std::string SUMO_PARAM_ORIGID
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
@ TRAFFIC_LIGHT_RIGHT_ON_RED
@ TRAFFIC_LIGHT_NOJUNCTION
bool gDebugFlag1
global utility flags for debugging
const double SUMO_const_laneWidth
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="")
add post process connections
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.
int getNumLanesThatAllow(SVCPermissions permissions, bool allPermissions=true) const
@ 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.
int getPriority() const
Returns the priority of the edge.
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
void append(NBEdge *continuation)
append another edge
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
static double getDiameter(const NodeSet &cluster)
compute the maximum distance between any two cluster nodes
NamedRTree myRTree
node positions for faster lookup
void avoidOverlap()
fix overlap
int removeRailComponents(NBDistrictCont &dc, NBEdgeCont &ec, NBPTStopCont &sc)
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
std::vector< NBNode * > retrieveByPos(const Position &position, const double offset=0.) const
Returns the node with the given coordinates.
NodeCont myNodes
The map of names to nodes.
bool reduceToCircle(NodeSet &cluster, int circleSize, NodeSet startNodes, double maxDist, std::vector< NBNode * > cands=std::vector< NBNode * >()) const
try to find a joinable subset (recursively)
void registerJoinedCluster(const NodeSet &cluster)
gets all joined clusters (see doc for myClusters2Join)
std::string getFreeID()
generates a new node ID
int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes self-loop edges (edges where the source and the destination node are the same)
bool recheckTLSThreshold(NBNode *node)
check whether a specific guessed tls should keep its type
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)
static bool geometryLikeForClass(const NBNode *n, SVCPermissions permissions)
check whether the node is geometryLike when only considering edges that support the given permissions
void applyConditionalDefaults()
apply default values after loading
void pruneSlipLaneNodes(NodeSet &cluster, double maxDist) const
remove nodes that form a slip lane from cluster
int remapIDs(bool numericaIDs, bool reservedIDs, bool keptIDs, const std::string &prefix, NBTrafficLightLogicCont &tlc)
remap node IDs according to options –numerical-ids and –reserved-ids
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
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 extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
void pruneClusterFringe(NodeSet &cluster, double maxDist, bool remove2TLS=false) const
remove geometry-like fringe nodes from cluster
int removeComponents(NBDistrictCont &dc, NBEdgeCont &ec, const int numKeep, bool hasPTStops)
Checks the network for weak connectivity and removes all but the largest components....
std::vector< std::string > getAllNames() const
get all node names
void computeLogics2(const NBEdgeCont &ec, OptionsCont &oc)
compute right-of-way logic for all lane-to-lane connections
bool shouldBeTLSControlled(const NodeSet &c, double laneSpeedThreshold, bool recheck=false) const
Returns whethe the given node cluster should be controlled by a tls.
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.
int removeIsolatedRoads(NBDistrictCont &dc, NBEdgeCont &ec)
Removes sequences of edges that are not connected with a junction. Simple roads without junctions som...
void joinNodeClusters(NodeClusters clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, bool resetConnections=false)
joins the given node clusters
void discardRailSignals()
discards rail signals
void addPrefix(const std::string &prefix)
add prefix to all nodes
void printBuiltNodesStatistics() const
Prints statistics about built nodes.
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
static NodeSet getClusterNeighbors(const NBNode *n, double longThreshold, NodeSet &cluster)
return all cluster neighbors for the given node
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 unregisterJoinedCluster(const std::set< std::string > &cluster)
remove cluster from list (on netedit-undo)
void generateNodeClusters(double maxDist, NodeClusters &into) const
Builds node clusters.
static bool isSlipLaneContinuation(const NBNode *cont)
whether the given node may continue a slip lane
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
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.
bool feasibleCluster(const NodeSet &cluster, const std::map< const NBNode *, std::vector< NBNode * > > &ptStopEnds, double maxDist, std::string &reason, NBNode *&tryRemove) const
determine wether the cluster is not too complex for joining
int joinSameJunctions(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, double maxDist)
Joins junctions with similar coordinates regardless of topology.
int guessFringe()
guess and mark fringe nodes
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)
std::set< NBNode *, ComparatorIdLess > myGuessedTLS
nodes that received a traffic light due to guessing (–tls.guess)
std::set< std::string > myJoined
ids found in loaded join clusters used for error checking
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
bool resetNodeShapes()
reset all node shapes
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
Represents a single node (junction) during network building.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
RightOfWay getRightOfWay() const
Returns hint on how to compute right of way.
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.
void setRightOfWay(RightOfWay rightOfWay)
set method for computing right-of-way
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
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.
int removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes edges which are both incoming and outgoing into this node.
std::vector< Crossing * > getCrossings() const
return this junctions pedestrian crossings
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurrences of the first edge within the list of incoming by the second Connections are rema...
EdgeVector getPassengerEdges(bool incoming) const
return edges that permit passengers (either incoming or outgoing)
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
Container for public transport stops during the net building process.
void replaceEdge(const std::string &edgeID, const std::vector< NBEdge * > &replacement)
replace the edge with the closes edge on the given edge list in all stops
const std::map< std::string, std::shared_ptr< NBPTStop > > & getStops() const
Returns an unmodifiable reference to the stored pt stops.
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
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.
A container for traffic light definitions and built programs.
bool exist(const std::string &newID, bool requireComputed=true) const
check if exists a definition with the given ID
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.
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 position 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
get key
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.