Eclipse SUMO - Simulation of Urban MObility
NBAlgorithms.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2012-2022 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
19 // Algorithms for network computation
20 /****************************************************************************/
21 #include <config.h>
22 
23 #include <sstream>
24 #include <iostream>
25 #include <cassert>
26 #include <algorithm>
28 #include <utils/common/ToString.h>
30 #include "NBEdge.h"
31 #include "NBOwnTLDef.h"
33 #include "NBNodeCont.h"
34 #include "NBTypeCont.h"
35 #include "NBNode.h"
36 #include "NBAlgorithms.h"
37 
38 
39 //#define DEBUG_SETPRIORITIES
40 #define DEBUGCOND (n.getID() == "C")
41 
42 // ===========================================================================
43 // method definitions
44 // ===========================================================================
45 // ---------------------------------------------------------------------------
46 // NBTurningDirectionsComputer
47 // ---------------------------------------------------------------------------
48 void
50  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
51  computeTurnDirectionsForNode(i->second, warn);
52  }
53 }
54 
55 void
57  const std::vector<NBEdge*>& incoming = node->getIncomingEdges();
58  const std::vector<NBEdge*>& outgoing = node->getOutgoingEdges();
59  // reset turning directions since this may be called multiple times
60  for (std::vector<NBEdge*>::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
61  (*k)->setTurningDestination(nullptr);
62  }
63  std::vector<Combination> combinations;
64  const bool geometryLike = node->geometryLike();
65  for (std::vector<NBEdge*>::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) {
66  NBEdge* outedge = *j;
67  for (std::vector<NBEdge*>::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
68  NBEdge* e = *k;
69  // @todo: check whether NBHelpers::relAngle is properly defined and whether it should really be used, here
70  const double signedAngle = NBHelpers::normRelAngle(e->getAngleAtNode(node), outedge->getAngleAtNode(node));
71  if (signedAngle > 0 && signedAngle < 177 && e->getGeometry().back().distanceTo2D(outedge->getGeometry().front()) < POSITION_EPS) {
72  // backwards curving edges can only be turnaround when there are
73  // non-default endpoints
74  continue;
75  }
76  double angle = fabs(signedAngle);
77  // std::cout << "incoming=" << e->getID() << " outgoing=" << outedge->getID() << " relAngle=" << NBHelpers::relAngle(e->getAngleAtNode(node), outedge->getAngleAtNode(node)) << "\n";
78  const bool badPermissions = ((outedge->getPermissions() & e->getPermissions() & ~SVC_PEDESTRIAN) == 0
79  && !geometryLike
80  && outedge->getPermissions() != e->getPermissions());
81  if (e->getFromNode() == outedge->getToNode()
82  && (angle > 120 || e->getFromNode()->getPosition() == e->getToNode()->getPosition())
83  && !badPermissions) {
84  // they connect the same nodes; should be the turnaround direction
85  // we'll assign a maximum number
86  //
87  // @todo: indeed, we have observed some pathological intersections
88  // see "294831560" in OSM/adlershof. Here, several edges are connecting
89  // same nodes. We have to do the angle check before...
90  //
91  // @todo: and well, there are some other as well, see plain import
92  // of delphi_muenchen (elmar), intersection "59534191". Not that it would
93  // be realistic in any means; we will warn, here.
94  angle += 360;
95  }
96  if (angle < 160) {
97  continue;
98  }
99  if (badPermissions) {
100  // penalty
101  angle -= 90;
102  }
103  Combination c;
104  c.from = e;
105  c.to = outedge;
106  c.angle = angle;
107  combinations.push_back(c);
108  }
109  }
110  // sort combinations so that the ones with the highest angle are at the begin
111  std::sort(combinations.begin(), combinations.end(), combination_by_angle_sorter());
112  std::set<NBEdge*> seen;
113  //std::cout << "check combinations at " << node->getID() << "\n";
114  for (std::vector<Combination>::const_iterator j = combinations.begin(); j != combinations.end(); ++j) {
115  //std::cout << " from=" << (*j).from->getID() << " to=" << (*j).to->getID() << " a=" << (*j).angle << "\n";
116  if (seen.find((*j).from) != seen.end() || seen.find((*j).to) != seen.end()) {
117  // do not regard already set edges
118  if ((*j).angle > 360 && warn) {
119  WRITE_WARNINGF("Ambiguity in turnarounds computation at junction '%'.", node->getID());
120  //std::cout << " already seen: " << toString(seen) << "\n";
121  warn = false;
122  }
123  continue;
124  }
125  // mark as seen
126  seen.insert((*j).from);
127  seen.insert((*j).to);
128  // set turnaround information
129  bool onlyPossible = (*j).from->getConnections().size() != 0 && !(*j).from->isConnectedTo((*j).to);
130  //std::cout << " setTurningDestination from=" << (*j).from->getID() << " to=" << (*j).to->getID() << " onlyPossible=" << onlyPossible << "\n";
131  (*j).from->setTurningDestination((*j).to, onlyPossible);
132  }
133 }
134 
135 
136 // ---------------------------------------------------------------------------
137 // NBNodesEdgesSorter
138 // ---------------------------------------------------------------------------
139 void
141  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
142  i->second->sortEdges(useNodeShape);
143  }
144 }
145 
146 
147 void
149  const std::vector<NBEdge*>::iterator& i1,
150  const std::vector<NBEdge*>::iterator& i2) {
151  NBEdge* e1 = *i1;
152  NBEdge* e2 = *i2;
153  // @todo: The difference between "isTurningDirectionAt" and "isTurnaround"
154  // is not nice. Maybe we could get rid of it if we would always mark edges
155  // as turnarounds, even if they do not have to be added, as mentioned in
156  // notes on NBTurningDirectionsComputer::computeTurnDirectionsForNode
157  if (e2->getToNode() == n && e2->isTurningDirectionAt(e1)) {
158  std::swap(*i1, *i2);
159  }
160 }
161 
162 
163 // ---------------------------------------------------------------------------
164 // NBNodeTypeComputer
165 // ---------------------------------------------------------------------------
166 void
168  validateRailCrossings(nc, tlc);
169  const OptionsCont& oc = OptionsCont::getOptions();
170  const double rightBeforeLeftSpeed = oc.getFloat("junctions.right-before-left.speed-threshold");
171  for (const auto& nodeIt : nc) {
172  NBNode* const n = nodeIt.second;
173  // the type may already be set from the data
175  n->myTypeWasGuessed = false;
176  continue;
177  }
178  // check whether the node was set to be unregulated by the user
179  if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", n->getID())
180  || (oc.getBool("keep-nodes-unregulated.district-nodes") && (n->isNearDistrict() || n->isDistrict()))) {
182  continue;
183  }
184  // check whether the node is a waterway node. Set to unregulated by default
185  bool waterway = true;
186  for (NBEdge* e : n->getEdges()) {
187  if (!isWaterway(e->getPermissions())) {
188  waterway = false;
189  break;
190  }
191  }
192  if (waterway && (n->myType == SumoXMLNodeType::UNKNOWN || n->myType == SumoXMLNodeType::DEAD_END)) {
194  continue;
195  }
196 
197  // check whether the junction is not a real junction
198  if (n->myIncomingEdges.size() == 1) {
200  continue;
201  }
202  // @todo "isSimpleContinuation" should be revalidated
203  if (n->isSimpleContinuation()) {
205  continue;
206  }
207  if (isRailwayNode(n)) {
208  // priority instead of unregulated to ensure that collisions can be detected
210  continue;
211  }
212  // determine the type
214  for (EdgeVector::const_iterator i = n->myIncomingEdges.begin(); i != n->myIncomingEdges.end(); i++) {
215  for (EdgeVector::const_iterator j = i + 1; j != n->myIncomingEdges.end(); j++) {
216  // @todo "getOppositeIncoming" should probably be refactored into something the edge knows
217  if (n->getOppositeIncoming(*j) == *i && n->myIncomingEdges.size() > 2) {
218  continue;
219  }
220  // @todo check against a legal document
221  // @todo figure out when SumoXMLNodeType::PRIORITY_STOP is appropriate
222  const double s1 = (*i)->getSpeed();
223  const double s2 = (*j)->getSpeed();
224  const int p1 = (*i)->getPriority();
225  const int p2 = (*j)->getPriority();
226  if (fabs(s1 - s2) > (9.5 / 3.6) || MAX2(s1, s2) >= rightBeforeLeftSpeed || p1 != p2) {
228  break;
229  }
230  }
231  }
232  // save type
233  n->myType = type;
234  n->myTypeWasGuessed = true;
235  }
236 }
237 
238 
239 void
241  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
242  NBNode* n = (*i).second;
244  // check if it really is a rail crossing
245  int numRailway = 0;
246  int numNonRailway = 0;
247  int numNonRailwayNonPed = 0;
248  for (NBEdge* e : n->getIncomingEdges()) {
249  if ((e->getPermissions() & ~SVC_RAIL_CLASSES) != 0) {
250  numNonRailway++;
251  if (e->getPermissions() != SVC_PEDESTRIAN) {
252  numNonRailwayNonPed++;
253  }
254  } else if ((e->getPermissions() & SVC_RAIL_CLASSES) != 0) {
255  numRailway++;
256  }
257  }
258  for (NBEdge* e : n->getOutgoingEdges()) {
259  if (e->getPermissions() == SVC_PEDESTRIAN) {
260  numNonRailway++;
261  }
262  }
263  if (numNonRailway == 0 || numRailway == 0) {
264  // not a crossing (maybe unregulated or rail_signal)
266  } else if (numNonRailwayNonPed > 2) {
267  // does not look like a rail crossing (roads in conflict). maybe a traffic light?
268  WRITE_WARNINGF("Converting invalid rail_crossing to traffic_light at junction '%'.", n->getID());
270  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(n->getID(), n, 0, type);
272  if (!tlc.insert(tlDef)) {
273  // actually, nothing should fail here
274  n->removeTrafficLight(tlDef);
276  delete tlDef;
277  WRITE_WARNINGF("Could not allocate tls '%'.", n->getID());
278  }
279  }
280  }
281  }
282 }
283 
284 
285 bool
287  bool hasRailway = false;
288  for (NBEdge* e : n->getIncomingEdges()) {
289  if ((e->getPermissions() & ~SVC_RAIL_CLASSES) != 0) {
290  return false;
291  } else if ((e->getPermissions() & SVC_RAIL_CLASSES) != 0) {
292  hasRailway = true;
293  }
294  }
295  return hasRailway;
296 }
297 
298 // ---------------------------------------------------------------------------
299 // NBEdgePriorityComputer
300 // ---------------------------------------------------------------------------
301 void
303  for (const auto& node : nc) {
304  // preset all junction's edge priorities to zero
305  for (NBEdge* const edge : node.second->myAllEdges) {
306  edge->setJunctionPriority(node.second, NBEdge::JunctionPriority::MINOR_ROAD);
307  }
308  node.second->markBentPriority(false);
309  // check if the junction is not a real junction
310  if (node.second->myIncomingEdges.size() == 1 && node.second->myOutgoingEdges.size() == 1) {
311  continue;
312  }
313  // compute the priorities on junction when needed
314  if (node.second->getType() != SumoXMLNodeType::RIGHT_BEFORE_LEFT && node.second->getType() != SumoXMLNodeType::ALLWAY_STOP && node.second->getType() != SumoXMLNodeType::NOJUNCTION) {
315  if (node.second->getRightOfWay() == RightOfWay::EDGEPRIORITY) {
316  for (NBEdge* e : node.second->getIncomingEdges()) {
317  e->setJunctionPriority(node.second, e->getPriority());
318  }
319  } else {
320  setPriorityJunctionPriorities(*node.second);
321  }
322  }
323  }
324 }
325 
326 
327 void
329  if (n.myIncomingEdges.size() == 0 || n.myOutgoingEdges.size() == 0) {
330  return;
331  }
332  int minPrio = std::numeric_limits<int>::max();
333  int maxPrio = -std::numeric_limits<int>::max();
334  int maxNumLanes = -std::numeric_limits<int>::max();
335  double maxSpeed = -std::numeric_limits<double>::max();
336  if (forceStraight) {
337  // called a second time, preset all junction's edge priorities to zero
338  for (NBEdge* const edge : n.myAllEdges) {
339  edge->setJunctionPriority(&n, NBEdge::JunctionPriority::MINOR_ROAD);
340  minPrio = MIN2(minPrio, edge->getPriority());
341  maxPrio = MAX2(maxPrio, edge->getPriority());
342  maxNumLanes = MAX2(maxNumLanes, edge->getNumLanes());
343  maxSpeed = MAX2(maxSpeed, edge->getSpeed());
344  }
345  }
346  EdgeVector incoming = n.myIncomingEdges;
347  EdgeVector outgoing = n.myOutgoingEdges;
348  // what we do want to have is to extract the pair of roads that are
349  // the major roads for this junction
350  // let's get the list of incoming edges with the highest priority
351  std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_priority_sorter());
352  EdgeVector bestIncoming;
353  NBEdge* bestIn = incoming[0];
354  while (incoming.size() > 0 && (forceStraight || samePriority(bestIn, incoming[0]))) {
355  bestIncoming.push_back(*incoming.begin());
356  incoming.erase(incoming.begin());
357  }
358  // now, let's get the list of best outgoing
359  assert(outgoing.size() != 0);
360  sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_priority_sorter());
361  EdgeVector bestOutgoing;
362  const NBEdge* const firstOut = outgoing[0];
363  while (outgoing.size() > 0 && (forceStraight || samePriority(firstOut, outgoing[0]))) { //->getPriority()==best->getPriority())
364  bestOutgoing.push_back(*outgoing.begin());
365  outgoing.erase(outgoing.begin());
366  }
367  // special case: user input makes mainDirection unambiguous
368  const bool mainDirectionExplicit = (
369  bestIncoming.size() == 1 && n.myIncomingEdges.size() <= 2
370  && (incoming.size() == 0 || bestIncoming[0]->getPriority() > incoming[0]->getPriority())
371  && bestOutgoing.size() == 1 && n.myOutgoingEdges.size() <= 2
372  && (outgoing.size() == 0 || bestOutgoing[0]->getPriority() > outgoing[0]->getPriority())
373  && !bestIncoming[0]->isTurningDirectionAt(bestOutgoing[0]));
374  // now, let's compute for each of the best incoming edges
375  // the incoming which is most opposite
376  // the outgoing which is most opposite
377  EdgeVector::iterator i;
378  std::map<NBEdge*, NBEdge*> counterIncomingEdges;
379  std::map<NBEdge*, NBEdge*> counterOutgoingEdges;
380  incoming = n.myIncomingEdges;
381  outgoing = n.myOutgoingEdges;
382  for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) {
383  std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n, !forceStraight));
384  counterIncomingEdges[*i] = *incoming.begin();
385  std::sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n, !forceStraight));
386  counterOutgoingEdges[*i] = *outgoing.begin();
387  }
388 #ifdef DEBUG_SETPRIORITIES
389  if (DEBUGCOND) {
390  std::map<std::string, std::string> tmp1;
391  for (auto item : counterIncomingEdges) {
392  tmp1[item.first->getID()] = item.second->getID();
393  }
394  std::map<std::string, std::string> tmp2;
395  for (auto item : counterOutgoingEdges) {
396  tmp2[item.first->getID()] = item.second->getID();
397  }
398  std::cout << "n=" << n.getID() << " bestIn=" << bestIn->getID() << " bestOut=" << bestOut->getID()
399  << " counterBest=" << counterIncomingEdges.find(bestIncoming[0])->second->getID()
400  << " mainExplicit=" << mainDirectionExplicit
401  << " forceStraight=" << forceStraight
402  << "\n bestIncoming=" << toString(bestIncoming) << " allIncoming=" << toString(incoming)
403  << "\n bestOutgoing=" << toString(bestOutgoing) << " allOutgoing=" << toString(outgoing)
404  << "\n counterIncomingEdges=" << toString(tmp1)
405  << "\n counterOutgoingEdges=" << toString(tmp2)
406  << "\n";
407  }
408 #endif
409  // at a tls junction we must prevent an underlying bent-priority layout
410  // because that would lead to invalid right-of-way rules for an oncoming
411  // tls layout (but not vice versa). See #7764
412  const bool hasTLS = n.isTLControlled();
413  // ok, let's try
414  // 1) there is one best incoming road
415  if (bestIncoming.size() == 1) {
416  // let's mark this road as the best
417  NBEdge* best1 = extractAndMarkFirst(n, bestIncoming);
418  if (!mainDirectionExplicit && counterIncomingEdges.find(best1) != counterIncomingEdges.end()) {
419  // ok, look, what we want is the opposit of the straight continuation edge
420  // but, what if such an edge does not exist? By now, we'll determine it
421  // geometrically
422  NBEdge* s = counterIncomingEdges.find(best1)->second;
423  const double minAngleDiff = GeomHelper::getMinAngleDiff(best1->getAngleAtNode(&n), s->getAngleAtNode(&n));
424  if (minAngleDiff > 180 - 45
425  || (minAngleDiff > 75 && s->getPriority() == best1->getPriority() && hasDifferentPriorities(incoming, best1))) {
427  }
428  }
429  markBestParallel(n, best1, nullptr);
430  assert(bestOutgoing.size() != 0);
431  // mark the best outgoing as the continuation
432  sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(best1));
433  // assign extra priority if the priorities are unambiguous (regardless of geometry)
434  NBEdge* bestOut = extractAndMarkFirst(n, bestOutgoing);
435  if (!mainDirectionExplicit && counterOutgoingEdges.find(bestOut) != counterOutgoingEdges.end()) {
436  NBEdge* s = counterOutgoingEdges.find(bestOut)->second;
437  if (GeomHelper::getMinAngleDiff(bestOut->getAngleAtNode(&n), s->getAngleAtNode(&n)) > 180 - 45) {
438  s->setJunctionPriority(&n, 1);
439  }
440  }
441  const bool isBent = n.getDirection(best1, bestOut) != LinkDirection::STRAIGHT;
442 #ifdef DEBUG_SETPRIORITIES
443  if (DEBUGCOND) {
444  std::cout << " best1=" << best1->getID() << " bestOut=" << bestOut->getID() << " bestOutgoing=" << toString(bestOutgoing) << " mainDirectionExplicit=" << mainDirectionExplicit << " isBent=" << isBent << "\n";
445  }
446 #endif
447  if (isBent && hasTLS && !forceStraight) {
448  // redo but force straight computation
450  } else {
451  n.markBentPriority(isBent);
452  }
453  return;
454  }
455 
456  // ok, what we want to do in this case is to determine which incoming
457  // has the best continuation...
458  // This means, when several incoming roads have the same priority,
459  // we want a (any) straight connection to be more priorised than a turning
460  double bestAngle = -1;
461  NBEdge* bestFirst = nullptr;
462  NBEdge* bestSecond = nullptr;
463  for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) {
464  EdgeVector::iterator j;
465  NBEdge* t1 = *i;
466  double angle1 = t1->getAngleAtNode(&n) + 180;
467  if (angle1 >= 360) {
468  angle1 -= 360;
469  }
470  for (j = i + 1; j != bestIncoming.end(); ++j) {
471  NBEdge* t2 = *j;
472  double angle2 = t2->getAngleAtNode(&n) + 180;
473  if (angle2 >= 360) {
474  angle2 -= 360;
475  }
476  double score = forceStraight ? getScore(t1, t2, minPrio, maxPrio, maxNumLanes, maxSpeed) : 0;
477  double angle = GeomHelper::getMinAngleDiff(angle1, angle2) + 45 * score;
478  if (angle > bestAngle) {
479  //if (forceStraight) std::cout << " node=" << n.getID() << " t1=" << t1->getID() << " t2=" << t2->getID() << " angle=" << angle << " bestAngle=" << bestAngle << " score=" << score << " minPrio=" << minPrio << " maxPrio=" << maxPrio << "\n";
480  bestAngle = MAX2(angle, bestAngle);
481  bestFirst = *i;
482  bestSecond = *j;
483  }
484  }
485  }
486  bestFirst->setJunctionPriority(&n, 1);
487  sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestFirst));
488 #ifdef DEBUG_SETPRIORITIES
489  if (DEBUGCOND) {
490  std::cout << " bestFirst=" << bestFirst->getID() << " bestOutgoingFirst=" << toString(bestOutgoing) << "\n";
491  }
492 #endif
493  if (bestOutgoing.size() != 0) {
494  extractAndMarkFirst(n, bestOutgoing);
495  }
496  bestSecond->setJunctionPriority(&n, 1);
497  sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestSecond));
498 #ifdef DEBUG_SETPRIORITIES
499  if (DEBUGCOND) {
500  std::cout << " bestSecond=" << bestSecond->getID() << " bestOutgoingSecond=" << toString(bestOutgoing) << "\n";
501  }
502 #endif
503  if (bestOutgoing.size() != 0) {
504  extractAndMarkFirst(n, bestOutgoing);
505  }
506  const bool isBent = GeomHelper::getMinAngleDiff(bestFirst->getAngleAtNode(&n), bestSecond->getAngleAtNode(&n)) < 135;
507  if (isBent && hasTLS && !forceStraight) {
508  // redo but force straight computation
510  } else {
511  n.markBentPriority(isBent);
512  markBestParallel(n, bestFirst, bestSecond);
513  }
514 }
515 
516 double
517 NBEdgePriorityComputer::getScore(const NBEdge* e1, const NBEdge* e2, int minPrio, int maxPrio, int maxNumLanes, double maxSpeed) {
518  // normalize priorities to [0.1,1]
519  double normPrio1 = 1;
520  double normPrio2 = 1;
521  if (minPrio != maxPrio) {
522  normPrio1 = ((e1->getPriority() - minPrio) / (maxPrio - minPrio)) * 0.9 + 0.1;
523  normPrio2 = ((e2->getPriority() - minPrio) / (maxPrio - minPrio)) * 0.9 + 0.1;
524  }
525  return (normPrio1
526  * e1->getNumLanes() / maxNumLanes
527  * e1->getSpeed() / maxSpeed
528  * normPrio2
529  * e2->getNumLanes() / maxNumLanes
530  * e2->getSpeed() / maxSpeed);
531 }
532 
533 void
534 NBEdgePriorityComputer::markBestParallel(const NBNode& n, NBEdge* bestFirst, NBEdge* bestSecond) {
535  // edges running parallel to the main direction should also be prioritised
536  const double a1 = bestFirst->getAngleAtNode(&n);
537  const double a2 = bestSecond == nullptr ? a1 : bestSecond->getAngleAtNode(&n);
538  SVCPermissions p1 = bestFirst->getPermissions();
539  SVCPermissions p2 = bestSecond == nullptr ? p1 : bestSecond->getPermissions();
540  for (NBEdge* e : n.getIncomingEdges()) {
541  // @note: this rule might also apply if there are common permissions but
542  // then we would not further rules to resolve the priority between the best edge and its parallel edge
543  SVCPermissions perm = e->getPermissions();
544  if (((GeomHelper::getMinAngleDiff(e->getAngleAtNode(&n), a1) < 10
545  || GeomHelper::getMinAngleDiff(e->getAngleAtNode(&n), a2) < 10))
546  && (p1 & perm) == 0 && (p2 & perm) == 0) {
547  e->setJunctionPriority(&n, 1);
548  }
549  }
550 }
551 
552 
553 NBEdge*
554 NBEdgePriorityComputer::extractAndMarkFirst(NBNode& n, std::vector<NBEdge*>& s, int prio) {
555  if (s.size() == 0) {
556  return nullptr;
557  }
558  NBEdge* ret = s.front();
559  s.erase(s.begin());
560  ret->setJunctionPriority(&n, prio);
561  return ret;
562 }
563 
564 
565 bool
566 NBEdgePriorityComputer::samePriority(const NBEdge* const e1, const NBEdge* const e2) {
567  if (e1 == e2) {
568  return true;
569  }
570  if (e1->getPriority() != e2->getPriority()) {
571  return false;
572  }
573  if ((int) e1->getSpeed() != (int) e2->getSpeed()) {
574  return false;
575  }
576  return (int) e1->getNumLanes() == (int) e2->getNumLanes();
577 }
578 
579 
580 bool
582  if (edges.size() < 2) {
583  return false;
584  }
585  int prio = edges[0] == excluded ? edges[1]->getPriority() : edges[0]->getPriority();
586  for (auto e : edges) {
587  if (e != excluded && e->getPriority() != prio) {
588  return true;
589  }
590  }
591  return false;
592 }
593 
594 
596  // reorder based on getAngleAtNodeToCenter
597  myOrdering = ordering;
599  // let the first edge remain the first
600  rotate(myOrdering.begin(), std::find(myOrdering.begin(), myOrdering.end(), ordering.front()), myOrdering.end());
601 }
602 
603 
604 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:281
#define DEBUGCOND
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
bool isWaterway(SVCPermissions permissions)
Returns whether an edge with the given permission is a waterway edge.
@ SVC_RAIL_CLASSES
classes which drive on tracks
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
TrafficLightType
@ STRAIGHT
The link is a straight direction.
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
T MIN2(T a, T b)
Definition: StdDefs.h:74
T MAX2(T a, T b)
Definition: StdDefs.h:80
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static double getMinAngleDiff(double angle1, double angle2)
Returns the minimum distance (clockwise/counter-clockwise) between both angles.
Definition: GeomHelper.cpp:173
Class to sort edges by their angle in relation to the given edge.
Definition: NBContHelper.h:142
The representation of a single edge during network building.
Definition: NBEdge.h:91
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:4022
@ PRIORITY_ROAD
Definition: NBEdge.h:381
const std::string & getID() const
Definition: NBEdge.h:1465
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:541
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:614
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:3356
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:515
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:752
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:2053
int getPriority() const
Returns the priority of the edge.
Definition: NBEdge.h:522
void setJunctionPriority(const NBNode *const node, int prio)
Sets the junction priority of the edge.
Definition: NBEdge.cpp:2037
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:534
EdgeVector getIncomingEdges() const
Returns the list of incoming edges unsorted.
Definition: NBEdge.cpp:1317
static double getScore(const NBEdge *e1, const NBEdge *e2, int minPrio, int maxPrio, int maxNumLanes, double maxSpeed)
score pair of edges for multi-criteria evaluatoin of angle, priority, laneNumber and speed
static void markBestParallel(const NBNode &n, NBEdge *bestFirst, NBEdge *bestSecond)
set priority for edges that are parallel to the best edges
static NBEdge * extractAndMarkFirst(NBNode &n, std::vector< NBEdge * > &s, int prio=1)
Sets the priorites in case of a priority junction.
static bool hasDifferentPriorities(const EdgeVector &edges, const NBEdge *excluded)
return whether the priorite attribute can be used to distinguish the edges
static void computeEdgePriorities(NBNodeCont &nc)
Computes edge priorities within a node.
static void setPriorityJunctionPriorities(NBNode &n, bool forceStraight=false)
Sets the priorites in case of a priority junction.
static bool samePriority(const NBEdge *const e1, const NBEdge *const e2)
Returns whether both edges have the same priority.
static double normRelAngle(double angle1, double angle2)
ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
Definition: NBHelpers.cpp:58
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:58
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:113
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:118
Represents a single node (junction) during network building.
Definition: NBNode.h:66
LinkDirection getDirection(const NBEdge *const incoming, const NBEdge *const outgoing, bool leftHand=false) const
Returns the representation of the described stream's direction.
Definition: NBNode.cpp:2221
bool isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
Definition: NBNode.cpp:479
bool myTypeWasGuessed
whether the node type was guessed rather than loaded
Definition: NBNode.h:929
SumoXMLNodeType myType
The type of the junction.
Definition: NBNode.h:879
EdgeVector myOutgoingEdges
Vector of outgoing edges.
Definition: NBNode.h:864
EdgeVector myAllEdges
Vector of incoming and outgoing edges.
Definition: NBNode.h:867
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:261
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition: NBNode.h:266
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:256
bool isDistrict() const
check if node is a district
Definition: NBNode.cpp:2464
void removeTrafficLight(NBTrafficLightDefinition *tlDef)
Removes the given traffic light from this node.
Definition: NBNode.cpp:375
void markBentPriority(bool isBent)
mark whether a priority road turns at this node
Definition: NBNode.h:790
const Position & getPosition() const
Definition: NBNode.h:248
bool geometryLike() const
whether this is structurally similar to a geometry node
Definition: NBNode.cpp:3343
bool isNearDistrict() const
@chech if node is near district
Definition: NBNode.cpp:2447
EdgeVector myIncomingEdges
Vector of incoming edges.
Definition: NBNode.h:861
bool isTLControlled() const
Returns whether this node is controlled by any tls.
Definition: NBNode.h:319
NBEdge * getOppositeIncoming(NBEdge *e) const
returns the opposite incoming edge of certain edge
Definition: NBNode.cpp:1756
static bool isRailwayNode(const NBNode *n)
whether the given node only has rail edges
static void computeNodeTypes(NBNodeCont &nc, NBTrafficLightLogicCont &tlc)
Computes node types.
static void validateRailCrossings(NBNodeCont &nc, NBTrafficLightLogicCont &tlc)
Checks rail_crossing for validity.
crossing_by_junction_angle_sorter(const NBNode *node, const EdgeVector &ordering)
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.
static void sortNodesEdges(NBNodeCont &nc, bool useNodeShape=false)
Sorts a node's edges clockwise regarding driving direction.
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:44
The base class for traffic light logic definitions.
A container for traffic light definitions and built programs.
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
Sorts "Combination"s by decreasing angle.
Definition: NBAlgorithms.h:75
static void computeTurnDirections(NBNodeCont &nc, bool warn=true)
Computes turnaround destinations for all edges (if exist)
static void computeTurnDirectionsForNode(NBNode *node, bool warn)
Computes turnaround destinations for all incoming edges of the given nodes (if any)
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
bool isInStringVector(const std::string &optionName, const std::string &itemName) const
Returns the named option is a list of string values containing the specified item.
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
T get(const std::string &str) const
Stores the information about the angle between an incoming ("from") and an outgoing ("to") edge.
Definition: NBAlgorithms.h:65