SUMO - Simulation of Urban MObility
NBNodeCont.cpp
Go to the documentation of this file.
1 /****************************************************************************/
13 // Container for nodes during the netbuilding process
14 /****************************************************************************/
15 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
16 // Copyright (C) 2001-2017 DLR (http://www.dlr.de/) and contributors
17 /****************************************************************************/
18 //
19 // This file is part of SUMO.
20 // SUMO is free software: you can redistribute it and/or modify
21 // it under the terms of the GNU General Public License as published by
22 // the Free Software Foundation, either version 3 of the License, or
23 // (at your option) any later version.
24 //
25 /****************************************************************************/
26 
27 
28 // ===========================================================================
29 // included modules
30 // ===========================================================================
31 #ifdef _MSC_VER
32 #include <windows_config.h>
33 #else
34 #include <config.h>
35 #endif
36 
37 #include <string>
38 #include <map>
39 #include <algorithm>
40 #include <cmath>
42 #include <utils/geom/Boundary.h>
43 #include <utils/geom/GeomHelper.h>
47 #include <utils/common/StdDefs.h>
48 #include <utils/common/ToString.h>
54 #include "NBHelpers.h"
55 #include "NBDistrict.h"
56 #include "NBEdgeCont.h"
58 #include "NBOwnTLDef.h"
59 #include "NBNodeCont.h"
60 
61 
62 // ===========================================================================
63 // method definitions
64 // ===========================================================================
66  : myInternalID(1) {
67 }
68 
69 
71  clear();
72 }
73 
74 
75 // ----------- Insertion/removal/retrieval of nodes
76 bool
77 NBNodeCont::insert(const std::string& id, const Position& position,
78  NBDistrict* district) {
79  NodeCont::iterator i = myNodes.find(id);
80  if (i != myNodes.end()) {
81  return false;
82  }
83  NBNode* node = new NBNode(id, position, district);
84  myNodes[id] = node;
85  const float pos[2] = {(float)position.x(), (float)position.y()};
86  myRTree.Insert(pos, pos, node);
87  return true;
88 }
89 
90 
91 bool
93  std::string id = node->getID();
94  NodeCont::iterator i = myNodes.find(id);
95  if (i != myNodes.end()) {
96  return false;
97  }
98  myNodes[id] = node;
99  const float pos[2] = {(float)node->getPosition().x(), (float)node->getPosition().y()};
100  myRTree.Insert(pos, pos, node);
101  return true;
102 }
103 
104 
105 NBNode*
106 NBNodeCont::retrieve(const std::string& id) const {
107  NodeCont::const_iterator i = myNodes.find(id);
108  if (i == myNodes.end()) {
109  return 0;
110  }
111  return (*i).second;
112 }
113 
114 
115 NBNode*
116 NBNodeCont::retrieve(const Position& position, const double offset) const {
117  const double extOffset = offset + POSITION_EPS;
118  const float cmin[2] = {(float)(position.x() - extOffset), (float)(position.y() - extOffset)};
119  const float cmax[2] = {(float)(position.x() + extOffset), (float)(position.y() + extOffset)};
120  std::set<std::string> into;
121  Named::StoringVisitor sv(into);
122  myRTree.Search(cmin, cmax, sv);
123  for (std::set<std::string>::const_iterator i = into.begin(); i != into.end(); i++) {
124  NBNode* const node = myNodes.find(*i)->second;
125  if (fabs(node->getPosition().x() - position.x()) <= offset
126  &&
127  fabs(node->getPosition().y() - position.y()) <= offset) {
128  return node;
129  }
130  }
131  return 0;
132 }
133 
134 
135 bool
137  if (extract(node)) {
138  delete node;
139  return true;
140  } else {
141  return false;
142  }
143 }
144 
145 
146 bool
147 NBNodeCont::extract(NBNode* node, bool remember) {
148  NodeCont::iterator i = myNodes.find(node->getID());
149  if (i == myNodes.end()) {
150  return false;
151  }
152  myNodes.erase(i);
153  const float pos[2] = {(float)node->getPosition().x(), (float)node->getPosition().y()};
154  myRTree.Remove(pos, pos, node);
155  node->removeTrafficLights();
156  if (remember) {
157  myExtractedNodes.insert(node);
158  }
159  return true;
160 }
161 
162 
163 // ----------- Adapting the input
164 void
166  int no = 0;
167  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
168  no += (*i).second->removeSelfLoops(dc, ec, tc);
169  }
170  if (no != 0) {
171  WRITE_WARNING(toString(no) + " self-looping edge(s) removed.");
172  }
173 }
174 
175 
176 void
178  // magic values
179  const double distanceThreshold = 7.; // don't merge edges further apart
180  const double lengthThreshold = 0.10; // don't merge edges with higher relative length-difference
181 
182  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
183  // count the edges to other nodes outgoing from the current node
184  std::map<NBNode*, EdgeVector> connectionCount;
185  const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
186  for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
187  connectionCount[(*j)->getToNode()].push_back(*j);
188  }
189  // check whether more than a single edge connect another node and join them
190  std::map<NBNode*, EdgeVector>::iterator k;
191  for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
192  // possibly we do not have anything to join...
193  if ((*k).second.size() < 2) {
194  continue;
195  }
196  // for the edges that seem to be a single street,
197  // check whether the geometry is similar
198  const EdgeVector& ev = (*k).second;
199  const NBEdge* const first = ev.front();
200  EdgeVector::const_iterator jci; // join candidate iterator
201  for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
202  const double relativeLengthDifference = fabs(first->getLoadedLength() - (*jci)->getLoadedLength()) / first->getLoadedLength();
203  if ((!first->isNearEnough2BeJoined2(*jci, distanceThreshold)) ||
204  (relativeLengthDifference > lengthThreshold) ||
205  (fabs(first->getSpeed() - (*jci)->getSpeed()) >= 0.01) || // output accuracy
206  (first->getPermissions() != (*jci)->getPermissions())
207  ) {
208  break;
209  }
210  }
211  // @bug If there are 3 edges of which 2 can be joined, no joining will
212  // take place with the current implementation
213  if (jci == ev.end()) {
214  ec.joinSameNodeConnectingEdges(dc, tlc, ev);
215  }
216  }
217  }
218 }
219 
220 
221 void
223  UNUSED_PARAMETER(tc);
224  // Warn of isolated edges, i.e. a single edge with no connection to another edge
225  int edgeCounter = 0;
226  const std::vector<std::string>& edgeNames = ec.getAllNames();
227  for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
228  // Test whether this node starts at a dead end, i.e. it has only one adjacent node
229  // to which an edge exists and from which an edge may come.
230  NBEdge* e = ec.retrieve(*it);
231  if (e == 0) {
232  continue;
233  }
234  NBNode* from = e->getFromNode();
235  const EdgeVector& outgoingEdges = from->getOutgoingEdges();
236  if (outgoingEdges.size() != 1) {
237  // At this node, several edges or no edge start; so, this node is no dead end.
238  continue;
239  }
240  const EdgeVector& incomingEdges = from->getIncomingEdges();
241  if (incomingEdges.size() > 1) {
242  // At this node, several edges end; so, this node is no dead end.
243  continue;
244  } else if (incomingEdges.size() == 1) {
245  NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
246  NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
247  if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
248  // At this node, an edge ends which is not the inverse direction of
249  // the starting node.
250  continue;
251  }
252  }
253  // Now we know that the edge e starts a dead end.
254  // Next we test if the dead end is isolated, i.e. does not lead to a junction
255  bool hasJunction = false;
256  EdgeVector road;
257  NBEdge* eOld = 0;
258  NBNode* to;
259  std::set<NBNode*> adjacentNodes;
260  do {
261  road.push_back(e);
262  eOld = e;
263  from = e->getFromNode();
264  to = e->getToNode();
265  const EdgeVector& outgoingEdgesOfToNode = to->getOutgoingEdges();
266  const EdgeVector& incomingEdgesOfToNode = to->getIncomingEdges();
267  adjacentNodes.clear();
268  for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
269  if ((*itOfOutgoings)->getToNode() != from // The back path
270  && (*itOfOutgoings)->getToNode() != to // A loop / dummy edge
271  ) {
272  e = *itOfOutgoings; // Probably the next edge
273  }
274  adjacentNodes.insert((*itOfOutgoings)->getToNode());
275  }
276  for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
277  adjacentNodes.insert((*itOfIncomings)->getFromNode());
278  }
279  adjacentNodes.erase(to); // Omit loops
280  if (adjacentNodes.size() > 2) {
281  hasJunction = true;
282  }
283  } while (!hasJunction && eOld != e);
284  if (!hasJunction) {
285  edgeCounter += int(road.size());
286  std::string warningString = "Removed a road without junctions: ";
287  for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
288  if (roadIt == road.begin()) {
289  warningString += (*roadIt)->getID();
290  } else {
291  warningString += ", " + (*roadIt)->getID();
292  }
293 
294  NBNode* fromNode = (*roadIt)->getFromNode();
295  NBNode* toNode = (*roadIt)->getToNode();
296  ec.erase(dc, *roadIt);
297  if (fromNode->getIncomingEdges().size() == 0 && fromNode->getOutgoingEdges().size() == 0) {
298  // Node is empty; can be removed
299  erase(fromNode);
300  }
301  if (toNode->getIncomingEdges().size() == 0 && toNode->getOutgoingEdges().size() == 0) {
302  // Node is empty; can be removed
303  erase(toNode);
304  }
305  }
306  WRITE_WARNING(warningString);
307  }
308  }
309  if (edgeCounter > 0 && !OptionsCont::getOptions().getBool("remove-edges.isolated")) {
310  WRITE_WARNING("Detected isolated roads. Use the option --remove-edges.isolated to get a list of all affected edges.");
311  }
312 }
313 
314 
315 int
318  bool removeGeometryNodes) {
319  // load edges that shall not be modified
320  std::set<std::string> edges2keep;
321  if (removeGeometryNodes) {
322  const OptionsCont& oc = OptionsCont::getOptions();
323  if (oc.isSet("geometry.remove.keep-edges.input-file")) {
324  NBHelpers::loadEdgesFromFile(oc.getString("geometry.remove.keep-edges.input-file"), edges2keep);
325  }
326  if (oc.isSet("geometry.remove.keep-edges.explicit")) {
327  const std::vector<std::string> edges = oc.getStringVector("geometry.remove.keep-edges.explicit");
328  edges2keep.insert(edges.begin(), edges.end());
329  }
330  }
331  int no = 0;
332  std::vector<NBNode*> toRemove;
333  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
334  NBNode* current = (*i).second;
335  bool remove = false;
336  std::vector<std::pair<NBEdge*, NBEdge*> > toJoin;
337  // check for completely empty nodes
338  if (current->getOutgoingEdges().size() == 0 && current->getIncomingEdges().size() == 0) {
339  // remove if empty
340  remove = true;
341  }
342  // check for nodes which are only geometry nodes
343  if (removeGeometryNodes && mySplit.count(current) == 0) {
344  if ((current->getOutgoingEdges().size() == 1 && current->getIncomingEdges().size() == 1)
345  ||
346  (current->getOutgoingEdges().size() == 2 && current->getIncomingEdges().size() == 2)) {
347  // ok, one in, one out or two in, two out
348  // -> ask the node whether to join
349  remove = current->checkIsRemovable();
350  // check whether any of the edges must be kept
351  for (EdgeVector::const_iterator it_edge = current->getEdges().begin(); it_edge != current->getEdges().end(); ++it_edge) {
352  if (edges2keep.find((*it_edge)->getID()) != edges2keep.end()) {
353  remove = false;
354  break;
355  }
356  }
357  if (remove) {
358  toJoin = current->getEdgesToJoin();
359  }
360  }
361  }
362  // remove the node and join the geometries when wished
363  if (!remove) {
364  continue;
365  }
366  for (std::vector<std::pair<NBEdge*, NBEdge*> >::iterator j = toJoin.begin(); j != toJoin.end(); j++) {
367  NBEdge* begin = (*j).first;
368  NBEdge* continuation = (*j).second;
369  begin->append(continuation);
370  continuation->getToNode()->replaceIncoming(continuation, begin, 0);
371  tlc.replaceRemoved(continuation, -1, begin, -1);
372  ec.extract(dc, continuation, true);
373  }
374  toRemove.push_back(current);
375  no++;
376  }
377  // erase all
378  for (std::vector<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
379  extract(*j, true);
380  }
381  return no;
382 }
383 
384 
385 void
387  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
388  (*i).second->avoidOverlap();
389  }
390 }
391 
392 // ----------- (Helper) methods for joining nodes
393 void
394 NBNodeCont::generateNodeClusters(double maxDist, NodeClusters& into) const {
395  std::set<NBNode*> visited;
396  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
397  std::vector<NodeAndDist> toProc;
398  if (visited.find((*i).second) != visited.end()) {
399  continue;
400  }
401  toProc.push_back(std::make_pair((*i).second, 0));
402  std::set<NBNode*> c;
403  while (!toProc.empty()) {
404  NodeAndDist nodeAndDist = toProc.back();
405  NBNode* n = nodeAndDist.first;
406  double dist = nodeAndDist.second;
407  toProc.pop_back();
408  if (visited.find(n) != visited.end()) {
409  continue;
410  }
411  c.insert(n);
412  visited.insert(n);
413  const EdgeVector& edges = n->getEdges();
414  for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
415  NBEdge* e = *j;
416  NBNode* s = 0;
417  if (e->getPermissions() == SVC_PEDESTRIAN) {
418  continue; // do not join pedestrian stuff
419  }
420  if (n->hasIncoming(e)) {
421  s = e->getFromNode();
422  } else {
423  s = e->getToNode();
424  }
425  if (visited.find(s) != visited.end()) {
426  continue;
427  }
428  if (e->getLoadedLength() + dist < maxDist) {
429  if (s->geometryLike()) {
430  toProc.push_back(std::make_pair(s, dist + e->getLoadedLength()));
431  } else {
432  toProc.push_back(std::make_pair(s, 0));
433  }
434  }
435  }
436  }
437  if (c.size() < 2) {
438  continue;
439  }
440  into.push_back(c);
441  }
442 }
443 
444 
445 void
446 NBNodeCont::addJoinExclusion(const std::vector<std::string>& ids, bool check) {
447  for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
448  // error handling has to take place here since joinExclusions could be
449  // loaded from multiple files / command line
450  if (myJoined.count(*it) > 0) {
451  WRITE_WARNING("Ignoring join exclusion for junction '" + *it + "' since it already occured in a list of nodes to be joined");
452  } else if (check && retrieve(*it) == 0) {
453  WRITE_WARNING("Ignoring join exclusion for unknown junction '" + *it + "'");
454  } else {
455  myJoinExclusions.insert(*it);
456  }
457  }
458 }
459 
460 
461 void
462 NBNodeCont::addCluster2Join(std::set<std::string> cluster) {
463  // error handling has to take place here since joins could be loaded from multiple files
464  for (std::set<std::string>::const_iterator it = cluster.begin(); it != cluster.end(); it++) {
465  if (myJoinExclusions.count(*it) > 0) {
466  WRITE_WARNING("Ignoring join-cluster because junction '" + *it + "' was already excluded from joining");
467  return;
468  } else if (myJoined.count(*it) > 0) {
469  WRITE_WARNING("Ignoring join-cluster because junction '" + *it + "' already occured in another join-cluster");
470  return;
471  } else {
472  myJoined.insert(*it);
473  }
474  }
475  myClusters2Join.push_back(cluster);
476 }
477 
478 
479 int
481  NodeClusters clusters;
482  for (std::vector<std::set<std::string> >::iterator it = myClusters2Join.begin(); it != myClusters2Join.end(); it++) {
483  // verify loaded cluster
484  std::set<NBNode*> cluster;
485  for (std::set<std::string>::iterator it_id = it->begin(); it_id != it->end(); it_id++) {
486  NBNode* node = retrieve(*it_id);
487  if (node == 0) {
488  WRITE_WARNING("Ignoring unknown junction '" + *it_id + "' while joining");
489  } else {
490  cluster.insert(node);
491  }
492  }
493  if (cluster.size() > 1) {
494  clusters.push_back(cluster);
495  }
496  }
497  joinNodeClusters(clusters, dc, ec, tlc);
498  myClusters2Join.clear(); // make save for recompute
499  return (int)clusters.size();
500 }
501 
502 
503 int
505  NodeClusters cands;
506  NodeClusters clusters;
507  generateNodeClusters(maxDist, cands);
508  for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
509  std::set<NBNode*> cluster = (*i);
510  // remove join exclusions
511  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
512  std::set<NBNode*>::iterator check = j;
513  ++j;
514  if (myJoinExclusions.count((*check)->getID()) > 0) {
515  cluster.erase(check);
516  }
517  }
518  // iteratively remove the fringe
519  bool pruneFringe = true;
520  while (pruneFringe) {
521  pruneFringe = false;
522  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
523  std::set<NBNode*>::iterator check = j;
524  NBNode* n = *check;
525  ++j;
526 
527  // compute clusterDist for node (length of shortest edge which connects this node to the cluster)
528  double clusterDist = std::numeric_limits<double>::max();
529  for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
530  NBNode* neighbor = (*it_edge)->getToNode();
531  if (cluster.count(neighbor) != 0) {
532  clusterDist = MIN2(clusterDist, (*it_edge)->getLoadedLength());
533  }
534  }
535  for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
536  NBNode* neighbor = (*it_edge)->getFromNode();
537  if (cluster.count(neighbor) != 0) {
538  clusterDist = MIN2(clusterDist, (*it_edge)->getLoadedLength());
539  }
540  }
541  // remove geometry-like nodes at fringe of the cluster
542  // (they have 1 neighbor in the cluster and at most 1 neighbor outside the cluster)
543  std::set<NBNode*> neighbors;
544  std::set<NBNode*> clusterNeigbors;
545  const double pedestrianFringeThreshold = 1.0;
546  for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
547  NBNode* neighbor = (*it_edge)->getToNode();
548  if (cluster.count(neighbor) == 0) {
549  if ((*it_edge)->getPermissions() != SVC_PEDESTRIAN || clusterDist < pedestrianFringeThreshold) {
550  neighbors.insert(neighbor);
551  }
552  } else {
553  clusterNeigbors.insert(neighbor);
554  }
555  }
556  for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
557  NBNode* neighbor = (*it_edge)->getFromNode();
558  if (cluster.count(neighbor) == 0) {
559  if ((*it_edge)->getPermissions() != SVC_PEDESTRIAN || clusterDist < pedestrianFringeThreshold) {
560  neighbors.insert(neighbor);
561  }
562  } else {
563  clusterNeigbors.insert(neighbor);
564  }
565  }
566  if (neighbors.size() <= 1 && clusterNeigbors.size() == 1) {
567  cluster.erase(check);
568  pruneFringe = true; // other nodes could belong to the fringe now
569  }
570  }
571  }
572  // exclude the fromNode of a long edge if the toNode is in the cluster (and they were both added via an alternative path).
573  std::set<NBNode*> toRemove;
574  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end(); ++j) {
575  NBNode* n = *j;
576  const EdgeVector& edges = n->getOutgoingEdges();
577  for (EdgeVector::const_iterator it_edge = edges.begin(); it_edge != edges.end(); ++it_edge) {
578  NBEdge* edge = *it_edge;
579  if (cluster.count(edge->getToNode()) != 0 && edge->getLoadedLength() > maxDist) {
580  //std::cout << "long edge " << edge->getID() << " (" << edge->getLoadedLength() << ", max=" << maxDist << ")\n";
581  toRemove.insert(n);
582  toRemove.insert(edge->getToNode());
583  }
584  }
585  }
586  for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
587  cluster.erase(*j);
588  }
589  if (cluster.size() < 2) {
590  continue;
591  }
592  // check for clusters which are to complex and probably won't work very well
593  // we count the incoming edges of the final junction
594  std::map<std::string, double> finalIncomingAngles;
595  std::map<std::string, double> finalOutgoingAngles;
596  std::vector<std::string> nodeIDs;
597  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
598  nodeIDs.push_back((*j)->getID());
599  for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
600  NBEdge* edge = *it_edge;
601  if (cluster.count(edge->getFromNode()) == 0 && edge->getPermissions() != SVC_PEDESTRIAN) {
602  // incoming edge, does not originate in the cluster
603  finalIncomingAngles[edge->getID()] = edge->getAngleAtNode(edge->getToNode());
604  }
605  }
606  for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
607  NBEdge* edge = *it_edge;
608  if (cluster.count(edge->getToNode()) == 0 && edge->getPermissions() != SVC_PEDESTRIAN) {
609  // outgoing edge, does not end in the cluster
610  finalOutgoingAngles[edge->getID()] = edge->getAngleAtNode(edge->getFromNode());
611  }
612  }
613 
614  }
615  if (finalIncomingAngles.size() > 4) {
616  std::sort(nodeIDs.begin(), nodeIDs.end());
617  WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (" + toString(finalIncomingAngles.size()) + " incoming edges)");
618  continue;
619  }
620  // check for incoming parallel edges
621  const double PARALLEL_INCOMING_THRESHOLD = 10.0;
622  bool foundParallel = false;
623  for (std::map<std::string, double>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
624  std::map<std::string, double>::const_iterator k = j;
625  for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
626  if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
627  WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (parallel incoming "
628  + j->first + "," + k->first + ")");
629  foundParallel = true;
630  }
631  }
632  }
633  // check for outgoing parallel edges
634  for (std::map<std::string, double>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
635  std::map<std::string, double>::const_iterator k = j;
636  for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
637  if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
638  WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (parallel outgoing "
639  + j->first + "," + k->first + ")");
640  foundParallel = true;
641  }
642  }
643  }
644  if (foundParallel) {
645  continue;
646  }
647  // compute all connected components of this cluster
648  // (may be more than 1 if intermediate nodes were removed)
649  NodeClusters components;
650  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end(); ++j) {
651  // merge all connected components into newComp
652  std::set<NBNode*> newComp;
653  NBNode* current = *j;
654  //std::cout << "checking connectivity for " << current->getID() << "\n";
655  newComp.insert(current);
656  for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
657  NodeClusters::iterator check = it_comp;
658  //std::cout << " connected with " << toString(*check) << "?\n";
659  bool connected = false;
660  for (std::set<NBNode*>::iterator k = (*check).begin(); k != (*check).end(); ++k) {
661  if (current->getConnectionTo(*k) != 0 || (*k)->getConnectionTo(current) != 0) {
662  //std::cout << "joining with connected component " << toString(*check) << "\n";
663  newComp.insert((*check).begin(), (*check).end());
664  it_comp = components.erase(check);
665  connected = true;
666  break;
667  }
668  }
669  if (!connected) {
670  it_comp++;
671  }
672  }
673  //std::cout << "adding new component " << toString(newComp) << "\n";
674  components.push_back(newComp);
675  }
676  for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
677  if ((*it_comp).size() > 1) {
678  //std::cout << "adding cluster " << toString(*it_comp) << "\n";
679  clusters.push_back(*it_comp);
680  }
681  }
682  }
683  joinNodeClusters(clusters, dc, ec, tlc);
684  return (int)clusters.size();
685 }
686 
687 
688 void
691  for (NodeClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) {
692  std::set<NBNode*> cluster = *i;
693  assert(cluster.size() > 1);
694  Position pos;
695  bool setTL;
696  std::string id;
697  TrafficLightType type;
698  analyzeCluster(cluster, id, pos, setTL, type);
699  if (!insert(id, pos)) {
700  // should not fail
701  WRITE_WARNING("Could not join junctions " + id);
702  continue;
703  }
704  NBNode* newNode = retrieve(id);
705  if (setTL) {
706  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, newNode, 0, type);
707  if (!tlc.insert(tlDef)) {
708  // actually, nothing should fail here
709  delete tlDef;
710  throw ProcessError("Could not allocate tls '" + id + "'.");
711  }
712  }
713  // collect edges
714  std::set<NBEdge*> allEdges;
715  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
716  const EdgeVector& edges = (*j)->getEdges();
717  allEdges.insert(edges.begin(), edges.end());
718  }
719 
720  // remap and remove edges which are completely within the new intersection
721  for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end();) {
722  NBEdge* e = (*j);
723  NBNode* from = e->getFromNode();
724  NBNode* to = e->getToNode();
725  if (cluster.count(from) > 0 && cluster.count(to) > 0) {
726  for (std::set<NBEdge*>::iterator l = allEdges.begin(); l != allEdges.end(); ++l) {
727  if (e != *l) {
728  (*l)->replaceInConnections(e, e->getConnections());
729  }
730  }
731  ec.extract(dc, e, true);
732  allEdges.erase(j++); // erase does not invalidate the other iterators
733  } else {
734  ++j;
735  }
736  }
737 
738  // remap edges which are incoming / outgoing
739  for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end(); ++j) {
740  NBEdge* e = (*j);
741  std::vector<NBEdge::Connection> conns = e->getConnections();
742  const bool outgoing = cluster.count(e->getFromNode()) > 0;
743  NBNode* from = outgoing ? newNode : e->getFromNode();
744  NBNode* to = outgoing ? e->getToNode() : newNode;
745  e->reinitNodes(from, to);
746  // re-add connections which previously existed and may still valid.
747  // connections to removed edges will be ignored
748  for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
749  e->addLane2LaneConnection((*k).fromLane, (*k).toEdge, (*k).toLane, NBEdge::L2L_USER, false, (*k).mayDefinitelyPass);
750  if ((*k).fromLane >= 0 && (*k).fromLane < e->getNumLanes() && e->getLaneStruct((*k).fromLane).connectionsDone) {
751  // @note (see NIImporter_DlrNavteq::ConnectedLanesHandler)
753  }
754  }
755  }
756  // remove original nodes
757  registerJoinedCluster(cluster);
758  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
759  erase(*j);
760  }
761  }
762 }
763 
764 
765 void
766 NBNodeCont::registerJoinedCluster(const std::set<NBNode*>& cluster) {
767  std::set<std::string> ids;
768  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); j++) {
769  ids.insert((*j)->getID());
770  }
771  myJoinedClusters.push_back(ids);
772 }
773 
774 
775 void
776 NBNodeCont::analyzeCluster(std::set<NBNode*> cluster, std::string& id, Position& pos,
777  bool& hasTLS, TrafficLightType& type) {
778  id = "cluster";
779  hasTLS = false;
780  std::vector<std::string> member_ids;
781  bool ambiguousType = false;
782  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); j++) {
783  member_ids.push_back((*j)->getID());
784  pos.add((*j)->getPosition());
785  // add a traffic light if any of the cluster members was controlled
786  if ((*j)->isTLControlled()) {
787  if (!hasTLS) {
788  // init type
789  type = (*(*j)->getControllingTLS().begin())->getType();
790  } else if (type != (*(*j)->getControllingTLS().begin())->getType()) {
791  ambiguousType = true;
792  }
793  hasTLS = true;
794  }
795  }
796  pos.mul(1.0 / cluster.size());
797  // need to sort the member names to make the output deterministic
798  sort(member_ids.begin(), member_ids.end());
799  for (std::vector<std::string>::iterator j = member_ids.begin(); j != member_ids.end(); j++) {
800  id = id + "_" + (*j);
801  }
802  if (ambiguousType) {
803  type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type"));
804  WRITE_WARNING("Ambiguous traffic light type for node cluster '" + id + "' set to '" + toString(type) + "'");
805  }
806 }
807 
808 
809 // ----------- (Helper) methods for guessing/computing traffic lights
810 bool
811 NBNodeCont::shouldBeTLSControlled(const std::set<NBNode*>& c) const {
812  int noIncoming = 0;
813  int noOutgoing = 0;
814  bool tooFast = false;
815  double f = 0;
816  std::set<NBEdge*> seen;
817  for (std::set<NBNode*>::const_iterator j = c.begin(); j != c.end(); ++j) {
818  const EdgeVector& edges = (*j)->getEdges();
819  for (EdgeVector::const_iterator k = edges.begin(); k != edges.end(); ++k) {
820  if (c.find((*k)->getFromNode()) != c.end() && c.find((*k)->getToNode()) != c.end()) {
821  continue;
822  }
823  if ((*j)->hasIncoming(*k)) {
824  ++noIncoming;
825  f += (double)(*k)->getNumLanes() * (*k)->getLaneSpeed(0);
826  } else {
827  ++noOutgoing;
828  }
829  if ((*k)->getLaneSpeed(0) * 3.6 > 79) {
830  tooFast = true;
831  }
832  }
833  }
834  return !tooFast && f >= 150. / 3.6 && c.size() != 0;
835 }
836 
837 
838 void
840  // build list of definitely not tls-controlled junctions
841  std::vector<NBNode*> ncontrolled;
842  if (oc.isSet("tls.unset")) {
843  std::vector<std::string> notTLControlledNodes = oc.getStringVector("tls.unset");
844  for (std::vector<std::string>::const_iterator i = notTLControlledNodes.begin(); i != notTLControlledNodes.end(); ++i) {
845  NBNode* n = NBNodeCont::retrieve(*i);
846  if (n == 0) {
847  throw ProcessError(" The junction '" + *i + "' to set as not-controlled is not known.");
848  }
849  std::set<NBTrafficLightDefinition*> tls = n->getControllingTLS();
850  for (std::set<NBTrafficLightDefinition*>::const_iterator j = tls.begin(); j != tls.end(); ++j) {
851  (*j)->removeNode(n);
852  }
853  n->removeTrafficLights();
854  ncontrolled.push_back(n);
855  }
856  }
857 
859  // loop#1 checking whether the node shall be tls controlled,
860  // because it is assigned to a district
861  if (oc.exists("tls.taz-nodes") && oc.getBool("tls.taz-nodes")) {
862  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
863  NBNode* cur = (*i).second;
864  if (cur->isNearDistrict() && find(ncontrolled.begin(), ncontrolled.end(), cur) == ncontrolled.end()) {
865  setAsTLControlled(cur, tlc, type);
866  }
867  }
868  }
869 
870  // figure out which nodes mark the locations of TLS signals
871  // This assumes nodes are already joined
872  if (oc.exists("tls.guess-signals") && oc.getBool("tls.guess-signals")) {
873  // prepare candidate edges
874  const double signalDist = oc.getFloat("tls.guess-signals.dist");
875  for (std::map<std::string, NBNode*>::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
876  NBNode* node = (*i).second;
877  if (node->isTLControlled() && node->geometryLike()) {
878  const EdgeVector& outgoing = node->getOutgoingEdges();
879  for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
880  (*it_o)->setSignalOffset((*it_o)->getLength());
881  }
882  }
883  }
884  // check which nodes should be controlled
885  for (std::map<std::string, NBNode*>::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
886  NBNode* node = i->second;
887  if (find(ncontrolled.begin(), ncontrolled.end(), node) != ncontrolled.end()) {
888  continue;
889  }
890  const EdgeVector& incoming = node->getIncomingEdges();
891  const EdgeVector& outgoing = node->getOutgoingEdges();
892  if (!node->isTLControlled() && incoming.size() > 1 && !node->geometryLike()) {
893  std::vector<NBNode*> signals;
894  bool isTLS = true;
895  for (EdgeVector::const_iterator it_i = incoming.begin(); it_i != incoming.end(); ++it_i) {
896  const NBEdge* inEdge = *it_i;
897  if (inEdge->getSignalOffset() == NBEdge::UNSPECIFIED_SIGNAL_OFFSET || inEdge->getSignalOffset() > signalDist) {
898  isTLS = false;
899  break;
900  }
901  if (inEdge->getSignalOffset() == inEdge->getLength()) {
902  signals.push_back(inEdge->getFromNode());
903  }
904  }
905  // outgoing edges may be tagged with pedestrian crossings. These
906  // should also be morged into the main TLS
907  for (EdgeVector::const_iterator it_i = outgoing.begin(); it_i != outgoing.end(); ++it_i) {
908  const NBEdge* outEdge = *it_i;
909  NBNode* cand = outEdge->getToNode();
910  if (cand->isTLControlled() && cand->geometryLike() && outEdge->getLength() <= signalDist) {
911  signals.push_back(cand);
912  }
913  }
914  if (isTLS) {
915  for (std::vector<NBNode*>::iterator j = signals.begin(); j != signals.end(); ++j) {
916  std::set<NBTrafficLightDefinition*> tls = (*j)->getControllingTLS();
917  (*j)->reinit((*j)->getPosition(), NODETYPE_PRIORITY);
918  for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
919  tlc.removeFully((*j)->getID());
920  }
921  }
922  NBTrafficLightDefinition* tlDef = new NBOwnTLDef("GS_" + node->getID(), node, 0, TLTYPE_STATIC);
923  // @todo patch endOffset for all incoming lanes according to the signal positions
924  if (!tlc.insert(tlDef)) {
925  // actually, nothing should fail here
926  WRITE_WARNING("Could not build joined tls '" + node->getID() + "'.");
927  delete tlDef;
928  return;
929  }
930  }
931  }
932  }
933  }
934 
935  // maybe no tls shall be guessed
936  if (!oc.getBool("tls.guess")) {
937  return;
938  }
939 
940  // guess joined tls first, if wished
941  if (oc.getBool("tls.join")) {
942  // get node clusters
943  std::vector<std::set<NBNode*> > cands;
944  generateNodeClusters(oc.getFloat("tls.join-dist"), cands);
945  // check these candidates (clusters) whether they should be controlled by a tls
946  for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end();) {
947  std::set<NBNode*>& c = (*i);
948  // regard only junctions which are not yet controlled and are not
949  // forbidden to be controlled
950  for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) {
951  if ((*j)->isTLControlled() || find(ncontrolled.begin(), ncontrolled.end(), *j) != ncontrolled.end()) {
952  c.erase(j++);
953  } else {
954  ++j;
955  }
956  }
957  // check whether the cluster should be controlled
958  if (!shouldBeTLSControlled(c)) {
959  i = cands.erase(i);
960  } else {
961  ++i;
962  }
963  }
964  // cands now only contain sets of junctions that shall be joined into being tls-controlled
965  int index = 0;
966  for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) {
967  std::vector<NBNode*> nodes;
968  for (std::set<NBNode*>::iterator j = (*i).begin(); j != (*i).end(); j++) {
969  nodes.push_back(*j);
970  }
971  std::string id = "joinedG_" + toString(index++);
972  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes, 0, type);
973  if (!tlc.insert(tlDef)) {
974  // actually, nothing should fail here
975  WRITE_WARNING("Could not build guessed, joined tls");
976  delete tlDef;
977  return;
978  }
979  }
980  }
981 
982  // guess tls
983  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
984  NBNode* cur = (*i).second;
985  // do nothing if already is tl-controlled
986  if (cur->isTLControlled()) {
987  continue;
988  }
989  // do nothing if in the list of explicit non-controlled junctions
990  if (find(ncontrolled.begin(), ncontrolled.end(), cur) != ncontrolled.end()) {
991  continue;
992  }
993  std::set<NBNode*> c;
994  c.insert(cur);
995  if (!shouldBeTLSControlled(c) || cur->getIncomingEdges().size() < 3) {
996  continue;
997  }
998  setAsTLControlled((*i).second, tlc, type);
999  }
1000 }
1001 
1002 
1003 void
1005  std::vector<std::set<NBNode*> > cands;
1006  generateNodeClusters(maxdist, cands);
1007  int index = 0;
1008  for (std::vector<std::set<NBNode*> >::iterator i = cands.begin(); i != cands.end(); ++i) {
1009  std::set<NBNode*>& c = (*i);
1010  for (std::set<NBNode*>::iterator j = c.begin(); j != c.end();) {
1011  if (!(*j)->isTLControlled()) {
1012  c.erase(j++);
1013  } else {
1014  ++j;
1015  }
1016  }
1017  if (c.size() < 2) {
1018  continue;
1019  }
1020  // figure out type of the joined TLS
1021  Position dummyPos;
1022  bool dummySetTL;
1023  std::string dummyId;
1024  TrafficLightType type;
1025  analyzeCluster(c, dummyId, dummyPos, dummySetTL, type);
1026  for (std::set<NBNode*>::iterator j = c.begin(); j != c.end(); ++j) {
1027  std::set<NBTrafficLightDefinition*> tls = (*j)->getControllingTLS();
1028  (*j)->removeTrafficLights();
1029  for (std::set<NBTrafficLightDefinition*>::iterator k = tls.begin(); k != tls.end(); ++k) {
1030  tlc.removeFully((*j)->getID());
1031  }
1032  }
1033  std::string id = "joinedS_" + toString(index++);
1034  std::vector<NBNode*> nodes;
1035  for (std::set<NBNode*>::iterator j = c.begin(); j != c.end(); j++) {
1036  nodes.push_back(*j);
1037  }
1038  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, nodes, 0, type);
1039  if (!tlc.insert(tlDef)) {
1040  // actually, nothing should fail here
1041  WRITE_WARNING("Could not build a joined tls.");
1042  delete tlDef;
1043  return;
1044  }
1045  }
1046 }
1047 
1048 
1049 void
1051  TrafficLightType type, std::string id) {
1052  if (id == "") {
1053  id = node->getID();
1054  }
1055  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, node, 0, type);
1056  if (!tlc.insert(tlDef)) {
1057  // actually, nothing should fail here
1058  WRITE_WARNING("Building a tl-logic for junction '" + id + "' twice is not possible.");
1059  delete tlDef;
1060  return;
1061  }
1062 }
1063 
1064 
1065 // -----------
1066 void
1068  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1069  (*i).second->computeLanes2Lanes();
1070  }
1071 }
1072 
1073 
1074 // computes the "wheel" of incoming and outgoing edges for every node
1075 void
1077  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1078  (*i).second->computeLogic(ec, oc);
1079  }
1080 }
1081 
1082 
1083 void
1085  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1086  delete((*i).second);
1087  }
1088  myNodes.clear();
1089  for (std::set<NBNode*>::iterator i = myExtractedNodes.begin(); i != myExtractedNodes.end(); i++) {
1090  delete(*i);
1091  }
1092  myExtractedNodes.clear();
1093 }
1094 
1095 
1096 std::string
1098  int counter = 0;
1099  std::string freeID = "SUMOGenerated" + toString<int>(counter);
1100  // While there is a node with id equal to freeID
1101  while (retrieve(freeID) != 0) {
1102  // update counter and generate a new freeID
1103  counter++;
1104  freeID = "SUMOGenerated" + toString<int>(counter);
1105  }
1106  return freeID;
1107 }
1108 
1109 
1110 void
1111 NBNodeCont::computeNodeShapes(double mismatchThreshold) {
1112  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1113  (*i).second->computeNodeShape(mismatchThreshold);
1114  }
1115 }
1116 
1117 
1118 void
1120  int numUnregulatedJunctions = 0;
1121  int numDeadEndJunctions = 0;
1122  int numPriorityJunctions = 0;
1123  int numRightBeforeLeftJunctions = 0;
1124  int numAllWayStopJunctions = 0;
1125  int numZipperJunctions = 0;
1126  int numRailSignals = 0;
1127  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1128  switch ((*i).second->getType()) {
1129  case NODETYPE_NOJUNCTION:
1131  ++numUnregulatedJunctions;
1132  break;
1133  case NODETYPE_DEAD_END:
1134  ++numDeadEndJunctions;
1135  break;
1136  case NODETYPE_PRIORITY:
1141  ++numPriorityJunctions;
1142  break;
1144  ++numRightBeforeLeftJunctions;
1145  break;
1146  case NODETYPE_ALLWAY_STOP:
1147  ++numAllWayStopJunctions;
1148  break;
1149  case NODETYPE_ZIPPER:
1150  ++numZipperJunctions;
1151  break;
1152  case NODETYPE_DISTRICT:
1153  ++numRightBeforeLeftJunctions;
1154  break;
1155  case NODETYPE_UNKNOWN:
1156  break;
1157  case NODETYPE_RAIL_SIGNAL:
1158  ++numRailSignals;
1159  break;
1160  default:
1161  break;
1162  }
1163  }
1164  WRITE_MESSAGE(" Node type statistics:");
1165  WRITE_MESSAGE(" Unregulated junctions : " + toString(numUnregulatedJunctions));
1166  if (numDeadEndJunctions > 0) {
1167  WRITE_MESSAGE(" Dead-end junctions : " + toString(numDeadEndJunctions));
1168  }
1169  WRITE_MESSAGE(" Priority junctions : " + toString(numPriorityJunctions));
1170  WRITE_MESSAGE(" Right-before-left junctions : " + toString(numRightBeforeLeftJunctions));
1171  if (numAllWayStopJunctions > 0) {
1172  WRITE_MESSAGE(" All-way stop junctions : " + toString(numAllWayStopJunctions));
1173  }
1174  if (numZipperJunctions > 0) {
1175  WRITE_MESSAGE(" Zipper-merge junctions : " + toString(numZipperJunctions));
1176  }
1177  if (numRailSignals > 0) {
1178  WRITE_MESSAGE(" Rail signal junctions : " + toString(numRailSignals));
1179  }
1180 }
1181 
1182 
1183 std::vector<std::string>
1185  std::vector<std::string> ret;
1186  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
1187  ret.push_back((*i).first);
1188  }
1189  return ret;
1190 }
1191 
1192 
1193 void
1194 NBNodeCont::rename(NBNode* node, const std::string& newID) {
1195  if (myNodes.count(newID) != 0) {
1196  throw ProcessError("Attempt to rename node using existing id '" + newID + "'");
1197  }
1198  myNodes.erase(node->getID());
1199  node->setID(newID);
1200  myNodes[newID] = node;
1201 }
1202 
1203 
1204 void
1205 NBNodeCont::discardTrafficLights(NBTrafficLightLogicCont& tlc, bool geometryLike, bool guessSignals) {
1206  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
1207  NBNode* node = i->second;
1208  if (!geometryLike || node->geometryLike()) {
1209  // make a copy of tldefs
1210  const std::set<NBTrafficLightDefinition*> tldefs = node->getControllingTLS();
1211  if (guessSignals && node->isTLControlled() && node->geometryLike()) {
1212  // record signal location
1213  const EdgeVector& outgoing = node->getOutgoingEdges();
1214  for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
1215  (*it_o)->setSignalOffset((*it_o)->getLength());
1216  }
1217  }
1218  for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
1219  NBTrafficLightDefinition* tlDef = *it;
1220  node->removeTrafficLight(tlDef);
1221  tlc.extract(tlDef);
1222  }
1223  node->reinit(node->getPosition(), NODETYPE_UNKNOWN);
1224  }
1225  }
1226 }
1227 
1228 
1229 int
1230 NBNodeCont::remapIDs(bool numericaIDs, bool reservedIDs) {
1231  std::vector<std::string> avoid = getAllNames();
1232  std::set<std::string> reserve;
1233  if (reservedIDs) {
1234  NBHelpers::loadPrefixedIDsFomFile(OptionsCont::getOptions().getString("reserved-ids"), "node:", reserve);
1235  avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1236  }
1237  IDSupplier idSupplier("", avoid);
1238  std::set<NBNode*, Named::ComparatorIdLess> toChange;
1239  for (NodeCont::iterator it = myNodes.begin(); it != myNodes.end(); it++) {
1240  if (numericaIDs) {
1241  try {
1242  TplConvert::_str2long(it->first);
1243  } catch (NumberFormatException&) {
1244  toChange.insert(it->second);
1245  }
1246  }
1247  if (reservedIDs && reserve.count(it->first) > 0) {
1248  toChange.insert(it->second);
1249  }
1250  }
1251  for (std::set<NBNode*, Named::ComparatorIdLess>::iterator it = toChange.begin(); it != toChange.end(); ++it) {
1252  NBNode* node = *it;
1253  myNodes.erase(node->getID());
1254  node->setID(idSupplier.getNext());
1255  myNodes[node->getID()] = node;
1256  }
1257  return (int)toChange.size();
1258 }
1259 
1260 /****************************************************************************/
1261 
std::string getFreeID()
generates a new node ID
std::set< std::string > myJoinExclusions
set of node ids which should not be joined
Definition: NBNodeCont.h:329
NodeCont myNodes
The map of names to nodes.
Definition: NBNodeCont.h:323
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition: NamedRTree.h:90
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:106
void joinSimilarEdges(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins edges connecting the same nodes.
Definition: NBNodeCont.cpp:177
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:481
void removeSelfLoops(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes self-loop edges (edges where the source and the destination node are the same) ...
Definition: NBNodeCont.cpp:165
void registerJoinedCluster(const std::set< NBNode *> &cluster)
gets all joined clusters (see doc for myClusters2Join)
Definition: NBNodeCont.cpp:766
is a pedestrian
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:114
void addJoinExclusion(const std::vector< std::string > &ids, bool check=false)
Definition: NBNodeCont.cpp:446
static void loadPrefixedIDsFomFile(const std::string &file, const std::string prefix, std::set< std::string > &into)
Add prefixed ids defined in file.
Definition: NBHelpers.cpp:111
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:133
int removeUnwishedNodes(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, bool removeGeometryNodes)
Removes "unwished" nodes.
Definition: NBNodeCont.cpp:316
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.
Definition: NBNode.cpp:262
double getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
Definition: NBEdge.h:558
std::vector< std::set< std::string > > myJoinedClusters
sets of node ids which were joined
Definition: NBNodeCont.h:335
double y() const
Returns the y-position.
Definition: Position.h:68
The representation of a single edge during network building.
Definition: NBEdge.h:71
void reinitNodes(NBNode *from, NBNode *to)
Resets nodes but keeps all other values the same (used when joining)
Definition: NBEdge.cpp:375
static const double UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
Definition: NBEdge.h:273
double x() const
Returns the x-position.
Definition: Position.h:63
A container for districts.
The base class for traffic light logic definitions.
int joinLoadedClusters(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins loaded junction clusters (see NIXMLNodesHandler)
Definition: NBNodeCont.cpp:480
NamedRTree myRTree
node positions for faster lookup
Definition: NBNodeCont.h:344
static long long int _str2long(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter, which
Definition: TplConvert.h:232
void guessTLs(OptionsCont &oc, NBTrafficLightLogicCont &tlc)
Guesses which junctions or junction clusters shall be controlled by tls.
Definition: NBNodeCont.cpp:839
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.
Definition: NBEdge.h:157
void avoidOverlap()
fix overlap
Definition: NBNodeCont.cpp:386
const std::string & getID() const
Returns the id.
Definition: Named.h:66
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1154
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.
Definition: NBHelpers.cpp:93
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:320
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:38
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:65
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:245
The edge has been loaded, nothing is computed yet.
Definition: NBEdge.h:94
void computeLogics(const NBEdgeCont &ec, OptionsCont &oc)
build the list of outgoing edges and lanes
A class representing a single district.
Definition: NBDistrict.h:72
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:1739
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.
Definition: NamedRTree.h:101
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:288
bool shouldBeTLSControlled(const std::set< NBNode *> &c) const
Returns whethe the given node cluster should be controlled by a tls.
Definition: NBNodeCont.cpp:811
#define max(a, b)
Definition: polyfonts.c:65
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:59
void computeLanes2Lanes()
divides the incoming lanes on outgoing lanes
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
~NBNodeCont()
Destructor.
Definition: NBNodeCont.cpp:70
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.
Definition: NBEdgeCont.cpp:392
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:413
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
NBNodeCont()
Constructor.
Definition: NBNodeCont.cpp:65
std::pair< NBNode *, double > NodeAndDist
Definition: NBNodeCont.h:287
void generateNodeClusters(double maxDist, NodeClusters &into) const
Builds node clusters.
Definition: NBNodeCont.cpp:394
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) ...
Definition: NBNode.h:250
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.
Definition: NBNode.cpp:327
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:2511
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
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) ...
T MIN2(T a, T b)
Definition: StdDefs.h:64
void computeNodeShapes(double mismatchThreshold=-1)
Compute the junction shape for this node.
#define POSITION_EPS
Definition: config.h:175
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1576
void joinNodeClusters(NodeClusters clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
joins the given node clusters
Definition: NBNodeCont.cpp:689
std::set< NBNode * > myExtractedNodes
The extracted nodes which are kept for reference.
Definition: NBNodeCont.h:326
int joinJunctions(double maxDist, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins junctions that are very close together.
Definition: NBNodeCont.cpp:504
The connection was given by the user.
Definition: NBEdge.h:115
void analyzeCluster(std::set< NBNode *> cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type)
Definition: NBNodeCont.cpp:776
int Search(const float a_min[2], const float a_max[2], const Named::StoringVisitor &c) const
Find all within search rectangle.
Definition: NamedRTree.h:123
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
Definition: NBEdge.cpp:2913
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.
Definition: NBNode.cpp:1218
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:692
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:507
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.
Definition: Named.h:100
std::vector< std::string > getAllNames() const
get all node names
void setID(const std::string &newID)
resets the id
Definition: Named.h:74
void addCluster2Join(std::set< std::string > cluster)
add ids of nodes which shall be joined into a single node
Definition: NBNodeCont.cpp:462
int remapIDs(bool numericaIDs, bool reservedIDs)
remap node IDs accoring to options –numerical-ids and –reserved-ids
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:240
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:834
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...
Definition: NBNode.cpp:1112
bool isNearDistrict() const
if node is near district
Definition: NBNode.cpp:1750
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node) ...
Definition: NBNode.h:298
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:251
void removeIsolatedRoads(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tc)
Removes sequences of edges that are not connected with a junction. Simple roads without junctions som...
Definition: NBNodeCont.cpp:222
std::set< std::string > myJoined
ids found in loaded join clusters used for error checking
Definition: NBNodeCont.h:338
A storage for options typed value containers)
Definition: OptionsCont.h:99
std::vector< std::set< NBNode * > > NodeClusters
Definition of a node cluster container.
Definition: NBNodeCont.h:286
std::string joinToStringSorting(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:244
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:385
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:77
void clear()
deletes all nodes
void append(NBEdge *continuation)
append another edge
Definition: NBEdge.cpp:2629
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)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:900
std::vector< std::set< std::string > > myClusters2Join
loaded sets of node ids to join (cleared after use)
Definition: NBNodeCont.h:332
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 ...
Definition: NBEdge.h:1168
const Position & getPosition() const
Definition: NBNode.h:232
Represents a single node (junction) during network building.
Definition: NBNode.h:75
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
Definition: NBNodeCont.h:341
void printBuiltNodesStatistics() const
Prints statistics about built nodes.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:427
void mul(double val)
Multiplies both positions with the given value.
Definition: Position.h:113
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)
Definition: NBOwnTLDef.h:54
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:490
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
Definition: NBNodeCont.cpp:147
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
bool erase(NBNode *node)
Removes the given node, deleting it.
Definition: NBNodeCont.cpp:136
bool checkIsRemovable() const
check if node is removable
Definition: NBNode.cpp:1642
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:542
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
get edges to join
Definition: NBNode.cpp:1693
bool isNearEnough2BeJoined2(NBEdge *e, double threshold) const
Check if edge is near enought to be joined to another edge.
Definition: NBEdge.cpp:2691
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:434
TrafficLightType