SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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-2016 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 #ifdef CHECK_MEMORY_LEAKS
62 #include <foreign/nvwa/debug_new.h>
63 #endif // CHECK_MEMORY_LEAKS
64 
65 
66 // ===========================================================================
67 // method definitions
68 // ===========================================================================
70  : myInternalID(1) {
71 }
72 
73 
75  clear();
76 }
77 
78 
79 // ----------- Insertion/removal/retrieval of nodes
80 bool
81 NBNodeCont::insert(const std::string& id, const Position& position,
82  NBDistrict* district) {
83  NodeCont::iterator i = myNodes.find(id);
84  if (i != myNodes.end()) {
85  return false;
86  }
87  NBNode* node = new NBNode(id, position, district);
88  myNodes[id] = node;
89  const float pos[2] = {(float)position.x(), (float)position.y()};
90  myRTree.Insert(pos, pos, node);
91  return true;
92 }
93 
94 
95 bool
97  std::string id = node->getID();
98  NodeCont::iterator i = myNodes.find(id);
99  if (i != myNodes.end()) {
100  return false;
101  }
102  myNodes[id] = node;
103  const float pos[2] = {(float)node->getPosition().x(), (float)node->getPosition().y()};
104  myRTree.Insert(pos, pos, node);
105  return true;
106 }
107 
108 
109 NBNode*
110 NBNodeCont::retrieve(const std::string& id) const {
111  NodeCont::const_iterator i = myNodes.find(id);
112  if (i == myNodes.end()) {
113  return 0;
114  }
115  return (*i).second;
116 }
117 
118 
119 NBNode*
120 NBNodeCont::retrieve(const Position& position, const SUMOReal offset) const {
121  const SUMOReal extOffset = offset + POSITION_EPS;
122  const float cmin[2] = {(float)(position.x() - extOffset), (float)(position.y() - extOffset)};
123  const float cmax[2] = {(float)(position.x() + extOffset), (float)(position.y() + extOffset)};
124  std::set<std::string> into;
125  Named::StoringVisitor sv(into);
126  myRTree.Search(cmin, cmax, sv);
127  for (std::set<std::string>::const_iterator i = into.begin(); i != into.end(); i++) {
128  NBNode* const node = myNodes.find(*i)->second;
129  if (fabs(node->getPosition().x() - position.x()) <= offset
130  &&
131  fabs(node->getPosition().y() - position.y()) <= offset) {
132  return node;
133  }
134  }
135  return 0;
136 }
137 
138 
139 bool
141  if (extract(node)) {
142  delete node;
143  return true;
144  } else {
145  return false;
146  }
147 }
148 
149 
150 bool
151 NBNodeCont::extract(NBNode* node, bool remember) {
152  NodeCont::iterator i = myNodes.find(node->getID());
153  if (i == myNodes.end()) {
154  return false;
155  }
156  myNodes.erase(i);
157  const float pos[2] = {(float)node->getPosition().x(), (float)node->getPosition().y()};
158  myRTree.Remove(pos, pos, node);
159  node->removeTrafficLights();
160  if (remember) {
161  myExtractedNodes.insert(node);
162  }
163  return true;
164 }
165 
166 
167 // ----------- Adapting the input
168 void
170  int no = 0;
171  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
172  no += (*i).second->removeSelfLoops(dc, ec, tc);
173  }
174  if (no != 0) {
175  WRITE_WARNING(toString(no) + " self-looping edge(s) removed.");
176  }
177 }
178 
179 
180 void
182  // magic values
183  SUMOReal distanceThreshold = 7; // don't merge edges further apart
184  SUMOReal lengthThreshold = 0.10; // don't merge edges with higher relative length-difference
185 
186  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
187  // count the edges to other nodes outgoing from the current node
188  std::map<NBNode*, EdgeVector> connectionCount;
189  const EdgeVector& outgoing = (*i).second->getOutgoingEdges();
190  for (EdgeVector::const_iterator j = outgoing.begin(); j != outgoing.end(); j++) {
191  connectionCount[(*j)->getToNode()].push_back(*j);
192  }
193  // check whether more than a single edge connect another node and join them
194  std::map<NBNode*, EdgeVector>::iterator k;
195  for (k = connectionCount.begin(); k != connectionCount.end(); k++) {
196  // possibly we do not have anything to join...
197  if ((*k).second.size() < 2) {
198  continue;
199  }
200  // for the edges that seem to be a single street,
201  // check whether the geometry is similar
202  const EdgeVector& ev = (*k).second;
203  const NBEdge* const first = ev.front();
204  EdgeVector::const_iterator jci; // join candidate iterator
205  for (jci = ev.begin() + 1; jci != ev.end(); ++jci) {
206  const SUMOReal relativeLengthDifference = fabs(first->getLoadedLength() - (*jci)->getLoadedLength()) / first->getLoadedLength();
207  if ((!first->isNearEnough2BeJoined2(*jci, distanceThreshold)) ||
208  (relativeLengthDifference > lengthThreshold) ||
209  (fabs(first->getSpeed() - (*jci)->getSpeed()) >= 0.01) || // output accuracy
210  (first->getPermissions() != (*jci)->getPermissions())
211  ) {
212  break;
213  }
214  }
215  // @bug If there are 3 edges of which 2 can be joined, no joining will
216  // take place with the current implementation
217  if (jci == ev.end()) {
218  ec.joinSameNodeConnectingEdges(dc, tlc, ev);
219  }
220  }
221  }
222 }
223 
224 
225 void
227  UNUSED_PARAMETER(tc);
228  // Warn of isolated edges, i.e. a single edge with no connection to another edge
229  int edgeCounter = 0;
230  const std::vector<std::string>& edgeNames = ec.getAllNames();
231  for (std::vector<std::string>::const_iterator it = edgeNames.begin(); it != edgeNames.end(); ++it) {
232  // Test whether this node starts at a dead end, i.e. it has only one adjacent node
233  // to which an edge exists and from which an edge may come.
234  NBEdge* e = ec.retrieve(*it);
235  if (e == 0) {
236  continue;
237  }
238  NBNode* from = e->getFromNode();
239  const EdgeVector& outgoingEdges = from->getOutgoingEdges();
240  if (outgoingEdges.size() != 1) {
241  // At this node, several edges or no edge start; so, this node is no dead end.
242  continue;
243  }
244  const EdgeVector& incomingEdges = from->getIncomingEdges();
245  if (incomingEdges.size() > 1) {
246  // At this node, several edges end; so, this node is no dead end.
247  continue;
248  } else if (incomingEdges.size() == 1) {
249  NBNode* fromNodeOfIncomingEdge = incomingEdges[0]->getFromNode();
250  NBNode* toNodeOfOutgoingEdge = outgoingEdges[0]->getToNode();
251  if (fromNodeOfIncomingEdge != toNodeOfOutgoingEdge) {
252  // At this node, an edge ends which is not the inverse direction of
253  // the starting node.
254  continue;
255  }
256  }
257  // Now we know that the edge e starts a dead end.
258  // Next we test if the dead end is isolated, i.e. does not lead to a junction
259  bool hasJunction = false;
260  EdgeVector road;
261  NBEdge* eOld = 0;
262  NBNode* to;
263  std::set<NBNode*> adjacentNodes;
264  do {
265  road.push_back(e);
266  eOld = e;
267  from = e->getFromNode();
268  to = e->getToNode();
269  const EdgeVector& outgoingEdgesOfToNode = to->getOutgoingEdges();
270  const EdgeVector& incomingEdgesOfToNode = to->getIncomingEdges();
271  adjacentNodes.clear();
272  for (EdgeVector::const_iterator itOfOutgoings = outgoingEdgesOfToNode.begin(); itOfOutgoings != outgoingEdgesOfToNode.end(); ++itOfOutgoings) {
273  if ((*itOfOutgoings)->getToNode() != from // The back path
274  && (*itOfOutgoings)->getToNode() != to // A loop / dummy edge
275  ) {
276  e = *itOfOutgoings; // Probably the next edge
277  }
278  adjacentNodes.insert((*itOfOutgoings)->getToNode());
279  }
280  for (EdgeVector::const_iterator itOfIncomings = incomingEdgesOfToNode.begin(); itOfIncomings != incomingEdgesOfToNode.end(); ++itOfIncomings) {
281  adjacentNodes.insert((*itOfIncomings)->getFromNode());
282  }
283  adjacentNodes.erase(to); // Omit loops
284  if (adjacentNodes.size() > 2) {
285  hasJunction = true;
286  }
287  } while (!hasJunction && eOld != e);
288  if (!hasJunction) {
289  edgeCounter += int(road.size());
290  std::string warningString = "Removed a road without junctions: ";
291  for (EdgeVector::iterator roadIt = road.begin(); roadIt != road.end(); ++roadIt) {
292  if (roadIt == road.begin()) {
293  warningString += (*roadIt)->getID();
294  } else {
295  warningString += ", " + (*roadIt)->getID();
296  }
297 
298  NBNode* fromNode = (*roadIt)->getFromNode();
299  NBNode* toNode = (*roadIt)->getToNode();
300  ec.erase(dc, *roadIt);
301  if (fromNode->getIncomingEdges().size() == 0 && fromNode->getOutgoingEdges().size() == 0) {
302  // Node is empty; can be removed
303  erase(fromNode);
304  }
305  if (toNode->getIncomingEdges().size() == 0 && toNode->getOutgoingEdges().size() == 0) {
306  // Node is empty; can be removed
307  erase(toNode);
308  }
309  }
310  WRITE_WARNING(warningString);
311  }
312  }
313  if (edgeCounter > 0 && !OptionsCont::getOptions().getBool("remove-edges.isolated")) {
314  WRITE_WARNING("Detected isolated roads. Use the option --remove-edges.isolated to get a list of all affected edges.");
315  }
316 }
317 
318 
319 int
322  bool removeGeometryNodes) {
323  // load edges that shall not be modified
324  std::set<std::string> edges2keep;
325  if (removeGeometryNodes) {
326  const OptionsCont& oc = OptionsCont::getOptions();
327  if (oc.isSet("geometry.remove.keep-edges.input-file")) {
328  NBHelpers::loadEdgesFromFile(oc.getString("geometry.remove.keep-edges.input-file"), edges2keep);
329  }
330  if (oc.isSet("geometry.remove.keep-edges.explicit")) {
331  const std::vector<std::string> edges = oc.getStringVector("geometry.remove.keep-edges.explicit");
332  edges2keep.insert(edges.begin(), edges.end());
333  }
334  }
335  int no = 0;
336  std::vector<NBNode*> toRemove;
337  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
338  NBNode* current = (*i).second;
339  bool remove = false;
340  std::vector<std::pair<NBEdge*, NBEdge*> > toJoin;
341  // check for completely empty nodes
342  if (current->getOutgoingEdges().size() == 0 && current->getIncomingEdges().size() == 0) {
343  // remove if empty
344  remove = true;
345  }
346  // check for nodes which are only geometry nodes
347  if (removeGeometryNodes && mySplit.count(current) == 0) {
348  if ((current->getOutgoingEdges().size() == 1 && current->getIncomingEdges().size() == 1)
349  ||
350  (current->getOutgoingEdges().size() == 2 && current->getIncomingEdges().size() == 2)) {
351  // ok, one in, one out or two in, two out
352  // -> ask the node whether to join
353  remove = current->checkIsRemovable();
354  // check whether any of the edges must be kept
355  for (EdgeVector::const_iterator it_edge = current->getEdges().begin(); it_edge != current->getEdges().end(); ++it_edge) {
356  if (edges2keep.find((*it_edge)->getID()) != edges2keep.end()) {
357  remove = false;
358  break;
359  }
360  }
361  if (remove) {
362  toJoin = current->getEdgesToJoin();
363  }
364  }
365  }
366  // remove the node and join the geometries when wished
367  if (!remove) {
368  continue;
369  }
370  for (std::vector<std::pair<NBEdge*, NBEdge*> >::iterator j = toJoin.begin(); j != toJoin.end(); j++) {
371  NBEdge* begin = (*j).first;
372  NBEdge* continuation = (*j).second;
373  begin->append(continuation);
374  continuation->getToNode()->replaceIncoming(continuation, begin, 0);
375  tlc.replaceRemoved(continuation, -1, begin, -1);
376  ec.extract(dc, continuation, true);
377  }
378  toRemove.push_back(current);
379  no++;
380  }
381  // erase all
382  for (std::vector<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
383  extract(*j, true);
384  }
385  return no;
386 }
387 
388 
389 void
391  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
392  (*i).second->avoidOverlap();
393  }
394 }
395 
396 // ----------- (Helper) methods for joining nodes
397 void
399  std::set<NBNode*> visited;
400  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
401  std::vector<NodeAndDist> toProc;
402  if (visited.find((*i).second) != visited.end()) {
403  continue;
404  }
405  toProc.push_back(std::make_pair((*i).second, 0));
406  std::set<NBNode*> c;
407  while (!toProc.empty()) {
408  NodeAndDist nodeAndDist = toProc.back();
409  NBNode* n = nodeAndDist.first;
410  SUMOReal dist = nodeAndDist.second;
411  toProc.pop_back();
412  if (visited.find(n) != visited.end()) {
413  continue;
414  }
415  c.insert(n);
416  visited.insert(n);
417  const EdgeVector& edges = n->getEdges();
418  for (EdgeVector::const_iterator j = edges.begin(); j != edges.end(); ++j) {
419  NBEdge* e = *j;
420  NBNode* s = 0;
421  if (e->getPermissions() == SVC_PEDESTRIAN) {
422  continue; // do not join pedestrian stuff
423  }
424  if (n->hasIncoming(e)) {
425  s = e->getFromNode();
426  } else {
427  s = e->getToNode();
428  }
429  if (visited.find(s) != visited.end()) {
430  continue;
431  }
432  if (e->getLoadedLength() + dist < maxDist) {
433  if (s->geometryLike()) {
434  toProc.push_back(std::make_pair(s, dist + e->getLoadedLength()));
435  } else {
436  toProc.push_back(std::make_pair(s, 0));
437  }
438  }
439  }
440  }
441  if (c.size() < 2) {
442  continue;
443  }
444  into.push_back(c);
445  }
446 }
447 
448 
449 void
450 NBNodeCont::addJoinExclusion(const std::vector<std::string>& ids, bool check) {
451  for (std::vector<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
452  // error handling has to take place here since joinExclusions could be
453  // loaded from multiple files / command line
454  if (myJoined.count(*it) > 0) {
455  WRITE_WARNING("Ignoring join exclusion for junction '" + *it + "' since it already occured in a list of nodes to be joined");
456  } else if (check && retrieve(*it) == 0) {
457  WRITE_WARNING("Ignoring join exclusion for unknown junction '" + *it + "'");
458  } else {
459  myJoinExclusions.insert(*it);
460  }
461  }
462 }
463 
464 
465 void
466 NBNodeCont::addCluster2Join(std::set<std::string> cluster) {
467  // error handling has to take place here since joins could be loaded from multiple files
468  for (std::set<std::string>::const_iterator it = cluster.begin(); it != cluster.end(); it++) {
469  if (myJoinExclusions.count(*it) > 0) {
470  WRITE_WARNING("Ignoring join-cluster because junction '" + *it + "' was already excluded from joining");
471  return;
472  } else if (myJoined.count(*it) > 0) {
473  WRITE_WARNING("Ignoring join-cluster because junction '" + *it + "' already occured in another join-cluster");
474  return;
475  } else {
476  myJoined.insert(*it);
477  }
478  }
479  myClusters2Join.push_back(cluster);
480 }
481 
482 
483 int
485  NodeClusters clusters;
486  for (std::vector<std::set<std::string> >::iterator it = myClusters2Join.begin(); it != myClusters2Join.end(); it++) {
487  // verify loaded cluster
488  std::set<NBNode*> cluster;
489  for (std::set<std::string>::iterator it_id = it->begin(); it_id != it->end(); it_id++) {
490  NBNode* node = retrieve(*it_id);
491  if (node == 0) {
492  WRITE_WARNING("Ignoring unknown junction '" + *it_id + "' while joining");
493  } else {
494  cluster.insert(node);
495  }
496  }
497  if (cluster.size() > 1) {
498  clusters.push_back(cluster);
499  }
500  }
501  joinNodeClusters(clusters, dc, ec, tlc);
502  myClusters2Join.clear(); // make save for recompute
503  return (int)clusters.size();
504 }
505 
506 
507 int
509  NodeClusters cands;
510  NodeClusters clusters;
511  generateNodeClusters(maxDist, cands);
512  for (NodeClusters::iterator i = cands.begin(); i != cands.end(); ++i) {
513  std::set<NBNode*> cluster = (*i);
514  // remove join exclusions
515  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
516  std::set<NBNode*>::iterator check = j;
517  ++j;
518  if (myJoinExclusions.count((*check)->getID()) > 0) {
519  cluster.erase(check);
520  }
521  }
522  // iteratively remove the fringe
523  bool pruneFringe = true;
524  while (pruneFringe) {
525  pruneFringe = false;
526  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end();) {
527  std::set<NBNode*>::iterator check = j;
528  NBNode* n = *check;
529  ++j;
530 
531  // compute clusterDist for node (length of shortest edge which connects this node to the cluster)
533  for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
534  NBNode* neighbor = (*it_edge)->getToNode();
535  if (cluster.count(neighbor) != 0) {
536  clusterDist = MIN2(clusterDist, (*it_edge)->getLoadedLength());
537  }
538  }
539  for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
540  NBNode* neighbor = (*it_edge)->getFromNode();
541  if (cluster.count(neighbor) != 0) {
542  clusterDist = MIN2(clusterDist, (*it_edge)->getLoadedLength());
543  }
544  }
545  // remove geometry-like nodes at fringe of the cluster
546  // (they have 1 neighbor in the cluster and at most 1 neighbor outside the cluster)
547  std::set<NBNode*> neighbors;
548  std::set<NBNode*> clusterNeigbors;
549  const SUMOReal pedestrianFringeThreshold = 1.0;
550  for (EdgeVector::const_iterator it_edge = n->getOutgoingEdges().begin(); it_edge != n->getOutgoingEdges().end(); ++it_edge) {
551  NBNode* neighbor = (*it_edge)->getToNode();
552  if (cluster.count(neighbor) == 0) {
553  if ((*it_edge)->getPermissions() != SVC_PEDESTRIAN || clusterDist < pedestrianFringeThreshold) {
554  neighbors.insert(neighbor);
555  }
556  } else {
557  clusterNeigbors.insert(neighbor);
558  }
559  }
560  for (EdgeVector::const_iterator it_edge = n->getIncomingEdges().begin(); it_edge != n->getIncomingEdges().end(); ++it_edge) {
561  NBNode* neighbor = (*it_edge)->getFromNode();
562  if (cluster.count(neighbor) == 0) {
563  if ((*it_edge)->getPermissions() != SVC_PEDESTRIAN || clusterDist < pedestrianFringeThreshold) {
564  neighbors.insert(neighbor);
565  }
566  } else {
567  clusterNeigbors.insert(neighbor);
568  }
569  }
570  if (neighbors.size() <= 1 && clusterNeigbors.size() == 1) {
571  cluster.erase(check);
572  pruneFringe = true; // other nodes could belong to the fringe now
573  }
574  }
575  }
576  // exclude the fromNode of a long edge if the toNode is in the cluster (and they were both added via an alternative path).
577  std::set<NBNode*> toRemove;
578  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end(); ++j) {
579  NBNode* n = *j;
580  const EdgeVector& edges = n->getOutgoingEdges();
581  for (EdgeVector::const_iterator it_edge = edges.begin(); it_edge != edges.end(); ++it_edge) {
582  NBEdge* edge = *it_edge;
583  if (cluster.count(edge->getToNode()) != 0 && edge->getLoadedLength() > maxDist) {
584  //std::cout << "long edge " << edge->getID() << " (" << edge->getLoadedLength() << ", max=" << maxDist << ")\n";
585  toRemove.insert(n);
586  toRemove.insert(edge->getToNode());
587  }
588  }
589  }
590  for (std::set<NBNode*>::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
591  cluster.erase(*j);
592  }
593  if (cluster.size() < 2) {
594  continue;
595  }
596  // check for clusters which are to complex and probably won't work very well
597  // we count the incoming edges of the final junction
598  std::map<std::string, SUMOReal> finalIncomingAngles;
599  std::map<std::string, SUMOReal> finalOutgoingAngles;
600  std::vector<std::string> nodeIDs;
601  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
602  nodeIDs.push_back((*j)->getID());
603  for (EdgeVector::const_iterator it_edge = (*j)->getIncomingEdges().begin(); it_edge != (*j)->getIncomingEdges().end(); ++it_edge) {
604  NBEdge* edge = *it_edge;
605  if (cluster.count(edge->getFromNode()) == 0 && edge->getPermissions() != SVC_PEDESTRIAN) {
606  // incoming edge, does not originate in the cluster
607  finalIncomingAngles[edge->getID()] = edge->getAngleAtNode(edge->getToNode());
608  }
609  }
610  for (EdgeVector::const_iterator it_edge = (*j)->getOutgoingEdges().begin(); it_edge != (*j)->getOutgoingEdges().end(); ++it_edge) {
611  NBEdge* edge = *it_edge;
612  if (cluster.count(edge->getToNode()) == 0 && edge->getPermissions() != SVC_PEDESTRIAN) {
613  // outgoing edge, does not end in the cluster
614  finalOutgoingAngles[edge->getID()] = edge->getAngleAtNode(edge->getFromNode());
615  }
616  }
617 
618  }
619  if (finalIncomingAngles.size() > 4) {
620  std::sort(nodeIDs.begin(), nodeIDs.end());
621  WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (" + toString(finalIncomingAngles.size()) + " incoming edges)");
622  continue;
623  }
624  // check for incoming parallel edges
625  const SUMOReal PARALLEL_INCOMING_THRESHOLD = 10.0;
626  bool foundParallel = false;
627  for (std::map<std::string, SUMOReal>::const_iterator j = finalIncomingAngles.begin(); j != finalIncomingAngles.end() && !foundParallel; ++j) {
628  std::map<std::string, SUMOReal>::const_iterator k = j;
629  for (++k; k != finalIncomingAngles.end() && !foundParallel; ++k) {
630  if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
631  WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (parallel incoming "
632  + j->first + "," + k->first + ")");
633  foundParallel = true;
634  }
635  }
636  }
637  // check for outgoing parallel edges
638  for (std::map<std::string, SUMOReal>::const_iterator j = finalOutgoingAngles.begin(); j != finalOutgoingAngles.end() && !foundParallel; ++j) {
639  std::map<std::string, SUMOReal>::const_iterator k = j;
640  for (++k; k != finalOutgoingAngles.end() && !foundParallel; ++k) {
641  if (fabs(j->second - k->second) < PARALLEL_INCOMING_THRESHOLD) {
642  WRITE_WARNING("Not joining junctions " + joinToStringSorting(nodeIDs, ',') + " because the cluster is too complex (parallel outgoing "
643  + j->first + "," + k->first + ")");
644  foundParallel = true;
645  }
646  }
647  }
648  if (foundParallel) {
649  continue;
650  }
651  // compute all connected components of this cluster
652  // (may be more than 1 if intermediate nodes were removed)
653  NodeClusters components;
654  for (std::set<NBNode*>::iterator j = cluster.begin(); j != cluster.end(); ++j) {
655  // merge all connected components into newComp
656  std::set<NBNode*> newComp;
657  NBNode* current = *j;
658  //std::cout << "checking connectivity for " << current->getID() << "\n";
659  newComp.insert(current);
660  for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end();) {
661  NodeClusters::iterator check = it_comp;
662  //std::cout << " connected with " << toString(*check) << "?\n";
663  bool connected = false;
664  for (std::set<NBNode*>::iterator k = (*check).begin(); k != (*check).end(); ++k) {
665  if (current->getConnectionTo(*k) != 0 || (*k)->getConnectionTo(current) != 0) {
666  //std::cout << "joining with connected component " << toString(*check) << "\n";
667  newComp.insert((*check).begin(), (*check).end());
668  it_comp = components.erase(check);
669  connected = true;
670  break;
671  }
672  }
673  if (!connected) {
674  it_comp++;
675  }
676  }
677  //std::cout << "adding new component " << toString(newComp) << "\n";
678  components.push_back(newComp);
679  }
680  for (NodeClusters::iterator it_comp = components.begin(); it_comp != components.end(); ++it_comp) {
681  if ((*it_comp).size() > 1) {
682  //std::cout << "adding cluster " << toString(*it_comp) << "\n";
683  clusters.push_back(*it_comp);
684  }
685  }
686  }
687  joinNodeClusters(clusters, dc, ec, tlc);
688  return (int)clusters.size();
689 }
690 
691 
692 void
695  for (NodeClusters::iterator i = clusters.begin(); i != clusters.end(); ++i) {
696  std::set<NBNode*> cluster = *i;
697  assert(cluster.size() > 1);
698  Position pos;
699  bool setTL;
700  std::string id;
701  TrafficLightType type;
702  analyzeCluster(cluster, id, pos, setTL, type);
703  if (!insert(id, pos)) {
704  // should not fail
705  WRITE_WARNING("Could not join junctions " + id);
706  continue;
707  }
708  NBNode* newNode = retrieve(id);
709  if (setTL) {
710  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(id, newNode, 0, type);
711  if (!tlc.insert(tlDef)) {
712  // actually, nothing should fail here
713  delete tlDef;
714  throw ProcessError("Could not allocate tls '" + id + "'.");
715  }
716  }
717  // collect edges
718  std::set<NBEdge*> allEdges;
719  for (std::set<NBNode*>::const_iterator j = cluster.begin(); j != cluster.end(); ++j) {
720  const EdgeVector& edges = (*j)->getEdges();
721  allEdges.insert(edges.begin(), edges.end());
722  }
723 
724  // remap and remove edges which are completely within the new intersection
725  for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end();) {
726  NBEdge* e = (*j);
727  NBNode* from = e->getFromNode();
728  NBNode* to = e->getToNode();
729  if (cluster.count(from) > 0 && cluster.count(to) > 0) {
730  for (std::set<NBEdge*>::iterator l = allEdges.begin(); l != allEdges.end(); ++l) {
731  if (e != *l) {
732  (*l)->replaceInConnections(e, e->getConnections());
733  }
734  }
735  ec.extract(dc, e, true);
736  allEdges.erase(j++); // erase does not invalidate the other iterators
737  } else {
738  ++j;
739  }
740  }
741 
742  // remap edges which are incoming / outgoing
743  for (std::set<NBEdge*>::iterator j = allEdges.begin(); j != allEdges.end(); ++j) {
744  NBEdge* e = (*j);
745  std::vector<NBEdge::Connection> conns = e->getConnections();
746  const bool outgoing = cluster.count(e->getFromNode()) > 0;
747  NBNode* from = outgoing ? newNode : e->getFromNode();
748  NBNode* to = outgoing ? e->getToNode() : newNode;
749  e->reinitNodes(from, to);
750  // re-add connections which previously existed and may still valid.
751  // connections to removed edges will be ignored
752  for (std::vector<NBEdge::Connection>::iterator k = conns.begin(); k != conns.end(); ++k) {
753  e->addLane2LaneConnection((*k).fromLane, (*k).toEdge, (*k).toLane, NBEdge::L2L_USER, false, (*k).mayDefinitelyPass);
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  SUMOReal 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 += (SUMOReal)(*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 SUMOReal 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  // !!! not guaranteed to be free
1099  std::string ret = "SUMOGenerated" + toString<int>(size());
1100  assert(retrieve(ret) == 0);
1101  return ret;
1102 }
1103 
1104 
1105 void
1107  for (NodeCont::iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1108  (*i).second->computeNodeShape(mismatchThreshold);
1109  }
1110 }
1111 
1112 
1113 void
1115  int numUnregulatedJunctions = 0;
1116  int numDeadEndJunctions = 0;
1117  int numPriorityJunctions = 0;
1118  int numRightBeforeLeftJunctions = 0;
1119  int numAllWayStopJunctions = 0;
1120  int numZipperJunctions = 0;
1121  int numRailSignals = 0;
1122  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); i++) {
1123  switch ((*i).second->getType()) {
1124  case NODETYPE_NOJUNCTION:
1126  ++numUnregulatedJunctions;
1127  break;
1128  case NODETYPE_DEAD_END:
1129  ++numDeadEndJunctions;
1130  break;
1131  case NODETYPE_PRIORITY:
1136  ++numPriorityJunctions;
1137  break;
1139  ++numRightBeforeLeftJunctions;
1140  break;
1141  case NODETYPE_ALLWAY_STOP:
1142  ++numAllWayStopJunctions;
1143  break;
1144  case NODETYPE_ZIPPER:
1145  ++numZipperJunctions;
1146  break;
1147  case NODETYPE_DISTRICT:
1148  ++numRightBeforeLeftJunctions;
1149  break;
1150  case NODETYPE_UNKNOWN:
1151  break;
1152  case NODETYPE_RAIL_SIGNAL:
1153  ++numRailSignals;
1154  break;
1155  default:
1156  break;
1157  }
1158  }
1159  WRITE_MESSAGE(" Node type statistics:");
1160  WRITE_MESSAGE(" Unregulated junctions : " + toString(numUnregulatedJunctions));
1161  if (numDeadEndJunctions > 0) {
1162  WRITE_MESSAGE(" Dead-end junctions : " + toString(numDeadEndJunctions));
1163  }
1164  WRITE_MESSAGE(" Priority junctions : " + toString(numPriorityJunctions));
1165  WRITE_MESSAGE(" Right-before-left junctions : " + toString(numRightBeforeLeftJunctions));
1166  if (numAllWayStopJunctions > 0) {
1167  WRITE_MESSAGE(" All-way stop junctions : " + toString(numAllWayStopJunctions));
1168  }
1169  if (numZipperJunctions > 0) {
1170  WRITE_MESSAGE(" Zipper-merge junctions : " + toString(numZipperJunctions));
1171  }
1172  if (numRailSignals > 0) {
1173  WRITE_MESSAGE(" Rail signal junctions : " + toString(numRailSignals));
1174  }
1175 }
1176 
1177 
1178 std::vector<std::string>
1180  std::vector<std::string> ret;
1181  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
1182  ret.push_back((*i).first);
1183  }
1184  return ret;
1185 }
1186 
1187 
1188 void
1189 NBNodeCont::rename(NBNode* node, const std::string& newID) {
1190  if (myNodes.count(newID) != 0) {
1191  throw ProcessError("Attempt to rename node using existing id '" + newID + "'");
1192  }
1193  myNodes.erase(node->getID());
1194  node->setID(newID);
1195  myNodes[newID] = node;
1196 }
1197 
1198 
1199 void
1200 NBNodeCont::discardTrafficLights(NBTrafficLightLogicCont& tlc, bool geometryLike, bool guessSignals) {
1201  for (NodeCont::const_iterator i = myNodes.begin(); i != myNodes.end(); ++i) {
1202  NBNode* node = i->second;
1203  if (!geometryLike || node->geometryLike()) {
1204  // make a copy of tldefs
1205  const std::set<NBTrafficLightDefinition*> tldefs = node->getControllingTLS();
1206  if (guessSignals && node->isTLControlled() && node->geometryLike()) {
1207  // record signal location
1208  const EdgeVector& outgoing = node->getOutgoingEdges();
1209  for (EdgeVector::const_iterator it_o = outgoing.begin(); it_o != outgoing.end(); ++it_o) {
1210  (*it_o)->setSignalOffset((*it_o)->getLength());
1211  }
1212  }
1213  for (std::set<NBTrafficLightDefinition*>::const_iterator it = tldefs.begin(); it != tldefs.end(); ++it) {
1214  NBTrafficLightDefinition* tlDef = *it;
1215  node->removeTrafficLight(tlDef);
1216  tlc.extract(tlDef);
1217  }
1218  node->reinit(node->getPosition(), NODETYPE_UNKNOWN);
1219  }
1220  }
1221 }
1222 
1223 
1224 int
1226  IDSupplier idSupplier("", getAllNames());
1227  std::vector<NBNode*> toChange;
1228  for (NodeCont::iterator it = myNodes.begin(); it != myNodes.end(); it++) {
1229  try {
1230  TplConvert::_str2int(it->first);
1231  } catch (NumberFormatException&) {
1232  toChange.push_back(it->second);
1233  }
1234  }
1235  for (std::vector<NBNode*>::iterator it = toChange.begin(); it != toChange.end(); ++it) {
1236  NBNode* node = *it;
1237  myNodes.erase(node->getID());
1238  node->setID(idSupplier.getNext());
1239  myNodes[node->getID()] = node;
1240  }
1241  return (int)toChange.size();
1242 }
1243 
1244 /****************************************************************************/
1245 
std::string getFreeID()
std::set< std::string > myJoinExclusions
Definition: NBNodeCont.h:383
NodeCont myNodes
The map of names to nodes.
Definition: NBNodeCont.h:377
void Insert(const float a_min[2], const float a_max[2], Named *const &a_data)
Insert entry.
Definition: NamedRTree.h:90
void joinSimilarEdges(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins edges connecting the same nodes.
Definition: NBNodeCont.cpp:181
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) ...
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges.
Definition: NBNode.h:240
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:169
is a pedestrian
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:520
static const SUMOReal UNSPECIFIED_SIGNAL_OFFSET
unspecified signal offset
Definition: NBEdge.h:255
void addJoinExclusion(const std::vector< std::string > &ids, bool check=false)
Definition: NBNodeCont.cpp:450
void add(const Position &pos)
Adds the given position to this one.
Definition: Position.h:119
int removeUnwishedNodes(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc, bool removeGeometryNodes)
Removes "unwished" nodes.
Definition: NBNodeCont.cpp:320
A container for traffic light definitions and built programs.
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:266
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:304
std::vector< std::set< std::string > > myJoinedClusters
Definition: NBNodeCont.h:388
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
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:367
A container for districts.
The base class for traffic light logic definitions.
std::pair< NBNode *, SUMOReal > NodeAndDist
Definition: NBNodeCont.h:337
int joinLoadedClusters(NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins loaded junction clusters (see NIXMLNodesHandler)
Definition: NBNodeCont.cpp:484
NamedRTree myRTree
node positions for faster lookup
Definition: NBNodeCont.h:397
int mapToNumericalIDs()
ensure that all node ids are integers
void guessTLs(OptionsCont &oc, NBTrafficLightLogicCont &tlc)
Guesses which junctions or junction clusters shall be controlled by tls.
Definition: NBNodeCont.cpp:839
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
void avoidOverlap()
fix overlap
Definition: NBNodeCont.cpp:390
bool checkIsRemovable() const
Definition: NBNode.cpp:1648
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:97
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:324
void extract(NBTrafficLightDefinition *definition)
Extracts a traffic light definition from myDefinitions but keeps it in myExtracted for eventual * del...
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
Definition: NBNode.cpp:1224
SUMOReal x() const
Returns the x-position.
Definition: Position.h:63
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:39
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
std::string joinToStringSorting(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:204
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:69
void computeLogics(const NBEdgeCont &ec, OptionsCont &oc)
build the list of outgoing edges and lanes
void generateNodeClusters(SUMOReal maxDist, NodeClusters &into) const
Builds node clusters.
Definition: NBNodeCont.cpp:398
A class representing a single district.
Definition: NBDistrict.h:72
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
Definition: NBNode.h:248
SUMOReal getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:472
const std::string & getID() const
Returns the id.
Definition: Named.h:66
void Remove(const float a_min[2], const float a_max[2], Named *const &a_data)
Remove entry.
Definition: NamedRTree.h:101
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:228
#define max(a, b)
Definition: polyfonts.c:65
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:63
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node.
Definition: NBNode.h:318
void computeLanes2Lanes()
divides the incoming lanes on outgoing lanes
int joinJunctions(SUMOReal maxDist, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Joins junctions that are very close together.
Definition: NBNodeCont.cpp:508
~NBNodeCont()
Destructor.
Definition: NBNodeCont.cpp:74
void joinTLS(NBTrafficLightLogicCont &tlc, SUMOReal maxdist)
Builds clusters of tls-controlled junctions and joins the control if possible.
static StringBijection< TrafficLightType > TrafficLightTypes
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:388
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
NBNodeCont()
Constructor.
Definition: NBNodeCont.cpp:69
static int _str2int(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter...
Definition: TplConvert.h:160
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:2498
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, SUMOReal contPos=UNSPECIFIED_CONTPOS, SUMOReal visibility=UNSPECIFIED_VISIBILITY_DISTANCE)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:802
void removeTrafficLights()
Removes all references to traffic lights that control this tls.
Definition: NBNode.cpp:331
const EdgeVector & getEdges() const
Returns all edges which participate in this node.
Definition: NBNode.h:256
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:66
T MIN2(T a, T b)
Definition: StdDefs.h:69
#define POSITION_EPS
Definition: config.h:188
void joinNodeClusters(NodeClusters clusters, NBDistrictCont &dc, NBEdgeCont &ec, NBTrafficLightLogicCont &tlc)
Definition: NBNodeCont.cpp:693
std::set< NBNode * > myExtractedNodes
The extracted nodes which are kept for reference.
Definition: NBNodeCont.h:380
std::vector< std::string > getAllNames() const
get all node names
std::string toString(const T &t, std::streamsize accuracy=OUTPUT_ACCURACY)
Definition: ToString.h:55
The connection was given by the user.
Definition: NBEdge.h:115
SUMOReal getSignalOffset() const
Returns the offset of a traffic signal from the end of this edge.
Definition: NBEdge.h:540
NBEdge * getConnectionTo(NBNode *n) const
Definition: NBNode.cpp:1745
bool shouldBeTLSControlled(const std::set< NBNode * > &c) const
Returns whethe the given node cluster should be controlled by a tls.
Definition: NBNodeCont.cpp:811
void rename(NBNode *node, const std::string &newID)
Renames the node. Throws exception if newID already exists.
std::vector< std::pair< NBEdge *, NBEdge * > > getEdgesToJoin() const
Definition: NBNode.cpp:1699
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:666
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2726
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
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:416
bool isNearDistrict() const
Definition: NBNode.cpp:1756
void setID(const std::string &newID)
resets the id
Definition: Named.h:74
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:247
void addCluster2Join(std::set< std::string > cluster)
add ids of nodes which shall be joined into a single node
Definition: NBNodeCont.cpp:466
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:1118
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
void analyzeCluster(std::set< NBNode * > cluster, std::string &id, Position &pos, bool &hasTLS, TrafficLightType &type)
Definition: NBNodeCont.cpp:776
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:226
std::set< std::string > myJoined
ids found in loaded join clusters used for error checking
Definition: NBNodeCont.h:391
SUMOReal y() const
Returns the y-position.
Definition: Position.h:68
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:336
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:381
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:81
void clear()
void mul(SUMOReal val)
Multiplies both positions with the given value.
Definition: Position.h:99
void append(NBEdge *continuation)
append another edge
Definition: NBEdge.cpp:2451
std::vector< std::set< std::string > > myClusters2Join
Definition: NBNodeCont.h:386
void computeNodeShapes(SUMOReal mismatchThreshold=-1)
Compute the junction shape for this node.
void discardTrafficLights(NBTrafficLightLogicCont &tlc, bool geometryLike, bool guessSignals)
Represents a single node (junction) during network building.
Definition: NBNode.h:74
T get(const std::string &str) const
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.
#define SUMOReal
Definition: config.h:214
bool isNearEnough2BeJoined2(NBEdge *e, SUMOReal threshold) const
Check if edge is near enought to be joined to another edge.
Definition: NBEdge.cpp:2511
std::set< const NBNode * > mySplit
nodes that were created when splitting an edge
Definition: NBNodeCont.h:394
int size() const
Returns the number of known nodes.
Definition: NBNodeCont.h:271
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:110
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:489
void printBuiltNodesStatistics() const
Prints statistics about built nodes.
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
bool extract(NBNode *node, bool remember=false)
Removes the given node but does not delete it.
Definition: NBNodeCont.cpp:151
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
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:201
bool erase(NBNode *node)
Removes the given node, deleting it.
Definition: NBNodeCont.cpp:140
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:803
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:126
bool exists(const std::string &name) const
Returns the information whether the named option is known.
TrafficLightType
SUMOReal getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:463
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1449
void registerJoinedCluster(const std::set< NBNode * > &cluster)
gets all joined clusters (see doc for myClusters2Join)
Definition: NBNodeCont.cpp:766
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:409