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 const double extOffset = offset + POSITION_EPS;
129 const float cmin[2] = {(float)(position.
x() - extOffset), (
float)(position.
y() - extOffset)};
130 const float cmax[2] = {(float)(position.
x() + extOffset), (
float)(position.
y() + extOffset)};
131 std::set<const Named*> into;
134 for (
const Named* namedNode : into) {
178 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
191 const double distanceThreshold = 7.;
192 const double lengthThreshold = 0.10;
194 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
196 std::map<NBNode*, EdgeVector> connectionCount;
197 const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
198 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
199 connectionCount[(*j)->getToNode()].push_back(*j);
202 std::map<NBNode*, EdgeVector>::iterator k;
203 for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
205 if ((*k).second.size() < 2) {
211 const NBEdge*
const first = ev.front();
212 EdgeVector::const_iterator jci;
213 for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
216 (relativeLengthDifference > lengthThreshold) ||
217 (fabs(first->
getSpeed() - (*jci)->getSpeed()) >= 0.01) ||
225 if (jci == ev.end()) {
226 if (removeDuplicates) {
227 for (
int ei = 1; ei < (int)ev.size(); ei++) {
241 int numRemovedEdges = 0;
243 const std::vector<std::string>& edgeNames = ec.
getAllNames();
244 for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
253 if (outgoingEdges.size() != 1) {
258 if (incomingEdges.size() > 1) {
261 }
else if (incomingEdges.size() == 1) {
262 NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
263 NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
264 if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
272 bool hasJunction =
false;
284 adjacentNodes.clear();
285 for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
286 if ((*itOfOutgoings)->getToNode() != from
287 && (*itOfOutgoings)->getToNode() != to
291 adjacentNodes.insert((*itOfOutgoings)->getToNode());
293 for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
294 adjacentNodes.insert((*itOfIncomings)->getFromNode());
296 adjacentNodes.erase(to);
297 if (adjacentNodes.size() > 2) {
300 }
while (!hasJunction && eOld != e);
302 std::string warningString;
303 for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
304 if (roadIt == road.begin()) {
305 warningString += (*roadIt)->
getID();
307 warningString +=
"," + (*roadIt)->getID();
310 NBNode* fromNode = (*roadIt)->getFromNode();
311 NBNode* toNode = (*roadIt)->getToNode();
312 ec.
erase(dc, *roadIt);
326 return numRemovedEdges;
333 std::vector<std::set<NBEdge*> > components;
335 std::set<std::string> edgesLeft;
336 for (std::map<std::string, NBEdge*>::const_iterator edgeIt = ec.
begin(); edgeIt != ec.
end(); ++edgeIt) {
337 edgesLeft.insert(edgeIt->first);
340 std::set<NBEdge*> toRemove;
341 int foundComponents = 0;
343 while (!edgesLeft.empty()) {
344 queue.push_back(ec.
getByID(*edgesLeft.begin()));
345 std::set<NBEdge*> component;
346 while (!queue.empty()) {
347 NBEdge*
const e = queue.back();
350 std::vector<EdgeVector> edgeLists;
355 for (std::vector<EdgeVector>::const_iterator listIt = edgeLists.begin(); listIt != edgeLists.end(); ++listIt) {
356 for (EdgeVector::const_iterator edgeIt = listIt->begin(); edgeIt != listIt->end(); ++edgeIt) {
357 std::set<std::string>::iterator leftIt = edgesLeft.find((*edgeIt)->getID());
358 if (leftIt != edgesLeft.end()) {
359 queue.push_back(*edgeIt);
360 edgesLeft.erase(leftIt);
366 std::vector<std::set<NBEdge*> >::iterator cIt;
367 for (cIt = components.begin(); cIt != components.end(); ++cIt) {
368 if (cIt->size() < component.size()) {
372 components.insert(cIt, component);
373 if ((
int)components.size() > numKeep) {
374 bool recheck =
false;
376 for (
NBEdge* e : components.back()) {
386 toRemove.insert(components.back().begin(), components.back().end());
389 std::vector<std::string> edgeIDs;
390 for (
NBEdge* e : components.back()) {
391 edgeIDs.push_back(e->getID());
395 components.pop_back();
399 for (
NBEdge* e : toRemove) {
400 NBNode*
const fromNode = e->getFromNode();
401 NBNode*
const toNode = e->getToNode();
410 if (foundComponents > 1) {
413 return (
int)toRemove.size();
419 std::set<std::string> stopEdges;
420 for (
const auto& item : sc.
getStops()) {
421 stopEdges.insert(item.second->getEdgeId());
424 int numRemovedEdges = 0;
427 for (std::string edgeID : component) {
428 if (stopEdges.count(edgeID) != 0) {
435 numRemovedEdges += (int)component.size();
436 for (std::string edgeID : component) {
452 if (numRemoved > 0) {
464 bool removeGeometryNodes) {
466 std::set<std::string> edges2keep;
467 if (removeGeometryNodes) {
469 if (oc.
isSet(
"geometry.remove.keep-edges.input-file")) {
472 if (oc.
isSet(
"geometry.remove.keep-edges.explicit")) {
473 const std::vector<std::string> edges = oc.
getStringVector(
"geometry.remove.keep-edges.explicit");
474 edges2keep.insert(edges.begin(), edges.end());
479 if (oc.
exists(
"geometry.remove.keep-ptstops") && oc.
getBool(
"geometry.remove.keep-ptstops")) {
484 std::map<NBEdge*, std::set<NBTrafficLightDefinition*> > tlsLookup;
485 for (
auto it = ec.
begin(); it != ec.
end(); it++) {
493 std::vector<NBNode*> toRemove;
494 for (
const auto& i :
myNodes) {
495 NBNode*
const current = i.second;
502 if (edges2keep.find(it_edge->getID()) != edges2keep.end()) {
512 for (
const std::pair<NBEdge*, NBEdge*>& j : current->
getEdgesToJoin()) {
514 NBEdge*
const continuation = j.second;
517 auto itTL = tlsLookup.find(continuation);
518 if (itTL != tlsLookup.end()) {
520 tls->replaceRemoved(continuation, -1,
begin, -1,
true);
522 tlsLookup[
begin] = itTL->second;
526 ec.
extract(dc, continuation,
true);
528 toRemove.push_back(current);
531 for (
NBNode* n : toRemove) {
534 return (
int)toRemove.size();
540 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
541 (*i).second->avoidOverlap();
549 std::set<NBNode*> visited;
550 for (
const auto& i :
myNodes) {
551 if (visited.count(i.second) > 0) {
554 std::vector<NodeAndDist> toProc;
555 toProc.emplace_back(i.second, 0.);
557 while (!toProc.empty()) {
558 NBNode*
const n = toProc.back().first;
559 const double dist = toProc.back().second;
561 if (visited.count(n) > 0) {
565 bool pureRail =
true;
566 bool railAndPeds =
true;
584 const double length = e->getLoadedLength();
585#ifdef DEBUG_JOINJUNCTIONS
587 std::cout <<
"generateNodeClusters: consider s=" << s->
getID()
588 <<
" clusterNode=" << n->
getID() <<
" edge=" << e->getID() <<
" dist=" << dist <<
" length=" << length <<
" with cluster " <<
joinNamedToString(c,
' ') <<
"\n";
592 bool railAndPeds2 =
true;
595 railAndPeds2 =
false;
606 const bool joinPedCrossings = bothCrossing && e->getPermissions() ==
SVC_PEDESTRIAN;
608 !joinPedCrossings && (
611 || (length > 3 * POSITION_EPS
614#ifdef DEBUG_JOINJUNCTIONS
625 bool foundRail =
false;
628 if ((e2->getPermissions() & railNoTram) != 0) {
641 if (visited.find(s) != visited.end()) {
644 if (length + dist < maxDist) {
649 const double fullLength = e->getGeometry().length2D();
650 const double length2 = bothCrossing || hasTLS || trueGeomLike ? length : fullLength;
651 toProc.emplace_back(s, dist + length2);
653 toProc.emplace_back(s, 0.);
661#ifdef DEBUG_JOINJUNCTIONS
674 if ((e->getPermissions() & ~ignored) != 0) {
675 allowedIn.push_back(e);
679 if ((e->getPermissions() & ~ignored) != 0) {
680 allowedOut.push_back(e);
683 if (allowedIn.size() > 0 && allowedOut.size() > 0) {
693 for (
const std::string& nodeID : ids) {
697 WRITE_WARNINGF(
TL(
"Ignoring join exclusion for junction '%' since it already occurred in a list of nodes to be joined."), nodeID);
709 maxIds = (int)cluster.size();
711 if ((
int)cluster.size() > maxIds) {
712 auto clusterIt = cluster.begin();
713 std::string result = prefix + *clusterIt;
714 for (
int i = 1; i < maxIds; i++) {
716 result +=
"_" + *clusterIt;
718 return result +
"_#" +
toString((
int)cluster.size() - maxIds) +
"more";
727 std::set<std::string> validCluster;
728 for (std::string nodeID : cluster) {
730 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' was already excluded from joining."), nodeID);
732 }
else if (
myJoined.count(nodeID) > 0) {
733 WRITE_WARNINGF(
TL(
"Ignoring join-cluster because junction '%' already occurred in another join-cluster."), nodeID);
737 validCluster.insert(nodeID);
739 WRITE_ERRORF(
TL(
"Unknown junction '%' in join-cluster."), nodeID);
743 if (validCluster.size() > 1) {
744 myJoined.insert(validCluster.begin(), validCluster.end());
747 WRITE_WARNINGF(
TL(
"Ignoring join-cluster '%' because it has size '%'."), node->
getID(), validCluster.size());
758 for (std::string nodeID : item.first) {
760 if (node ==
nullptr) {
763 cluster.insert(node);
766 if (cluster.size() > 1) {
779#ifdef DEBUG_JOINJUNCTIONS
780 std::cout <<
"joinJunctions...\n";
784 std::map<const NBNode*, std::vector<NBNode*> > ptStopEnds;
786 for (
const auto& stopIt : sc.
getStops()) {
788 if (edge !=
nullptr) {
793 for (
NodeSet& cluster : cands) {
794#ifdef DEBUG_JOINJUNCTIONS
796 for (
NBNode* n : cluster) {
803 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
804 NodeSet::iterator check = j;
807 cluster.erase(check);
813 if (cluster.size() < 2) {
818 if (cluster.size() < 2) {
819 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
823 NBNode* tryRemove =
nullptr;
825 std::string origReason;
827 bool feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, origReason, tryRemove);
828 if (feasible && ((
int)cluster.size() -
pruneLongEdges(cluster, maxDist,
true) < 2)) {
829 origReason =
"long edge";
833#ifdef DEBUG_JOINJUNCTIONS
835 std::cout <<
" try to reduce to 4-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
839 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
841 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
846#ifdef DEBUG_JOINJUNCTIONS
848 std::cout <<
" try to reduce to 2-circle nodes=" <<
joinNamedToString(cluster,
',') <<
"\n";
852 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
854 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
858 while (!feasible && tryRemove !=
nullptr) {
859 cluster.erase(tryRemove);
862 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, reason, tryRemove);
864 WRITE_WARNINGF(
TL(
"Reducing junction cluster % (%)."), origCluster, origReason);
867 if (cluster.size() < 2) {
868 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"after reduction");
873 if (cluster.size() < 2) {
874 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
880 if (cluster.size() < 2) {
881 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"long edge");
885 if (cluster.size() < 2) {
886 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster,
"slip lane");
890 feasible =
feasibleCluster(cluster, ptStopEnds, maxDist, origReason, tryRemove);
892 WRITE_WARNINGF(
TL(
"Not joining junctions % (%)."), origCluster, origReason);
898 for (
NBNode* current : cluster) {
902 newComp.insert(current);
903 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
904 NodeClusters::iterator check = it_comp;
906 bool connected =
false;
907 for (
NBNode* k : *check) {
908 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
910 newComp.insert((*check).begin(), (*check).end());
911 it_comp = components.erase(check);
921 components.push_back(newComp);
923 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
924 if ((*it_comp).size() > 1) {
926 clusters.push_back(*it_comp);
929#ifdef DEBUG_JOINJUNCTIONS
934 return (
int)clusters.size();
940#ifdef DEBUG_JOINJUNCTIONS
941 std::cout <<
"joinSameJunctions...\n";
943 std::map<std::string, NodeSet> positions;
945 const Position& pos = item.second->getPosition();
947 positions[rounded].insert(item.second);
950 for (
auto& item : positions) {
951 if (item.second.size() > 1) {
952 for (
NBNode* n : item.second) {
954 item.second.erase(n);
957 if (item.second.size() > 1) {
958 clusters.push_back(item.second);
963 return (
int)clusters.size();
968#ifdef DEBUG_JOINJUNCTIONS
975 bool pruneFringe =
true;
976 bool pruneNoisyFringe =
false;
979 while (pruneFringe) {
981 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
982 NodeSet::iterator check = j;
987 double clusterDist = std::numeric_limits<double>::max();
988 bool touchingCluster =
false;
990 NBNode* neighbor = (*it_edge)->getToNode();
991 if (cluster.count(neighbor) != 0) {
992 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
997 NBNode* neighbor = (*it_edge)->getFromNode();
998 if (cluster.count(neighbor) != 0) {
999 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
1005 std::set<NBNode*> outsideNeighbors;
1006 std::set<NBNode*> clusterNeighbors;
1007 const double pedestrianFringeThreshold = 0.3;
1009 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1010 if (cluster.count(neighbor) == 0) {
1013 || (clusterDist <= pedestrianFringeThreshold
1014 && (!pruneNoisyFringe
1018 || cluster.size() == 2))
1019 || touchingCluster) {
1020 outsideNeighbors.insert(neighbor);
1023 clusterNeighbors.insert(neighbor);
1026#ifdef DEBUG_JOINJUNCTIONS
1028 <<
" clusterDist=" << clusterDist
1029 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
1030 <<
" touching=" << touchingCluster
1036 if (clusterNeighbors.size() == 0
1037 || (outsideNeighbors.size() <= 1
1038 && clusterNeighbors.size() == 1
1040 cluster.erase(check);
1042#ifdef DEBUG_JOINJUNCTIONS
1044 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
1047 }
else if (outsideNeighbors.size() <= 1 && clusterNeighbors.size() == 1) {
1048 geometryLikeTLS.insert(n);
1051 if (!pruneFringe && !pruneNoisyFringe) {
1054 pruneNoisyFringe =
true;
1058 if (remove2TLS && geometryLikeTLS.size() == cluster.size()) {
1066 for (
const NBNode* n1 : cluster) {
1067 for (
const NBNode* n2 : cluster) {
1068 result =
MAX2(result, n1->getPosition().distanceTo2D(n2->getPosition()));
1076 std::set<NBNode*> toRemove;
1077 int maxPassengerLanes = 0;
1078 for (
NBNode* n : cluster) {
1079 for (
NBEdge* edge : n->getEdges()) {
1080 maxPassengerLanes =
MAX2(maxPassengerLanes, edge->getNumLanesThatAllow(
SVC_PASSENGER));
1083 for (
NBNode* n : cluster) {
1084 for (
NBEdge* edge : n->getOutgoingEdges()) {
1088 std::vector<NBNode*> passed;
1091 NBNode* to = edge->getToNode();
1092 while (cluster.count(to) != 0) {
1094 bool goStraight = (std::find(passed.begin(), passed.end(), to) == passed.end()
1099 passed.push_back(to);
1102 if (cur !=
nullptr) {
1113#ifdef DEBUG_JOINJUNCTIONS
1115 std::cout <<
"check edge length " << edge->getID() <<
" (" << length <<
", passed=" << passed.size() <<
", max=" << longThreshold <<
")\n";
1118 if (length > longThreshold) {
1122 const bool keepStart =
getClusterNeighbors(passed.back(), longThreshold, cluster).size() == 1;
1123 const bool keepEnd = !keepStart &&
getClusterNeighbors(n, longThreshold, cluster).size() == 1;
1124#ifdef DEBUG_JOINJUNCTIONS
1126 std::cout <<
"node=" << n->getID() <<
" long edge " << edge->getID() <<
" (" << length <<
", passed=" <<
toString(passed) <<
", max=" << longThreshold <<
") keepStart=" << keepStart <<
" keepEnd=" << keepEnd <<
"\n";
1132 toRemove.insert(passed.begin(), passed.end() - 1);
1134 toRemove.insert(passed.back());
1141 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
1145 return (
int)toRemove.size();
1153 if (e->getLength() > longThreshold) {
1156 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1157 if (cluster.count(neighbor) != 0) {
1158 result.insert(neighbor);
1167#ifdef DEBUG_JOINJUNCTIONS
1169 std::cout <<
"pruning slip-lanes at cluster=" <<
joinNamedToString(cluster,
' ') <<
"\n";
1173 if (cluster.size() <= 2) {
1177 for (
NBNode* n : cluster) {
1183#ifdef DEBUG_JOINJUNCTIONS
1185 std::cout <<
" candidate slip-lane start=" << n->
getID() <<
" outgoing=" <<
toString(outgoing) <<
"\n";
1188 for (
NBEdge* contEdge : outgoing) {
1192 double slipLength = contEdge->getLength();
1193 NBNode* cont = contEdge->getToNode();
1197 if (cands.count(cont) != 0) {
1201#ifdef DEBUG_JOINJUNCTIONS
1203 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1210#ifdef DEBUG_JOINJUNCTIONS
1212 std::cout <<
" candidate slip-lane end=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1219 const NBEdge*
const otherEdge = (contEdge == outgoing.front() ? outgoing.back() : outgoing.front());
1222 std::vector<NodeAndDist> toProc;
1225 while (!toProc.empty()) {
1227 NBNode* cont2 = nodeAndDist.first;
1228 double dist = nodeAndDist.second;
1229#ifdef DEBUG_JOINJUNCTIONS
1231 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1235 if (visited.find(cont2) != visited.end()) {
1238 visited.insert(cont2);
1239 if (cont2 == cont) {
1244 const double dist2 = dist + e->getLength();
1245 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1246 toProc.push_back(std::make_pair(e->getToNode(), dist2));
1253 toRemove.insert(cands.begin(), cands.end());
1254#ifdef DEBUG_JOINJUNCTIONS
1256 std::cout <<
" found slip-lane with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1269#ifdef DEBUG_JOINJUNCTIONS
1271 std::cout <<
" candidate slip-lane end=" << n->getID() <<
" incoming=" <<
toString(incoming) <<
"\n";
1274 for (
NBEdge* contEdge : incoming) {
1278 double slipLength = contEdge->getLength();
1279 NBNode* cont = contEdge->getFromNode();
1283 if (cands.count(cont) != 0) {
1287#ifdef DEBUG_JOINJUNCTIONS
1289 std::cout <<
" candidate slip-lane cont=" << cont->
getID() <<
"\n";
1296#ifdef DEBUG_JOINJUNCTIONS
1298 std::cout <<
" candidate slip-lane start=" << cont->
getID() <<
" slipLength=" << slipLength <<
"\n";
1305 const NBEdge*
const otherEdge = (contEdge == incoming.front() ? incoming.back() : incoming.front());
1308 std::vector<NodeAndDist> toProc;
1311 while (!toProc.empty()) {
1313 NBNode* cont2 = nodeAndDist.first;
1314 double dist = nodeAndDist.second;
1315#ifdef DEBUG_JOINJUNCTIONS
1317 std::cout <<
" search alternative cont2=" << cont2->
getID() <<
" dist=" << dist <<
"\n";
1321 if (visited.find(cont2) != visited.end()) {
1324 visited.insert(cont2);
1325 if (cont2 == cont) {
1330 const double dist2 = dist + e->getLength();
1331 if (dist2 < slipLength * 2 && (e->getPermissions() &
SVC_PASSENGER) != 0) {
1332 toProc.push_back(std::make_pair(e->getFromNode(), dist2));
1339 toRemove.insert(cands.begin(), cands.end());
1340#ifdef DEBUG_JOINJUNCTIONS
1342 std::cout <<
" found slip-lane start with nodes=" <<
joinNamedToString(cands,
' ') <<
"\n";
1354 for (
NBNode* n : toRemove) {
1355 numRemoved += (int)cluster.erase(n);
1357 if (numRemoved > 0) {
1358#ifdef DEBUG_JOINJUNCTIONS
1360 std::cout <<
" removed " << numRemoved <<
" nodes from cluster: " <<
joinNamedToString(toRemove,
' ') <<
"\n";
1378 if (inPE.size() == 1 && outPE.size() == 2) {
1379 outgoing.insert(outgoing.begin(), outPE.begin(), outPE.end());
1380 inAngle = inPE.front()->getAngleAtNode(n);
1382 }
else if (inPE.size() >= 2 && outPE.size() == 3) {
1385 const double inRelAngle = fabs(
NBHelpers::relAngle(inPE.front()->getAngleAtNode(n), inPE.back()->getAngleAtNode(n)));
1387 if (inRelAngle < 135) {
1390 for (
NBEdge* in : inPE) {
1393 for (
NBEdge* out : outPE) {
1394 const double outRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1395 if (outRelAngle <= 45) {
1396 straight.push_back(out);
1397 }
else if (outRelAngle >= 135) {
1401 if (straight.size() == 2 && numReverse == 1) {
1402 outgoing.insert(outgoing.begin(), straight.begin(), straight.end());
1403 inAngle = in->getAngleAtNode(n);
1416 if (inPE.size() == 2 && outPE.size() == 1) {
1417 incoming.insert(incoming.begin(), inPE.begin(), inPE.end());
1418 outAngle = outPE.front()->getAngleAtNode(n);
1420 }
else if (inPE.size() == 3 && outPE.size() >= 2) {
1423 const double outRelAngle = fabs(
NBHelpers::relAngle(outPE.front()->getAngleAtNode(n), outPE.back()->getAngleAtNode(n)));
1425 if (outRelAngle < 135) {
1428 for (
NBEdge* out : outPE) {
1431 for (
NBEdge* in : inPE) {
1432 const double inRelAngle = fabs(
NBHelpers::relAngle(in->getAngleAtNode(n), out->getAngleAtNode(n)));
1433 if (inRelAngle <= 45) {
1434 straight.push_back(in);
1435 }
else if (inRelAngle >= 135) {
1439 if (straight.size() == 2 && numReverse == 1) {
1440 incoming.insert(incoming.begin(), straight.begin(), straight.end());
1441 outAngle = out->getAngleAtNode(n);
1451 double maxDist, std::string& reason,
NBNode*& tryRemove)
const {
1454 std::map<NBEdge*, double, ComparatorIdLess> finalIncomingAngles;
1455 std::map<NBEdge*, double, ComparatorIdLess> finalOutgoingAngles;
1456 for (
NBNode* n : cluster) {
1457 for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
1464 for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
1473#ifdef DEBUG_JOINJUNCTIONS
1474 for (
NBNode* n : cluster) {
1483 if (finalIncomingAngles.size() > 5) {
1484 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
1489 const double PARALLEL_THRESHOLD_SAME_NODE = PARALLEL_THRESHOLD_DIFF_NODE / 3;
1490 bool foundParallel =
false;
1491 for (
auto j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
1493 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
1494 const double angleDiff = fabs(j->second - k->second);
1495 if (angleDiff < PARALLEL_THRESHOLD_DIFF_NODE) {
1500#ifdef DEBUG_JOINJUNCTIONS
1502 std::cout <<
" angleDiff=" << angleDiff <<
" shapeDist=" << edgeDist <<
"\n";
1505 if (angleDiff >= PARALLEL_THRESHOLD_SAME_NODE && (
1507 || (edgeDist < maxDist)))) {
1510 reason =
"parallel incoming " + e1->
getID() +
"," + e2->
getID();
1525 for (
auto j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
1527 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
1528 const double angleDiff = fabs(j->second - k->second);
1529 if (angleDiff < PARALLEL_THRESHOLD_DIFF_NODE) {
1534#ifdef DEBUG_JOINJUNCTIONS
1536 std::cout <<
" angleDiff=" << angleDiff <<
" shapeDist=" << edgeDist <<
"\n";
1539 if (angleDiff >= PARALLEL_THRESHOLD_SAME_NODE && (
1541 || (edgeDist < maxDist)))) {
1544 reason =
"parallel outgoing " + e1->
getID() +
"," + e2->
getID();
1559 bool hasTLS =
false;
1560 for (
NBNode* n : cluster) {
1561 if (n->isTLControlled() || n->hadSignal()) {
1564 const auto& stopEnds = ptStopEnds.find(n);
1565 if (stopEnds != ptStopEnds.end()) {
1566 for (
NBNode*
const to : stopEnds->second) {
1567 if (cluster.count(to) != 0) {
1568 reason =
"it contains a pt stop edge";
1575 if (cluster.size() > 2) {
1577 double maxLength = -1;
1578 NBEdge* maxEdge =
nullptr;
1579 for (
NBNode* n1 : cluster) {
1580 for (
NBNode* n2 : cluster) {
1581 NBEdge* e1 = n1->getConnectionTo(n2);
1582 NBEdge* e2 = n2->getConnectionTo(n1);
1593#ifdef DEBUG_JOINJUNCTIONS
1594 for (
NBNode* n : cluster) {
1596 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxLength=" << maxLength <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
1600 if (!hasTLS && maxLength > 5) {
1602 std::vector<NBNode*> toCheck;
1603 std::set<NBNode*> visited;
1604 toCheck.push_back(maxEdge->
getToNode());
1605 bool foundCircle =
false;
1606 while (!toCheck.empty()) {
1607 NBNode* n = toCheck.back();
1616 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
1617 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
1618 toCheck.push_back(cand);
1624 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxLength) +
")";
1630 if (cluster.size() >= 2) {
1635 int edgesWithin = 0;
1636 for (
NBNode* n : cluster) {
1637 bool foundOutsideIncoming =
false;
1638 for (
NBEdge* e : n->getIncomingEdges()) {
1639 if (cluster.count(e->getFromNode()) == 0) {
1641 outsideIncoming.push_back(e);
1642 foundOutsideIncoming =
true;
1647 if (foundOutsideIncoming) {
1650 bool foundOutsideOutgoing =
false;
1651 for (
NBEdge* e : n->getOutgoingEdges()) {
1652 if (cluster.count(e->getToNode()) == 0) {
1654 outsideOutgoing.push_back(e);
1655 foundOutsideOutgoing =
true;
1658 if (foundOutsideOutgoing) {
1663 if (entryNodes < 2) {
1664 reason =
"only 1 entry node";
1667 if (exitNodes < 2) {
1668 reason =
"only 1 exit node";
1671 if (cluster.size() == 2) {
1672 if (edgesWithin == 1 && outsideIncoming.size() < 3 && outsideOutgoing.size() < 3) {
1673 reason =
"only 1 edge within and no cross-traffic";
1692 std::cout <<
"reduceToCircle cs=" << circleSize <<
" cands=" <<
toString(cands,
',') <<
" startNodes=" <<
joinNamedToString(startNodes,
',') <<
"\n";
1694 assert(circleSize >= 2);
1695 if ((
int)cands.size() == circleSize) {
1696 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1699 candCluster.insert(cands.begin(), cands.end());
1701 bool feasible = (int)candCluster.size() == circleSize;
1704 cluster.insert(cands.begin(), cands.end());
1711 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1714 std::cout <<
" abort\n";
1718 if (cands.size() == 0) {
1724 if (
reduceToCircle(cluster, circleSize, startNodes, maxDist, cands)) {
1733 singleStart.insert(cands.back());
1736 std::vector<NBNode*> cands2(cands);
1738 if (
reduceToCircle(cluster, circleSize, startNodes, maxDist, cands2)) {
1744 std::cout <<
" abort2\n";
1752 double minDist = std::numeric_limits<double>::max();
1753 NBEdge* result =
nullptr;
1754 for (
NBNode* n : startNodes) {
1755 for (
NBEdge* e : n->getOutgoingEdges()) {
1756 NBNode* neigh = e->getToNode();
1757 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1760 if (dist < minDist) {
1774 for (
NodeSet cluster : clusters) {
1783 assert(cluster.size() > 1);
1784 std::string
id =
"cluster_";
1790 std::set<NBEdge*, ComparatorIdLess> allEdges;
1791 for (
NBNode* n : cluster) {
1793 allEdges.insert(edges.begin(), edges.end());
1796 std::set<NBEdge*, ComparatorIdLess> clusterIncoming;
1797 std::set<NBEdge*, ComparatorIdLess> inside;
1798 for (
NBEdge* e : allEdges) {
1799 if (cluster.count(e->getToNode()) > 0) {
1800 if (cluster.count(e->getFromNode()) > 0) {
1807 clusterIncoming.insert(e);
1811#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1813 <<
" resetConnections=" << resetConnections <<
"\n"
1818 NBNode* newNode =
nullptr;
1819 if (predefined !=
nullptr) {
1820 newNode = predefined;
1829 std::string tlID = id;
1830 if (predefined !=
nullptr) {
1832 nodeType = predefined->
getType();
1845 newNode->
reinit(pos, nodeType);
1851 if (!tlc.
insert(tlDef)) {
1859 std::map<NBEdge*, EdgeSet> reachable;
1860 std::map<std::pair<NBEdge*, NBEdge*>,
SVCPermissions> conPermissions;
1862 for (
NBEdge*
const e : clusterIncoming) {
1866 while (open.size() > 0) {
1867 NBEdge*
const cur = open.back();
1869#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1870 std::cout <<
"e=" << e->getID() <<
" cur=" << cur->
getID() <<
" open=" <<
toString(open) <<
"\n";
1871 std::cout <<
"e=" << e->getID() <<
" cur=" << cur->
getID() <<
" open=" <<
toString(open) <<
"\n";
1875 if (cluster.count(cur->
getToNode()) == 0) {
1883 if (allEdges.count(out) != 0) {
1885 if (seen.count(out) == 0 || (~conPermissions[ {e, out}] & p) != 0) {
1887 open.push_back(out);
1888 conPermissions[ {e, out}] |= p;
1889#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1898 for (
const auto& con : cons) {
1899 if (con.toEdge !=
nullptr && allEdges.count(con.toEdge) != 0) {
1902 p &= con.permissions;
1904 if (seen.count(con.toEdge) == 0 || (~conPermissions[ {e, con.toEdge}] & p) != 0) {
1905 open.push_back(con.toEdge);
1906 conPermissions[ {e, con.toEdge}] |= p;
1914 for (
NBEdge* reached : seen) {
1916 if (inside.count(reached) == 0) {
1921 reachable[e].insert(reached);
1922 const SVCPermissions pDefault = e->getPermissions() & reached->getPermissions();
1923 if (conPermissions[ {e, reached}] != pDefault) {
1924 specialPermissions.insert(e);
1925#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1926 std::cout <<
"e=" << e->getID() <<
" out=" << reached->getID() <<
" special=" <<
getVehicleClassNames(conPermissions[ {e, reached}]) <<
"\n";
1931#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1932 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1940 for (
NBEdge* e : inside) {
1941 for (
NBEdge* e2 : allEdges) {
1943 e2->replaceInConnections(e, e->getConnections());
1951 for (
NBEdge* e : allEdges) {
1952 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1953 NBNode* from = outgoing ? newNode : e->getFromNode();
1954 NBNode* to = outgoing ? e->getToNode() : newNode;
1957 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1959 e->setParameter(
"origTo", e->getToNode()->getID());
1962 if (e->getTurnSignTarget() !=
"") {
1963 for (
NBNode* n : cluster) {
1964 if (e->getTurnSignTarget() == n->getID()) {
1965 e->setTurnSignTarget(to->
getID());
1970 e->reinitNodes(from, to);
1973 std::vector<NBEdge::Connection> conns = e->getConnections();
1974 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1975 if ((*k).toEdge ==
nullptr) {
1980 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1983#ifdef DEBUG_JOINJUNCTIONS_CONNECTIONS
1984 std::cout <<
" e=" << e->getID() <<
" declareConnectionsAsLoaded\n";
1989 if (!resetConnections) {
1994 if (reachable[in].count(out) == 0) {
1997 in->removeFromConnections(out, -1, -1,
true,
false,
true);
2001 }
else if (specialPermissions.count(in) != 0) {
2002 SVCPermissions pDefault = in->getPermissions() & out->getPermissions();
2003 SVCPermissions p = conPermissions[ {in, out}] == 0 ? pDefault : conPermissions[ {in, out}];
2004 in->addEdge2EdgeConnection(out,
true, p == pDefault ?
SVC_UNSPECIFIED : p);
2011 in->invalidateConnections(
true);
2017 for (
NBNode* n : cluster) {
2025 std::set<std::string> ids;
2026 for (
NBNode* n : cluster) {
2027 ids.insert(n->getID());
2050 bool ambiguousType =
false;
2051 for (
NBNode* j : cluster) {
2052 pos.
add(j->getPosition());
2054 if (j->isTLControlled()) {
2057 type = (*j->getControllingTLS().begin())->getType();
2058 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
2059 ambiguousType =
true;
2065 nodeType = otherType;
2066 }
else if (nodeType != otherType) {
2078 pos.
mul(1. / (
double)cluster.size());
2079 if (ambiguousType) {
2089 bool tooFast =
false;
2090 double laneSpeedSum = 0;
2091 std::set<NBEdge*> seen;
2093 for (
const NBEdge* e : j->getEdges()) {
2094 if (c.find(e->getFromNode()) != c.end() && c.find(e->getToNode()) != c.end()) {
2098 if (j->hasIncoming(e)) {
2099 if (recheck && !j->hasConflict(e)) {
2104 laneSpeedSum += (double)e->getNumLanes() * e->getLaneSpeed(0);
2106 if (e->getLaneSpeed(0) * 3.6 > 79) {
2112 return !tooFast && laneSpeedSum >= laneSpeedThreshold && c.size() != 0;
2122 for (
NBEdge* e : node->getIncomingEdges()) {
2124 nonPedIncoming.push_back(e);
2127 for (
NBEdge* e : node->getOutgoingEdges()) {
2129 nonPedOutgoing.push_back(e);
2132 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
2148 if (node->isTLControlled()) {
2154 const std::string tlID = tl->
getID();
2155 if (tlID != node->getID()
2171 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
2172 if (oc.
isSet(
"tls.unset")) {
2173 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
2174 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
2177 throw ProcessError(
TLF(
" The junction '%' to set as not-controlled is not known.", *i));
2180 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
2181 (*j)->removeNode(n);
2191 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
2192 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2193 NBNode* cur = (*i).second;
2202 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
2204 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
2205 for (
const auto& item :
myNodes) {
2206 const NBNode* node = item.second;
2208#ifdef DEBUG_GUESSSIGNALS
2210 std::cout <<
" propagate TLS from " << node->
getID() <<
" downstream\n";
2216 edge->setSignalPosition(node->
getPosition(), node);
2221 std::set<NBEdge*> seen;
2222 std::set<NBEdge*> check;
2223 for (
const auto& item :
myNodes) {
2224 for (
NBEdge* edge : item.second->getOutgoingEdges()) {
2228#ifdef DEBUG_GUESSSIGNALS
2229 if (
DEBUGCOND(edge->getSignalNode()) ||
true) {
2230 std::cout <<
" primary signalPosition edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2237 while (check.size() > 0) {
2238 NBEdge*
const edge = *check.begin();
2239 check.erase(check.begin());
2244 if (seen.count(outEdge) == 0) {
2246#ifdef DEBUG_GUESSSIGNALS
2248 std::cout <<
" setSignalPosition edge=" << outEdge->
getID() <<
" pos=" << edge->
getSignalPosition() <<
"\n";
2251 check.insert(outEdge);
2258 const int slack = oc.
getInt(
"tls.guess-signals.slack");
2259 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2260 NBNode* node = i->second;
2269 std::vector<const NBNode*> signals;
2270 int foundSignals = 0;
2271 int missingSignals = 0;
2273 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2274 const NBEdge* inEdge = *it_i;
2277#ifdef DEBUG_GUESSSIGNALS
2279 std::cout <<
" noTLS, edge=" << inEdge->
getID() <<
"\n";
2283 if (missingSignals > slack) {
2292 int foundSignalsAtDist = 0;
2293 if (foundSignals > 1 && missingSignals <= slack && missingSignals < foundSignals) {
2297 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
2298 const NBEdge* inEdge = *it_i;
2301#ifdef DEBUG_GUESSSIGNALS
2307 if (missingSignals > slack) {
2312 foundSignalsAtDist++;
2315 if (signal !=
nullptr) {
2316 signals.push_back(signal);
2321 for (
const NBEdge* outEdge : outgoing) {
2322 NBNode* cand = outEdge->getToNode();
2324#ifdef DEBUG_GUESSSIGNALS
2326 std::cout <<
" node=" << node->
getID() <<
" outEdge=" << outEdge->getID() <<
" signalNode=" << cand->
getID() <<
" len=" << outEdge->getLength() <<
"\n";
2329 signals.push_back(cand);
2333 if (foundSignalsAtDist > 1 && missingSignals <= slack && missingSignals < foundSignalsAtDist) {
2334 for (
const NBNode* s : signals) {
2335 std::set<NBTrafficLightDefinition*> tls = s->getControllingTLS();
2337 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
2344 if (!tlc.
insert(tlDef)) {
2356 if (oc.
getBool(
"tls.guess.joining")) {
2361 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
2365 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2366 if ((*j)->isTLControlled() ||
myUnsetTLS.count(*j) != 0) {
2381 for (
auto nodeSet : cands) {
2382 std::vector<NBNode*> nodes;
2383 for (
NBNode* node : nodeSet) {
2384 nodes.push_back(node);
2389 if (!tlc.
insert(tlDef)) {
2399 if (oc.
getBool(
"tls.guess")) {
2400 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2401 NBNode* cur = (*i).second;
2424 std::set<NBTrafficLightDefinition*> recompute;
2427 const std::set<NBTrafficLightDefinition*>& tlDefs = node->getControllingTLS();
2428 recompute.insert(tlDefs.begin(), tlDefs.end());
2429 node->removeTrafficLights(
true);
2430 for (
NBEdge* edge : node->getIncomingEdges()) {
2431 edge->clearControllingTLInformation();
2436 if (def->getNodes().size() == 0) {
2439 def->setParticipantsInformation();
2440 def->setTLControllingInformation();
2465 for (
const auto& item :
myNodes) {
2466 item.second->computeKeepClear();
2474 for (
const std::string& tlsID : excludeList) {
2475 if (!tlc.
exist(tlsID,
false)) {
2476 WRITE_WARNINGF(
"Unknown tls ID '%' in option tls.join-exclude", tlsID);
2479 std::set<std::string> exclude(excludeList.begin(), excludeList.end());
2483 for (NodeSet::iterator j = c.begin(); j != c.end();) {
2484 if (!(*j)->isTLControlled() || exclude.count((*(*j)->getControllingTLS().begin())->getID()) != 0) {
2495 bool dummySetTL =
false;
2496 std::string
id =
"joinedS_";
2501 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
2502 j->removeTrafficLights();
2507 std::vector<NBNode*> nodes;
2512 if (!tlc.
insert(tlDef)) {
2529 if (!tlc.
insert(tlDef)) {
2531 WRITE_WARNINGF(
TL(
"Building a tl-logic for junction '%' twice is not possible."),
id);
2541 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2542 (*i).second->computeLanes2Lanes();
2550 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2551 (*i).second->computeLogic(ec);
2558 std::set<NBNode*> roundaboutNodes;
2559 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
2560 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
2561 if (checkLaneFoesRoundabout) {
2563 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
2564 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
2565 roundaboutNodes.insert((*j)->getToNode());
2569 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2570 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
2571 (*i).second->computeLogic2(checkLaneFoes);
2578 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2579 delete ((*i).second);
2592 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
2594 while (
retrieve(freeID) !=
nullptr) {
2597 freeID =
"SUMOGenerated" + toString<int>(counter);
2605 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2606 (*i).second->computeNodeShape(mismatchThreshold);
2613 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2616 int numUnregulatedJunctions = 0;
2617 int numDeadEndJunctions = 0;
2618 int numTrafficLightJunctions = 0;
2619 int numPriorityJunctions = 0;
2620 int numRightBeforeLeftJunctions = 0;
2621 int numLeftBeforeRightJunctions = 0;
2622 int numAllWayStopJunctions = 0;
2623 int numZipperJunctions = 0;
2624 int numDistrictJunctions = 0;
2625 int numRailCrossing = 0;
2626 int numRailSignals = 0;
2627 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
2628 switch ((*i).second->getType()) {
2630 ++numUnregulatedJunctions;
2633 ++numDeadEndJunctions;
2638 ++numTrafficLightJunctions;
2642 ++numPriorityJunctions;
2645 ++numRightBeforeLeftJunctions;
2648 ++numLeftBeforeRightJunctions;
2651 ++numAllWayStopJunctions;
2654 ++numZipperJunctions;
2657 ++numDistrictJunctions;
2674 if (numDeadEndJunctions > 0) {
2679 if (numLeftBeforeRightJunctions > 0) {
2682 if (numTrafficLightJunctions > 0) {
2685 if (numAllWayStopJunctions > 0) {
2688 if (numZipperJunctions > 0) {
2691 if (numRailCrossing > 0) {
2694 if (numRailSignals > 0) {
2697 if (numDistrictJunctions > 0) {
2705 WRITE_MESSAGE(
TL(
"-----------------------------------------------------"));
2709std::vector<std::string>
2711 std::vector<std::string> ret;
2712 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2713 ret.push_back((*i).first);
2722 const auto nodeContainerCopy =
myNodes;
2724 for (
const auto& node : nodeContainerCopy) {
2725 node.second->setID(prefix + node.second->getID());
2726 myNodes[node.second->getID()] = node.second;
2733 if (
myNodes.count(newID) != 0) {
2734 throw ProcessError(
TLF(
"Attempt to rename node using existing id '%'", newID));
2744 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
2745 NBNode* node = i->second;
2749 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
2759 edge->setSignalPosition(node->
getPosition(),
nullptr);
2760#ifdef DEBUG_GUESSSIGNALS
2761 std::cout <<
" discard-simple " << node->
getID() <<
" edge=" << edge->getID() <<
" pos=" << edge->getSignalPosition() <<
"\n";
2764 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
2779 NBNode* node = item.second;
2790 if (!numericaIDs && !reservedIDs && prefix ==
"" && !startGiven) {
2793 std::vector<std::string> avoid;
2799 std::set<std::string> reserve;
2803 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
2807 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
2809 toChange.insert(it->second);
2816 toChange.insert(it->second);
2819 if (reservedIDs && reserve.count(it->first) > 0) {
2820 toChange.insert(it->second);
2823 std::set<std::string> keep;
2827 for (
auto it = toChange.begin(); it != toChange.end();) {
2828 if (keep.count((*it)->getID()) != 0) {
2829 it = toChange.erase(it++);
2836 for (
NBNode* node : toChange) {
2839 for (
NBNode* node : toChange) {
2843 node->setID(idSupplier.
getNext());
2845 tlc.
rename(tlDef, node->getID());
2847 myNodes[node->getID()] = node;
2849 if (prefix.empty()) {
2850 return (
int)toChange.size();
2855 for (
auto item : oldNodes) {
2857 rename(item.second, prefix + item.first);
2860 tlc.
rename(tlDef, prefix + tlDef->getID());
2878 for (
const auto& item :
myNodes) {
2881 paretoCheck(item.second, bottomRightFront, 1, -1);
2882 paretoCheck(item.second, bottomLeftFront, -1, -1);
2885 front.insert(topRightFront.begin(), topRightFront.end());
2886 front.insert(topLeftFront.begin(), topLeftFront.end());
2887 front.insert(bottomRightFront.begin(), bottomRightFront.end());
2888 front.insert(bottomLeftFront.begin(), bottomLeftFront.end());
2890 for (
NBNode* n : front) {
2891 const int in = (int)n->getIncomingEdges().size();
2892 const int out = (int)n->getOutgoingEdges().size();
2893 if ((in <= 1 && out <= 1) &&
2894 (in == 0 || out == 0
2895 || n->getIncomingEdges().front()->isTurningDirectionAt(n->getOutgoingEdges().front()))) {
2902 for (
const auto& item :
myNodes) {
2904 if (front.count(n) != 0) {
2907 if (n->
getEdges().size() == 1 && n->
getEdges().front()->getSpeed() > speedThreshold) {
2920 std::vector<NBNode*> dominated;
2922 const double x2 =
fn->getPosition().x() * xSign;
2923 const double y2 =
fn->getPosition().y() * ySign;
2924 if (x2 >= x && y2 >= y) {
2926 }
else if (x2 <= x && y2 <= y) {
2927 dominated.push_back(
fn);
2930 frontier.insert(node);
2931 for (
NBNode* r : dominated) {
2939 for (
const auto& item :
myNodes) {
2942 bool hasNEMA =
false;
2960 bool hadShapes =
false;
2961 for (
const auto& item :
myNodes) {
2962 if (item.second->getShape().size() > 0 && !item.second->hasCustomShape()) {
2964 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
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 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
int joinSameJunctions(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins junctions with the same coordinates regardless of topology.
void analyzeCluster(NodeSet cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type, SumoXMLNodeType &nodeType)
void addCluster2Join(const std::set< std::string > &cluster, NBNode *node)
add ids of nodes which shall be joined into a single node
bool customTLID(const NodeSet &c) const
check wheter the set of nodes contains traffic lights with custom id
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.