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);
711 std::string result = base;
714 result = base + sep +
toString(i++);
724 maxIds = (int)cluster.size();
726 if ((
int)cluster.size() > maxIds) {
727 auto clusterIt = cluster.begin();
728 std::string result = prefix + *clusterIt;
729 for (
int i = 1; i < maxIds; i++) {
731 result +=
"_" + *clusterIt;
733 return result +
"_#" +
toString((
int)cluster.size() - maxIds) +
"more";
743 for (std::string nodeID : cluster) {
745 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' was already excluded from joining."), nodeID);
747 }
else if (
myJoined.count(nodeID) > 0) {
748 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' already occurred in another join-cluster."), nodeID);
752 join.cluster.insert(nodeID);
754 WRITE_ERRORF(
TL(
"Unknown junction '%' in join-cluster."), nodeID);
758 if (join.cluster.size() > 1) {
759 myJoined.insert(join.cluster.begin(), join.cluster.end());
762 WRITE_WARNINGF(
TL(
"Ignoring join-cluster '%' because it has size '%'."), node->
getID(), join.cluster.size());
773 for (std::string nodeID : item.cluster) {
775 if (node ==
nullptr) {
778 cluster.insert(node);
781 if (cluster.size() > 1) {
782 joinNodeCluster(cluster, dc, ec, tlc, item.node, item.resetConnections);
794#ifdef DEBUG_JOINJUNCTIONS
795 std::cout <<
"joinJunctions...\n";
799 std::map<const NBNode*, std::vector<NBNode*> > ptStopEnds;
801 for (
const auto& stopIt : sc.
getStops()) {
803 if (edge !=
nullptr) {
808 for (
NodeSet& cluster : cands) {
809#ifdef DEBUG_JOINJUNCTIONS
811 for (
NBNode* n : cluster) {
818 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
819 NodeSet::iterator check = j;
822 cluster.erase(check);
828 if (cluster.size() < 2) {
833 if (cluster.size() < 2) {
834 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
838 NBNode* tryRemove =
nullptr;
840 std::string origReason;
842 bool feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, origReason, tryRemove);
843 if (feasible && ((
int)cluster.size() -
pruneLongEdges(cluster, maxDist,
true) < 2)) {
844 origReason =
"long edge";
848#ifdef DEBUG_JOINJUNCTIONS
850 std::cout <<
" try to reduce to 4-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
854 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
856 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
861#ifdef DEBUG_JOINJUNCTIONS
863 std::cout <<
" try to reduce to 2-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
867 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
869 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
873 while (!feasible && tryRemove !=
nullptr) {
874 cluster.erase(tryRemove);
877 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
879 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
882 if (cluster.size() < 2) {
883 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"after reduction");
888 if (cluster.size() < 2) {
889 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
895 if (cluster.size() < 2) {
896 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
900 if (cluster.size() < 2) {
901 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
905 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, origReason, tryRemove);
907 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster, origReason);
913 for (
NBNode* current : cluster) {
917 newComp.insert(current);
918 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
919 NodeClusters::iterator check = it_comp;
921 bool connected =
false;
922 for (
NBNode* k : *check) {
923 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
925 newComp.insert((*check).begin(), (*check).end());
926 it_comp = components.erase(check);
936 components.push_back(newComp);
938 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
939 if ((*it_comp).size() > 1) {
941 clusters.push_back(*it_comp);
944#ifdef DEBUG_JOINJUNCTIONS
949 return (
int)clusters.size();
955#ifdef DEBUG_JOINJUNCTIONS
956 std::cout <<
"joinSameJunctions...\n";
958 std::set<NBNode*> checked;
967 for (
NBNode* n2 : nearby) {
972 if (cluster.size() > 1) {
973 checked.insert(cluster.begin(), cluster.end());
974 clusters.push_back(cluster);
978 return (
int)clusters.size();
983#ifdef DEBUG_JOINJUNCTIONS
990 bool pruneFringe =
true;
991 bool pruneNoisyFringe =
false;
994 while (pruneFringe) {
996 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
997 NodeSet::iterator check = j;
1002 double clusterDist = std::numeric_limits<double>::max();
1003 bool touchingCluster =
false;
1005 NBNode* neighbor = (*it_edge)->getToNode();
1006 if (cluster.count(neighbor) != 0) {
1007 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
1012 NBNode* neighbor = (*it_edge)->getFromNode();
1013 if (cluster.count(neighbor) != 0) {
1014 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
1020 std::set<NBNode*> outsideNeighbors;
1021 std::set<NBNode*> clusterNeighbors;
1022 const double pedestrianFringeThreshold = 0.3;
1024 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1025 if (cluster.count(neighbor) == 0) {
1028 || (clusterDist <= pedestrianFringeThreshold
1029 && (!pruneNoisyFringe
1033 || cluster.size() == 2))
1034 || touchingCluster) {
1035 outsideNeighbors.insert(neighbor);
1038 clusterNeighbors.insert(neighbor);
1041#ifdef DEBUG_JOINJUNCTIONS
1043 <<
" clusterDist=" << clusterDist
1044 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
1045 <<
" touching=" << touchingCluster
1051 if (clusterNeighbors.size() == 0
1052 || (outsideNeighbors.size() <= 1
1053 && clusterNeighbors.size() == 1
1055 cluster.erase(check);
1057#ifdef DEBUG_JOINJUNCTIONS
1059 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
1062 }
else if (outsideNeighbors.size() <= 1 && clusterNeighbors.size() == 1) {
1063 geometryLikeTLS.insert(n);
1066 if (!pruneFringe && !pruneNoisyFringe) {
1069 pruneNoisyFringe =
true;
1073 if (remove2TLS && geometryLikeTLS.size() == cluster.size()) {
1081 for (
const NBNode* n1 : cluster) {
1082 for (
const NBNode* n2 : cluster) {
1083 result =
MAX2(result, n1->getPosition().distanceTo2D(n2->getPosition()));
1091 std::set<NBNode*> toRemove;
1092 int maxPassengerLanes = 0;
1093 for (
NBNode* n : cluster) {
1094 for (
NBEdge* edge : n->getEdges()) {
1095 maxPassengerLanes =
MAX2(maxPassengerLanes, edge->getNumLanesThatAllow(
SVC_PASSENGER));
1098 for (
NBNode* n : cluster) {
1099 for (
NBEdge* edge : n->getOutgoingEdges()) {
1103 std::vector<NBNode*> passed;
1106 NBNode* to = edge->getToNode();
1107 while (cluster.count(to) != 0) {
1109 bool goStraight = (std::find(passed.begin(), passed.end(), to) == passed.end()
1114 passed.push_back(to);
1117 if (cur !=
nullptr) {
1128#ifdef DEBUG_JOINJUNCTIONS
1130 std::cout <<
"check edge length " << edge->getID() <<
" (" << length <<
", passed=" << passed.size() <<
", max=" << longThreshold <<
")\n";
1133 if (length > longThreshold) {
1137 const bool keepStart =
getClusterNeighbors(passed.back(), longThreshold, cluster).size() == 1;
1138 const bool keepEnd = !keepStart &&
getClusterNeighbors(n, longThreshold, cluster).size() == 1;
1139#ifdef DEBUG_JOINJUNCTIONS
1141 std::cout <<
"node=" << n->getID() <<
" long edge " << edge->getID() <<
" (" << length <<
", passed=" <<
toString(passed) <<
", max=" << longThreshold <<
") keepStart=" << keepStart <<
" keepEnd=" << keepEnd <<
"\n";
1147 toRemove.insert(passed.begin(), passed.end() - 1);
1149 toRemove.insert(passed.back());
1156 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
1160 return (
int)toRemove.size();
1168 if (e->getLength() > longThreshold) {
1171 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1172 if (cluster.count(neighbor) != 0) {
1173 result.insert(neighbor);
1182#ifdef DEBUG_JOINJUNCTIONS
1184 std::cout <<
"pruning slip-lanes at cluster=" <<
joinNamedToString(cluster,
' ') <<
"\n";
1188 if (cluster.size() <= 2) {
1192 for (
NBNode* n : cluster) {
1198#ifdef DEBUG_JOINJUNCTIONS
1200 std::cout <<
" candidate slip-lane start=" << n->
getID() <<
" outgoing=" <<
toString(outgoing) <<
"\n";
1203 for (
NBEdge* contEdge : outgoing) {
1207 double slipLength = contEdge->getLength();
1208 NBNode* cont = contEdge->getToNode();
1212 if (cands.count(cont) != 0) {
1216#ifdef DEBUG_JOINJUNCTIONS
1218 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1225#ifdef DEBUG_JOINJUNCTIONS
1227 std::cout <<
" candidate slip-lane end=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1234 const NBEdge*
const otherEdge = (contEdge == outgoing.front() ? outgoing.back() : outgoing.front());
1237 std::vector<NodeAndDist> toProc;
1240 while (!toProc.empty()) {
1242 NBNode* cont2 = nodeAndDist.first;
1243 double dist = nodeAndDist.second;
1244#ifdef DEBUG_JOINJUNCTIONS
1246 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1250 if (visited.find(cont2) != visited.end()) {
1253 visited.insert(cont2);
1254 if (cont2 == cont) {
1259 const double dist2 = dist + e->getLength();
1260 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1261 toProc.push_back(std::make_pair(e->getToNode(), dist2));
1268 toRemove.insert(cands.begin(), cands.end());
1269#ifdef DEBUG_JOINJUNCTIONS
1271 std::cout <<
" found slip-lane with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1284#ifdef DEBUG_JOINJUNCTIONS
1286 std::cout <<
" candidate slip-lane end=" << n->getID() <<
" incoming=" <<
toString(incoming) <<
"\n";
1289 for (
NBEdge* contEdge : incoming) {
1293 double slipLength = contEdge->getLength();
1294 NBNode* cont = contEdge->getFromNode();
1298 if (cands.count(cont) != 0) {
1302#ifdef DEBUG_JOINJUNCTIONS
1304 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1311#ifdef DEBUG_JOINJUNCTIONS
1313 std::cout <<
" candidate slip-lane start=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1320 const NBEdge*
const otherEdge = (contEdge == incoming.front() ? incoming.back() : incoming.front());
1323 std::vector<NodeAndDist> toProc;
1326 while (!toProc.empty()) {
1328 NBNode* cont2 = nodeAndDist.first;
1329 double dist = nodeAndDist.second;
1330#ifdef DEBUG_JOINJUNCTIONS
1332 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1336 if (visited.find(cont2) != visited.end()) {
1339 visited.insert(cont2);
1340 if (cont2 == cont) {
1345 const double dist2 = dist + e->getLength();
1346 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1347 toProc.push_back(std::make_pair(e->getFromNode(), dist2));
1354 toRemove.insert(cands.begin(), cands.end());
1355#ifdef DEBUG_JOINJUNCTIONS
1357 std::cout <<
" found slip-lane start with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1369 for (
NBNode* n : toRemove) {
1370 numRemoved += (int)cluster.erase(n);
1372 if (numRemoved > 0) {
1373#ifdef DEBUG_JOINJUNCTIONS
1375 std::cout <<
" removed " << numRemoved <<
" nodes from cluster: " <<
joinNamedToString(toRemove,
' ') <<
"\n";
1393 if (inPE.size() == 1 && outPE.size() == 2) {
1394 outgoing.insert(outgoing.begin(), outPE.begin(), outPE.end());
1395 inAngle = inPE.front()->getAngleAtNode(n);
1397 }
else if (inPE.size() >= 2 && outPE.size() == 3) {
1400 const double inRelAngle = fabs(
NBHelpers::relAngle(inPE.front()->getAngleAtNode(n), inPE.back()->getAngleAtNode(n)));
1402 if (inRelAngle < 135) {
1405 for (
NBEdge* in : inPE) {
1408 for (
NBEdge* out : outPE) {
1409 const double outRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1410 if (outRelAngle <= 45) {
1411 straight.push_back(out);
1412 }
else if (outRelAngle >= 135) {
1416 if (straight.size() == 2 && numReverse == 1) {
1417 outgoing.insert(outgoing.begin(), straight.begin(), straight.end());
1418 inAngle = in->getAngleAtNode(n);
1431 if (inPE.size() == 2 && outPE.size() == 1) {
1432 incoming.insert(incoming.begin(), inPE.begin(), inPE.end());
1433 outAngle = outPE.front()->getAngleAtNode(n);
1435 }
else if (inPE.size() == 3 && outPE.size() >= 2) {
1438 const double outRelAngle = fabs(
NBHelpers::relAngle(outPE.front()->getAngleAtNode(n), outPE.back()->getAngleAtNode(n)));
1440 if (outRelAngle < 135) {
1443 for (
NBEdge* out : outPE) {
1446 for (
NBEdge* in : inPE) {
1447 const double inRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1448 if (inRelAngle <= 45) {
1449 straight.push_back(in);
1450 }
else if (inRelAngle >= 135) {
1454 if (straight.size() == 2 && numReverse == 1) {
1455 incoming.insert(incoming.begin(), straight.begin(), straight.end());
1456 outAngle = out->getAngleAtNode(n);
1466 double maxDist, std::string& reason,
NBNode*& tryRemove)
const {
1469 std::map<NBEdge*, double, ComparatorIdLess> finalIncomingAngles;
1470 std::map<NBEdge*, double, ComparatorIdLess> finalOutgoingAngles;
1471 for (
NBNode* n : cluster) {
1472 for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
1479 for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
1488#ifdef DEBUG_JOINJUNCTIONS
1489 for (
NBNode* n : cluster) {
1498 if (finalIncomingAngles.size() > 5) {
1499 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
1504 const double PARALLEL_THRESHOLD_SAME_NODE = PARALLEL_THRESHOLD_DIFF_NODE / 3;
1505 bool foundParallel =
false;
1506 for (
auto j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
1508 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
1509 const double angleDiff = fabs(j->second - k->second);
1510 if (angleDiff < PARALLEL_THRESHOLD_DIFF_NODE) {
1515#ifdef DEBUG_JOINJUNCTIONS
1517 std::cout <<
" angleDiff=" << angleDiff <<
" shapeDist=" << edgeDist <<
"\n";
1520 if (angleDiff >= PARALLEL_THRESHOLD_SAME_NODE && (
1522 || (edgeDist < maxDist)))) {
1525 reason =
"parallel incoming " + e1->
getID() +
"," + e2->
getID();
1540 for (
auto j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
1542 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
1543 const double angleDiff = fabs(j->second - k->second);
1544 if (angleDiff < PARALLEL_THRESHOLD_DIFF_NODE) {
1549#ifdef DEBUG_JOINJUNCTIONS
1551 std::cout <<
" angleDiff=" << angleDiff <<
" shapeDist=" << edgeDist <<
"\n";
1554 if (angleDiff >= PARALLEL_THRESHOLD_SAME_NODE && (
1556 || (edgeDist < maxDist)))) {
1559 reason =
"parallel outgoing " + e1->
getID() +
"," + e2->
getID();
1574 bool hasTLS =
false;
1575 for (
NBNode* n : cluster) {
1576 if (n->isTLControlled() || n->hadSignal()) {
1579 const auto& stopEnds = ptStopEnds.find(n);
1580 if (stopEnds != ptStopEnds.end()) {
1581 for (
NBNode*
const to : stopEnds->second) {
1582 if (cluster.count(to) != 0) {
1583 reason =
"it contains a pt stop edge";
1590 if (cluster.size() > 2) {
1592 double maxLength = -1;
1593 NBEdge* maxEdge =
nullptr;
1594 for (
NBNode* n1 : cluster) {
1595 for (
NBNode* n2 : cluster) {
1596 NBEdge* e1 = n1->getConnectionTo(n2);
1597 NBEdge* e2 = n2->getConnectionTo(n1);
1608#ifdef DEBUG_JOINJUNCTIONS
1609 for (
NBNode* n : cluster) {
1611 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxLength=" << maxLength <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
1615 if (!hasTLS && maxLength > 5) {
1617 std::vector<NBNode*> toCheck;
1618 std::set<NBNode*> visited;
1619 toCheck.push_back(maxEdge->
getToNode());
1620 bool foundCircle =
false;
1621 while (!toCheck.empty()) {
1622 NBNode* n = toCheck.back();
1631 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1632 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
1633 toCheck.push_back(cand);
1639 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxLength) +
")";
1645 if (cluster.size() >= 2) {
1650 int edgesWithin = 0;
1651 for (
NBNode* n : cluster) {
1652 bool foundOutsideIncoming =
false;
1653 for (
NBEdge* e : n->getIncomingEdges()) {
1654 if (cluster.count(e->getFromNode()) == 0) {
1656 outsideIncoming.push_back(e);
1657 foundOutsideIncoming =
true;
1662 if (foundOutsideIncoming) {
1665 bool foundOutsideOutgoing =
false;
1666 for (
NBEdge* e : n->getOutgoingEdges()) {
1667 if (cluster.count(e->getToNode()) == 0) {
1669 outsideOutgoing.push_back(e);
1670 foundOutsideOutgoing =
true;
1673 if (foundOutsideOutgoing) {
1678 if (entryNodes < 2) {
1679 reason =
"only 1 entry node";
1682 if (exitNodes < 2) {
1683 reason =
"only 1 exit node";
1686 if (cluster.size() == 2) {
1687 if (edgesWithin == 1 && outsideIncoming.size() < 3 && outsideOutgoing.size() < 3) {
1688 reason =
"only 1 edge within and no cross-traffic";
1707 std::cout <<
"reduceToCircle cs=" << circleSize <<
" cands=" <<
toString(cands,
',') <<
" startNodes=" <<
joinNamedToString(startNodes,
',') <<
"\n";
1709 assert(circleSize >= 2);
1710 if ((
int)cands.size() == circleSize) {
1711 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1714 candCluster.insert(cands.begin(), cands.end());
1716 bool feasible = (int)candCluster.size() == circleSize;
1719 cluster.insert(cands.begin(), cands.end());
1726 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1729 std::cout <<
" abort\n";
1733 if (cands.size() == 0) {
1739 if (
reduceToCircle(cluster, circleSize, startNodes, maxDist, cands)) {
1748 singleStart.insert(cands.back());
1751 std::vector<NBNode*> cands2(cands);
1753 if (
reduceToCircle(cluster, circleSize, startNodes, maxDist, cands2)) {
1759 std::cout <<
" abort2\n";
1767 double minDist = std::numeric_limits<double>::max();
1768 NBEdge* result =
nullptr;
1769 for (
NBNode* n : startNodes) {
1770 for (
NBEdge* e : n->getOutgoingEdges()) {
1771 NBNode* neigh = e->getToNode();
1772 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1775 if (dist < minDist) {
1789 for (
NodeSet cluster : clusters) {
1798 assert(cluster.size() > 1);
1799 std::string
id =
"cluster_";
1805 std::set<NBEdge*, ComparatorIdLess> allEdges;
1806 for (
NBNode* n : cluster) {
1808 allEdges.insert(edges.begin(), edges.end());
1811 std::set<NBEdge*, ComparatorIdLess> clusterIncoming;
1812 std::set<NBEdge*, ComparatorIdLess> inside;
1813 for (
NBEdge* e : allEdges) {
1814 if (cluster.count(e->getToNode()) > 0) {
1815 if (cluster.count(e->getFromNode()) > 0) {
1822 clusterIncoming.insert(e);
1826#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1828 <<
" resetConnections=" << resetConnections <<
"\n"
1833 NBNode* newNode =
nullptr;
1834 if (predefined !=
nullptr) {
1835 newNode = predefined;
1844 std::string tlID = id;
1845 if (predefined !=
nullptr) {
1847 nodeType = predefined->
getType();
1861 newNode->
reinit(pos, nodeType);
1867 if (!tlc.
insert(tlDef)) {
1875 std::map<NBEdge*, EdgeSet> reachable;
1876 std::map<std::pair<NBEdge*, NBEdge*>,
SVCPermissions> conPermissions;
1878 for (
NBEdge*
const e : clusterIncoming) {
1882 while (open.size() > 0) {
1883 NBEdge*
const cur = open.back();
1885#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1886 std::cout <<
"e=" << e->getID() <<
" cur=" << cur->
getID() <<
" open=" <<
toString(open) <<
"\n";
1887 std::cout <<
"e=" << e->getID() <<
" cur=" << cur->
getID() <<
" open=" <<
toString(open) <<
"\n";
1891 if (cluster.count(cur->
getToNode()) == 0) {
1899 if (allEdges.count(out) != 0) {
1901 if (seen.count(out) == 0 || (~conPermissions[ {e, out}] & p) != 0) {
1903 open.push_back(out);
1904 conPermissions[ {e, out}] |= p;
1905#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1914 for (
const auto& con : cons) {
1915 if (con.toEdge !=
nullptr && allEdges.count(con.toEdge) != 0) {
1918 p &= con.permissions;
1920 if (seen.count(con.toEdge) == 0 || (~conPermissions[ {e, con.toEdge}] & p) != 0) {
1921 open.push_back(con.toEdge);
1922 conPermissions[ {e, con.toEdge}] |= p;
1930 for (
NBEdge* reached : seen) {
1932 if (inside.count(reached) == 0) {
1937 reachable[e].insert(reached);
1938 const SVCPermissions pDefault = e->getPermissions() & reached->getPermissions();
1939 if (conPermissions[ {e, reached}] != pDefault) {
1940 specialPermissions.insert(e);
1941#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1942 std::cout <<
"e=" << e->getID() <<
" out=" << reached->getID() <<
" special=" <<
getVehicleClassNames(conPermissions[ {e, reached}]) <<
"\n";
1947#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1948 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1956 for (
NBEdge* e : inside) {
1957 for (
NBEdge* e2 : allEdges) {
1959 e2->replaceInConnections(e, e->getConnections());
1967 for (
NBEdge* e : allEdges) {
1968 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1969 NBNode* from = outgoing ? newNode : e->getFromNode();
1970 NBNode* to = outgoing ? e->getToNode() : newNode;
1973 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1975 e->setParameter(
"origTo", e->getToNode()->getID());
1978 if (e->getTurnSignTarget() !=
"") {
1979 for (
NBNode* n : cluster) {
1980 if (e->getTurnSignTarget() == n->getID()) {
1981 e->setTurnSignTarget(to->
getID());
1986 e->reinitNodes(from, to);
1989 std::vector<NBEdge::Connection> conns = e->getConnections();
1990 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1991 if ((*k).toEdge ==
nullptr) {
1996 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1999#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
2000 std::cout <<
" e=" << e->getID() <<
" declareConnectionsAsLoaded\n";
2005 if (!resetConnections) {
2010 if (reachable[in].count(out) == 0) {
2013 in->removeFromConnections(out, -1, -1,
true,
false,
true);
2017 }
else if (specialPermissions.count(in) != 0) {
2018 SVCPermissions pDefault = in->getPermissions() & out->getPermissions();
2019 SVCPermissions p = conPermissions[ {in, out}] == 0 ? pDefault : conPermissions[ {in, out}];
2020 in->addEdge2EdgeConnection(out,
true, p == pDefault ?
SVC_UNSPECIFIED : p);
2027 in->invalidateConnections(
true);
2033 for (
NBNode* n : cluster) {
2041 std::set<std::string> ids;
2042 for (
NBNode* n : cluster) {
2043 ids.insert(n->getID());
2066 bool ambiguousType =
false;
2067 for (
NBNode* j : cluster) {
2068 pos.
add(j->getPosition());
2070 if (j->isTLControlled()) {
2073 type = (*j->getControllingTLS().begin())->getType();
2074 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
2075 ambiguousType =
true;
2081 nodeType = otherType;
2082 }
else if (nodeType != otherType) {
2094 pos.
mul(1. / (
double)cluster.size());
2095 if (ambiguousType) {
2105 bool tooFast =
false;
2106 double laneSpeedSum = 0;
2107 std::set<NBEdge*> seen;
2109 for (
const NBEdge* e : j->getEdges()) {
2110 if (c.find(e->getFromNode()) != c.end() && c.find(e->getToNode()) != c.end()) {
2114 if (j->hasIncoming(e)) {
2115 if (recheck && !j->hasConflict(e)) {
2120 laneSpeedSum += (double)e->getNumLanes() * e->getLaneSpeed(0);
2122 if (e->getLaneSpeed(0) * 3.6 > 79) {
2128 return !tooFast && laneSpeedSum >= laneSpeedThreshold && c.size() != 0;
2138 for (
NBEdge* e : node->getIncomingEdges()) {
2140 nonPedIncoming.push_back(e);
2143 for (
NBEdge* e : node->getOutgoingEdges()) {
2145 nonPedOutgoing.push_back(e);
2148 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
2164 if (node->isTLControlled()) {
2170 const std::string tlID = tl->
getID();
2171 if (tlID != node->getID()
2187 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
2188 if (oc.
isSet(
"tls.unset")) {
2189 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
2190 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
2193 throw ProcessError(
TLF(
" The junction '%' to set as not-controlled is not known.", *i));
2196 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
2197 (*j)->removeNode(n);
2207 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
2208 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2209 NBNode* cur = (*i).second;
2218 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
2220 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
2221 for (
const auto& item :
myNodes) {
2222 const NBNode* node = item.second;
2224#ifdef DEBUG_GUESSSIGNALS
2226 std::cout <<
" propagate TLS from " << node->
getID() <<
" downstream\n";
2232 edge->setSignalPosition(node->
getPosition(), node);
2237 std::set<NBEdge*> seen;
2238 std::set<NBEdge*> check;
2239 for (
const auto& item :
myNodes) {
2240 for (
NBEdge* edge : item.second->getOutgoingEdges()) {
2244#ifdef DEBUG_GUESSSIGNALS
2245 if (
DEBUGCOND(edge->getSignalNode()) ||
true) {
2246 std::cout <<
" primary signalPosition edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2253 while (check.size() > 0) {
2254 NBEdge*
const edge = *check.begin();
2255 check.erase(check.begin());
2260 if (seen.count(outEdge) == 0) {
2262#ifdef DEBUG_GUESSSIGNALS
2264 std::cout <<
" setSignalPosition edge=" << outEdge->
getID() <<
" pos=" << edge->
getSignalPosition() <<
"\n";
2267 check.insert(outEdge);
2274 const int slack = oc.
getInt(
"tls.guess-signals.slack");
2275 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2276 NBNode* node = i->second;
2285 std::vector<const NBNode*> signals;
2286 int foundSignals = 0;
2287 int missingSignals = 0;
2289 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2290 const NBEdge* inEdge = *it_i;
2293#ifdef DEBUG_GUESSSIGNALS
2295 std::cout <<
" noTLS, edge=" << inEdge->
getID() <<
"\n";
2299 if (missingSignals > slack) {
2308 int foundSignalsAtDist = 0;
2309 if (foundSignals > 1 && missingSignals <= slack && missingSignals < foundSignals) {
2313 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2314 const NBEdge* inEdge = *it_i;
2317#ifdef DEBUG_GUESSSIGNALS
2323 if (missingSignals > slack) {
2328 foundSignalsAtDist++;
2331 if (signal !=
nullptr) {
2332 signals.push_back(signal);
2337 for (
const NBEdge* outEdge : outgoing) {
2338 NBNode* cand = outEdge->getToNode();
2340#ifdef DEBUG_GUESSSIGNALS
2342 std::cout <<
" node=" << node->
getID() <<
" outEdge=" << outEdge->getID() <<
" signalNode=" << cand->
getID() <<
" len=" << outEdge->getLength() <<
"\n";
2345 signals.push_back(cand);
2349 if (foundSignalsAtDist > 1 && missingSignals <= slack && missingSignals < foundSignalsAtDist) {
2350 for (
const NBNode* s : signals) {
2351 std::set<NBTrafficLightDefinition*> tls = s->getControllingTLS();
2353 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
2360 if (!tlc.
insert(tlDef)) {
2372 if (oc.
getBool(
"tls.guess.joining")) {
2377 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
2381 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2382 if ((*j)->isTLControlled() ||
myUnsetTLS.count(*j) != 0) {
2397 for (
auto nodeSet : cands) {
2398 std::vector<NBNode*> nodes;
2399 for (
NBNode* node : nodeSet) {
2400 nodes.push_back(node);
2405 if (!tlc.
insert(tlDef)) {
2415 if (oc.
getBool(
"tls.guess")) {
2416 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2417 NBNode* cur = (*i).second;
2440 std::set<NBTrafficLightDefinition*> recompute;
2443 const std::set<NBTrafficLightDefinition*>& tlDefs = node->getControllingTLS();
2444 recompute.insert(tlDefs.begin(), tlDefs.end());
2445 node->removeTrafficLights(
true);
2446 for (
NBEdge* edge : node->getIncomingEdges()) {
2447 edge->clearControllingTLInformation();
2452 if (def->getNodes().size() == 0) {
2455 def->setParticipantsInformation();
2456 def->setTLControllingInformation();
2481 for (
const auto& item :
myNodes) {
2482 item.second->computeKeepClear();
2490 for (
const std::string& tlsID : excludeList) {
2491 if (!tlc.
exist(tlsID,
false)) {
2492 WRITE_WARNINGF(
"Unknown tls ID '%' in option tls.join-exclude", tlsID);
2495 std::set<std::string> exclude(excludeList.begin(), excludeList.end());
2499 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2500 if (!(*j)->isTLControlled() || exclude.count((*(*j)->getControllingTLS().begin())->getID()) != 0) {
2511 bool dummySetTL =
false;
2512 std::string
id =
"joinedS_";
2517 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
2518 j->removeTrafficLights();
2523 std::vector<NBNode*> nodes;
2528 if (!tlc.
insert(tlDef)) {
2545 if (!tlc.
insert(tlDef)) {
2547 WRITE_WARNINGF(
TL(
"Building a tl-logic for junction '%' twice is not possible."),
id);
2557 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2558 (*i).second->computeLanes2Lanes();
2566 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2567 (*i).second->computeLogic(ec);
2574 std::set<NBNode*> roundaboutNodes;
2575 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
2576 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
2577 if (checkLaneFoesRoundabout) {
2579 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
2580 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
2581 roundaboutNodes.insert((*j)->getToNode());
2585 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2586 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
2587 (*i).second->computeLogic2(checkLaneFoes);
2594 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2595 delete ((*i).second);
2608 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
2610 while (
retrieve(freeID) !=
nullptr) {
2613 freeID =
"SUMOGenerated" + toString<int>(counter);
2621 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2622 (*i).second->computeNodeShape(mismatchThreshold);
2629 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2632 int numUnregulatedJunctions = 0;
2633 int numDeadEndJunctions = 0;
2634 int numTrafficLightJunctions = 0;
2635 int numPriorityJunctions = 0;
2636 int numRightBeforeLeftJunctions = 0;
2637 int numLeftBeforeRightJunctions = 0;
2638 int numAllWayStopJunctions = 0;
2639 int numZipperJunctions = 0;
2640 int numDistrictJunctions = 0;
2641 int numRailCrossing = 0;
2642 int numRailSignals = 0;
2643 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2644 switch ((*i).second->getType()) {
2646 ++numUnregulatedJunctions;
2649 ++numDeadEndJunctions;
2654 ++numTrafficLightJunctions;
2658 ++numPriorityJunctions;
2661 ++numRightBeforeLeftJunctions;
2664 ++numLeftBeforeRightJunctions;
2667 ++numAllWayStopJunctions;
2670 ++numZipperJunctions;
2673 ++numDistrictJunctions;
2690 if (numDeadEndJunctions > 0) {
2695 if (numLeftBeforeRightJunctions > 0) {
2698 if (numTrafficLightJunctions > 0) {
2701 if (numAllWayStopJunctions > 0) {
2704 if (numZipperJunctions > 0) {
2707 if (numRailCrossing > 0) {
2710 if (numRailSignals > 0) {
2713 if (numDistrictJunctions > 0) {
2721 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2725std::vector<std::string>
2727 std::vector<std::string> ret;
2728 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2729 ret.push_back((*i).first);
2738 const auto nodeContainerCopy =
myNodes;
2740 for (
const auto& node : nodeContainerCopy) {
2741 node.second->setID(prefix + node.second->getID());
2742 myNodes[node.second->getID()] = node.second;
2749 if (
myNodes.count(newID) != 0) {
2750 throw ProcessError(
TLF(
"Attempt to rename node using existing id '%'", newID));
2760 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2761 NBNode* node = i->second;
2765 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
2775 edge->setSignalPosition(node->
getPosition(),
nullptr);
2776#ifdef DEBUG_GUESSSIGNALS
2777 std::cout <<
" discard-simple " << node->
getID() <<
" edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2780 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
2795 NBNode* node = item.second;
2806 if (!numericaIDs && !reservedIDs && prefix ==
"" && !startGiven) {
2809 std::vector<std::string> avoid;
2815 std::set<std::string> reserve;
2819 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
2823 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
2825 toChange.insert(it->second);
2832 toChange.insert(it->second);
2835 if (reservedIDs && reserve.count(it->first) > 0) {
2836 toChange.insert(it->second);
2839 std::set<std::string> keep;
2843 for (
auto it = toChange.begin(); it != toChange.end();) {
2844 if (keep.count((*it)->getID()) != 0) {
2845 it = toChange.erase(it++);
2852 for (
NBNode* node : toChange) {
2855 for (
NBNode* node : toChange) {
2859 node->setID(idSupplier.
getNext());
2861 tlc.
rename(tlDef, node->getID());
2863 myNodes[node->getID()] = node;
2865 if (prefix.empty()) {
2866 return (
int)toChange.size();
2871 for (
auto item : oldNodes) {
2873 rename(item.second, prefix + item.first);
2876 tlc.
rename(tlDef, prefix + tlDef->getID());
2894 for (
const auto& item :
myNodes) {
2897 paretoCheck(item.second, bottomRightFront, 1, -1);
2898 paretoCheck(item.second, bottomLeftFront, -1, -1);
2901 front.insert(topRightFront.begin(), topRightFront.end());
2902 front.insert(topLeftFront.begin(), topLeftFront.end());
2903 front.insert(bottomRightFront.begin(), bottomRightFront.end());
2904 front.insert(bottomLeftFront.begin(), bottomLeftFront.end());
2906 for (
NBNode* n : front) {
2907 const int in = (int)n->getIncomingEdges().size();
2908 const int out = (int)n->getOutgoingEdges().size();
2909 if ((in <= 1 && out <= 1) &&
2910 (in == 0 || out == 0
2911 || n->getIncomingEdges().front()->isTurningDirectionAt(n->getOutgoingEdges().front()))) {
2918 for (
const auto& item :
myNodes) {
2920 if (front.count(n) != 0) {
2923 if (n->
getEdges().size() == 1 && n->
getEdges().front()->getSpeed() > speedThreshold) {
2936 std::vector<NBNode*> dominated;
2938 const double x2 =
fn->getPosition().x() * xSign;
2939 const double y2 =
fn->getPosition().y() * ySign;
2940 if (x2 >= x && y2 >= y) {
2942 }
else if (x2 <= x && y2 <= y) {
2943 dominated.push_back(
fn);
2946 frontier.insert(node);
2947 for (
NBNode* r : dominated) {
2955 for (
const auto& item :
myNodes) {
2958 bool hasNEMA =
false;
2976 bool hadShapes =
false;
2977 for (
const auto& item :
myNodes) {
2978 if (item.second->getShape().size() > 0 && !item.second->hasCustomShape()) {
2980 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::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.
std::vector< JoinCluster > myClusters2Join
loaded sets of node ids to join (cleared after use)
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 addCluster2Join(const std::set< std::string > &cluster, NBNode *node, const bool resetConnections=false)
add ids of nodes which shall be joined into a single node
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)
std::string createUnusedID(const std::string &base, const std::string &sep)
if base is an existing node id, find a unused id of the form base + sep + INT
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 fringe type
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.