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