60 #define DEBUGNODEID "1311774270" 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 for (std::set<std::string>::const_iterator it = cluster.begin(); it != cluster.end(); it++) {
585 WRITE_WARNING(
"Ignoring join-cluster because junction '" + *it +
"' was already excluded from joining");
587 }
else if (
myJoined.count(*it) > 0) {
588 WRITE_WARNING(
"Ignoring join-cluster because junction '" + *it +
"' already occurred in another join-cluster");
604 for (std::set<std::string>::iterator it_id = it->begin(); it_id != it->end(); it_id++) {
606 if (node ==
nullptr) {
607 WRITE_WARNING(
"Ignoring unknown junction '" + *it_id +
"' while joining");
609 cluster.insert(node);
612 if (cluster.size() > 1) {
613 clusters.push_back(cluster);
618 return (
int)clusters.size();
624 #ifdef DEBUG_JOINJUNCTIONS 625 std::cout <<
"joinJunctions...\n";
630 for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
633 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
634 NodeSet::iterator check = j;
637 cluster.erase(check);
643 std::set<NBNode*> toRemove;
644 for (
NBNode* n : cluster) {
645 for (
NBEdge* edge : n->getOutgoingEdges()) {
646 if (cluster.count(edge->getToNode()) != 0 && edge->getLoadedLength() > maxDist ) {
647 #ifdef DEBUG_JOINJUNCTIONS 649 std::cout <<
"long edge " << edge->getID() <<
" (" << edge->getLoadedLength() <<
", max=" << maxDist <<
")\n";
653 toRemove.insert(edge->getToNode());
657 for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
660 if (cluster.size() < 2) {
672 WRITE_WARNING(
"Reducing junction cluster " + origCluster +
" (" + reason +
")");
682 WRITE_WARNING(
"Reducing junction cluster " + origCluster +
" (" + reason +
")");
693 for (
NBNode* current : cluster) {
697 newComp.insert(current);
698 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
699 NodeClusters::iterator check = it_comp;
701 bool connected =
false;
702 for (
NBNode* k : *check) {
703 if (current->getConnectionTo(k) !=
nullptr || k->getConnectionTo(current) !=
nullptr) {
705 newComp.insert((*check).begin(), (*check).end());
706 it_comp = components.erase(check);
716 components.push_back(newComp);
718 for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
719 if ((*it_comp).size() > 1) {
721 clusters.push_back(*it_comp);
726 return (
int)clusters.size();
732 #ifdef DEBUG_JOINJUNCTIONS 738 bool pruneFringe =
true;
741 while (pruneFringe) {
743 for (NodeSet::iterator j = cluster.begin(); j != cluster.end();) {
744 NodeSet::iterator check = j;
749 double clusterDist = std::numeric_limits<double>::max();
750 bool touchingCluster =
false;
752 NBNode* neighbor = (*it_edge)->getToNode();
753 if (cluster.count(neighbor) != 0) {
754 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
759 NBNode* neighbor = (*it_edge)->getFromNode();
760 if (cluster.count(neighbor) != 0) {
761 clusterDist =
MIN2(clusterDist, (*it_edge)->getLoadedLength());
767 std::set<NBNode*> outsideNeighbors;
768 std::set<NBNode*> clusterNeighbors;
769 const double pedestrianFringeThreshold = 0.3;
771 NBNode* neighbor = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
772 if (cluster.count(neighbor) == 0) {
773 if ((e->getPermissions() &
SVC_PASSENGER) != 0 || clusterDist <= pedestrianFringeThreshold || touchingCluster) {
774 outsideNeighbors.insert(neighbor);
777 clusterNeighbors.insert(neighbor);
780 #ifdef DEBUG_JOINJUNCTIONS 782 <<
" clusterDist=" << clusterDist
783 <<
" cd<th=" << (clusterDist <= pedestrianFringeThreshold)
784 <<
" touching=" << touchingCluster
789 if (outsideNeighbors.size() <= 1
790 && clusterNeighbors.size() == 1
792 cluster.erase(check);
794 #ifdef DEBUG_JOINJUNCTIONS 796 std::cout <<
" pruned n=" << n->
getID() <<
"\n";
809 std::map<std::string, double> finalIncomingAngles;
810 std::map<std::string, double> finalOutgoingAngles;
811 for (NodeSet::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
812 for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
819 for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
828 #ifdef DEBUG_JOINJUNCTIONS 829 for (
NBNode* n : cluster) {
832 <<
"\n inAngles=" <<
joinToString(finalIncomingAngles,
' ',
':')
833 <<
"\n outAngles=" <<
joinToString(finalOutgoingAngles,
' ',
':')
838 if (finalIncomingAngles.size() > 4) {
839 reason =
toString(finalIncomingAngles.size()) +
" incoming edges";
843 const double PARALLEL_INCOMING_THRESHOLD = 10.0;
844 bool foundParallel =
false;
845 for (std::map<std::string, double>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
846 std::map<std::string, double>::const_iterator k = j;
847 for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
848 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
849 reason =
"parallel incoming " + j->first +
"," + k->first;
855 for (std::map<std::string, double>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
856 std::map<std::string, double>::const_iterator k = j;
857 for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
858 if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
859 reason =
"parallel outgoing " + j->first +
"," + k->first;
866 for (
auto it = sc.
begin(); it != sc.
end(); it++) {
868 if (edge !=
nullptr && cluster.count(edge->
getFromNode()) != 0 && cluster.count(edge->
getToNode()) != 0) {
869 reason =
"it contains stop '" + it->first +
"'";
875 if (cluster.size() > 2) {
879 NBEdge* maxEdge =
nullptr;
880 for (
NBNode* n1 : cluster) {
881 hasTLS |= n1->isTLControlled();
882 for (
NBNode* n2 : cluster) {
883 NBEdge* e1 = n1->getConnectionTo(n2);
884 NBEdge* e2 = n2->getConnectionTo(n1);
895 #ifdef DEBUG_JOINJUNCTIONS 896 for (
NBNode* n : cluster) {
898 std::cout <<
"feasible hasTLS=" << hasTLS <<
" maxDist=" << maxDist <<
" maxEdge=" << maxEdge->
getID() <<
"\n";
902 if (!hasTLS && maxDist > 5) {
904 std::vector<NBNode*> toCheck;
905 std::set<NBNode*> visited;
907 bool foundCircle =
false;
908 while (!toCheck.empty()) {
909 NBNode* n = toCheck.back();
918 NBNode* cand = e->getFromNode() == n ? e->getToNode() : e->getFromNode();
919 if (visited.count(cand) == 0 && cluster.count(cand) != 0) {
920 toCheck.push_back(cand);
926 reason =
"not compact (maxEdge=" + maxEdge->
getID() +
" length=" +
toString(maxDist) +
")";
938 assert(circleSize >= 2);
939 if ((
int)cands.size() == circleSize) {
940 if (cands.back()->getConnectionTo(cands.front()) !=
nullptr) {
943 cluster.insert(cands.begin(), cands.end());
949 if ((
int)cluster.size() <= circleSize || startNodes.size() == 0) {
953 if (cands.size() == 0) {
968 singleStart.insert(cands.back());
971 std::vector<NBNode*> cands2(cands);
984 double minDist = std::numeric_limits<double>::max();
986 for (
NBNode* n : startNodes) {
987 for (
NBEdge* e : n->getOutgoingEdges()) {
988 NBNode* neigh = e->getToNode();
989 if (cluster.count(neigh) != 0 && std::find(exclude.begin(), exclude.end(), neigh) == exclude.end()) {
992 if (dist < minDist) {
1006 for (NodeClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) {
1008 assert(cluster.size() > 1);
1011 std::string
id =
"cluster";
1021 newNode->
reinit(pos, nodeType);
1024 if (!tlc.
insert(tlDef)) {
1027 throw ProcessError(
"Could not allocate tls '" +
id +
"'.");
1031 std::set<NBEdge*> allEdges;
1032 for (
NBNode* n : cluster) {
1034 allEdges.insert(edges.begin(), edges.end());
1038 for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end();) {
1042 if (cluster.count(from) > 0 && cluster.count(to) > 0) {
1043 for (std::set<NBEdge*>::iterator l = allEdges.begin(); l != allEdges.end(); ++l) {
1049 allEdges.erase(j++);
1056 for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end(); ++j) {
1059 const bool outgoing = cluster.count(e->
getFromNode()) > 0;
1065 for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
1075 for (NodeSet::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
1084 std::set<std::string> ids;
1085 for (
NBNode* n : cluster) {
1086 ids.insert(n->getID());
1097 bool ambiguousType =
false;
1098 for (
NBNode* j : cluster) {
1099 pos.
add(j->getPosition());
1101 if (j->isTLControlled()) {
1104 type = (*j->getControllingTLS().begin())->getType();
1105 }
else if (type != (*j->getControllingTLS().begin())->getType()) {
1106 ambiguousType =
true;
1112 nodeType = otherType;
1113 }
else if (nodeType != otherType) {
1125 pos.
mul(1.0 / cluster.size());
1126 if (ambiguousType) {
1128 WRITE_WARNING(
"Ambiguous traffic light type for node cluster '" +
id +
"' set to '" +
toString(type) +
"'");
1138 bool tooFast =
false;
1140 std::set<NBEdge*> seen;
1143 for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
1144 if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
1147 if (j->hasIncoming(*k)) {
1149 f += (double)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
1153 if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
1158 return !tooFast && f >= laneSpeedThreshold && c.size() != 0;
1165 const double laneSpeedThreshold = oc.
getFloat(
"tls.guess.threshold");
1166 std::vector<NBNode*> ncontrolled;
1167 if (oc.
isSet(
"tls.unset")) {
1168 std::vector<std::string> notTLControlledNodes = oc.
getStringVector(
"tls.unset");
1169 for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
1172 throw ProcessError(
" The junction '" + *i +
"' to set as not-controlled is not known.");
1175 for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
1176 (*j)->removeNode(n);
1179 ncontrolled.push_back(n);
1186 if (oc.
exists(
"tls.taz-nodes") && oc.
getBool(
"tls.taz-nodes")) {
1187 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1188 NBNode* cur = (*i).second;
1189 if (cur->
isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
1197 if (oc.
exists(
"tls.guess-signals") && oc.
getBool(
"tls.guess-signals")) {
1199 const double signalDist = oc.
getFloat(
"tls.guess-signals.dist");
1200 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1201 NBNode* node = (*i).second;
1204 for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
1205 (*it_o)->setSignalOffset((*it_o)->getLength());
1210 for (std::map<std::string, NBNode*>::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1211 NBNode* node = i->second;
1212 if (find(ncontrolled.begin(), ncontrolled.end(), node) != ncontrolled.end()) {
1218 std::vector<NBNode*> signals;
1220 for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
1221 const NBEdge* inEdge = *it_i;
1232 for (EdgeVector::const_iterator it_i = outgoing.begin(); it_i != outgoing.end(); ++it_i) {
1233 const NBEdge* outEdge = *it_i;
1236 signals.push_back(cand);
1240 for (std::vector<NBNode*>::iterator j = signals.begin(); j != signals.end(); ++j) {
1243 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
1249 if (!tlc.
insert(tlDef)) {
1261 if (!oc.
getBool(
"tls.guess")) {
1271 for (NodeClusters::iterator i = cands.begin(); i != cands.end();) {
1275 for (NodeSet::iterator j = c.begin(); j != c.end();) {
1276 if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
1291 for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
1292 std::vector<NBNode*> nodes;
1293 for (NodeSet::iterator j = (*i).begin(); j != (*i).end(); j++) {
1294 nodes.push_back(*j);
1296 std::string
id =
"joinedG_" +
toString(index++);
1298 if (!tlc.
insert(tlDef)) {
1308 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1309 NBNode* cur = (*i).second;
1315 if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
1334 for (NodeSet::iterator j = c.begin(); j != c.end();) {
1335 if (!(*j)->isTLControlled()) {
1347 std::string
id =
"joined";
1352 std::set<NBTrafficLightDefinition*> tls = j->getControllingTLS();
1353 j->removeTrafficLights();
1354 for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
1358 id =
"joinedS_" +
toString(index++);
1359 std::vector<NBNode*> nodes;
1364 if (!tlc.
insert(tlDef)) {
1381 if (!tlc.
insert(tlDef)) {
1383 WRITE_WARNING(
"Building a tl-logic for junction '" +
id +
"' twice is not possible.");
1393 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1394 (*i).second->computeLanes2Lanes();
1402 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1403 (*i).second->computeLogic(ec, oc);
1410 std::set<NBNode*> roundaboutNodes;
1411 const bool checkLaneFoesAll = oc.
getBool(
"check-lane-foes.all");
1412 const bool checkLaneFoesRoundabout = !checkLaneFoesAll && oc.
getBool(
"check-lane-foes.roundabout");
1413 if (checkLaneFoesRoundabout) {
1415 for (std::set<EdgeSet>::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) {
1416 for (EdgeSet::const_iterator j = (*i).begin(); j != (*i).end(); ++j) {
1417 roundaboutNodes.insert((*j)->getToNode());
1421 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1422 const bool checkLaneFoes = checkLaneFoesAll || (checkLaneFoesRoundabout && roundaboutNodes.count((*i).second) > 0);
1423 (*i).second->computeLogic2(checkLaneFoes);
1430 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1431 delete((*i).second);
1444 std::string freeID =
"SUMOGenerated" + toString<int>(counter);
1446 while (
retrieve(freeID) !=
nullptr) {
1449 freeID =
"SUMOGenerated" + toString<int>(counter);
1457 for (NodeCont::iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1458 (*i).second->computeNodeShape(mismatchThreshold);
1465 int numUnregulatedJunctions = 0;
1466 int numDeadEndJunctions = 0;
1467 int numPriorityJunctions = 0;
1468 int numRightBeforeLeftJunctions = 0;
1469 int numAllWayStopJunctions = 0;
1470 int numZipperJunctions = 0;
1471 int numRailSignals = 0;
1472 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); i++) {
1473 switch ((*i).second->getType()) {
1476 ++numUnregulatedJunctions;
1479 ++numDeadEndJunctions;
1486 ++numPriorityJunctions;
1489 ++numRightBeforeLeftJunctions;
1492 ++numAllWayStopJunctions;
1495 ++numZipperJunctions;
1498 ++numRightBeforeLeftJunctions;
1511 if (numDeadEndJunctions > 0) {
1516 if (numAllWayStopJunctions > 0) {
1519 if (numZipperJunctions > 0) {
1522 if (numRailSignals > 0) {
1528 std::vector<std::string>
1530 std::vector<std::string> ret;
1531 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1532 ret.push_back((*i).first);
1540 if (
myNodes.count(newID) != 0) {
1541 throw ProcessError(
"Attempt to rename node using existing id '" + newID +
"'");
1551 for (NodeCont::const_iterator i =
myNodes.begin(); i !=
myNodes.end(); ++i) {
1552 NBNode* node = i->second;
1559 for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
1560 (*it_o)->setSignalOffset((*it_o)->getLength());
1563 for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
1578 NBNode* node = item.second;
1589 std::set<std::string> reserve;
1592 avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1596 for (NodeCont::iterator it =
myNodes.begin(); it !=
myNodes.end(); it++) {
1601 toChange.insert(it->second);
1604 if (reservedIDs && reserve.count(it->first) > 0) {
1605 toChange.insert(it->second);
1609 for (
NBNode* node : toChange) {
1614 node->setID(idSupplier.
getNext());
1615 myNodes[node->getID()] = node;
1617 if (prefix.empty()) {
1618 return (
int)toChange.size();
1623 for (
auto item : oldNodes) {
1625 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.
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.
void addJoinExclusion(const std::vector< std::string > &ids, bool check=false)
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.
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...
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.
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
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)
bool connectionsDone
Whether connection information for this lane is already completed.
void avoidOverlap()
fix overlap
const std::string & getID() const
Returns the id.
Lane & getLaneStruct(int lane)
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...
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
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED)
Adds a connection between the specified this edge's lane and an approached one.
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::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.
int getNumLanes() const
Returns the number of lanes.
A point in 2D or 3D with translation and scaling methods.
classes which drive on tracks
std::pair< NBNode *, double > NodeAndDist
static bool isRailwayNode(NBNode *n)
whether the given node only has rail edges
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.
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.
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
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
std::set< NBNode * > myExtractedNodes
The extracted nodes which are kept for reference.
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 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
void addCluster2Join(std::set< std::string > cluster)
add ids of nodes which shall be joined into a single node
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
std::vector< std::set< std::string > > myClusters2Join
loaded sets of node ids to join (cleared after use)
void discardTrafficLights(NBTrafficLightLogicCont &tlc, bool geometryLike, bool guessSignals)
void declareConnectionsAsLoaded(EdgeBuildingStep step=LANES2LANES_USER)
declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has ...
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.
std::set< const NBNode * > mySplit
nodes that were created when splitting an edge
void printBuiltNodesStatistics() const
Prints statistics about built nodes.
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.
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 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.