60 #define DEBUGNODEID "C1" 62 #define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID)) 81 NodeCont::iterator i =
myNodes.find(
id);
87 const float pos[2] = {(float)position.
x(), (float)position.
y()};
95 std::string
id = node->
getID();
96 NodeCont::iterator i =
myNodes.find(
id);
109 NodeCont::const_iterator i =
myNodes.find(
id);
120 const float cmin[2] = {(float)(position.
x() - extOffset), (
float)(position.
y() - extOffset)};
121 const float cmax[2] = {(float)(position.
x() + extOffset), (
float)(position.
y() + extOffset)};
122 std::set<std::string> into;
125 for (std::set<std::string>::const_iterator i = into.begin(); i != into.end(); i++) {
169 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
170 no += (*i).second->removeSelfLoops(dc, ec, tc);
181 const double distanceThreshold = 7.;
182 const double lengthThreshold = 0.10;
184 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
186 std::map<NBNode*, EdgeVector> connectionCount;
187 const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
188 for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
189 connectionCount[(*j)->getToNode()].push_back(*j);
192 std::map<NBNode*, EdgeVector>::iterator k;
193 for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
195 if ((*k).second.size() < 2) {
201 const NBEdge*
const first = ev.front();
202 EdgeVector::const_iterator jci;
203 for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
206 (relativeLengthDifference > lengthThreshold) ||
207 (fabs(first->
getSpeed() - (*jci)->getSpeed()) >= 0.01) ||
215 if (jci == ev.end()) {
226 const std::vector<std::string>& edgeNames = ec.
getAllNames();
227 for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
236 if (outgoingEdges.size() != 1) {
241 if (incomingEdges.size() > 1) {
244 }
else if (incomingEdges.size() == 1) {
245 NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
246 NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
247 if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
255 bool hasJunction =
false;
267 adjacentNodes.clear();
268 for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
269 if ((*itOfOutgoings)->getToNode() != from
270 && (*itOfOutgoings)->getToNode() != to
274 adjacentNodes.insert((*itOfOutgoings)->getToNode());
276 for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
277 adjacentNodes.insert((*itOfIncomings)->getFromNode());
279 adjacentNodes.erase(to);
280 if (adjacentNodes.size() > 2) {
283 }
while (!hasJunction && eOld != e);
285 std::string warningString =
"Removed a road without junctions: ";
286 for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
287 if (roadIt == road.begin()) {
288 warningString += (*roadIt)->
getID();
290 warningString +=
", " + (*roadIt)->getID();
293 NBNode* fromNode = (*roadIt)->getFromNode();
294 NBNode* toNode = (*roadIt)->getToNode();
295 ec.
erase(dc, *roadIt);
313 std::vector<std::set<NBEdge*> > components;
315 std::set<std::string> edgesLeft;
316 for (std::map<std::string, NBEdge*>::const_iterator edgeIt = ec.
begin(); edgeIt != ec.
end(); ++edgeIt) {
317 edgesLeft.insert(edgeIt->first);
320 std::set<NBEdge*> toRemove;
321 while (!edgesLeft.empty()) {
322 queue.push_back(ec.
getByID(*edgesLeft.begin()));
323 std::set<NBEdge*> component;
324 while (!queue.empty()) {
325 NBEdge*
const e = queue.back();
328 std::vector<EdgeVector> edgeLists;
333 for (std::vector<EdgeVector>::const_iterator listIt = edgeLists.begin(); listIt != edgeLists.end(); ++listIt) {
334 for (EdgeVector::const_iterator edgeIt = listIt->begin(); edgeIt != listIt->end(); ++edgeIt) {
335 std::set<std::string>::iterator leftIt = edgesLeft.find((*edgeIt)->getID());
336 if (leftIt != edgesLeft.end()) {
337 queue.push_back(*edgeIt);
338 edgesLeft.erase(leftIt);
343 std::vector<std::set<NBEdge*> >::iterator cIt;
344 for (cIt = components.begin(); cIt != components.end(); ++cIt) {
345 if (cIt->size() < component.size()) {
349 components.insert(cIt, component);
350 if ((
int)components.size() > numKeep) {
351 toRemove.insert(components.back().begin(), components.back().end());
352 components.pop_back();
355 for (std::set<NBEdge*>::iterator edgeIt = toRemove.begin(); edgeIt != toRemove.end(); ++edgeIt) {
356 NBNode*
const fromNode = (*edgeIt)->getFromNode();
357 NBNode*
const toNode = (*edgeIt)->getToNode();
358 ec.
erase(dc, *edgeIt);
373 bool removeGeometryNodes) {
375 std::set<std::string> edges2keep;
376 if (removeGeometryNodes) {
378 if (oc.
isSet(
"geometry.remove.keep-edges.input-file")) {
381 if (oc.
isSet(
"geometry.remove.keep-edges.explicit")) {
382 const std::vector<std::string> edges = oc.
getStringVector(
"geometry.remove.keep-edges.explicit");
383 edges2keep.insert(edges.begin(), edges.end());
390 std::vector<NBNode*> toRemove;
391 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
392 NBNode* current = (*i).second;
394 std::vector<std::pair<NBEdge*, NBEdge*> > toJoin;
401 if (removeGeometryNodes &&
mySplit.count(current) == 0) {
409 for (EdgeVector::const_iterator it_edge = current->
getEdges().begin(); it_edge != current->
getEdges().end(); ++it_edge) {
410 if (edges2keep.find((*it_edge)->getID()) != edges2keep.end()) {
424 for (std::vector<std::pair<NBEdge*, NBEdge*> >::iterator j = toJoin.begin(); j != toJoin.end(); j++) {
426 NBEdge* continuation = (*j).second;
427 begin->
append(continuation);
430 ec.
extract(dc, continuation,
true);
432 toRemove.push_back(current);
436 for (std::vector<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
445 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
446 (*i).second->avoidOverlap();
453 std::set<NBNode*> visited;
454 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
455 std::vector<NodeAndDist> toProc;
456 if (visited.find((*i).second) != visited.end()) {
459 toProc.push_back(std::make_pair((*i).second, 0));
461 while (!toProc.empty()) {
463 NBNode* n = nodeAndDist.first;
464 double dist = nodeAndDist.second;
466 if (visited.find(n) != visited.end()) {
470 bool pureRail =
true;
471 bool railAndPeds =
true;
489 const double length = e->getLoadedLength();
490 #ifdef DEBUG_JOINJUNCTIONS 492 std::cout <<
"generateNodeClusters: consider s=" << s->
getID()
493 <<
" clusterNode=" << n->
getID() <<
" edge=" << e->getID() <<
" length=" << length <<
" with cluster " <<
joinNamedToString(c,
' ') <<
"\n";
497 bool railAndPeds2 =
true;
500 railAndPeds2 =
false;
511 const bool joinPedCrossings = bothCrossing && e->getPermissions() ==
SVC_PEDESTRIAN;
513 !joinPedCrossings && (
525 bool foundRail =
false;
528 if ((e2->getPermissions() & railNoTram) != 0) {
541 if (visited.find(s) != visited.end()) {
544 if (length + dist < maxDist) {
546 toProc.push_back(std::make_pair(s, dist + length));
548 toProc.push_back(std::make_pair(s, 0));
556 #ifdef DEBUG_JOINJUNCTIONS 566 for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
570 WRITE_WARNING(
"Ignoring join exclusion for junction '" + *it +
"' since it already occurred in a list of nodes to be joined");
571 }
else if (check &&
retrieve(*it) ==
nullptr) {
572 WRITE_WARNING(
"Ignoring join exclusion for unknown junction '" + *it +
"'");
583 std::set<std::string> validCluster;
584 for (std::string nodeID : cluster) {
586 WRITE_WARNING(
"Ignoring join-cluster because junction '" + nodeID +
"' was already excluded from joining");
588 }
else if (
myJoined.count(nodeID) > 0) {
589 WRITE_WARNING(
"Ignoring join-cluster because junction '" + nodeID +
"' already occurred in another join-cluster");
593 if (node !=
nullptr) {
594 validCluster.insert(nodeID);
598 std::set<std::string> subIDs;
599 for (std::string nID :
StringTokenizer(nodeID.substr(8),
"_").getVector()) {
601 if (node !=
nullptr) {
602 validCluster.insert(nID);
604 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster (componentID)");
608 WRITE_ERROR(
"Unknown junction '" + nodeID +
"' in join-cluster");
613 for (std::string nodeID : validCluster) {
626 for (std::string nodeID : item.first) {
628 if (node ==
nullptr) {
629 WRITE_ERROR(
"unknown junction '" + nodeID +
"' while joining");
631 cluster.insert(node);
634 if (cluster.size() > 1) {
640 myClusters2Join.clear();
647 #ifdef DEBUG_JOINJUNCTIONS 648 std::cout <<
"joinJunctions...\n";
653 for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
656 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
657 NodeSet::iterator check = j;
660 cluster.erase(check);
666 std::set<NBNode*> toRemove;
667 for (
NBNode* n : cluster) {
668 for (
NBEdge* edge : n->getOutgoingEdges()) {
669 if (cluster.count(edge->getToNode()) != 0 && edge->getLoadedLength() > maxDist ) {
670 #ifdef DEBUG_JOINJUNCTIONS 672 std::cout <<
"long edge " << edge->getID() <<
" (" << edge->getLoadedLength() <<
", max=" << maxDist <<
")\n";
676 toRemove.insert(edge->getToNode());
680 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
683 if (cluster.size() < 2) {
695 WRITE_WARNING(
"Reducing junction cluster " + origCluster +
" (" + reason +
")");
705 WRITE_WARNING(
"Reducing junction cluster " + origCluster +
" (" + reason +
")");
716 for (
NBNode* current : cluster) {
720 newComp.insert(current);
721 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
722 NodeClusters::iterator check = it_comp;
724 bool connected =
false;
725 for (
NBNode* k : *check) {
726 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
728 newComp.insert((*check).begin(), (*check).end());
729 it_comp = components.erase(check);
739 components.push_back(newComp);
741 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
742 if ((*it_comp).size() > 1) {
744 clusters.push_back(*it_comp);
749 return (
int)clusters.size();
755 #ifdef DEBUG_JOINJUNCTIONS 761 bool pruneFringe =
true;
764 while (pruneFringe) {
766 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
767 NodeSet::iterator check = j;
772 double clusterDist = std::numeric_limits<double>::max();
773 bool touchingCluster =
false;
775 NBNode* neighbor = (*it_edge)->getToNode();
776 if (cluster.count(neighbor) != 0) {
777 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
782 NBNode* neighbor = (*it_edge)->getFromNode();
783 if (cluster.count(neighbor) != 0) {
784 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
790 std::set<NBNode*> outsideNeighbors;
791 std::set<NBNode*> clusterNeighbors;
792 const double pedestrianFringeThreshold = 0.3;
794 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
795 if (cluster.count(neighbor) == 0) {
798 || clusterDist <= pedestrianFringeThreshold
799 || touchingCluster) {
800 outsideNeighbors.insert(neighbor);
803 clusterNeighbors.insert(neighbor);
806 #ifdef DEBUG_JOINJUNCTIONS 808 <<
" clusterDist=" << clusterDist
809 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
810 <<
" touching=" << touchingCluster
815 if (outsideNeighbors.size() <= 1
816 && clusterNeighbors.size() == 1
818 cluster.erase(check);
820 #ifdef DEBUG_JOINJUNCTIONS 822 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
835 std::map<std::string, double> finalIncomingAngles;
836 std::map<std::string, double> finalOutgoingAngles;
837 for (NodeSet::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
838 for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
845 for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
854 #ifdef DEBUG_JOINJUNCTIONS 855 for (
NBNode* n : cluster) {
858 <<
"\n inAngles=" <<
joinToString(finalIncomingAngles,
' ',
':')
859 <<
"\n outAngles=" <<
joinToString(finalOutgoingAngles,
' ',
':')
864 if (finalIncomingAngles.size() > 4) {
865 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
869 const double PARALLEL_INCOMING_THRESHOLD = 10.0;
870 bool foundParallel =
false;
871 for (std::map<std::string, double>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
872 std::map<std::string, double>::const_iterator k = j;
873 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
874 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
875 reason =
"parallel incoming " + j->first +
"," + k->first;
881 for (std::map<std::string, double>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
882 std::map<std::string, double>::const_iterator k = j;
883 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
884 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
885 reason =
"parallel outgoing " + j->first +
"," + k->first;
892 for (
auto it = sc.
begin(); it != sc.
end(); it++) {
894 if (edge !=
nullptr && cluster.count(edge->
getFromNode()) != 0 && cluster.count(edge->
getToNode()) != 0) {
895 reason =
"it contains stop '" + it->first +
"'";
901 for (
NBNode* n : cluster) {
902 if (n->isTLControlled()) {
906 const bool hasTLS = numTLS > 0;
908 if (cluster.size() > 2) {
911 NBEdge* maxEdge =
nullptr;
912 for (
NBNode* n1 : cluster) {
913 for (
NBNode* n2 : cluster) {
914 NBEdge* e1 = n1->getConnectionTo(n2);
915 NBEdge* e2 = n2->getConnectionTo(n1);
926 #ifdef DEBUG_JOINJUNCTIONS 927 for (
NBNode* n : cluster) {
929 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxDist=" << maxDist <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
933 if (!hasTLS && maxDist > 5) {
935 std::vector<NBNode*> toCheck;
936 std::set<NBNode*> visited;
938 bool foundCircle =
false;
939 while (!toCheck.empty()) {
940 NBNode* n = toCheck.back();
949 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
950 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
951 toCheck.push_back(cand);
957 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxDist) +
")";
963 if (!hasTLS && cluster.size() >= 2) {
966 int outsideIncoming = 0;
967 int outsideOutgoing = 0;
969 for (
NBNode* n : cluster) {
970 bool foundOutsideIncoming =
false;
972 if (cluster.count(e->getFromNode()) == 0) {
975 foundOutsideIncoming =
true;
980 if (foundOutsideIncoming) {
983 bool foundOutsideOutgoing =
false;
984 for (
NBEdge* e : n->getOutgoingEdges()) {
985 if (cluster.count(e->getToNode()) == 0) {
988 foundOutsideOutgoing =
true;
991 if (foundOutsideOutgoing) {
995 if (entryNodes < 2) {
996 reason =
"only 1 entry node";
1000 reason =
"only 1 exit node";
1003 if (cluster.size() == 2) {
1004 if (edgesWithin == 1 && outsideIncoming < 3 && outsideOutgoing < 3) {
1005 reason =
"only 1 edge within and no cross-traffic";
1017 assert(circleSize >= 2);
1018 if ((
int)cands.size() == circleSize) {
1019 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
1022 cluster.insert(cands.begin(), cands.end());
1028 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
1032 if (cands.size() == 0) {
1047 singleStart.insert(cands.back());
1050 std::vector<NBNode*> cands2(cands);
1063 double minDist = std::numeric_limits<double>::max();
1064 NBEdge* result =
nullptr;
1065 for (
NBNode* n : startNodes) {
1066 for (
NBEdge* e : n->getOutgoingEdges()) {
1067 NBNode* neigh = e->getToNode();
1068 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
1071 if (dist < minDist) {
1085 for (
NodeSet cluster : clusters) {
1094 assert(cluster.size() > 1);
1097 std::string
id =
"cluster";
1101 NBNode* newNode =
nullptr;
1102 if (predefined !=
nullptr) {
1103 newNode = predefined;
1112 std::string tlID = id;
1113 if (predefined !=
nullptr) {
1115 nodeType = predefined->
getType();
1128 newNode->
reinit(pos, nodeType);
1131 if (!tlc.
insert(tlDef)) {
1134 throw ProcessError(
"Could not allocate tls '" +
id +
"'.");
1139 for (
NBNode* n : cluster) {
1141 allEdges.insert(edges.begin(), edges.end());
1146 for (
NBEdge* e : allEdges) {
1147 if (cluster.count(e->getToNode()) > 0) {
1148 if (cluster.count(e->getFromNode()) > 0) {
1151 clusterIncoming.insert(e);
1155 #ifdef DEBUG_JOINJUNCTIONS 1157 <<
" incoming=" <<
toString(clusterIncoming) <<
"\n" 1158 <<
" inside=" <<
toString(inside) <<
"\n";
1162 std::map<NBEdge*, EdgeSet> reachable;
1163 for (
NBEdge* e : clusterIncoming) {
1167 while (open.size() > 0) {
1168 NBEdge* cur = open.back();
1172 if (cluster.count(cur->
getToNode()) == 0) {
1180 if (seen.count(out) == 0
1181 && allEdges.count(out) != 0
1183 open.push_back(out);
1188 for (
const auto& con : cons) {
1189 if (con.toEdge !=
nullptr 1190 && seen.count(con.toEdge) == 0
1191 && allEdges.count(con.toEdge) != 0) {
1192 open.push_back(con.toEdge);
1198 for (
NBEdge* reached : seen) {
1200 if (inside.count(reached) == 0) {
1201 reachable[e].insert(reached);
1204 #ifdef DEBUG_JOINJUNCTIONS 1205 std::cout <<
" reachable e=" << e->getID() <<
" seen=" <<
toString(seen) <<
" reachable=" <<
toString(reachable[e]) <<
"\n";
1210 for (
NBEdge* e : inside) {
1211 for (
NBEdge* e2 : allEdges) {
1213 e2->replaceInConnections(e, e->getConnections());
1221 for (
NBEdge* e : allEdges) {
1222 std::vector<NBEdge::Connection> conns = e->getConnections();
1223 const bool outgoing = cluster.count(e->getFromNode()) > 0;
1224 NBNode* from = outgoing ? newNode : e->getFromNode();
1225 NBNode* to = outgoing ? e->getToNode() : newNode;
1228 e->
setParameter(
"origFrom", e->getFromNode()->getID());
1230 e->setParameter(
"origTo", e->getToNode()->getID());
1233 e->reinitNodes(from, to);
1236 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1237 e->addLane2LaneConnection((*k).fromLane, (*k).toEdge, (*k).toLane,
NBEdge::L2L_USER,
false, (*k).mayDefinitelyPass);
1238 if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
1249 in->removeFromConnections(out, -1, -1,
true,
false,
true);
1256 for (
NBNode* n : cluster) {
1264 std::set<std::string> ids;
1265 for (
NBNode* n : cluster) {
1266 ids.insert(n->getID());
1277 bool ambiguousType =
false;
1278 for (
NBNode* j : cluster) {
1279 pos.
add(j->getPosition());
1281 if (j->isTLControlled()) {
1284 type = (*j->getControllingTLS().begin())->getType();
1285 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
1286 ambiguousType =
true;
1292 nodeType = otherType;
1293 }
else if (nodeType != otherType) {
1305 pos.
mul(1.0 / cluster.size());
1306 if (ambiguousType) {
1308 WRITE_WARNING(
"Ambiguous traffic light type for node cluster '" +
id +
"' set to '" +
toString(type) +
"'");
1318 bool tooFast =
false;
1320 std::set<NBEdge*> seen;
1323 for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
1324 if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
1327 if (j->hasIncoming(*k)) {
1329 f += (double)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
1333 if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
1339 return !tooFast && f >= laneSpeedThreshold && c.size() != 0;
1351 nonPedIncoming.push_back(e);
1354 for (
NBEdge* e : node->getOutgoingEdges()) {
1356 nonPedOutgoing.push_back(e);
1359 if (!node->geometryLike(nonPedIncoming, nonPedOutgoing)) {
1375 if (node->isTLControlled()) {
1376 const std::string tlID = (*node->getControllingTLS().begin())->getID();
1377 if (tlID != node->getID()
1392 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
1393 std::vector<NBNode*> ncontrolled;
1394 if (oc.
isSet(
"tls.unset")) {
1395 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
1396 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
1399 throw ProcessError(
" The junction '" + *i +
"' to set as not-controlled is not known.");
1402 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
1403 (*j)->removeNode(n);
1406 ncontrolled.push_back(n);
1413 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
1414 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1415 NBNode* cur = (*i).second;
1416 if (cur->
isNearDistrict() && std::find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
1424 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
1426 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
1427 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1428 NBNode* node = (*i).second;
1430 std::set<NBEdge*> seen;
1431 std::set<std::pair<NBEdge*, double> > check;
1433 double offset = edge->getLength();
1434 edge->setSignalOffset(offset, node);
1436 check.insert(std::make_pair(edge, offset));
1439 while (check.size() > 0) {
1440 NBEdge* edge = check.begin()->first;
1441 const double offset = check.begin()->second;
1442 check.erase(check.begin());
1446 if (seen.count(edge) == 0) {
1447 double offset2 = offset + edge->
getLength();
1450 check.insert(std::make_pair(edge, offset2));
1458 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1459 NBNode* node = i->second;
1460 if (find(ncontrolled.begin(), ncontrolled.end(), node) != ncontrolled.end()) {
1468 std::vector<NBNode*> signals;
1470 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
1471 const NBEdge* inEdge = *it_i;
1479 if (signal !=
nullptr) {
1481 signals.push_back(signal);
1486 for (EdgeVector::const_iterator it_i = outgoing.begin(); it_i != outgoing.end(); ++it_i) {
1487 const NBEdge* outEdge = *it_i;
1491 signals.push_back(cand);
1495 for (std::vector<NBNode*>::iterator j = signals.begin(); j != signals.end(); ++j) {
1498 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
1505 if (!tlc.
insert(tlDef)) {
1517 if (oc.
getBool(
"tls.guess.joining")) {
1522 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
1526 for (NodeSet::iterator j = c.begin(); j != c.end();) {
1527 if ((*j)->isTLControlled() || std::find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
1543 for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
1544 std::vector<NBNode*> nodes;
1545 for (NodeSet::iterator j = (*i).begin(); j != (*i).end(); j++) {
1546 nodes.push_back(*j);
1548 std::string
id =
"joinedG_" +
toString(index++);
1550 if (!tlc.
insert(tlDef)) {
1560 if (oc.
getBool(
"tls.guess")) {
1561 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1562 NBNode* cur = (*i).second;
1568 if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
1588 for (NodeSet::iterator j = c.begin(); j != c.end();) {
1589 if (!(*j)->isTLControlled()) {
1601 std::string
id =
"joined";
1606 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
1607 j->removeTrafficLights();
1608 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
1612 std::vector<NBNode*> nodes;
1621 if (!tlc.
insert(tlDef)) {
1638 if (!tlc.
insert(tlDef)) {
1640 WRITE_WARNING(
"Building a tl-logic for junction '" +
id +
"' twice is not possible.");
1650 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1651 (*i).second->computeLanes2Lanes();
1659 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1660 (*i).second->computeLogic(ec, oc);
1667 std::set<NBNode*> roundaboutNodes;
1668 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
1669 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
1670 if (checkLaneFoesRoundabout) {
1672 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
1673 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
1674 roundaboutNodes.insert((*j)->getToNode());
1678 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1679 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
1680 (*i).second->computeLogic2(checkLaneFoes);
1687 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1688 delete ((*i).second);
1694 myExtractedNodes.clear();
1701 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
1703 while (
retrieve(freeID) !=
nullptr) {
1706 freeID =
"SUMOGenerated" + toString<int>(counter);
1714 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1715 (*i).second->computeNodeShape(mismatchThreshold);
1722 int numUnregulatedJunctions = 0;
1723 int numDeadEndJunctions = 0;
1724 int numTrafficLightJunctions = 0;
1725 int numPriorityJunctions = 0;
1726 int numRightBeforeLeftJunctions = 0;
1727 int numAllWayStopJunctions = 0;
1728 int numZipperJunctions = 0;
1729 int numDistrictJunctions = 0;
1730 int numRailCrossing = 0;
1731 int numRailSignals = 0;
1732 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1733 switch ((*i).second->getType()) {
1735 ++numUnregulatedJunctions;
1738 ++numDeadEndJunctions;
1743 ++numTrafficLightJunctions;
1747 ++numPriorityJunctions;
1750 ++numRightBeforeLeftJunctions;
1753 ++numAllWayStopJunctions;
1756 ++numZipperJunctions;
1759 ++numDistrictJunctions;
1776 if (numDeadEndJunctions > 0) {
1781 if (numTrafficLightJunctions > 0) {
1784 if (numAllWayStopJunctions > 0) {
1787 if (numZipperJunctions > 0) {
1790 if (numRailCrossing > 0) {
1793 if (numRailSignals > 0) {
1796 if (numDistrictJunctions > 0) {
1802 std::vector<std::string>
1804 std::vector<std::string> ret;
1805 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1806 ret.push_back((*i).first);
1814 if (
myNodes.count(newID) != 0) {
1815 throw ProcessError(
"Attempt to rename node using existing id '" + newID +
"'");
1825 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1826 NBNode* node = i->second;
1830 if (geometryLike && (*tldefs.begin())->getNodes().size() > 1) {
1837 for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
1838 (*it_o)->setSignalOffset((*it_o)->getLength(),
nullptr);
1841 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
1856 NBNode* node = item.second;
1867 std::set<std::string> reserve;
1871 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1875 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
1880 toChange.insert(it->second);
1883 if (reservedIDs && reserve.count(it->first) > 0) {
1884 toChange.insert(it->second);
1888 for (
NBNode* node : toChange) {
1893 node->setID(idSupplier.
getNext());
1894 myNodes[node->getID()] = node;
1896 if (prefix.empty()) {
1897 return (
int)toChange.size();
1902 for (
auto item : oldNodes) {
1904 rename(item.second, prefix + item.first);
std::string getFreeID()
generates a new node ID
std::set< std::string > myJoinExclusions
set of node ids which should not be joined
NodeCont myNodes
The map of names to nodes.
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
const std::map< std::string, NBTrafficLightDefinition * > & getPrograms(const std::string &id) const
Returns all programs for the given tl-id.
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
void joinSimilarEdges(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins edges connecting the same nodes.
double getLength() const
Returns the computed length of the edge.
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
void removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes self-loop edges (edges where the source and the destination node are the same) ...
bool feasibleCluster(const NodeSet &cluster, const NBEdgeCont &ec, const NBPTStopCont &sc, std::string &reason) const
determine wether the cluster is not too complex for joining
std::string joinNamedToString(const std::set< T *, C > &ns, const T_BETWEEN &between)
bool reduceToCircle(NodeSet &cluster, int circleSize, NodeSet startNodes, std::vector< NBNode *> cands=std::vector< NBNode *>()) const
try to find a joinable subset (recursively)
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
void computeLogics2(const NBEdgeCont &ec, OptionsCont &oc)
compute right-of-way logic for all lane-to-lane connections
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
double z() const
Returns the z-position.
void addJoinExclusion(const std::vector< std::string > &ids, bool check=false)
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
int removeUnwishedNodes(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, NBPTStopCont &sc, NBPTLineCont &lc, NBParkingCont &pc, bool removeGeometryNodes)
Removes "unwished" nodes.
static void loadPrefixedIDsFomFile(const std::string &file, const std::string prefix, std::set< std::string > &into)
Add prefixed ids defined in file.
void add(const Position &pos)
Adds the given position to this one.
NodeCont myExtractedNodes
The extracted nodes which are kept for reference.
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
void removeIsolatedRoads(NBDistrictCont &dc, NBEdgeCont &ec)
Removes sequences of edges that are not connected with a junction. Simple roads without junctions som...
bool onlyCrossings(const NodeSet &c) const
check wheter the set of nodes only contains pedestrian crossings
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
A container for traffic light definitions and built programs.
void joinTLS(NBTrafficLightLogicCont &tlc, double maxdist)
Builds clusters of tls-controlled junctions and joins the control if possible.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
double getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
std::vector< std::set< std::string > > myJoinedClusters
sets of node ids which were joined
const double SUMO_const_laneWidth
double y() const
Returns the y-position.
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
The representation of a single edge during network building.
static const double UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
double x() const
Returns the x-position.
A container for districts.
The base class for traffic light logic definitions.
std::vector< NodeSet > NodeClusters
int joinLoadedClusters(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins loaded junction clusters (see NIXMLNodesHandler)
NamedRTree myRTree
node positions for faster lookup
void guessTLs(OptionsCont &oc, NBTrafficLightLogicCont &tlc)
Guesses which junctions or junction clusters shall be controlled by tls.
std::map< std::string, NBEdge * >::const_iterator end() const
Returns the pointer to the end of the stored edges.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
void avoidOverlap()
fix overlap
const std::string & getID() const
Returns the id.
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
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 removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
NBNode * getSignalNode() const
Returns the node that (possibly) represents a traffic signal controlling at the end of this edge...
void discardRailSignals()
#define WRITE_WARNING(msg)
static OptionsCont & getOptions()
Retrieves the options.
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
The edge has been loaded, nothing is computed yet.
void computeLogics(const NBEdgeCont &ec, OptionsCont &oc)
build the list of outgoing edges and lanes
A class representing a single district.
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void Remove(const float a_min[2], const float a_max[2], Named *const &a_data)
Remove entry.
void registerJoinedCluster(const NodeSet &cluster)
gets all joined clusters (see doc for myClusters2Join)
bool isTLControlled() const
Returns whether this node is controlled by any tls.
int joinJunctions(double maxDist, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, NBPTStopCont &sc)
Joins junctions that are very close together.
std::map< std::string, NBPTStop * >::const_iterator begin() const
Returns the pointer to the begin of the stored pt stops.
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
std::map< std::string, NBEdge * >::const_iterator begin() const
Returns the pointer to the begin of the stored edges.
std::set< NBEdge * > EdgeSet
container for unique edges
std::string getNext()
Returns the next id.
void computeLanes2Lanes()
divides the incoming lanes on outgoing lanes
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
NBEdge * shortestEdge(const NodeSet &cluster, const NodeSet &startNodes, const std::vector< NBNode *> &exclude) const
find closest neighbor for building circle
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
void extract(NBDistrictCont &dc, NBEdge *edge, bool remember=false)
Removes the given edge from the container like erase but does not delete it.
A point in 2D or 3D with translation and scaling methods.
classes which drive on tracks
void setx(double x)
set position x
std::pair< NBNode *, double > NodeAndDist
void generateNodeClusters(double maxDist, NodeClusters &into) const
Builds node clusters.
T get(const std::string &str) const
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void removeTrafficLights()
Removes all references to traffic lights that control this tls.
const std::string & getID() const
bool shouldBeTLSControlled(const NodeSet &c, double laneSpeedThreshold) const
Returns whethe the given node cluster should be controlled by a tls.
bool geometryLike() const
whether this is structurally similar to a geometry node
Storage for edges, including some functionality operating on multiple edges.
std::vector< std::string > getStringVector(const std::string &name) const
Returns the list of string-vector-value of the named option (only for Option_String) ...
void computeNodeShapes(double mismatchThreshold=-1)
Compute the junction shape for this node.
EdgeBuildingStep getStep() const
The building step of this edge.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
void joinNodeClusters(NodeClusters clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
joins the given node clusters
The connection was given by the user.
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
std::map< std::string, NBPTStop * >::const_iterator end() const
Returns the pointer to the end of the stored pt stops.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
vehicle is a passenger car (a "normal" car)
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string &prefix)
remap node IDs accoring to options –numerical-ids and –reserved-ids
void rename(NBNode *node, const std::string &newID)
Renames the node. Throws exception if newID already exists.
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
std::set< NBNode *, ComparatorIdLess > NodeSet
Definition of a node cluster container.
double getSpeed() const
Returns the speed allowed on this edge.
void addCluster2Join(std::set< std::string > cluster, NBNode *node)
add ids of nodes which shall be joined into a single node
void setAsTLControlled(NBNode *node, NBTrafficLightLogicCont &tlc, TrafficLightType type, std::string id="")
Sets the given node as being controlled by a tls.
Allows to store the object; used as context while traveling the rtree in TraCI.
std::vector< std::string > getAllNames() const
get all node names
void setID(const std::string &newID)
resets the id
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
const std::vector< Connection > & getConnections() const
Returns the connections.
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
bool isNearDistrict() const
if node is near district
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node) ...
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
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, which
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
std::set< std::string > myJoined
ids found in loaded join clusters used for error checking
A storage for options typed value containers)
SumoXMLNodeType getType() const
Returns the type of this node.
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
void clear()
deletes all nodes
const std::string SUMO_PARAM_ORIGID
void append(NBEdge *continuation)
append another edge
bool hasPostProcessConnection(const std::string &from, const std::string &to="")
void discardTrafficLights(NBTrafficLightLogicCont &tlc, bool geometryLike, bool guessSignals)
const Position & getPosition() const
Represents a single node (junction) during network building.
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.
static bool isRailwayNode(const NBNode *n)
whether the given node only has rail edges
std::set< const NBNode * > mySplit
nodes that were created when splitting an edge
void printBuiltNodesStatistics() const
Prints statistics about built nodes.
bool customTLID(const NodeSet &c) const
check wheter the set of nodes contains traffic lights with custom id
NBNode * getFromNode() const
Returns the origin node of the edge.
void analyzeCluster(NodeSet cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type, SumoXMLNodeType &nodeType)
void mul(double val)
Multiplies both positions with the given value.
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
A traffic light logics which must be computed (only nodes/edges are given)
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
#define WRITE_MESSAGE(msg)
bool erase(NBNode *node)
Removes the given node, deleting it.
std::vector< std::pair< std::set< std::string >, NBNode * > > myClusters2Join
loaded sets of node ids to join (cleared after use)
void joinNodeCluster(NodeSet clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, NBNode *predefined=nullptr)
bool checkIsRemovable() const
check if node is removable
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
bool isNearEnough2BeJoined2(NBEdge *e, double threshold) const
Check if edge is near enought to be joined to another edge.
NBNode * getToNode() const
Returns the destination node of the edge.
void pruneClusterFringe(NodeSet &cluster) const
remove geometry-like fringe nodes from cluster
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
void setSignalOffset(double offset, NBNode *signalNode)
sets the offset of a traffic signal from the end of this edge
static const Position INVALID
used to indicate that a position is valid
void removeComponents(NBDistrictCont &dc, NBEdgeCont &ec, const int numKeep)
Checks the network for weak connectivity and removes all but the largest components. The connectivity check is done regardless of edge direction and vclass.