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