Eclipse SUMO - Simulation of Urban MObility
NBAlgorithms_Ramps.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-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
16 // Algorithms for highway on-/off-ramps computation
17 /****************************************************************************/
18 
19 
20 // ===========================================================================
21 // included modules
22 // ===========================================================================
23 #include <config.h>
24 
25 #include <cassert>
28 #include <utils/common/ToString.h>
29 #include "NBNetBuilder.h"
30 #include "NBNodeCont.h"
31 #include "NBNode.h"
32 #include "NBEdge.h"
33 #include "NBAlgorithms_Ramps.h"
34 
35 //#define DEBUG_RAMPS
36 #define DEBUGNODEID "260479469"
37 #define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
38 
39 // ===========================================================================
40 // static members
41 // ===========================================================================
42 const std::string NBRampsComputer::ADDED_ON_RAMP_EDGE("-AddedOnRampEdge");
43 
44 // ===========================================================================
45 // method definitions
46 // ===========================================================================
47 // ---------------------------------------------------------------------------
48 // NBRampsComputer
49 // ---------------------------------------------------------------------------
50 void
52  const bool guessAndAdd = oc.getBool("ramps.guess");
53  double minHighwaySpeed = oc.getFloat("ramps.min-highway-speed");
54  double maxRampSpeed = oc.getFloat("ramps.max-ramp-speed");
55  double rampLength = oc.getFloat("ramps.ramp-length");
56  bool dontSplit = oc.getBool("ramps.no-split");
57  NBEdgeCont& ec = nb.getEdgeCont();
58  std::set<NBEdge*> incremented;
59  // collect join exclusions
60  std::set<std::string> noramps;
61  if (oc.isSet("ramps.unset")) {
62  std::vector<std::string> edges = oc.getStringVector("ramps.unset");
63  noramps.insert(edges.begin(), edges.end());
64  }
65  // exclude roundabouts
66  const std::set<EdgeSet>& roundabouts = ec.getRoundabouts();
67  for (std::set<EdgeSet>::const_iterator it_round = roundabouts.begin();
68  it_round != roundabouts.end(); ++it_round) {
69  for (EdgeSet::const_iterator it_edge = it_round->begin(); it_edge != it_round->end(); ++it_edge) {
70  noramps.insert((*it_edge)->getID());
71  }
72  }
73  // exclude public transport edges
74  nb.getPTStopCont().addEdges2Keep(oc, noramps);
75  nb.getPTLineCont().addEdges2Keep(oc, noramps);
76  nb.getParkingCont().addEdges2Keep(oc, noramps);
77 
78  // check whether on-off ramps shall be guessed
79  if (guessAndAdd || oc.getBool("ramps.guess-acceleration-lanes")) {
80  NBNodeCont& nc = nb.getNodeCont();
82 
83  // if an edge is part of two ramps, ordering is important
84  std::set<NBNode*, ComparatorIdLess> potOnRamps;
85  std::set<NBNode*, ComparatorIdLess> potOffRamps;
86  for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
87  NBNode* cur = (*i).second;
88  if (mayNeedOnRamp(cur, minHighwaySpeed, maxRampSpeed, noramps)) {
89  potOnRamps.insert(cur);
90  }
91  if (guessAndAdd) {
92  if (mayNeedOffRamp(cur, minHighwaySpeed, maxRampSpeed, noramps)) {
93  potOffRamps.insert(cur);
94  }
95  }
96  }
97  for (std::set<NBNode*, ComparatorIdLess>::const_iterator i = potOnRamps.begin(); i != potOnRamps.end(); ++i) {
98  buildOnRamp(*i, nc, ec, dc, rampLength, dontSplit || !guessAndAdd, guessAndAdd);
99  }
100  for (std::set<NBNode*, ComparatorIdLess>::const_iterator i = potOffRamps.begin(); i != potOffRamps.end(); ++i) {
101  buildOffRamp(*i, nc, ec, dc, rampLength, dontSplit);
102  }
103  }
104  // check whether on-off ramps are specified
105  if (oc.isSet("ramps.set")) {
106  std::vector<std::string> edges = oc.getStringVector("ramps.set");
107  NBNodeCont& nc = nb.getNodeCont();
108  NBEdgeCont& ec = nb.getEdgeCont();
109  NBDistrictCont& dc = nb.getDistrictCont();
110  for (std::vector<std::string>::iterator i = edges.begin(); i != edges.end(); ++i) {
111  NBEdge* e = ec.retrieve(*i);
112  if (noramps.count(*i) != 0) {
113  WRITE_WARNING("Can not build ramp on edge '" + *i + "' - the edge is unsuitable.");
114  continue;
115  }
116  if (e == nullptr) {
117  WRITE_WARNING("Can not build on ramp on edge '" + *i + "' - the edge is not known.");
118  continue;
119  }
120  NBNode* from = e->getFromNode();
121  if (from->getIncomingEdges().size() == 2 && from->getOutgoingEdges().size() == 1) {
122  buildOnRamp(from, nc, ec, dc, rampLength, dontSplit, true);
123  }
124  // load edge again to check offramps
125  e = ec.retrieve(*i);
126  if (e == nullptr) {
127  WRITE_WARNING("Can not build off ramp on edge '" + *i + "' - the edge is not known.");
128  continue;
129  }
130  NBNode* to = e->getToNode();
131  if (to->getIncomingEdges().size() == 1 && to->getOutgoingEdges().size() == 2) {
132  buildOffRamp(to, nc, ec, dc, rampLength, dontSplit);
133  }
134  }
135  }
136 }
137 
138 
139 bool
140 NBRampsComputer::mayNeedOnRamp(NBNode* cur, double minHighwaySpeed, double maxRampSpeed, const std::set<std::string>& noramps) {
141  if (cur->getOutgoingEdges().size() != 1 || cur->getIncomingEdges().size() != 2) {
142  return false;
143  }
144  NBEdge* potHighway, *potRamp, *cont;
145  getOnRampEdges(cur, &potHighway, &potRamp, &cont);
146  // may be an on-ramp
147  return fulfillsRampConstraints(potHighway, potRamp, cont, minHighwaySpeed, maxRampSpeed, noramps);
148 }
149 
150 
151 bool
152 NBRampsComputer::mayNeedOffRamp(NBNode* cur, double minHighwaySpeed, double maxRampSpeed, const std::set<std::string>& noramps) {
153  if (cur->getIncomingEdges().size() != 1 || cur->getOutgoingEdges().size() != 2) {
154  return false;
155  }
156  // may be an off-ramp
157  NBEdge* potHighway, *potRamp, *prev;
158  getOffRampEdges(cur, &potHighway, &potRamp, &prev);
159  return fulfillsRampConstraints(potHighway, potRamp, prev, minHighwaySpeed, maxRampSpeed, noramps);
160 }
161 
162 
163 void
164 NBRampsComputer::buildOnRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, double rampLength, bool dontSplit, bool addLanes) {
165  NBEdge* potHighway, *potRamp, *cont;
166  getOnRampEdges(cur, &potHighway, &potRamp, &cont);
167 #ifdef DEBUG_RAMPS
168  if (DEBUGCOND(cur)) {
169  std::cout << "buildOnRamp cur=" << cur->getID() << " hw=" << potHighway->getID() << " ramp=" << potRamp->getID() << " cont=" << cont->getID() << "\n";
170  }
171 #endif
172  // compute the number of lanes to append
173  const int firstLaneNumber = cont->getNumLanes();
174  int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber;
175  NBEdge* first = cont;
176  NBEdge* last = cont;
177  NBEdge* curr = cont;
178  std::set<NBEdge*> incremented;
179  if (addLanes && toAdd > 0 && std::find(incremented.begin(), incremented.end(), cont) == incremented.end()) {
180  double currLength = 0;
181  while (curr != nullptr && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) {
182  if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
183  curr->incLaneNo(toAdd);
185  curr->invalidateConnections(true);
186  }
187  incremented.insert(curr);
188  moveRampRight(curr, toAdd);
189  currLength += curr->getGeometry().length(); // !!! loaded length?
190  last = curr;
191  // mark acceleration lanes
192  for (int i = 0; i < curr->getNumLanes() - potHighway->getNumLanes(); ++i) {
193  curr->setAcceleration(i, true);
194  }
195  }
196  NBNode* nextN = curr->getToNode();
197  if (nextN->getOutgoingEdges().size() == 1 && nextN->getIncomingEdges().size() == 1) {
198  curr = nextN->getOutgoingEdges()[0];
199  if (curr->getNumLanes() != firstLaneNumber) {
200  // the number of lanes changes along the computation; we'll stop...
201  curr = nullptr;
202  } else if (curr->isTurningDirectionAt(last)) {
203  // turnarounds certainly should not be included in a ramp
204  curr = nullptr;
205  } else if (curr == potHighway || curr == potRamp) {
206  // circular connectivity. do not split!
207  curr = nullptr;
208  }
209  } else {
210  // ambigous; and, in fact, what should it be? ...stop
211  curr = nullptr;
212  }
213  }
214  // check whether a further split is necessary
215  if (curr != nullptr && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && std::find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
216  // there is enough place to build a ramp; do it
217  bool wasFirst = first == curr;
218  NBNode* rn = new NBNode(curr->getID() + "-AddedOnRampNode", curr->getGeometry().positionAtOffset(rampLength - currLength));
219  if (!nc.insert(rn)) {
220  throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!");
221  }
222  std::string name = curr->getID();
223  bool ok = ec.splitAt(dc, curr, rn, curr->getID() + ADDED_ON_RAMP_EDGE, curr->getID(), curr->getNumLanes() + toAdd, curr->getNumLanes());
224  if (!ok) {
225  WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!");
226  return;
227  }
228  //ec.retrieve(name)->invalidateConnections();
229  curr = ec.retrieve(name + ADDED_ON_RAMP_EDGE);
230  incremented.insert(curr);
231  last = curr;
232  moveRampRight(curr, toAdd);
233  if (wasFirst) {
234  first = curr;
235  }
236  // mark acceleration lanes
237  for (int i = 0; i < curr->getNumLanes() - potHighway->getNumLanes(); ++i) {
238  curr->setAcceleration(i, true);
239  }
240  }
241  if (curr == cont && dontSplit && addLanes) {
242  WRITE_WARNING("Could not build on-ramp for edge '" + curr->getID() + "' due to option '--ramps.no-split'");
243  return;
244  }
245  } else {
246  // mark acceleration lanes
247  for (int i = 0; i < firstLaneNumber - potHighway->getNumLanes(); ++i) {
248  cont->setAcceleration(i, true);
249  }
250  }
251  // set connections from ramp/highway to added ramp
252  if (addLanes) {
254  if (!potHighway->addLane2LaneConnections(0, first, potRamp->getNumLanes(), MIN2(first->getNumLanes() - potRamp->getNumLanes(), potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) {
255  throw ProcessError("Could not set connection!");
256  }
257  }
259  if (!potRamp->addLane2LaneConnections(0, first, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, true)) {
260  throw ProcessError("Could not set connection!");
261  }
262  }
263  patchRampGeometry(potRamp, first, potHighway, false);
264  }
265 }
266 
267 
268 void
269 NBRampsComputer::buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, double rampLength, bool dontSplit) {
270  NBEdge* potHighway, *potRamp, *prev;
271  getOffRampEdges(cur, &potHighway, &potRamp, &prev);
272 #ifdef DEBUG_RAMPS
273  if (DEBUGCOND(cur)) {
274  std::cout << "buildOffRamp cur=" << cur->getID() << " hw=" << potHighway->getID() << " ramp=" << potRamp->getID() << " prev=" << prev->getID() << "\n";
275  }
276 #endif
277  // compute the number of lanes to append
278  const int firstLaneNumber = prev->getNumLanes();
279  int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber;
280  NBEdge* first = prev;
281  NBEdge* last = prev;
282  NBEdge* curr = prev;
283  std::set<NBEdge*> incremented;
284  if (toAdd > 0 && std::find(incremented.begin(), incremented.end(), prev) == incremented.end()) {
285  double currLength = 0;
286  while (curr != nullptr && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) {
287  if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
288  curr->incLaneNo(toAdd);
290  curr->invalidateConnections(true);
291  }
292  incremented.insert(curr);
293  moveRampRight(curr, toAdd);
294  currLength += curr->getGeometry().length(); // !!! loaded length?
295  last = curr;
296  }
297  NBNode* prevN = curr->getFromNode();
298  if (prevN->getIncomingEdges().size() == 1 && prevN->getOutgoingEdges().size() == 1) {
299  curr = prevN->getIncomingEdges()[0];
300  if (curr->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER && toAdd != 0) {
301  // curr might be an onRamp. In this case connections need to be rebuilt
302  curr->invalidateConnections();
303  }
304  if (curr->getNumLanes() != firstLaneNumber) {
305  // the number of lanes changes along the computation; we'll stop...
306  curr = nullptr;
307  } else if (last->isTurningDirectionAt(curr)) {
308  // turnarounds certainly should not be included in a ramp
309  curr = nullptr;
310  } else if (curr == potHighway || curr == potRamp) {
311  // circular connectivity. do not split!
312  curr = nullptr;
313  }
314  } else {
315  // ambigous; and, in fact, what should it be? ...stop
316  curr = nullptr;
317  }
318  }
319  // check whether a further split is necessary
320  if (curr != nullptr && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && std::find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
321  // there is enough place to build a ramp; do it
322  bool wasFirst = first == curr;
323  Position pos = curr->getGeometry().positionAtOffset(curr->getGeometry().length() - (rampLength - currLength));
324  NBNode* rn = new NBNode(curr->getID() + "-AddedOffRampNode", pos);
325  if (!nc.insert(rn)) {
326  throw ProcessError("Ups - could not build off-ramp for edge '" + curr->getID() + "' (node could not be build)!");
327  }
328  std::string name = curr->getID();
329  bool ok = ec.splitAt(dc, curr, rn, curr->getID(), curr->getID() + "-AddedOffRampEdge", curr->getNumLanes(), curr->getNumLanes() + toAdd);
330  if (!ok) {
331  WRITE_ERROR("Ups - could not build off-ramp for edge '" + curr->getID() + "'!");
332  return;
333  }
334  curr = ec.retrieve(name + "-AddedOffRampEdge");
335  incremented.insert(curr);
336  last = curr;
337  moveRampRight(curr, toAdd);
338  if (wasFirst) {
339  first = curr;
340  }
341  }
342  if (curr == prev && dontSplit) {
343  WRITE_WARNING("Could not build off-ramp for edge '" + curr->getID() + "' due to option '--ramps.no-split'");
344  return;
345  }
346  }
347  // set connections from added ramp to ramp/highway
349  if (!first->addLane2LaneConnections(potRamp->getNumLanes(), potHighway, 0, MIN2(first->getNumLanes() - 1, potHighway->getNumLanes()), NBEdge::L2L_VALIDATED, true)) {
350  throw ProcessError("Could not set connection!");
351  }
352  if (!first->addLane2LaneConnections(0, potRamp, 0, potRamp->getNumLanes(), NBEdge::L2L_VALIDATED, false)) {
353  throw ProcessError("Could not set connection!");
354  }
355  }
356  patchRampGeometry(potRamp, first, potHighway, true);
357 }
358 
359 
360 void
361 NBRampsComputer::moveRampRight(NBEdge* ramp, int addedLanes) {
362  if (ramp->getLaneSpreadFunction() != LANESPREAD_CENTER) {
363  return;
364  }
365  try {
366  PositionVector g = ramp->getGeometry();
367  const double offset = (0.5 * addedLanes *
369  g.move2side(offset);
370  ramp->setGeometry(g);
371  } catch (InvalidArgument&) {
372  WRITE_WARNING("For edge '" + ramp->getID() + "': could not compute shape.");
373  }
374 }
375 
376 
377 bool
379  if (fabs((*potHighway)->getSpeed() - (*potRamp)->getSpeed()) < .1) {
380  return false;
381  }
382  if ((*potHighway)->getSpeed() < (*potRamp)->getSpeed()) {
383  std::swap(*potHighway, *potRamp);
384  }
385  return true;
386 }
387 
388 
389 bool
391  if ((*potHighway)->getNumLanes() == (*potRamp)->getNumLanes()) {
392  return false;
393  }
394  if ((*potHighway)->getNumLanes() < (*potRamp)->getNumLanes()) {
395  std::swap(*potHighway, *potRamp);
396  }
397  return true;
398 }
399 
400 
401 void
402 NBRampsComputer::getOnRampEdges(NBNode* n, NBEdge** potHighway, NBEdge** potRamp, NBEdge** other) {
403  *other = n->getOutgoingEdges()[0];
404  const std::vector<NBEdge*>& edges = n->getIncomingEdges();
405  assert(edges.size() == 2);
406  *potHighway = edges[0];
407  *potRamp = edges[1];
408  /*
409  // heuristic: highway is faster than ramp
410  if(determinedBySpeed(potHighway, potRamp)) {
411  return;
412  }
413  // heuristic: highway has more lanes than ramp
414  if(determinedByLaneNumber(potHighway, potRamp)) {
415  return;
416  }
417  */
418  // heuristic: ramp comes from right
419  if (NBContHelper::relative_incoming_edge_sorter(*other)(*potRamp, *potHighway)) {
420  std::swap(*potHighway, *potRamp);
421  }
422 }
423 
424 
425 void
426 NBRampsComputer::getOffRampEdges(NBNode* n, NBEdge** potHighway, NBEdge** potRamp, NBEdge** other) {
427  *other = n->getIncomingEdges()[0];
428  const std::vector<NBEdge*>& edges = n->getOutgoingEdges();
429  *potHighway = edges[0];
430  *potRamp = edges[1];
431  assert(edges.size() == 2);
432  /*
433  // heuristic: highway is faster than ramp
434  if(determinedBySpeed(potHighway, potRamp)) {
435  return;
436  }
437  // heuristic: highway has more lanes than ramp
438  if(determinedByLaneNumber(potHighway, potRamp)) {
439  return;
440  }
441  */
442  // heuristic: ramp goes to right
443  const std::vector<NBEdge*>& edges2 = n->getEdges();
444 #ifdef DEBUG_RAMPS
445  if (DEBUGCOND(n)) {
446  std::cout << " edges=" << toString(edges) << " edges2=" << toString(edges2) << "\n";
447  }
448 #endif
449  std::vector<NBEdge*>::const_iterator i = std::find(edges2.begin(), edges2.end(), *other);
450  NBContHelper::nextCW(edges2, i);
451  if ((*i) == *potRamp) {
452  std::swap(*potHighway, *potRamp);
453  }
454  // the following would be better but runs afoul of misleading angles when both edges
455  // have the same geometry start point but different references lanes are
456  // chosen for NBEdge::computeAngle()
457  //if (NBContHelper::relative_outgoing_edge_sorter(*other)(*potHighway, *potRamp)) {
458  // std::swap(*potHighway, *potRamp);
459  //}
460 }
461 
462 
463 bool
465  NBEdge* potHighway, NBEdge* potRamp, NBEdge* other, double minHighwaySpeed, double maxRampSpeed,
466  const std::set<std::string>& noramps) {
467  // check modes that are not appropriate for rampsdo not build ramps on rail edges
468  if (hasWrongMode(potHighway) || hasWrongMode(potRamp) || hasWrongMode(other)) {
469  return false;
470  }
471  // do not build ramps at traffic lights
472  if (NBNode::isTrafficLight(potRamp->getToNode()->getType())) {
473  return false;
474  }
475  // do not build ramps on connectors
476  if (potHighway->isMacroscopicConnector() || potRamp->isMacroscopicConnector() || other->isMacroscopicConnector()) {
477  return false;
478  }
479  // check whether a lane is missing
480  if (potHighway->getNumLanes() + potRamp->getNumLanes() < other->getNumLanes()) {
481  return false;
482  }
483  // is it really a highway?
484  double maxSpeed = MAX3(potHighway->getSpeed(), other->getSpeed(), potRamp->getSpeed());
485  if (maxSpeed < minHighwaySpeed) {
486  return false;
487  }
488  // is any of the connections a turnaround?
489  if (other->getToNode() == potHighway->getFromNode()) {
490  // off ramp
491  if (other->isTurningDirectionAt(potHighway) ||
492  other->isTurningDirectionAt(potRamp)) {
493  return false;
494  }
495  } else {
496  // on ramp
497  if (other->isTurningDirectionAt(potHighway) ||
498  other->isTurningDirectionAt(potRamp)) {
499  return false;
500  }
501  }
502  // are the angles between highway and other / ramp and other more or less straight?
503  const NBNode* node = ((potHighway->getToNode() == potRamp->getToNode() && potHighway->getToNode() == other->getFromNode())
504  ? potHighway->getToNode() : potHighway->getFromNode());
505  double angle = fabs(NBHelpers::relAngle(potHighway->getAngleAtNode(node), other->getAngleAtNode(node)));
506  if (angle >= 60) {
507  return false;
508  }
509  angle = fabs(NBHelpers::relAngle(potRamp->getAngleAtNode(node), other->getAngleAtNode(node)));
510  if (angle >= 60) {
511  return false;
512  }
513  /*
514  if (potHighway->getSpeed() < minHighwaySpeed || other->getSpeed() < minHighwaySpeed) {
515  return false;
516  }
517  */
518  // is it really a ramp?
519  if (maxRampSpeed > 0 && maxRampSpeed < potRamp->getSpeed()) {
520  return false;
521  }
522  if (noramps.find(other->getID()) != noramps.end()) {
523  return false;
524  }
525  return true;
526 }
527 
528 
529 bool
531  // must allow passenger vehicles
532  if ((edge->getPermissions() & SVC_PASSENGER) == 0) {
533  return true;
534  }
535  // must not have a green verge or a lane that is only for soft modes
536  for (int i = 0; i < (int)edge->getNumLanes(); ++i) {
537  if ((edge->getPermissions(i) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) {
538  return true;
539  }
540  }
541  return false;
542 }
543 
544 void
545 NBRampsComputer::patchRampGeometry(NBEdge* potRamp, NBEdge* first, NBEdge* potHighway, bool onRamp) {
546  // geometry of first and highway should allign on the left side
548  const NBNode* n = onRamp ? potHighway->getToNode() : potHighway->getFromNode();
549  if (potHighway->hasDefaultGeometryEndpointAtNode(n)) {
550  PositionVector p2 = first->getGeometry();
551  try {
552  p2.move2side((first->getNumLanes() - potHighway->getNumLanes()) * first->getLaneWidth(0) * 0.5);
553  first->setGeometry(p2);
554  } catch (InvalidArgument&) {}
555  }
556  }
557 
558  // ramp should merge smoothly with first
559  PositionVector p = potRamp->getGeometry();
560  double offset = 0;
561  int firstIndex = MAX2(0, MIN2(potRamp->getNumLanes(), first->getNumLanes()) - 1);
562  if (potRamp->getLaneSpreadFunction() == LANESPREAD_RIGHT) {
563  offset = -first->getLaneWidth(firstIndex) / 2;
564  } else {
565  if (firstIndex % 2 == 1) {
566  // even number of lanes
567  offset = -first->getLaneWidth(firstIndex / 2) / 2;
568  }
569  firstIndex /= 2; // integer division
570  }
571  PositionVector l = first->getLaneShape(firstIndex);
572  try {
573  l.move2side(offset);
574  } catch (InvalidArgument&) {}
575  //std::cout << " ramp=" << potRamp->getID() << " firstIndex=" << firstIndex << " offset=" << offset << " l=" << l << "\n";
576 
577  if (onRamp) {
578  p[0] = l[-1];
579  } else {
580  p.pop_back();
581  p.push_back(l[0]);
582  }
583  potRamp->setGeometry(p);
584 
585 }
586 
587 /****************************************************************************/
588 
OptionsCont::isSet
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
Definition: OptionsCont.cpp:135
SVC_PEDESTRIAN
pedestrian
Definition: SUMOVehicleClass.h:156
ToString.h
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:73
NBRampsComputer::mayNeedOnRamp
static bool mayNeedOnRamp(NBNode *cur, double minHighwaySpeed, double maxRampSpeed, const std::set< std::string > &noramps)
Determines whether the given node may be an on-ramp begin.
Definition: NBAlgorithms_Ramps.cpp:140
NBEdgeCont::retrieve
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:246
NBRampsComputer::ADDED_ON_RAMP_EDGE
static const std::string ADDED_ON_RAMP_EDGE
suffix for newly generated on-ramp edges
Definition: NBAlgorithms_Ramps.h:57
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:275
NBParkingCont::addEdges2Keep
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
Definition: NBParking.cpp:79
NBEdgeCont
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:60
NBNetBuilder
Instance responsible for building networks.
Definition: NBNetBuilder.h:109
NBEdge::getStep
EdgeBuildingStep getStep() const
The building step of this edge.
Definition: NBEdge.h:580
NBNodeCont::end
std::map< std::string, NBNode * >::const_iterator end() const
Returns the pointer to the end of the stored nodes.
Definition: NBNodeCont.h:120
NBPTStopCont::addEdges2Keep
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
Definition: NBPTStopCont.cpp:315
NBEdge::addLane2LaneConnections
bool addLane2LaneConnections(int fromLane, NBEdge *dest, int toLane, int no, Lane2LaneInfoType type, bool invalidatePrevious=false, bool mayDefinitelyPass=false)
Builds no connections starting at the given lanes.
Definition: NBEdge.cpp:1012
OptionsCont.h
NBRampsComputer::getOnRampEdges
static void getOnRampEdges(NBNode *n, NBEdge **potHighway, NBEdge **potRamp, NBEdge **other)
Definition: NBAlgorithms_Ramps.cpp:402
NBRampsComputer::mayNeedOffRamp
static bool mayNeedOffRamp(NBNode *cur, double minHighwaySpeed, double maxRampSpeed, const std::set< std::string > &noramps)
Determines whether the given node may be an off-ramp end.
Definition: NBAlgorithms_Ramps.cpp:152
LANESPREAD_RIGHT
Definition: SUMOXMLDefinitions.h:1098
NBRampsComputer::moveRampRight
static void moveRampRight(NBEdge *ramp, int addedLanes)
Moves the ramp to the right, as new lanes were added.
Definition: NBAlgorithms_Ramps.cpp:361
MsgHandler.h
NBRampsComputer::hasWrongMode
static bool hasWrongMode(NBEdge *edge)
whether the edge has a mode that does not indicate a ramp edge
Definition: NBAlgorithms_Ramps.cpp:530
NBNodeCont::insert
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:78
NBEdge::isTurningDirectionAt
bool isTurningDirectionAt(const NBEdge *const edge) const
Returns whether the given edge is the opposite direction to this edge.
Definition: NBEdge.cpp:2756
NBNode::getOutgoingEdges
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:260
NBNodeCont::begin
std::map< std::string, NBNode * >::const_iterator begin() const
Returns the pointer to the begin of the stored nodes.
Definition: NBNodeCont.h:115
OptionsCont::getBool
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Definition: OptionsCont.cpp:222
NBRampsComputer::buildOnRamp
static void buildOnRamp(NBNode *cur, NBNodeCont &nc, NBEdgeCont &ec, NBDistrictCont &dc, double rampLength, bool dontSplit, bool addLanes)
Builds an on-ramp starting at the given node.
Definition: NBAlgorithms_Ramps.cpp:164
SVC_BICYCLE
vehicle is a bicycle
Definition: SUMOVehicleClass.h:179
NBNode::getType
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:272
SUMO_const_laneWidth
const double SUMO_const_laneWidth
Definition: StdDefs.h:49
PositionVector::length
double length() const
Returns the length.
Definition: PositionVector.cpp:484
MAX3
T MAX3(T a, T b, T c)
Definition: StdDefs.h:93
NBEdge::getPermissions
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3404
PositionVector
A list of positions.
Definition: PositionVector.h:45
NBContHelper::relative_incoming_edge_sorter
Definition: NBContHelper.h:98
NBEdge::hasDefaultGeometryEndpointAtNode
bool hasDefaultGeometryEndpointAtNode(const NBNode *node) const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:571
NBDistrictCont
A container for districts.
Definition: NBDistrictCont.h:52
LANESPREAD_CENTER
Definition: SUMOXMLDefinitions.h:1099
NBEdgeCont::splitAt
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:557
NBHelpers::relAngle
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:46
NBNodeCont
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:59
NBNetBuilder::getEdgeCont
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:150
NBEdge
The representation of a single edge during network building.
Definition: NBEdge.h:91
OptionsCont::getStringVector
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
Definition: OptionsCont.cpp:235
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:79
NBEdge::invalidateConnections
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1336
NBEdge::getToNode
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:498
NBEdge::getGeometry
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:692
NBNetBuilder::getPTStopCont
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
Definition: NBNetBuilder.h:176
NBRampsComputer::determinedBySpeed
static bool determinedBySpeed(NBEdge **potHighway, NBEdge **potRamp)
Definition: NBAlgorithms_Ramps.cpp:378
NBRampsComputer::buildOffRamp
static void buildOffRamp(NBNode *cur, NBNodeCont &nc, NBEdgeCont &ec, NBDistrictCont &dc, double rampLength, bool dontSplit)
Builds an off-ramp ending at the given node.
Definition: NBAlgorithms_Ramps.cpp:269
NBNetBuilder::getPTLineCont
NBPTLineCont & getPTLineCont()
Returns a reference to the pt line container.
Definition: NBNetBuilder.h:181
NBEdge::getLaneWidth
double getLaneWidth() const
Returns the default width of lanes of this edge.
Definition: NBEdge.h:587
NBNetBuilder::getParkingCont
NBParkingCont & getParkingCont()
Definition: NBNetBuilder.h:186
NBPTLineCont::addEdges2Keep
void addEdges2Keep(const OptionsCont &oc, std::set< std::string > &into)
add edges that must be kept
Definition: NBPTLineCont.cpp:333
NBRampsComputer::determinedByLaneNumber
static bool determinedByLaneNumber(NBEdge **potHighway, NBEdge **potRamp)
Definition: NBAlgorithms_Ramps.cpp:390
SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
Definition: SUMOVehicleClass.h:159
PositionVector::positionAtOffset
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
Definition: PositionVector.cpp:248
NBEdge::getNumLanes
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:477
NBNetBuilder.h
ProcessError
Definition: UtilExceptions.h:39
Position
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:38
OptionsCont
A storage for options typed value containers)
Definition: OptionsCont.h:89
NBRampsComputer::patchRampGeometry
static void patchRampGeometry(NBEdge *potRamp, NBEdge *first, NBEdge *potHighway, bool onRamp)
shift ramp geometry to merge smoothly with the motorway
Definition: NBAlgorithms_Ramps.cpp:545
NBNode::getEdges
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition: NBNode.h:265
DEBUGCOND
#define DEBUGCOND(obj)
Definition: NBAlgorithms_Ramps.cpp:37
NBAlgorithms_Ramps.h
NBRampsComputer::getOffRampEdges
static void getOffRampEdges(NBNode *n, NBEdge **potHighway, NBEdge **potRamp, NBEdge **other)
Definition: NBAlgorithms_Ramps.cpp:426
NBEdge::L2L_VALIDATED
The connection was computed and validated.
Definition: NBEdge.h:135
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:208
NBEdge::getLaneShape
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:879
NBNodeCont.h
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:47
NBEdge::setAcceleration
void setAcceleration(int lane, bool accelRamp)
marks one lane as acceleration lane
Definition: NBEdge.cpp:3360
NBEdge::getSpeed
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:571
InvalidArgument
Definition: UtilExceptions.h:56
NBNode::getIncomingEdges
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:255
NBNetBuilder::getDistrictCont
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:170
NBNode::isTrafficLight
static bool isTrafficLight(SumoXMLNodeType type)
return whether the given type is a traffic light
Definition: NBNode.cpp:3250
NBEdge::UNSPECIFIED_WIDTH
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:315
NBEdge::isMacroscopicConnector
bool isMacroscopicConnector() const
Returns whether this edge was marked as a macroscopic connector.
Definition: NBEdge.h:1029
NBContHelper::nextCW
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
Definition: NBContHelper.cpp:39
config.h
NBRampsComputer::computeRamps
static void computeRamps(NBNetBuilder &nb, OptionsCont &oc)
Computes highway on-/off-ramps (if wished)
Definition: NBAlgorithms_Ramps.cpp:51
NBEdge::incLaneNo
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:3150
NBNode
Represents a single node (junction) during network building.
Definition: NBNode.h:67
NBNetBuilder::getNodeCont
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:155
NBNode.h
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:76
NBEdge::getAngleAtNode
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1836
POSITION_EPS
#define POSITION_EPS
Definition: config.h:172
WRITE_ERROR
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:283
NBEdge::getFromNode
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:491
NBEdgeCont::getRoundabouts
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
Definition: NBEdgeCont.cpp:1345
NBEdge::setGeometry
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:582
PositionVector::move2side
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
Definition: PositionVector.cpp:1103
NBRampsComputer::fulfillsRampConstraints
static bool fulfillsRampConstraints(NBEdge *potHighway, NBEdge *potRamp, NBEdge *other, double minHighwaySpeed, double maxRampSpeed, const std::set< std::string > &noramps)
Checks whether an on-/off-ramp can be bult here.
Definition: NBAlgorithms_Ramps.cpp:464
NBEdge::EdgeBuildingStep::LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
NBEdge.h
NBEdge::getLaneSpreadFunction
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.h:777
NBEdge::hasDefaultGeometryEndpoints
bool hasDefaultGeometryEndpoints() const
Returns whether the geometry is terminated by the node positions This default may be violated by init...
Definition: NBEdge.cpp:564
NBEdge::getID
const std::string & getID() const
Definition: NBEdge.h:1380