SUMO - Simulation of Urban MObility
NBAlgorithms.cpp
Go to the documentation of this file.
1 /****************************************************************************/
8 // Algorithms for network computation
9 /****************************************************************************/
10 // SUMO, Simulation of Urban MObility; see http://sumo.dlr.de/
11 // Copyright (C) 2012-2016 DLR (http://www.dlr.de/) and contributors
12 /****************************************************************************/
13 //
14 // This file is part of SUMO.
15 // SUMO is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #ifdef _MSC_VER
27 #include <windows_config.h>
28 #else
29 #include <config.h>
30 #endif
31 
32 #include <sstream>
33 #include <iostream>
34 #include <cassert>
35 #include <algorithm>
37 #include <utils/common/ToString.h>
38 #include "NBEdge.h"
39 #include "NBNodeCont.h"
40 #include "NBTypeCont.h"
41 #include "NBNode.h"
42 #include "NBAlgorithms.h"
43 
44 #ifdef CHECK_MEMORY_LEAKS
45 #include <foreign/nvwa/debug_new.h>
46 #endif // CHECK_MEMORY_LEAKS
47 
48 
49 // ===========================================================================
50 // method definitions
51 // ===========================================================================
52 // ---------------------------------------------------------------------------
53 // NBTurningDirectionsComputer
54 // ---------------------------------------------------------------------------
55 void
57  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
58  computeTurnDirectionsForNode(i->second, warn);
59  }
60 }
61 
62 void
64  const std::vector<NBEdge*>& incoming = node->getIncomingEdges();
65  const std::vector<NBEdge*>& outgoing = node->getOutgoingEdges();
66  // reset turning directions since this may be called multiple times
67  for (std::vector<NBEdge*>::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
68  (*k)->setTurningDestination(0);
69  }
70  std::vector<Combination> combinations;
71  for (std::vector<NBEdge*>::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) {
72  NBEdge* outedge = *j;
73  for (std::vector<NBEdge*>::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
74  NBEdge* e = *k;
75  // @todo: check whether NBHelpers::relAngle is properly defined and whether it should really be used, here
76  const SUMOReal signedAngle = NBHelpers::normRelAngle(e->getAngleAtNode(node), outedge->getAngleAtNode(node));
77  if (signedAngle > 0 && signedAngle < 177 && e->getGeometry().back().distanceTo2D(outedge->getGeometry().front()) < POSITION_EPS) {
78  // backwards curving edges can only be turnaround when there are
79  // non-default endpoints
80  continue;
81  }
82  SUMOReal angle = fabs(signedAngle);
83  // std::cout << "incoming=" << e->getID() << " outgoing=" << outedge->getID() << " relAngle=" << NBHelpers::relAngle(e->getAngleAtNode(node), outedge->getAngleAtNode(node)) << "\n";
84  if (e->getFromNode() == outedge->getToNode() && angle > 120) {
85  // they connect the same nodes; should be the turnaround direction
86  // we'll assign a maximum number
87  //
88  // @todo: indeed, we have observed some pathological intersections
89  // see "294831560" in OSM/adlershof. Here, several edges are connecting
90  // same nodes. We have to do the angle check before...
91  //
92  // @todo: and well, there are some other as well, see plain import
93  // of delphi_muenchen (elmar), intersection "59534191". Not that it would
94  // be realistic in any means; we will warn, here.
95  angle += 360;
96  }
97  if (angle < 160) {
98  continue;
99  }
100  Combination c;
101  c.from = e;
102  c.to = outedge;
103  c.angle = angle;
104  combinations.push_back(c);
105  }
106  }
107  // sort combinations so that the ones with the highest angle are at the begin
108  std::sort(combinations.begin(), combinations.end(), combination_by_angle_sorter());
109  std::set<NBEdge*> seen;
110  for (std::vector<Combination>::const_iterator j = combinations.begin(); j != combinations.end(); ++j) {
111  if (seen.find((*j).from) != seen.end() || seen.find((*j).to) != seen.end()) {
112  // do not regard already set edges
113  if ((*j).angle > 360 && warn) {
114  WRITE_WARNING("Ambiguity in turnarounds computation at junction '" + node->getID() + "'.");
115  warn = false;
116  }
117  continue;
118  }
119  // mark as seen
120  seen.insert((*j).from);
121  seen.insert((*j).to);
122  // set turnaround information
123  bool onlyPossible = (*j).from->getConnections().size() != 0 && !(*j).from->isConnectedTo((*j).to);
124  //std::cout << " setTurningDestination from=" << (*j).from->getID() << " to=" << (*j).to->getID() << " onlyPossible=" << onlyPossible << "\n";
125  (*j).from->setTurningDestination((*j).to, onlyPossible);
126  }
127 }
128 
129 
130 // ---------------------------------------------------------------------------
131 // NBNodesEdgesSorter
132 // ---------------------------------------------------------------------------
133 void
135  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
136  NBNode* const n = i->second;
137  if (n->myAllEdges.size() == 0) {
138  continue;
139  }
140  EdgeVector& allEdges = n->myAllEdges;
141  EdgeVector& incoming = n->myIncomingEdges;
142  EdgeVector& outgoing = n->myOutgoingEdges;
143  std::vector<NBNode::Crossing>& crossings = n->myCrossings;
144  if (!useNodeShape || n->getShape().area() < 1) {
145  // if the area is too small (i.e. for simple-continuation nodes) we better not use it
146  // sort by the angle of the adjoining line segment of the edge geometry
147  // sort the edges
148  std::sort(allEdges.begin(), allEdges.end(), edge_by_junction_angle_sorter(n));
149  std::sort(incoming.begin(), incoming.end(), edge_by_junction_angle_sorter(n));
150  std::sort(outgoing.begin(), outgoing.end(), edge_by_junction_angle_sorter(n));
151  std::vector<NBEdge*>::iterator j;
152  for (j = allEdges.begin(); j != allEdges.end() - 1 && j != allEdges.end(); ++j) {
153  swapWhenReversed(n, j, j + 1);
154  }
155  if (allEdges.size() > 1 && j != allEdges.end()) {
156  swapWhenReversed(n, allEdges.end() - 1, allEdges.begin());
157  }
158  } else {
159  NBEdge* firstOfAll = allEdges.front();
160  NBEdge* firstOfIncoming = incoming.size() > 0 ? incoming.front() : 0;
161  NBEdge* firstOfOutgoing = outgoing.size() > 0 ? outgoing.front() : 0;
162  // sort by the angle between the node shape center and the point where the edge meets the node shape
163  sort(allEdges.begin(), allEdges.end(), NBContHelper::edge_by_angle_to_nodeShapeCentroid_sorter(n));
164  sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_angle_to_nodeShapeCentroid_sorter(n));
165  sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_angle_to_nodeShapeCentroid_sorter(n));
166  // let the first edge remain the first
167  rotate(allEdges.begin(), std::find(allEdges.begin(), allEdges.end(), firstOfAll), allEdges.end());
168  if (firstOfIncoming != 0) {
169  rotate(incoming.begin(), std::find(incoming.begin(), incoming.end(), firstOfIncoming), incoming.end());
170  }
171  if (firstOfOutgoing != 0) {
172  rotate(outgoing.begin(), std::find(outgoing.begin(), outgoing.end(), firstOfOutgoing), outgoing.end());
173  }
174  }
175  // fixing some pathological all edges orderings
176  // if every of the edges a,b,c has a turning edge a',b',c' the all edges ordering should be a,a',b,b',c,c'
177  if (incoming.size() == outgoing.size() && incoming.front() == allEdges.front()) {
178  std::vector<NBEdge*>::const_iterator in, out;
179  std::vector<NBEdge*> allTmp;
180  for (in = incoming.begin(), out = outgoing.begin(); in != incoming.end(); ++in, ++out) {
181  if ((*in)->isTurningDirectionAt(*out)) {
182  allTmp.push_back(*in);
183  allTmp.push_back(*out);
184  } else {
185  break;
186  }
187  }
188  if (allTmp.size() == allEdges.size()) {
189  allEdges = allTmp;
190  }
191  }
192  // sort the crossings
193  std::sort(crossings.begin(), crossings.end(), crossing_by_junction_angle_sorter(n, allEdges));
194  // DEBUG
195  //if (n->getID() == "cluster_492462300_671564296") {
196  // if (crossings.size() > 0) {
197  // std::cout << " crossings at " << n->getID() << "\n";
198  // for (std::vector<NBNode::Crossing>::iterator it = crossings.begin(); it != crossings.end(); ++it) {
199  // std::cout << " " << toString((*it).edges) << "\n";
200  // }
201  // }
202  //}
203  }
204 }
205 
206 
207 void
209  const std::vector<NBEdge*>::iterator& i1,
210  const std::vector<NBEdge*>::iterator& i2) {
211  NBEdge* e1 = *i1;
212  NBEdge* e2 = *i2;
213  // @todo: The difference between "isTurningDirectionAt" and "isTurnaround"
214  // is not nice. Maybe we could get rid of it if we would always mark edges
215  // as turnarounds, even if they do not have to be added, as mentioned in
216  // notes on NBTurningDirectionsComputer::computeTurnDirectionsForNode
217  if (e2->getToNode() == n && e2->isTurningDirectionAt(e1)) {
218  std::swap(*i1, *i2);
219  }
220 }
221 
222 
223 // ---------------------------------------------------------------------------
224 // NBNodeTypeComputer
225 // ---------------------------------------------------------------------------
226 void
228  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
229  NBNode* n = (*i).second;
230  // the type may already be set from the data
231  if (n->myType != NODETYPE_UNKNOWN) {
232  continue;
233  }
234  // check whether the node is a waterway node. Set to unregulated by default
235  bool waterway = true;
236  for (EdgeVector::const_iterator i = n->getEdges().begin(); i != n->getEdges().end(); ++i) {
237  if (!isWaterway((*i)->getPermissions())) {
238  waterway = false;
239  break;
240  }
241  }
242  if (waterway && n->myType == NODETYPE_UNKNOWN) {
244  continue;
245  }
246 
247  // check whether the junction is not a real junction
248  if (n->myIncomingEdges.size() == 1) {
250  continue;
251  }
252  // @todo "isSimpleContinuation" should be revalidated
253  if (n->isSimpleContinuation()) {
255  continue;
256  }
257  // determine the type
259  for (EdgeVector::const_iterator i = n->myIncomingEdges.begin(); i != n->myIncomingEdges.end(); i++) {
260  for (EdgeVector::const_iterator j = i + 1; j != n->myIncomingEdges.end(); j++) {
261  // @todo "getOppositeIncoming" should probably be refactored into something the edge knows
262  if (n->getOppositeIncoming(*j) == *i && n->myIncomingEdges.size() > 2) {
263  continue;
264  }
265  // @todo check against a legal document
266  // @todo figure out when NODETYPE_PRIORITY_STOP is appropriate
267  const SUMOReal s1 = (*i)->getSpeed() * (SUMOReal) 3.6;
268  const SUMOReal s2 = (*j)->getSpeed() * (SUMOReal) 3.6;
269  const int p1 = (*i)->getPriority();
270  const int p2 = (*j)->getPriority();
271  if (fabs(s1 - s2) > (SUMOReal) 9.5 || MAX2(s1, s2) >= (SUMOReal) 49. || p1 != p2) {
272  type = NODETYPE_PRIORITY;
273  break;
274  }
275  }
276  }
277  // save type
278  n->myType = type;
279  }
280 }
281 
282 
283 // ---------------------------------------------------------------------------
284 // NBEdgePriorityComputer
285 // ---------------------------------------------------------------------------
286 void
288  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
289  NBNode* n = (*i).second;
290  // preset all junction's edge priorities to zero
291  for (EdgeVector::iterator j = n->myAllEdges.begin(); j != n->myAllEdges.end(); ++j) {
292  (*j)->setJunctionPriority(n, 0);
293  }
294  // check if the junction is not a real junction
295  if (n->myIncomingEdges.size() == 1 && n->myOutgoingEdges.size() == 1) {
296  continue;
297  }
298  // compute the priorities on junction when needed
300  setPriorityJunctionPriorities(*n);
301  }
302  }
303 }
304 
305 
306 void
308  if (n.myIncomingEdges.size() == 0 || n.myOutgoingEdges.size() == 0) {
309  return;
310  }
311  EdgeVector incoming = n.myIncomingEdges;
312  EdgeVector outgoing = n.myOutgoingEdges;
313  // what we do want to have is to extract the pair of roads that are
314  // the major roads for this junction
315  // let's get the list of incoming edges with the highest priority
316  std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_priority_sorter());
317  EdgeVector bestIncoming;
318  NBEdge* best = incoming[0];
319  while (incoming.size() > 0 && samePriority(best, incoming[0])) {
320  bestIncoming.push_back(*incoming.begin());
321  incoming.erase(incoming.begin());
322  }
323  // now, let's get the list of best outgoing
324  assert(outgoing.size() != 0);
325  sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_priority_sorter());
326  EdgeVector bestOutgoing;
327  best = outgoing[0];
328  while (outgoing.size() > 0 && samePriority(best, outgoing[0])) { //->getPriority()==best->getPriority()) {
329  bestOutgoing.push_back(*outgoing.begin());
330  outgoing.erase(outgoing.begin());
331  }
332  // special case: user input makes mainDirection unambiguous
333  const bool mainDirectionExplicit = (
334  bestIncoming.size() == 1 && n.myIncomingEdges.size() <= 2
335  && (incoming.size() == 0 || bestIncoming[0]->getPriority() > incoming[0]->getPriority())
336  && bestOutgoing.size() == 1 && n.myOutgoingEdges.size() <= 2
337  && (outgoing.size() == 0 || bestOutgoing[0]->getPriority() > outgoing[0]->getPriority())
338  && !bestIncoming[0]->isTurningDirectionAt(bestOutgoing[0]));
339  // now, let's compute for each of the best incoming edges
340  // the incoming which is most opposite
341  // the outgoing which is most opposite
342  EdgeVector::iterator i;
343  std::map<NBEdge*, NBEdge*> counterIncomingEdges;
344  std::map<NBEdge*, NBEdge*> counterOutgoingEdges;
345  incoming = n.myIncomingEdges;
346  outgoing = n.myOutgoingEdges;
347  for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) {
348  std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n));
349  counterIncomingEdges[*i] = *incoming.begin();
350  std::sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n));
351  counterOutgoingEdges[*i] = *outgoing.begin();
352  }
353  // ok, let's try
354  // 1) there is one best incoming road
355  if (bestIncoming.size() == 1) {
356  // let's mark this road as the best
357  NBEdge* best1 = extractAndMarkFirst(n, bestIncoming);
358  if (!mainDirectionExplicit && counterIncomingEdges.find(best1) != counterIncomingEdges.end()) {
359  // ok, look, what we want is the opposit of the straight continuation edge
360  // but, what if such an edge does not exist? By now, we'll determine it
361  // geometrically
362  NBEdge* s = counterIncomingEdges.find(best1)->second;
363  if (GeomHelper::getMinAngleDiff(best1->getAngleAtNode(&n), s->getAngleAtNode(&n)) > 180 - 45) {
364  s->setJunctionPriority(&n, 1);
365  }
366  }
367  assert(bestOutgoing.size() != 0);
368  // mark the best outgoing as the continuation
369  sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(best1));
370  // assign extra priority if the priorities are unambiguous (regardless of geometry)
371  best1 = extractAndMarkFirst(n, bestOutgoing);
372  if (!mainDirectionExplicit && counterOutgoingEdges.find(best1) != counterOutgoingEdges.end()) {
373  NBEdge* s = counterOutgoingEdges.find(best1)->second;
374  if (GeomHelper::getMinAngleDiff(best1->getAngleAtNode(&n), s->getAngleAtNode(&n)) > 180 - 45) {
375  s->setJunctionPriority(&n, 1);
376  }
377  }
378  return;
379  }
380 
381  // ok, what we want to do in this case is to determine which incoming
382  // has the best continuation...
383  // This means, when several incoming roads have the same priority,
384  // we want a (any) straight connection to be more priorised than a turning
385  SUMOReal bestAngle = 0;
386  NBEdge* bestFirst = 0;
387  NBEdge* bestSecond = 0;
388  bool hadBest = false;
389  for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) {
390  EdgeVector::iterator j;
391  NBEdge* t1 = *i;
392  SUMOReal angle1 = t1->getAngleAtNode(&n) + 180;
393  if (angle1 >= 360) {
394  angle1 -= 360;
395  }
396  for (j = i + 1; j != bestIncoming.end(); ++j) {
397  NBEdge* t2 = *j;
398  SUMOReal angle2 = t2->getAngleAtNode(&n) + 180;
399  if (angle2 >= 360) {
400  angle2 -= 360;
401  }
402  SUMOReal angle = GeomHelper::getMinAngleDiff(angle1, angle2);
403  if (!hadBest || angle > bestAngle) {
404  bestAngle = angle;
405  bestFirst = *i;
406  bestSecond = *j;
407  hadBest = true;
408  }
409  }
410  }
411  bestFirst->setJunctionPriority(&n, 1);
412  sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestFirst));
413  if (bestOutgoing.size() != 0) {
414  extractAndMarkFirst(n, bestOutgoing);
415  }
416  bestSecond->setJunctionPriority(&n, 1);
417  sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestSecond));
418  if (bestOutgoing.size() != 0) {
419  extractAndMarkFirst(n, bestOutgoing);
420  }
421 }
422 
423 
424 NBEdge*
425 NBEdgePriorityComputer::extractAndMarkFirst(NBNode& n, std::vector<NBEdge*>& s, int prio) {
426  if (s.size() == 0) {
427  return 0;
428  }
429  NBEdge* ret = s.front();
430  s.erase(s.begin());
431  ret->setJunctionPriority(&n, prio);
432  return ret;
433 }
434 
435 
436 bool
437 NBEdgePriorityComputer::samePriority(const NBEdge* const e1, const NBEdge* const e2) {
438  if (e1 == e2) {
439  return true;
440  }
441  if (e1->getPriority() != e2->getPriority()) {
442  return false;
443  }
444  if ((int) e1->getSpeed() != (int) e2->getSpeed()) {
445  return false;
446  }
447  return (int) e1->getNumLanes() == (int) e2->getNumLanes();
448 }
449 
450 
452  // reorder based on getAngleAtNodeToCenter
453  myOrdering = ordering;
454  sort(myOrdering.begin(), myOrdering.end(), NBContHelper::edge_by_angle_to_nodeShapeCentroid_sorter(node));
455  // let the first edge remain the first
456  rotate(myOrdering.begin(), std::find(myOrdering.begin(), myOrdering.end(), ordering.front()), myOrdering.end());
457 }
458 
459 
460 /****************************************************************************/
461 
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges.
Definition: NBNode.h:240
std::vector< Crossing > myCrossings
Vector of crossings.
Definition: NBNode.h:751
Sorts incoming and outgoing edges clockwise around the given node.
Definition: NBAlgorithms.h:161
Sorts crossings by minimum clockwise clockwise edge angle. Use the ordering found in myAllEdges of th...
Definition: NBAlgorithms.h:120
NBEdge * getOppositeIncoming(NBEdge *e) const
Definition: NBNode.cpp:1152
SumoXMLNodeType myType
The type of the junction.
Definition: NBNode.h:757
static SUMOReal normRelAngle(SUMOReal angle1, SUMOReal angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
Definition: NBHelpers.cpp:69
The representation of a single edge during network building.
Definition: NBEdge.h:70
Class to sort edges by their angle in relation to the given edge.
Definition: NBContHelper.h:148
static void swapWhenReversed(const NBNode *const n, const std::vector< NBEdge * >::iterator &i1, const std::vector< NBEdge * >::iterator &i2)
Assures correct order for same-angle opposite-direction edges.
T MAX2(T a, T b)
Definition: StdDefs.h:75
static void sortNodesEdges(NBNodeCont &nc, bool useNodeShape=false)
Sorts a node&#39;s edges clockwise regarding driving direction.
Stores the information about the angle between an incoming ("from") and an outgoing ("to") edge...
Definition: NBAlgorithms.h:75
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges.
Definition: NBNode.h:248
const std::string & getID() const
Returns the id.
Definition: Named.h:65
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
Definition: NBNode.h:748
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:353
bool isSimpleContinuation() const
Definition: NBNode.cpp:444
static void computeEdgePriorities(NBNodeCont &nc)
Computes edge priorities within a node.
bool isWaterway(SVCPermissions permissions)
Returns whether an edge with the given permission is a waterway edge.
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:345
static NBEdge * extractAndMarkFirst(NBNode &n, std::vector< NBEdge * > &s, int prio=1)
Sets the priorites in case of a priority junction.
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:1867
const EdgeVector & getEdges() const
Returns all edges which participate in this node.
Definition: NBNode.h:256
#define POSITION_EPS
Definition: config.h:187
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:135
crossing_by_junction_angle_sorter(const NBNode *node, const EdgeVector &ordering)
const PositionVector & getShape() const
retrieve the junction shape
Definition: NBNode.cpp:1638
EdgeVector myIncomingEdges
Vector of incoming edges.
Definition: NBNode.h:742
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any) ...
static bool samePriority(const NBEdge *const e1, const NBEdge *const e2)
Returns whether both edges have the same priority.
EdgeVector myOutgoingEdges
Vector of outgoing edges.
Definition: NBNode.h:745
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:369
static void computeNodeTypes(NBNodeCont &nc)
Computes node types.
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:41
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:523
static SUMOReal getMinAngleDiff(SUMOReal angle1, SUMOReal angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:172
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
Definition: NBEdge.cpp:1277
Represents a single node (junction) during network building.
Definition: NBNode.h:74
static void computeTurnDirections(NBNodeCont &nc, bool warn=true)
Computes turnaround destinations for all edges (if exist)
#define SUMOReal
Definition: config.h:213
Sorts "Combination"s by decreasing angle.
Definition: NBAlgorithms.h:85
static void setPriorityJunctionPriorities(NBNode &n)
Sets the priorites in case of a priority junction.
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:431
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
SUMOReal area() const
Returns the area (0 for non-closed)
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:127
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1287
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:361