Eclipse SUMO - Simulation of Urban MObility
NBEdgeCont.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-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 /****************************************************************************/
18 // Storage for edges, including some functionality operating on multiple edges
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <vector>
28 #include <string>
29 #include <cassert>
30 #include <algorithm>
31 #include <cmath>
32 #include <utils/geom/Boundary.h>
33 #include <utils/geom/GeomHelper.h>
36 #include <utils/common/ToString.h>
44 #include "NBNetBuilder.h"
45 #include "NBEdgeCont.h"
46 #include "NBNodeCont.h"
47 #include "NBHelpers.h"
48 #include "NBCont.h"
50 #include "NBDistrictCont.h"
51 #include "NBTypeCont.h"
52 
53 
54 // ===========================================================================
55 // method definitions
56 // ===========================================================================
58  myTypeCont(tc),
59  myEdgesSplit(0),
60  myVehicleClasses2Keep(0),
61  myVehicleClasses2Remove(0),
62  myNeedGeoTransformedPruningBoundary(false) {
63 }
64 
65 
67  clear();
68 }
69 
70 
71 void
73  // set edges dismiss/accept options
74  myEdgesMinSpeed = oc.getFloat("keep-edges.min-speed");
75  myRemoveEdgesAfterJoining = oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload");
76  // we possibly have to load the edges to keep/remove
77  if (oc.isSet("keep-edges.input-file")) {
78  NBHelpers::loadEdgesFromFile(oc.getString("keep-edges.input-file"), myEdges2Keep);
79  }
80  if (oc.isSet("remove-edges.input-file")) {
81  NBHelpers::loadEdgesFromFile(oc.getString("remove-edges.input-file"), myEdges2Remove);
82  }
83  if (oc.isSet("keep-edges.explicit")) {
84  const std::vector<std::string> edges = oc.getStringVector("keep-edges.explicit");
85  myEdges2Keep.insert(edges.begin(), edges.end());
86  }
87  if (oc.isSet("remove-edges.explicit")) {
88  const std::vector<std::string> edges = oc.getStringVector("remove-edges.explicit");
89  myEdges2Remove.insert(edges.begin(), edges.end());
90  }
91  if (oc.exists("keep-edges.by-vclass") && oc.isSet("keep-edges.by-vclass")) {
92  myVehicleClasses2Keep = parseVehicleClasses(oc.getStringVector("keep-edges.by-vclass"));
93  }
94  if (oc.exists("remove-edges.by-vclass") && oc.isSet("remove-edges.by-vclass")) {
95  myVehicleClasses2Remove = parseVehicleClasses(oc.getStringVector("remove-edges.by-vclass"));
96  }
97  if (oc.exists("keep-edges.by-type") && oc.isSet("keep-edges.by-type")) {
98  const std::vector<std::string> types = oc.getStringVector("keep-edges.by-type");
99  myTypes2Keep.insert(types.begin(), types.end());
100  }
101  if (oc.exists("remove-edges.by-type") && oc.isSet("remove-edges.by-type")) {
102  const std::vector<std::string> types = oc.getStringVector("remove-edges.by-type");
103  myTypes2Remove.insert(types.begin(), types.end());
104  }
105 
106  if (oc.isSet("keep-edges.in-boundary") || oc.isSet("keep-edges.in-geo-boundary")) {
107  std::vector<std::string> polyS = oc.getStringVector(oc.isSet("keep-edges.in-boundary") ?
108  "keep-edges.in-boundary" : "keep-edges.in-geo-boundary");
109  // !!! throw something if length<4 || length%2!=0?
110  std::vector<double> poly;
111  for (std::vector<std::string>::iterator i = polyS.begin(); i != polyS.end(); ++i) {
112  poly.push_back(StringUtils::toDouble((*i))); // !!! may throw something anyhow...
113  }
114  if (poly.size() < 4) {
115  throw ProcessError("Invalid boundary: need at least 2 coordinates");
116  } else if (poly.size() % 2 != 0) {
117  throw ProcessError("Invalid boundary: malformed coordinate");
118  } else if (poly.size() == 4) {
119  // prunning boundary (box)
120  myPruningBoundary.push_back(Position(poly[0], poly[1]));
121  myPruningBoundary.push_back(Position(poly[2], poly[1]));
122  myPruningBoundary.push_back(Position(poly[2], poly[3]));
123  myPruningBoundary.push_back(Position(poly[0], poly[3]));
124  } else {
125  for (std::vector<double>::iterator j = poly.begin(); j != poly.end();) {
126  double x = *j++;
127  double y = *j++;
128  myPruningBoundary.push_back(Position(x, y));
129  }
130  }
131  myNeedGeoTransformedPruningBoundary = oc.isSet("keep-edges.in-geo-boundary");
132  }
133 }
134 
135 
136 void
138  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
139  delete ((*i).second);
140  }
141  myEdges.clear();
142  for (EdgeCont::iterator i = myExtractedEdges.begin(); i != myExtractedEdges.end(); i++) {
143  delete ((*i).second);
144  }
145  myExtractedEdges.clear();
146 }
147 
148 
149 
150 // ----- edge access methods
151 bool
152 NBEdgeCont::insert(NBEdge* edge, bool ignorePrunning) {
153  if (myEdges.count(edge->getID()) != 0) {
154  return false;
155  }
156  if (!ignorePrunning && ignoreFilterMatch(edge)) {
157  edge->getFromNode()->removeEdge(edge);
158  edge->getToNode()->removeEdge(edge);
159  myIgnoredEdges.insert(edge->getID());
160  delete edge;
161  } else {
163  if (oc.exists("dismiss-vclasses") && oc.getBool("dismiss-vclasses")) {
165  }
166  myEdges[edge->getID()] = edge;
167  }
168  return true;
169 }
170 
171 
172 bool
174  // remove edges which allow a speed below a set one (set using "keep-edges.min-speed")
175  if (edge->getSpeed() < myEdgesMinSpeed) {
176  return true;
177  }
178  // check whether the edge is a named edge to keep
179  if (!myRemoveEdgesAfterJoining && myEdges2Keep.size() != 0) {
180  if (myEdges2Keep.count(edge->getID()) == 0) {
181  // explicit whitelisting may be combined additively with other filters
183  && myTypes2Keep.size() == 0 && myTypes2Remove.size() == 0
184  && myPruningBoundary.size() == 0) {
185  return true;
186  }
187  } else {
188  // explicit whitelisting overrides other filters
189  return false;
190  }
191  }
192  // check whether the edge is a named edge to remove
193  if (myEdges2Remove.size() != 0) {
194  if (myEdges2Remove.count(edge->getID()) != 0) {
195  return true;
196  }
197  }
198  // check whether the edge shall be removed because it does not allow any of the wished classes
199  if (myVehicleClasses2Keep != 0 && (myVehicleClasses2Keep & edge->getPermissions()) == 0) {
200  return true;
201  }
202  // check whether the edge shall be removed due to allowing unwished classes only
204  return true;
205  }
206  // check whether the edge shall be removed because it does not have one of the requested types
207  if (myTypes2Keep.size() != 0) {
208  if (myTypes2Keep.count(edge->getTypeID()) == 0) {
209  return true;
210  }
211  }
212  // check whether the edge shall be removed because it has one of the forbidden types
213  if (myTypes2Remove.size() != 0) {
214  if (myTypes2Remove.count(edge->getTypeID()) > 0) {
215  return true;
216  }
217  }
218  // check whether the edge is within the pruning boundary
219  if (myPruningBoundary.size() != 0) {
223  } else if (GeoConvHelper::getLoaded().usingGeoProjection()) {
224  // XXX what if input file with different projections are loaded?
225  for (int i = 0; i < (int) myPruningBoundary.size(); i++) {
227  }
228  } else {
229  WRITE_ERROR("Cannot prune edges using a geo-boundary because no projection has been loaded");
230  }
232  }
234  return true;
235  }
236  }
238  return true;
239  }
240  return false;
241 }
242 
243 
244 NBEdge*
245 NBEdgeCont::retrieve(const std::string& id, bool retrieveExtracted) const {
246  EdgeCont::const_iterator i = myEdges.find(id);
247  if (i == myEdges.end()) {
248  if (retrieveExtracted) {
249  i = myExtractedEdges.find(id);
250  if (i == myExtractedEdges.end()) {
251  return nullptr;
252  }
253  } else {
254  return nullptr;
255  }
256  }
257  return (*i).second;
258 }
259 
260 // FIXME: This can't work
261 /*
262 NBEdge*
263 NBEdgeCont::retrievePossiblySplit(const std::string& id, bool downstream) const {
264  NBEdge* edge = retrieve(id);
265  if (edge == 0) {
266  return 0;
267  }
268  const EdgeVector* candidates = downstream ? &edge->getToNode()->getOutgoingEdges() : &edge->getFromNode()->getIncomingEdges();
269  while (candidates->size() == 1) {
270  const std::string& nextID = candidates->front()->getID();
271  if (nextID.find(id) != 0 || nextID.size() <= id.size() + 1 || (nextID[id.size()] != '.' && nextID[id.size()] != '-')) {
272  break;
273  }
274  edge = candidates->front();
275  candidates = downstream ? &edge->getToNode()->getOutgoingEdges() : &edge->getFromNode()->getIncomingEdges();
276  }
277  return edge;
278 }*/
279 
280 NBEdge*
281 NBEdgeCont::retrievePossiblySplit(const std::string& id, bool downstream) const {
282  NBEdge* edge = retrieve(id);
283  if (edge != nullptr) {
284  return edge;
285  }
286  // NOTE: (TODO) for multiply split edges (e.g. 15[0][0]) one could try recursion
287  if ((retrieve(id + "[0]") != nullptr) && (retrieve(id + "[1]") != nullptr)) {
288  // Edge was split during the netbuilding process
289  if (downstream == true) {
290  return retrieve(id + "[1]");
291  } else {
292  return retrieve(id + "[0]");
293  }
294  }
295  return edge;
296 }
297 
298 
299 NBEdge*
300 NBEdgeCont::retrievePossiblySplit(const std::string& id, const std::string& hint, bool incoming) const {
301  // try to retrieve using the given name (iterative)
302  NBEdge* edge = retrieve(id);
303  if (edge != nullptr) {
304  return edge;
305  }
306  // now, we did not find it; we have to look over all possibilities
307  EdgeVector hints;
308  // check whether at least the hint was not splitted
309  NBEdge* hintedge = retrieve(hint);
310  if (hintedge == nullptr) {
311  hints = getGeneratedFrom(hint);
312  } else {
313  hints.push_back(hintedge);
314  }
315  EdgeVector candidates = getGeneratedFrom(id);
316  for (EdgeVector::iterator i = hints.begin(); i != hints.end(); i++) {
317  NBEdge* hintedge = (*i);
318  for (EdgeVector::iterator j = candidates.begin(); j != candidates.end(); j++) {
319  NBEdge* poss_searched = (*j);
320  NBNode* node = incoming
321  ? poss_searched->myTo : poss_searched->myFrom;
322  const EdgeVector& cont = incoming
323  ? node->getOutgoingEdges() : node->getIncomingEdges();
324  if (find(cont.begin(), cont.end(), hintedge) != cont.end()) {
325  return poss_searched;
326  }
327  }
328  }
329  return nullptr;
330 }
331 
332 
333 NBEdge*
334 NBEdgeCont::retrievePossiblySplit(const std::string& id, double pos) const {
335  // check whether the edge was not split, yet
336  NBEdge* edge = retrieve(id);
337  if (edge != nullptr) {
338  return edge;
339  }
340  int maxLength = 0;
341  std::string tid = id + "[";
342  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
343  if ((*i).first.find(tid) == 0) {
344  maxLength = MAX2(maxLength, (int)(*i).first.length());
345  }
346  }
347  // find the part of the edge which matches the position
348  double seen = 0;
349  std::vector<std::string> names;
350  names.push_back(id + "[1]");
351  names.push_back(id + "[0]");
352  while (names.size() > 0) {
353  // retrieve the first subelement (to follow)
354  std::string cid = names.back();
355  names.pop_back();
356  edge = retrieve(cid);
357  // The edge was splitted; check its subparts within the
358  // next step
359  if (edge == nullptr) {
360  if ((int)cid.length() + 3 < maxLength) {
361  names.push_back(cid + "[1]");
362  names.push_back(cid + "[0]");
363  }
364  }
365  // an edge with the name was found,
366  // check whether the position lies within it
367  else {
368  seen += edge->getLength();
369  if (seen >= pos) {
370  return edge;
371  }
372  }
373  }
374  return nullptr;
375 }
376 
377 
378 void
380  extract(dc, edge);
381  delete edge;
382 }
383 
384 
385 void
386 NBEdgeCont::extract(NBDistrictCont& dc, NBEdge* edge, bool remember) {
387  if (remember) {
388  myExtractedEdges[edge->getID()] = edge;
389  }
390  myEdges.erase(edge->getID());
391  edge->myFrom->removeEdge(edge);
392  edge->myTo->removeEdge(edge);
393  dc.removeFromSinksAndSources(edge);
394 }
395 
396 
397 void
398 NBEdgeCont::rename(NBEdge* edge, const std::string& newID) {
399  if (myEdges.count(newID) != 0) {
400  throw ProcessError("Attempt to rename edge using existing id '" + newID + "'");
401  }
402  myEdges.erase(edge->getID());
403  edge->setID(newID);
404  myEdges[newID] = edge;
405 }
406 
407 
408 // ----- explicit edge manipulation methods
409 
410 void
411 NBEdgeCont::processSplits(NBEdge* e, std::vector<Split> splits,
413  if (splits.size() == 0) {
414  return;
415  }
416  const std::string origID = e->getID();
417  std::vector<Split>::iterator i;
418  sort(splits.begin(), splits.end(), split_sorter());
419  int noLanesMax = e->getNumLanes();
420  // compute the node positions and sort the lanes
421  for (i = splits.begin(); i != splits.end(); ++i) {
422  sort((*i).lanes.begin(), (*i).lanes.end());
423  noLanesMax = MAX2(noLanesMax, (int)(*i).lanes.size());
424  }
425  // split the edge
426  std::vector<int> currLanes;
427  for (int l = 0; l < e->getNumLanes(); ++l) {
428  currLanes.push_back(l);
429  }
430  if (e->getNumLanes() != (int)splits.back().lanes.size()) {
431  // invalidate traffic light definitions loaded from a SUMO network
432  e->getToNode()->invalidateTLS(tlc, true, true);
433  // if the number of lanes changes the connections should be
434  // recomputed
435  e->invalidateConnections(true);
436  }
437 
438  std::string firstID = "";
439  double seen = 0;
440  for (i = splits.begin(); i != splits.end(); ++i) {
441  const Split& exp = *i;
442  assert(exp.lanes.size() != 0);
443  if (exp.pos > 0 && e->getGeometry().length() + seen > exp.pos && exp.pos > seen) {
444  nc.insert(exp.node);
445  nc.markAsSplit(exp.node);
446  // split the edge
447  std::string idBefore = exp.idBefore == "" ? e->getID() : exp.idBefore;
448  std::string idAfter = exp.idAfter == "" ? exp.nameID : exp.idAfter;
449  if (firstID == "") {
450  firstID = idBefore;
451  }
452  const bool ok = splitAt(dc, e, exp.pos - seen, exp.node,
453  idBefore, idAfter, e->getNumLanes(), (int) exp.lanes.size(), exp.speed);
454  if (!ok) {
455  WRITE_WARNING("Error on parsing a split (edge '" + origID + "').");
456  }
457  seen = exp.pos;
458  std::vector<int> newLanes = exp.lanes;
459  NBEdge* pe = retrieve(idBefore);
460  NBEdge* ne = retrieve(idAfter);
461  // reconnect lanes
462  pe->invalidateConnections(true);
463  // new on right
464  int rightMostP = currLanes[0];
465  int rightMostN = newLanes[0];
466  for (int l = 0; l < (int) rightMostP - (int) rightMostN; ++l) {
467  pe->addLane2LaneConnection(0, ne, l, NBEdge::L2L_VALIDATED, true);
468  }
469  // new on left
470  int leftMostP = currLanes.back();
471  int leftMostN = newLanes.back();
472  for (int l = 0; l < (int) leftMostN - (int) leftMostP; ++l) {
473  pe->addLane2LaneConnection(pe->getNumLanes() - 1, ne, leftMostN - l - rightMostN, NBEdge::L2L_VALIDATED, true);
474  }
475  // all other connected
476  for (int l = 0; l < noLanesMax; ++l) {
477  if (find(currLanes.begin(), currLanes.end(), l) == currLanes.end()) {
478  continue;
479  }
480  if (find(newLanes.begin(), newLanes.end(), l) == newLanes.end()) {
481  continue;
482  }
483  pe->addLane2LaneConnection(l - rightMostP, ne, l - rightMostN, NBEdge::L2L_VALIDATED, true);
484  }
485  // if there are edges at this node which are not connected
486  // we can assume that this split was attached to an
487  // existing node. Reset all connections to let the default
488  // algorithm recompute them
489  if (exp.node->getIncomingEdges().size() > 1 || exp.node->getOutgoingEdges().size() > 1) {
490  for (NBEdge* in : exp.node->getIncomingEdges()) {
491  in->invalidateConnections(true);
492  }
493  }
494  // move to next
495  e = ne;
496  currLanes = newLanes;
497  } else if (exp.pos == 0) {
498  const int laneCountDiff = e->getNumLanes() - (int)exp.lanes.size();
499  if (laneCountDiff < 0) {
500  e->incLaneNo(-laneCountDiff);
501  } else {
502  e->decLaneNo(laneCountDiff);
503  }
504  currLanes = exp.lanes;
505  // invalidate traffic light definition loaded from a SUMO network
506  // XXX it would be preferable to reconstruct the phase definitions heuristically
507  e->getFromNode()->invalidateTLS(tlc, true, true);
508  } else {
509  WRITE_WARNING("Split at '" + toString(exp.pos) + "' lies beyond the edge's length (edge '" + origID + "').");
510  }
511  }
512  // patch lane offsets
513  e = retrieve(firstID);
514  if (splits.front().pos != 0) {
515  // add a dummy split at the beginning to ensure correct offset
516  Split start;
517  start.pos = 0;
518  for (int lane = 0; lane < (int)e->getNumLanes(); ++lane) {
519  start.lanes.push_back(lane);
520  }
521  start.offset = splits.front().offset;
522  start.offsetFactor = splits.front().offsetFactor;
523  splits.insert(splits.begin(), start);
524  }
525  i = splits.begin();
526  if (e != nullptr) {
527  for (; i != splits.end(); ++i) {
528  int maxLeft = (*i).lanes.back();
529  double offset = (*i).offset;
530  if (maxLeft < noLanesMax) {
532  offset += (*i).offsetFactor * SUMO_const_laneWidthAndOffset * (noLanesMax - 1 - maxLeft);
533  } else {
534  offset += (*i).offsetFactor * SUMO_const_halfLaneAndOffset * (noLanesMax - 1 - maxLeft);
535  }
536  }
537  int maxRight = (*i).lanes.front();
538  if (maxRight > 0 && e->getLaneSpreadFunction() == LANESPREAD_CENTER) {
539  offset -= (*i).offsetFactor * SUMO_const_halfLaneAndOffset * maxRight;
540  }
541  //std::cout << " processSplits " << origID << " splitOffset=" << (*i).offset << " offset=" << offset << "\n";
542  if (offset != 0) {
543  PositionVector g = e->getGeometry();
544  g.move2side(offset);
545  e->setGeometry(g);
546  }
547  if (e->getToNode()->getOutgoingEdges().size() != 0) {
548  e = e->getToNode()->getOutgoingEdges()[0];
549  }
550  }
551  }
552 }
553 
554 
555 bool
557  return splitAt(dc, edge, node, edge->getID() + "[0]", edge->getID() + "[1]",
558  (int) edge->myLanes.size(), (int) edge->myLanes.size());
559 }
560 
561 
562 bool
564  const std::string& firstEdgeName,
565  const std::string& secondEdgeName,
566  int noLanesFirstEdge, int noLanesSecondEdge,
567  const double speed,
568  const int changedLeft) {
569  double pos;
570  pos = edge->getGeometry().nearest_offset_to_point2D(node->getPosition());
571  if (pos <= 0) {
573  edge->myFrom->getPosition(), edge->myTo->getPosition(),
574  node->getPosition());
575  }
576  if (pos <= 0 || pos + POSITION_EPS > edge->getGeometry().length()) {
577  return false;
578  }
579  return splitAt(dc, edge, pos, node, firstEdgeName, secondEdgeName,
580  noLanesFirstEdge, noLanesSecondEdge, speed, changedLeft);
581 }
582 
583 
584 bool
586  NBEdge* edge, double pos, NBNode* node,
587  const std::string& firstEdgeName,
588  const std::string& secondEdgeName,
589  int noLanesFirstEdge, int noLanesSecondEdge,
590  const double speed,
591  const int changedLeft
592  ) {
593  // there must be at least some overlap between first and second edge
594  assert(changedLeft > -((int)noLanesFirstEdge));
595  assert(changedLeft < (int)noLanesSecondEdge);
596 
597  // build the new edges' geometries
598  std::pair<PositionVector, PositionVector> geoms =
599  edge->getGeometry().splitAt(pos);
600  // build and insert the edges
601  NBEdge* one = new NBEdge(firstEdgeName, edge->myFrom, node, edge, geoms.first, noLanesFirstEdge);
602  NBEdge* two = new NBEdge(secondEdgeName, node, edge->myTo, edge, geoms.second, noLanesSecondEdge);
603  if (OptionsCont::getOptions().getBool("output.original-names")) {
604  const std::string origID = edge->getLaneStruct(0).getParameter(SUMO_PARAM_ORIGID, edge->getID());
605  if (firstEdgeName != origID) {
606  one->setOrigID(origID);
607  }
608  if (secondEdgeName != origID) {
609  two->setOrigID(origID);
610  }
611  }
612  two->copyConnectionsFrom(edge);
613  if (speed != -1.) {
614  two->setSpeed(-1, speed);
615  }
616  // replace information about this edge within the nodes
617  edge->myFrom->replaceOutgoing(edge, one, 0);
618  edge->myTo->replaceIncoming(edge, two, 0);
619  // patch tls
620  std::set<NBTrafficLightDefinition*> fromTLS = edge->myFrom->getControllingTLS();
621  for (std::set<NBTrafficLightDefinition*>::iterator i = fromTLS.begin(); i != fromTLS.end(); ++i) {
622  (*i)->replaceRemoved(edge, -1, one, -1);
623  }
624  std::set<NBTrafficLightDefinition*> toTLS = edge->myTo->getControllingTLS();
625  for (std::set<NBTrafficLightDefinition*>::iterator i = toTLS.begin(); i != toTLS.end(); ++i) {
626  (*i)->replaceRemoved(edge, -1, two, -1);
627  }
628  // the edge is now occuring twice in both nodes...
629  // clean up
630  edge->myFrom->removeDoubleEdges();
631  edge->myTo->removeDoubleEdges();
632  // add connections from the first to the second edge
633  // there will be as many connections as there are lanes on the second edge
634  // by default lanes will be added / discontinued on the right side
635  // (appropriate for highway on-/off-ramps)
636  const int offset = (int)one->getNumLanes() - (int)two->getNumLanes() + changedLeft;
637  for (int i2 = 0; i2 < (int)two->getNumLanes(); i2++) {
638  const int i1 = MIN2(MAX2((int)0, i2 + offset), (int)one->getNumLanes());
639  if (!one->addLane2LaneConnection(i1, two, i2, NBEdge::L2L_COMPUTED)) {
640  throw ProcessError("Could not set connection!");
641  }
642  }
644  if (myEdges2Keep.count(edge->getID()) != 0) {
645  myEdges2Keep.insert(one->getID());
646  myEdges2Keep.insert(two->getID());
647  }
648  if (myEdges2Remove.count(edge->getID()) != 0) {
649  myEdges2Remove.insert(one->getID());
650  myEdges2Remove.insert(two->getID());
651  }
652  }
653  // erase the splitted edge
654  patchRoundabouts(edge, one, two, myRoundabouts);
655  patchRoundabouts(edge, one, two, myGuessedRoundabouts);
656  const std::string oldID = edge->getID();
657  erase(dc, edge);
658  if (!insert(one, true)) {
659  WRITE_ERROR("Could not insert edge '" + one->getID() + "' before split of edge '" + oldID + "'");
660  };
661  if (!insert(two, true)) {
662  WRITE_ERROR("Could not insert edge '" + two->getID() + "' after split of edge '" + oldID + "'");
663  }
664  myEdgesSplit++;
665  return true;
666 }
667 
668 
669 void
670 NBEdgeCont::patchRoundabouts(NBEdge* orig, NBEdge* part1, NBEdge* part2, std::set<EdgeSet>& roundabouts) {
671  std::set<EdgeSet> addLater;
672  for (std::set<EdgeSet>::iterator it = roundabouts.begin(); it != roundabouts.end(); ++it) {
673  EdgeSet roundaboutSet = *it;
674  if (roundaboutSet.count(orig) > 0) {
675  roundaboutSet.erase(orig);
676  roundaboutSet.insert(part1);
677  roundaboutSet.insert(part2);
678  }
679  addLater.insert(roundaboutSet);
680  }
681  roundabouts.clear();
682  roundabouts.insert(addLater.begin(), addLater.end());
683 }
684 
685 
686 // ----- container access methods
687 std::vector<std::string>
689  std::vector<std::string> ret;
690  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
691  ret.push_back((*i).first);
692  }
693  return ret;
694 }
695 
696 
697 // ----- Adapting the input
698 void
700  EdgeVector toRemove;
701  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
702  NBEdge* edge = (*i).second;
703  if (!myEdges2Keep.count(edge->getID())) {
704  edge->getFromNode()->removeEdge(edge);
705  edge->getToNode()->removeEdge(edge);
706  toRemove.push_back(edge);
707  }
708  }
709  for (EdgeVector::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
710  erase(dc, *j);
711  }
712 }
713 
714 
715 void
717  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
718  if ((*i).second->getGeometry().size() < 3) {
719  continue;
720  }
721  (*i).second->splitGeometry(*this, nc);
722  }
723 }
724 
725 
726 void
727 NBEdgeCont::reduceGeometries(const double minDist) {
728  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
729  (*i).second->reduceGeometry(minDist);
730  }
731 }
732 
733 
734 void
735 NBEdgeCont::checkGeometries(const double maxAngle, const double minRadius, bool fix) {
736  if (maxAngle > 0 || minRadius > 0) {
737  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
738  (*i).second->checkGeometry(maxAngle, minRadius, fix);
739  }
740  }
741 }
742 
743 
744 // ----- processing methods
745 void
747  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); i++) {
748  (*i).second->clearControllingTLInformation();
749  }
750 }
751 
752 
753 void
755  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
756  (*i).second->sortOutgoingConnectionsByAngle();
757  }
758 }
759 
760 
761 void
762 NBEdgeCont::computeEdge2Edges(bool noLeftMovers) {
763  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
764  (*i).second->computeEdge2Edges(noLeftMovers);
765  }
766 }
767 
768 
769 void
771  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
772  (*i).second->computeLanes2Edges();
773  }
774 }
775 
776 
777 void
779  const bool fixOppositeLengths = OptionsCont::getOptions().getBool("opposites.guess.fix-lengths");
780  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
781  NBEdge* edge = i->second;
782  edge->recheckLanes();
783  // check opposites
784  if (edge->getNumLanes() > 0) {
785  const std::string& oppositeID = edge->getLanes().back().oppositeID;
786  if (oppositeID != "" && oppositeID != "-") {
787  NBEdge* oppEdge = retrieve(oppositeID.substr(0, oppositeID.rfind("_")));
788  if (oppEdge == nullptr || oppEdge->getLaneID(oppEdge->getNumLanes() - 1) != oppositeID) {
789  WRITE_WARNING("Removing unknown opposite lane '" + oppositeID + "' for edge '" + edge->getID() + "'.");
790  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
791  continue;
792  }
793  if (fabs(oppEdge->getLoadedLength() - edge->getLoadedLength()) > NUMERICAL_EPS) {
794  if (fixOppositeLengths) {
795  const double avgLength = 0.5 * (edge->getFinalLength() + oppEdge->getFinalLength());
796  WRITE_WARNING("Averaging edge lengths for lane '" + oppositeID + "' (length " + toString(oppEdge->getLoadedLength()) + ") and edge '" + edge->getID() + "' (length "
797  + toString(edge->getLoadedLength()) + ").");
798  edge->setLoadedLength(avgLength);
799  oppEdge->setLoadedLength(avgLength);
800  } else {
801  WRITE_ERROR("Opposite lane '" + oppositeID + "' (length " + toString(oppEdge->getLoadedLength()) + ") differs in length from edge '" + edge->getID() + "' (length "
802  + toString(edge->getLoadedLength()) + "). Set --opposites.guess.fix-lengths to fix this.");
803  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
804  continue;
805  }
806  }
807  if (oppEdge->getFromNode() != edge->getToNode() || oppEdge->getToNode() != edge->getFromNode()) {
808  WRITE_ERROR("Opposite lane '" + oppositeID + "' does not connect the same nodes as edge '" + edge->getID() + "'!");
809  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
810  }
811  }
812  }
813  }
814 }
815 
816 
817 void
818 NBEdgeCont::appendTurnarounds(bool noTLSControlled, bool onlyDeadends, bool noGeometryLike) {
819  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
820  (*i).second->appendTurnaround(noTLSControlled, onlyDeadends, noGeometryLike, true);
821  }
822 }
823 
824 
825 void
826 NBEdgeCont::appendTurnarounds(const std::set<std::string>& ids, bool noTLSControlled) {
827  for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
828  myEdges[*it]->appendTurnaround(noTLSControlled, false, false, false);
829  }
830 }
831 
832 
833 void
835  std::set<std::string> stopEdgeIDs;
836  for (auto& stopItem : sc.getStops()) {
837  stopEdgeIDs.insert(stopItem.second->getEdgeId());
838  }
839  for (auto& item : myEdges) {
840  NBEdge* edge = item.second;
841  if (edge->isBidiRail()
842  && (stopEdgeIDs.count(item.first) > 0 ||
843  stopEdgeIDs.count(edge->getTurnDestination(true)->getID()) > 0)) {
844  NBEdge* to = edge->getTurnDestination(true);
845  assert(to != 0);
846  edge->setConnection(edge->getNumLanes() - 1,
847  to, to->getNumLanes() - 1, NBEdge::L2L_VALIDATED, false, false, true,
850  }
851  }
852 }
853 
854 void
855 NBEdgeCont::computeEdgeShapes(double smoothElevationThreshold) {
856  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
857  (*i).second->computeEdgeShape(smoothElevationThreshold);
858  }
859 }
860 
861 
862 void
864  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
865  (*i).second->computeLaneShapes();
866  }
867 }
868 
869 
870 void
873  EdgeVector edges) {
874  // !!! Attention!
875  // No merging of the geometry to come is being done
876  // The connections are moved from one edge to another within
877  // the replacement where the edge is a node's incoming edge.
878 
879  // count the number of lanes, the speed and the id
880  int nolanes = 0;
881  double speed = 0;
882  int priority = 0;
883  std::string id;
884  sort(edges.begin(), edges.end(), NBContHelper::same_connection_edge_sorter());
885  // retrieve the connected nodes
886  NBEdge* tpledge = *(edges.begin());
887  NBNode* from = tpledge->getFromNode();
888  NBNode* to = tpledge->getToNode();
889  EdgeVector::const_iterator i;
890  for (i = edges.begin(); i != edges.end(); i++) {
891  // some assertions
892  assert((*i)->getFromNode() == from);
893  assert((*i)->getToNode() == to);
894  // ad the number of lanes the current edge has
895  nolanes += (*i)->getNumLanes();
896  // build the id
897  if (i != edges.begin()) {
898  id += "+";
899  }
900  id += (*i)->getID();
901  // compute the speed
902  speed += (*i)->getSpeed();
903  // build the priority
904  priority = MAX2(priority, (*i)->getPriority());
905  }
906  speed /= edges.size();
907  // build the new edge
908  NBEdge* newEdge = new NBEdge(id, from, to, "", speed, nolanes, priority,
910  tpledge->getStreetName(), tpledge->myLaneSpreadFunction);
911  // copy lane attributes
912  int laneIndex = 0;
913  for (i = edges.begin(); i != edges.end(); ++i) {
914  const std::vector<NBEdge::Lane>& lanes = (*i)->getLanes();
915  for (int j = 0; j < (int)lanes.size(); ++j) {
916  newEdge->setPermissions(lanes[j].permissions, laneIndex);
917  newEdge->setLaneWidth(laneIndex, lanes[j].width);
918  newEdge->setEndOffset(laneIndex, lanes[j].endOffset);
919  laneIndex++;
920  }
921  }
922  insert(newEdge, true);
923  // replace old edge by current within the nodes
924  // and delete the old
925  from->replaceOutgoing(edges, newEdge);
926  to->replaceIncoming(edges, newEdge);
927  // patch connections
928  // add edge2edge-information
929  for (i = edges.begin(); i != edges.end(); i++) {
930  EdgeVector ev = (*i)->getConnectedEdges();
931  for (EdgeVector::iterator j = ev.begin(); j != ev.end(); j++) {
932  newEdge->addEdge2EdgeConnection(*j);
933  }
934  }
935  // copy outgoing connections to the new edge
936  int currLane = 0;
937  for (i = edges.begin(); i != edges.end(); i++) {
938  newEdge->moveOutgoingConnectionsFrom(*i, currLane);
939  currLane += (*i)->getNumLanes();
940  }
941  // patch tl-information
942  currLane = 0;
943  for (i = edges.begin(); i != edges.end(); i++) {
944  int noLanes = (*i)->getNumLanes();
945  for (int j = 0; j < noLanes; j++, currLane++) {
946  // replace in traffic lights
947  tlc.replaceRemoved(*i, j, newEdge, currLane);
948  }
949  }
950  // delete joined edges
951  for (i = edges.begin(); i != edges.end(); i++) {
952  extract(dc, *i, true);
953  }
954 }
955 
956 
957 void
959  //@todo magic values
960  const double distanceThreshold = 7;
961  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
962  NBEdge* edge = i->second;
963  const int numLanes = edge->getNumLanes();
964  if (numLanes > 0) {
965  NBEdge::Lane& lastLane = edge->getLaneStruct(numLanes - 1);
966  if (lastLane.oppositeID == "") {
967  NBEdge* opposite = nullptr;
968  //double minOppositeDist = std::numeric_limits<double>::max();
969  for (EdgeVector::const_iterator j = edge->getToNode()->getOutgoingEdges().begin(); j != edge->getToNode()->getOutgoingEdges().end(); ++j) {
970  if ((*j)->getToNode() == edge->getFromNode() && !(*j)->getLanes().empty()) {
971  const double distance = VectorHelper<double>::maxValue(lastLane.shape.distances((*j)->getLanes().back().shape));
972  if (distance < distanceThreshold) {
973  //minOppositeDist = distance;
974  opposite = *j;
975  }
976  }
977  }
978  if (opposite != nullptr) {
979  lastLane.oppositeID = opposite->getLaneID(opposite->getNumLanes() - 1);
980  }
981  }
982  }
983  }
984 }
985 
986 
987 void
989  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
990  NBEdge* opposite = getOppositeByID(i->first);
991  if (opposite != nullptr) {
992  i->second->setLaneSpreadFunction(LANESPREAD_RIGHT);
994  } else {
995  i->second->setLaneSpreadFunction(LANESPREAD_CENTER);
996  }
997  }
998 }
999 
1000 
1001 NBEdge*
1002 NBEdgeCont::getOppositeByID(const std::string& edgeID) const {
1003  const std::string oppositeID = edgeID[0] == '-' ? edgeID.substr(1) : "-" + edgeID;
1004  EdgeCont::const_iterator it = myEdges.find(oppositeID);
1005  return it != myEdges.end() ? it->second : (NBEdge*)nullptr;
1006 }
1007 
1008 NBEdge*
1009 NBEdgeCont::getByID(const std::string& edgeID) const {
1010  EdgeCont::const_iterator it = myEdges.find(edgeID);
1011  return it != myEdges.end() ? it->second : (NBEdge*)nullptr;
1012 }
1013 
1014 // ----- other
1015 void
1016 NBEdgeCont::addPostProcessConnection(const std::string& from, int fromLane, const std::string& to, int toLane, bool mayDefinitelyPass,
1017  bool keepClear, double contPos, double visibility, double speed,
1018  const PositionVector& customShape, bool uncontrolled, bool warnOnly) {
1019  myConnections[from].push_back(PostProcessConnection(from, fromLane, to, toLane, mayDefinitelyPass, keepClear, contPos, visibility, speed, customShape, uncontrolled, warnOnly));
1020 }
1021 
1022 bool
1023 NBEdgeCont::hasPostProcessConnection(const std::string& from, const std::string& to) {
1024  if (myConnections.count(from) == 0) {
1025  return false;
1026  } else {
1027  if (to == "") {
1028  // wildcard
1029  return true;
1030  }
1031  for (const auto& ppc : myConnections[from]) {
1032  if (ppc.to == to) {
1033  return true;
1034  }
1035  }
1036  return false;
1037  }
1038 }
1039 
1040 void
1042  const bool warnOnly = OptionsCont::getOptions().exists("ignore-errors.connections") && OptionsCont::getOptions().getBool("ignore-errors.connections");
1043  for (const auto& item : myConnections) {
1044  for (std::vector<PostProcessConnection>::const_iterator i = item.second.begin(); i != item.second.end(); ++i) {
1045  NBEdge* from = retrievePossiblySplit((*i).from, true);
1046  NBEdge* to = retrievePossiblySplit((*i).to, false);
1047  if (from == nullptr || to == nullptr ||
1048  !from->addLane2LaneConnection((*i).fromLane, to, (*i).toLane, NBEdge::L2L_USER, true, (*i).mayDefinitelyPass,
1049  (*i).keepClear, (*i).contPos, (*i).visibility, (*i).speed, (*i).customShape, (*i).uncontrolled)) {
1050  const std::string msg = "Could not insert connection between '" + (*i).from + "' and '" + (*i).to + "' after build.";
1051  if (warnOnly || (*i).warnOnly) {
1052  WRITE_WARNING(msg);
1053  } else {
1054  WRITE_ERROR(msg);
1055  }
1056  }
1057  }
1058  }
1059  // during loading we also kept some ambiguous connections in hope they might be valid after processing
1060  // we need to make sure that all invalid connections are removed now
1061  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); ++it) {
1062  NBEdge* edge = it->second;
1063  NBNode* to = edge->getToNode();
1064  // make a copy because we may delete connections
1065  std::vector<NBEdge::Connection> connections = edge->getConnections();
1066  for (std::vector<NBEdge::Connection>::iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
1067  NBEdge::Connection& c = *it_con;
1068  if (c.toEdge != nullptr && c.toEdge->getFromNode() != to) {
1069  WRITE_WARNING("Found and removed invalid connection from edge '" + edge->getID() +
1070  "' to edge '" + c.toEdge->getID() + "' via junction '" + to->getID() + "'.");
1071  edge->removeFromConnections(c.toEdge);
1072  }
1073  }
1074  }
1075 }
1076 
1077 
1078 EdgeVector
1079 NBEdgeCont::getGeneratedFrom(const std::string& id) const {
1080  int len = (int)id.length();
1081  EdgeVector ret;
1082  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
1083  std::string curr = (*i).first;
1084  // the next check makes it possibly faster - we don not have
1085  // to compare the names
1086  if ((int)curr.length() <= len) {
1087  continue;
1088  }
1089  // the name must be the same as the given id but something
1090  // beginning with a '[' must be appended to it
1091  if (curr.substr(0, len) == id && curr[len] == '[') {
1092  ret.push_back((*i).second);
1093  continue;
1094  }
1095  // ok, maybe the edge is a compound made during joining of edges
1096  std::string::size_type pos = curr.find(id);
1097  // surely not
1098  if (pos == std::string::npos) {
1099  continue;
1100  }
1101  // check leading char
1102  if (pos > 0) {
1103  if (curr[pos - 1] != ']' && curr[pos - 1] != '+') {
1104  // actually, this is another id
1105  continue;
1106  }
1107  }
1108  if (pos + id.length() < curr.length()) {
1109  if (curr[pos + id.length()] != '[' && curr[pos + id.length()] != '+') {
1110  // actually, this is another id
1111  continue;
1112  }
1113  }
1114  ret.push_back((*i).second);
1115  }
1116  return ret;
1117 }
1118 
1119 
1120 int
1122  myGuessedRoundabouts.clear();
1123  std::set<NBEdge*> loadedRoundaboutEdges;
1124  for (std::set<EdgeSet>::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
1125  loadedRoundaboutEdges.insert(it->begin(), it->end());
1126  }
1127  // step 1: keep only those edges which have no turnarounds and which are not
1128  // part of a loaded roundabout
1129  std::set<NBEdge*> candidates;
1130  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
1131  NBEdge* e = (*i).second;
1132  NBNode* const to = e->getToNode();
1133  if (e->getTurnDestination() == nullptr && to->getConnectionTo(e->getFromNode()) == nullptr && loadedRoundaboutEdges.count(e) == 0) {
1134  candidates.insert(e);
1135  }
1136  }
1137 
1138  // step 2:
1139  std::set<NBEdge*> visited;
1140  for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) {
1141  EdgeVector loopEdges;
1142  // start with a random edge (this doesn't have to be a roundabout edge)
1143  // loop over connected edges (using always the leftmost one)
1144  // and keep the list in loopEdges
1145  // continue until we loop back onto a loopEdges and extract the loop
1146  NBEdge* e = (*i);
1147  if (visited.count(e) > 0) {
1148  // already seen
1149  continue;
1150  }
1151  loopEdges.push_back(e);
1152  bool doLoop = true;
1153  do {
1154  visited.insert(e);
1155  const EdgeVector& edges = e->getToNode()->getEdges();
1157  doLoop = false;
1158  break;
1159  }
1160  if (edges.size() < 2) {
1161  doLoop = false;
1162  break;
1163  }
1164  if (e->getTurnDestination() != nullptr || e->getToNode()->getConnectionTo(e->getFromNode()) != nullptr) {
1165  // do not follow turn-arounds while in a (tentative) loop
1166  doLoop = false;
1167  break;
1168  }
1169  EdgeVector::const_iterator me = std::find(edges.begin(), edges.end(), e);
1170  NBContHelper::nextCW(edges, me);
1171  NBEdge* left = *me;
1172  double angle = fabs(NBHelpers::relAngle(e->getAngleAtNode(e->getToNode()), left->getAngleAtNode(e->getToNode())));
1173  if (angle >= 90) {
1174  // roundabouts do not have sharp turns (or they wouldn't be called 'round')
1175  doLoop = false;
1176  break;
1177  }
1178  EdgeVector::const_iterator loopClosed = std::find(loopEdges.begin(), loopEdges.end(), left);
1179  const int loopSize = (int)(loopEdges.end() - loopClosed);
1180  if (loopSize > 0) {
1181  // loop found
1182  if (loopSize < 3) {
1183  doLoop = false; // need at least 3 edges for a roundabout
1184  } else if (loopSize < (int)loopEdges.size()) {
1185  // remove initial edges not belonging to the loop
1186  EdgeVector(loopEdges.begin() + (loopEdges.size() - loopSize), loopEdges.end()).swap(loopEdges);
1187  }
1188  // count attachments to the outside. need at least 3 or a roundabout doesn't make much sense
1189  int attachments = 0;
1190  for (EdgeVector::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) {
1191  if ((*j)->getToNode()->getEdges().size() > 2) {
1192  attachments++;
1193  }
1194  }
1195  if (attachments < 3) {
1196  doLoop = false;
1197  }
1198  break;
1199  }
1200  if (visited.count(left) > 0) {
1201  doLoop = false;
1202  } else {
1203  // keep going
1204  loopEdges.push_back(left);
1205  e = left;
1206  }
1207  } while (doLoop);
1208  if (doLoop) {
1209  // check form factor to avoid elongated shapes (circle: 1, square: ~0.79)
1210  if (formFactor(loopEdges) > 0.6) {
1211  // collected edges are marked in markRoundabouts
1212  myGuessedRoundabouts.insert(EdgeSet(loopEdges.begin(), loopEdges.end()));
1213  }
1214  }
1215  }
1216  return (int)myGuessedRoundabouts.size();
1217 }
1218 
1219 
1220 double
1222  PositionVector points;
1223  for (EdgeVector::const_iterator it = loopEdges.begin(); it != loopEdges.end(); ++it) {
1224  points.append((*it)->getGeometry());
1225  }
1226  double circumference = points.length2D();
1227  return 4 * M_PI * points.area() / (circumference * circumference);
1228 }
1229 
1230 
1231 const std::set<EdgeSet>
1233  std::set<EdgeSet> result = myRoundabouts;
1234  result.insert(myGuessedRoundabouts.begin(), myGuessedRoundabouts.end());
1235  return result;
1236 }
1237 
1238 
1239 void
1241  if (roundabout.size() > 0) {
1242  if (find(myRoundabouts.begin(), myRoundabouts.end(), roundabout) != myRoundabouts.end()) {
1243  WRITE_WARNING("Ignoring duplicate roundabout: " + toString(roundabout));
1244  } else {
1245  myRoundabouts.insert(roundabout);
1246  }
1247  }
1248 }
1249 
1250 void
1252  for (auto it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
1253  for (NBEdge* e : *it) {
1254  if (e->getToNode() == node) {
1255  myRoundabouts.erase(it);
1256  return;
1257  }
1258  }
1259  }
1260 }
1261 
1262 
1263 void
1265  const std::set<EdgeSet> roundabouts = getRoundabouts();
1266  for (std::set<EdgeSet>::const_iterator it = roundabouts.begin(); it != roundabouts.end(); ++it) {
1267  const EdgeSet roundaboutSet = *it;
1268  for (std::set<NBEdge*>::const_iterator j = roundaboutSet.begin(); j != roundaboutSet.end(); ++j) {
1269  // disable turnarounds on incoming edges
1270  NBNode* node = (*j)->getToNode();
1271  const EdgeVector& incoming = node->getIncomingEdges();
1272  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
1273  NBEdge* inEdge = *k;
1274  if (roundaboutSet.count(inEdge) > 0) {
1275  continue;
1276  }
1277  if ((inEdge)->getStep() >= NBEdge::LANES2LANES_USER) {
1278  continue;
1279  }
1280  if (inEdge->getTurnDestination() != nullptr) {
1281  inEdge->removeFromConnections(inEdge->getTurnDestination(), -1);
1282  }
1283  }
1284  // let the connections to succeeding roundabout edge have a higher priority
1285  (*j)->setJunctionPriority(node, NBEdge::ROUNDABOUT);
1286  (*j)->setJunctionPriority((*j)->getFromNode(), NBEdge::ROUNDABOUT);
1287  node->setRoundabout();
1288  }
1289  }
1290 }
1291 
1292 void
1294  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
1295  NBEdge* e = i->second;
1296  const double offset = MAX2(0., e->getLength() - 3);
1297  if (e->getToNode()->isSimpleContinuation(false)) {
1298  // not a "real" junction?
1299  continue;
1300  }
1301  const SumoXMLNodeType nodeType = e->getToNode()->getType();
1302  switch (nodeType) {
1303  case NODETYPE_PRIORITY:
1304  // yield or major?
1305  if (e->getJunctionPriority(e->getToNode()) > 0) {
1307  } else {
1308  e->addSign(NBSign(NBSign::SIGN_TYPE_YIELD, offset));
1309  }
1310  break;
1312  // yield or major?
1313  if (e->getJunctionPriority(e->getToNode()) > 0) {
1315  } else {
1316  e->addSign(NBSign(NBSign::SIGN_TYPE_STOP, offset));
1317  }
1318  break;
1319  case NODETYPE_ALLWAY_STOP:
1321  break;
1324  break;
1325  default:
1326  break;
1327  }
1328  }
1329 }
1330 
1331 
1332 int
1333 NBEdgeCont::guessSpecialLanes(SUMOVehicleClass svc, double width, double minSpeed, double maxSpeed, bool fromPermissions, const std::string& excludeOpt) {
1334  int lanesCreated = 0;
1335  std::vector<std::string> edges;
1336  if (excludeOpt != "") {
1337  edges = OptionsCont::getOptions().getStringVector(excludeOpt);
1338  }
1339  std::set<std::string> exclude(edges.begin(), edges.end());
1340  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1341  NBEdge* edge = it->second;
1342  if (// not excluded
1343  exclude.count(edge->getID()) == 0
1344  // does not yet have a sidewalk
1345  && !edge->hasRestrictedLane(svc)
1346  && (
1347  // guess.from-permissions
1348  (fromPermissions && (edge->getPermissions() & svc) != 0)
1349  // guess from speed
1350  || (!fromPermissions && edge->getSpeed() > minSpeed && edge->getSpeed() <= maxSpeed)
1351  )) {
1352  edge->addRestrictedLane(width, svc);
1353  lanesCreated += 1;
1354  }
1355  }
1356  return lanesCreated;
1357 }
1358 
1359 
1360 int
1361 NBEdgeCont::remapIDs(bool numericaIDs, bool reservedIDs, const std::string& prefix, NBPTStopCont& sc) {
1362  std::vector<std::string> avoid = getAllNames();
1363  std::set<std::string> reserve;
1364  if (reservedIDs) {
1365  NBHelpers::loadPrefixedIDsFomFile(OptionsCont::getOptions().getString("reserved-ids"), "edge:", reserve);
1366  avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1367  }
1368  IDSupplier idSupplier("", avoid);
1369  std::set<NBEdge*, ComparatorIdLess> toChange;
1370  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1371  if (numericaIDs) {
1372  try {
1373  StringUtils::toLong(it->first);
1374  } catch (NumberFormatException&) {
1375  toChange.insert(it->second);
1376  }
1377  }
1378  if (reservedIDs && reserve.count(it->first) > 0) {
1379  toChange.insert(it->second);
1380  }
1381  }
1382 
1383  std::map<std::string, std::vector<NBPTStop*> > stopsOnEdge;
1384  for (const auto& item : sc.getStops()) {
1385  stopsOnEdge[item.second->getEdgeId()].push_back(item.second);
1386  }
1387 
1388  const bool origNames = OptionsCont::getOptions().getBool("output.original-names");
1389  for (std::set<NBEdge*, ComparatorIdLess>::iterator it = toChange.begin(); it != toChange.end(); ++it) {
1390  NBEdge* edge = *it;
1391  const std::string origID = edge->getID();
1392  myEdges.erase(origID);
1393  if (origNames) {
1394  edge->setOrigID(origID);
1395  }
1396  edge->setID(idSupplier.getNext());
1397  myEdges[edge->getID()] = edge;
1398  for (NBPTStop* stop : stopsOnEdge[origID]) {
1399  stop->setEdgeId(prefix + edge->getID(), *this);
1400  }
1401  }
1402  if (prefix.empty()) {
1403  return (int)toChange.size();
1404  } else {
1405  int renamed = 0;
1406  // make a copy because we will modify the map
1407  auto oldEdges = myEdges;
1408  for (auto item : oldEdges) {
1409  if (!StringUtils::startsWith(item.first, prefix)) {
1410  rename(item.second, prefix + item.first);
1411  renamed++;
1412  }
1413  }
1414  return renamed;
1415  }
1416 }
1417 
1418 
1419 void
1420 NBEdgeCont::checkOverlap(double threshold, double zThreshold) const {
1421  for (EdgeCont::const_iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1422  const NBEdge* e1 = it->second;
1423  Boundary b1 = e1->getGeometry().getBoxBoundary();
1424  b1.grow(e1->getTotalWidth());
1425  PositionVector outline1 = e1->getCCWBoundaryLine(*e1->getFromNode());
1426  outline1.append(e1->getCCWBoundaryLine(*e1->getToNode()));
1427  // check is symmetric. only check once per pair
1428  for (EdgeCont::const_iterator it2 = it; it2 != myEdges.end(); it2++) {
1429  const NBEdge* e2 = it2->second;
1430  if (e1 == e2) {
1431  continue;
1432  }
1433  Boundary b2 = e2->getGeometry().getBoxBoundary();
1434  b2.grow(e2->getTotalWidth());
1435  if (b1.overlapsWith(b2)) {
1436  PositionVector outline2 = e2->getCCWBoundaryLine(*e2->getFromNode());
1437  outline2.append(e2->getCCWBoundaryLine(*e2->getToNode()));
1438  const double overlap = outline1.getOverlapWith(outline2, zThreshold);
1439  if (overlap > threshold) {
1440  WRITE_WARNING("Edge '" + e1->getID() + "' overlaps with edge '" + e2->getID() + "' by " + toString(overlap) + ".");
1441  }
1442  }
1443  }
1444  }
1445 }
1446 
1447 
1448 void
1449 NBEdgeCont::checkGrade(double threshold) const {
1450  for (EdgeCont::const_iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1451  const NBEdge* edge = it->second;
1452  for (int i = 0; i < (int)edge->getNumLanes(); i++) {
1453  double maxJump = 0;
1454  const double grade = edge->getLaneShape(i).getMaxGrade(maxJump);
1455  if (maxJump > 0.01) {
1456  WRITE_WARNING("Edge '" + edge->getID() + "' has a vertical jump of " + toString(maxJump) + "m.");
1457  } else if (grade > threshold) {
1458  WRITE_WARNING("Edge '" + edge->getID() + "' has a grade of " + toString(grade * 100) + "%.");
1459  break;
1460  }
1461  }
1462  const std::vector<NBEdge::Connection>& connections = edge->getConnections();
1463  for (std::vector<NBEdge::Connection>::const_iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
1464  const NBEdge::Connection& c = *it_con;
1465  double maxJump = 0;
1466  const double grade = MAX2(c.shape.getMaxGrade(maxJump), c.viaShape.getMaxGrade(maxJump));
1467  if (maxJump > 0.01) {
1468  WRITE_WARNING("Connection '" + c.getDescription(edge) + "' has a vertical jump of " + toString(maxJump) + "m.");
1469  } else if (grade > threshold) {
1470  WRITE_WARNING("Connection '" + c.getDescription(edge) + "' has a grade of " + toString(grade * 100) + "%.");
1471  break;
1472  }
1473  }
1474  }
1475 }
1476 
1477 int
1479  int affectedEdges = 0;
1480  for (auto item : myEdges) {
1481  if (item.second->joinLanes(perms)) {
1482  affectedEdges++;
1483  }
1484  }
1485  return affectedEdges;
1486 }
1487 
1488 EdgeVector
1490  EdgeVector result;
1491  for (auto item : myEdges) {
1492  item.second->setNumericalID((int)result.size());
1493  result.push_back(item.second);
1494  }
1495  return result;
1496 }
1497 
1500  EdgeVector all = getAllEdges();
1501  return RouterEdgeVector(all.begin(), all.end());
1502 }
1503 
1504 /****************************************************************************/
NBEdgeCont::split_sorter
Sorts splits by their position (increasing)
Definition: NBEdgeCont.h:725
OptionsCont::isSet
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
Definition: OptionsCont.cpp:136
Boundary.h
NODETYPE_PRIORITY
Definition: SUMOXMLDefinitions.h:1056
NBEdge::UNSPECIFIED_OFFSET
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:306
SUMOVehicleClass
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types.
Definition: SUMOVehicleClass.h:134
ToString.h
NBEdge::Connection::toEdge
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:206
NBEdgeCont::~NBEdgeCont
~NBEdgeCont()
Destructor.
Definition: NBEdgeCont.cpp:66
NBEdgeCont::checkGeometries
void checkGeometries(const double maxAngle, const double minRadius, bool fix)
Definition: NBEdgeCont.cpp:735
NBEdge::ROUNDABOUT
Definition: NBEdge.h:336
NBEdge::myTo
NBNode * myTo
Definition: NBEdge.h:1533
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:74
NBPTStopCont
Definition: NBPTStopCont.h:28
NBEdge::setOrigID
void setOrigID(const std::string origID)
set origID for all lanes
Definition: NBEdge.cpp:3725
NBEdgeCont::myTypeCont
NBTypeCont & myTypeCont
The network builder; used to obtain type information.
Definition: NBEdgeCont.h:612
NBEdgeCont::myIgnoredEdges
std::set< std::string > myIgnoredEdges
The ids of ignored edges.
Definition: NBEdgeCont.h:678
NBEdgeCont::Split::offsetFactor
int offsetFactor
direction in which to apply the offset (used by netgenerate for lefthand networks)
Definition: NBEdgeCont.h:225
NBEdgeCont::retrieve
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
NBSign::SIGN_TYPE_RIGHT_BEFORE_LEFT
Definition: NBSign.h:54
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
NBNode::replaceOutgoing
void replaceOutgoing(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of outgoing by the second Connections are remap...
Definition: NBNode.cpp:1392
NBEdgeCont::myEdgesMinSpeed
double myEdgesMinSpeed
The minimum speed an edge may have in order to be kept (default: -1)
Definition: NBEdgeCont.h:687
NBEdgeCont::myExtractedEdges
EdgeCont myExtractedEdges
The extracted nodes which are kept for reference.
Definition: NBEdgeCont.h:675
GeoConvHelper::x2cartesian_const
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation.
Definition: GeoConvHelper.cpp:418
NBTrafficLightLogicCont
A container for traffic light definitions and built programs.
Definition: NBTrafficLightLogicCont.h:58
NBSign::SIGN_TYPE_ALLWAY_STOP
Definition: NBSign.h:51
NBEdgeCont::erase
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:379
NBEdge::hasRestrictedLane
bool hasRestrictedLane(SUMOVehicleClass vclass) const
returns whether any lane already allows the given vclass exclusively
Definition: NBEdge.cpp:3600
NBSign
A class representing a single street sign.
Definition: NBSign.h:44
NBEdgeCont::getOppositeByID
NBEdge * getOppositeByID(const std::string &edgeID) const
Returns the edge with negated id if it exists.
Definition: NBEdgeCont.cpp:1002
NUMERICAL_EPS
#define NUMERICAL_EPS
Definition: config.h:145
NBNodeCont::markAsSplit
void markAsSplit(const NBNode *node)
mark a node as being created form a split
Definition: NBNodeCont.h:317
OptionsCont.h
NBNode::getConnectionTo
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:2161
LANESPREAD_RIGHT
Definition: SUMOXMLDefinitions.h:1093
StringUtils::toDouble
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
Definition: StringUtils.cpp:313
MsgHandler.h
EdgeVector
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
NBEdge::copyConnectionsFrom
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
Definition: NBEdge.cpp:1478
NBNodeCont::insert
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
NBEdgeCont::applyOptions
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
Definition: NBEdgeCont.cpp:72
NBEdgeCont::checkGrade
void checkGrade(double threshold) const
check whether edges are to steep
Definition: NBEdgeCont.cpp:1449
OptionsCont::getString
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
Definition: OptionsCont.cpp:202
NBNode::getOutgoingEdges
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:264
GeoConvHelper::getProcessing
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:87
NBEdge::isBidiRail
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:683
NBEdge::addEdge2EdgeConnection
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:990
NBEdgeCont::processSplits
void processSplits(NBEdge *e, std::vector< Split > splits, NBNodeCont &nc, NBDistrictCont &dc, NBTrafficLightLogicCont &tlc)
Definition: NBEdgeCont.cpp:411
NBNetBuilder::transformCoordinates
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
Definition: NBNetBuilder.cpp:690
OptionsCont::exists
bool exists(const std::string &name) const
Returns the information whether the named option is known.
Definition: OptionsCont.cpp:130
NBEdgeCont.h
GeoConvHelper.h
NBEdgeCont::computeLaneShapes
void computeLaneShapes()
Computes the shapes of all lanes of all edges stored in the container.
Definition: NBEdgeCont.cpp:863
IDSupplier
Definition: IDSupplier.h:38
NBEdgeCont::myConnections
std::map< std::string, std::vector< PostProcessConnection > > myConnections
The list of connections to recheck.
Definition: NBEdgeCont.h:665
OptionsCont::getBool
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Definition: OptionsCont.cpp:223
NBEdgeCont::patchRoundabouts
void patchRoundabouts(NBEdge *orig, NBEdge *part1, NBEdge *part2, std::set< EdgeSet > &roundabouts)
fix roundabout information after splitting an edge
Definition: NBEdgeCont.cpp:670
OptionsCont::getOptions
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
NBNode::getType
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:276
NBEdgeCont::getByID
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
Definition: NBEdgeCont.cpp:1009
NBEdgeCont::insert
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:152
PositionVector::length
double length() const
Returns the length.
Definition: PositionVector.cpp:476
NBEdgeCont::Split::offset
double offset
lateral offset to edge geometry
Definition: NBEdgeCont.h:223
GeoConvHelper::getLoaded
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
Definition: GeoConvHelper.h:92
SUMO_const_laneWidthAndOffset
const double SUMO_const_laneWidthAndOffset
Definition: StdDefs.h:54
NBEdge::setPermissions
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:3413
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:3441
NBEdge::setLoadedLength
void setLoadedLength(double val)
set loaded lenght
Definition: NBEdge.cpp:3456
NBEdge::setLaneSpreadFunction
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:877
GeomHelper::nearest_offset_on_line_to_point2D
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
Definition: GeomHelper.cpp:90
NBEdgeCont::Split::speed
double speed
The speed after this change.
Definition: NBEdgeCont.h:213
NBEdgeCont::markRoundabouts
void markRoundabouts()
mark edge priorities and prohibit turn-arounds for all roundabout edges
Definition: NBEdgeCont.cpp:1264
NBEdge::L2L_USER
The connection was given by the user.
Definition: NBEdge.h:128
PositionVector
A list of positions.
Definition: PositionVector.h:46
SUMO_const_halfLaneAndOffset
const double SUMO_const_halfLaneAndOffset
Definition: StdDefs.h:55
NBTypeCont::knows
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:72
NBEdgeCont::myTypes2Remove
std::set< std::string > myTypes2Remove
Set of edges types which shall be removed.
Definition: NBEdgeCont.h:708
NBDistrictCont
A container for districts.
Definition: NBDistrictCont.h:53
LANESPREAD_CENTER
Definition: SUMOXMLDefinitions.h:1094
NBEdgeCont::splitAt
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:556
NBEdgeCont::ignoreFilterMatch
bool ignoreFilterMatch(NBEdge *edge)
Returns true if this edge matches one of the removal criteria.
Definition: NBEdgeCont.cpp:173
RouterEdgeVector
std::vector< NBRouterEdge * > RouterEdgeVector
Definition: NBCont.h:43
NBEdgeCont::remapIDs
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string &prefix, NBPTStopCont &sc)
remap node IDs accoring to options –numerical-ids and –reserved-ids
Definition: NBEdgeCont.cpp:1361
PositionVector::getBoxBoundary
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
Definition: PositionVector.cpp:382
GeoConvHelper::usingGeoProjection
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
Definition: GeoConvHelper.cpp:282
NBHelpers::relAngle
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:47
NBNodeCont
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:60
SUMO_const_haltingSpeed
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:61
Parameterised::getParameter
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
Definition: Parameterised.cpp:71
NBEdge
The representation of a single edge during network building.
Definition: NBEdge.h:86
NBEdgeCont::myVehicleClasses2Keep
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
Definition: NBEdgeCont.h:699
NBEdgeCont::getGeneratedFrom
EdgeVector getGeneratedFrom(const std::string &id) const
Returns the edges which have been built by splitting the edge of the given id.
Definition: NBEdgeCont.cpp:1079
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:80
parseVehicleClasses
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
Definition: SUMOVehicleClass.cpp:223
NBEdgeCont::joinSameNodeConnectingEdges
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:871
NBNode::getPosition
const Position & getPosition() const
Definition: NBNode.h:251
NBEdge::setEndOffset
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3332
NBEdge::dismissVehicleClassInformation
void dismissVehicleClassInformation()
dimiss vehicle class information
Definition: NBEdge.cpp:3462
PositionVector::nearest_offset_to_point2D
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
Definition: PositionVector.cpp:809
NBEdge::invalidateConnections
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1363
NumberFormatException
Definition: UtilExceptions.h:96
NBContHelper::same_connection_edge_sorter
Definition: NBContHelper.h:331
NBHelpers::loadPrefixedIDsFomFile
static void loadPrefixedIDsFomFile(const std::string &file, const std::string prefix, std::set< std::string > &into)
Add prefixed ids defined in file.
Definition: NBHelpers.cpp:106
NODETYPE_ALLWAY_STOP
Definition: SUMOXMLDefinitions.h:1059
NBEdge::myFrom
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1533
NBEdgeCont::myEdges
EdgeCont myEdges
The instance of the dictionary (id->edge)
Definition: NBEdgeCont.h:672
NBEdgeCont::computeLanes2Edges
void computeLanes2Edges()
Computes for each edge which lanes approach the next edges.
Definition: NBEdgeCont.cpp:770
NBEdge::getToNode
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486
NBEdge::addLane2LaneConnection
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:1014
NBEdge::Connection::viaShape
PositionVector viaShape
shape of via
Definition: NBEdge.h:251
NBEdge::decLaneNo
void decLaneNo(int by)
decrement lane
Definition: NBEdge.cpp:3213
NBEdgeCont::checkOverlap
void checkOverlap(double threshold, double zThreshold) const
check whether edges overlap
Definition: NBEdgeCont.cpp:1420
NBEdge::getGeometry
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:680
NBEdgeCont::myEdges2Remove
std::set< std::string > myEdges2Remove
Set of ids of edges which shall explicitly be removed.
Definition: NBEdgeCont.h:696
NBEdgeCont::Split::node
NBNode * node
The new node that is created for this split.
Definition: NBEdgeCont.h:215
NBEdgeCont::generateStreetSigns
void generateStreetSigns()
assigns street signs to edges based on toNode types
Definition: NBEdgeCont.cpp:1293
SVCPermissions
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
Definition: SUMOVehicleClass.h:219
PositionVector::getOverlapWith
double getOverlapWith(const PositionVector &poly, double zThreshold) const
Returns the maximum overlaps between this and the given polygon (when not separated by at least zThre...
Definition: PositionVector.cpp:129
NODETYPE_PRIORITY_STOP
Definition: SUMOXMLDefinitions.h:1057
NBEdgeCont::hasPostProcessConnection
bool hasPostProcessConnection(const std::string &from, const std::string &to="")
Definition: NBEdgeCont.cpp:1023
NBNode::typeWasGuessed
bool typeWasGuessed() const
return whether a priority road turns at this node
Definition: NBNode.h:768
NBEdge::UNSPECIFIED_CONTPOS
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:312
NBEdge::Connection::getDescription
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:88
NBEdgeCont::guessRoundabouts
int guessRoundabouts()
Determines which edges belong to roundabouts and increases their priority.
Definition: NBEdgeCont.cpp:1121
SumoXMLNodeType
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
Definition: SUMOXMLDefinitions.h:1049
NBEdge::getLaneID
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:3125
NBEdge::recheckLanes
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again
Definition: NBEdge.cpp:2225
EdgeSet
std::set< NBEdge * > EdgeSet
container for unique edges
Definition: NBCont.h:50
NBTypeCont.h
SUMO_PARAM_ORIGID
const std::string SUMO_PARAM_ORIGID
NBEdge::Connection::shape
PositionVector shape
shape of Connection
Definition: NBEdge.h:239
NBEdge::moveOutgoingConnectionsFrom
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
Definition: NBEdge.cpp:2810
Boundary
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
NBEdgeCont::myTypes2Keep
std::set< std::string > myTypes2Keep
Set of edges types which shall be kept.
Definition: NBEdgeCont.h:705
NBEdgeCont::Split::lanes
std::vector< int > lanes
The lanes after this change.
Definition: NBEdgeCont.h:209
NBEdgeCont::recheckPostProcessConnections
void recheckPostProcessConnections()
Try to set any stored connections.
Definition: NBEdgeCont.cpp:1041
NBEdge::getNumLanes
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:465
NBNode::setRoundabout
void setRoundabout()
update the type of this node as a roundabout
Definition: NBNode.cpp:3081
OutputDevice.h
NBEdge::L2L_COMPUTED
The connection was computed.
Definition: NBEdge.h:126
NBNetBuilder.h
NBEdgeCont::clear
void clear()
Deletes all edges.
Definition: NBEdgeCont.cpp:137
ProcessError
Definition: UtilExceptions.h:40
NBEdgeCont::retrievePossiblySplit
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
Definition: NBEdgeCont.cpp:281
NBEdge::setSpeed
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3382
Position
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
PositionVector::append
void append(const PositionVector &v, double sameThreshold=2.0)
Definition: PositionVector.cpp:688
NBEdge::getTotalWidth
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:3308
NBEdgeCont::myNeedGeoTransformedPruningBoundary
bool myNeedGeoTransformedPruningBoundary
whether a geo transform has been applied to the pruning boundary
Definition: NBEdgeCont.h:714
UtilExceptions.h
NBHelpers.h
NBEdgeCont::removeUnwishedEdges
void removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
Definition: NBEdgeCont.cpp:699
NBEdgeCont::recheckLanes
void recheckLanes()
Rechecks whether all lanes have a successor for each of the stored edges.
Definition: NBEdgeCont.cpp:778
NBEdgeCont::addPostProcessConnection
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass, bool keepClear, double contPos, double visibility, double speed, const PositionVector &customShape, bool uncontrolled, bool warnOnly)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:1016
OptionsCont
A storage for options typed value containers)
Definition: OptionsCont.h:90
NBTypeCont::getShallBeDiscarded
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:196
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:269
NBEdge::getLaneStruct
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1271
NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:315
StringUtils::startsWith
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
Definition: StringUtils.cpp:142
IDSupplier.h
PositionVector::length2D
double length2D() const
Returns the length.
Definition: PositionVector.cpp:489
NBEdgeCont::appendTurnarounds
void appendTurnarounds(bool noTLSControlled, bool onlyDeadends, bool noGeometryLike)
Appends turnarounds to all edges stored in the container.
Definition: NBEdgeCont.cpp:818
NBEdgeCont::myPruningBoundary
PositionVector myPruningBoundary
Boundary within which an edge must be located in order to be kept.
Definition: NBEdgeCont.h:711
NBEdge::removeFromConnections
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1293
NBEdge::L2L_VALIDATED
The connection was computed and validated.
Definition: NBEdge.h:130
NBEdgeCont::Split::pos
double pos
The position of this change.
Definition: NBEdgeCont.h:211
NODETYPE_RIGHT_BEFORE_LEFT
Definition: SUMOXMLDefinitions.h:1058
NBNode::removeEdge
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:1607
NBEdgeCont::splitGeometry
void splitGeometry(NBNodeCont &nc)
Splits edges into multiple if they have a complex geometry.
Definition: NBEdgeCont.cpp:716
PositionVector::splitAt
std::pair< PositionVector, PositionVector > splitAt(double where, bool use2D=false) const
Returns the two lists made when this list vector is splitted at the given point.
Definition: PositionVector.cpp:544
NBEdgeCont::getAllEdges
EdgeVector getAllEdges() const
return all edges
Definition: NBEdgeCont.cpp:1489
NBEdge::getLanes
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:644
NBEdgeCont::appendRailwayTurnarounds
void appendRailwayTurnarounds(const NBPTStopCont &sc)
Appends turnarounds to all bidiRail edges with stops.
Definition: NBEdgeCont.cpp:834
NBEdge::getLoadedLength
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn't set.
Definition: NBEdge.h:542
NBEdgeCont::getAllNames
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:688
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:209
NBEdge::getLength
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:533
NBEdge::getLaneShape
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:871
NBNodeCont.h
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
PositionVector::getMaxGrade
double getMaxGrade(double &maxJump) const
Definition: PositionVector.cpp:1621
StringUtils.h
NBEdgeCont::sortOutgoingLanesConnections
void sortOutgoingLanesConnections()
Sorts all lanes of all edges within the container by their direction.
Definition: NBEdgeCont.cpp:754
NBPTStopCont::getStops
const std::map< std::string, NBPTStop * > & getStops() const
Definition: NBPTStopCont.h:62
NBEdgeCont::reduceGeometries
void reduceGeometries(const double minDist)
Definition: NBEdgeCont.cpp:727
NBEdgeCont::myEdges2Keep
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
Definition: NBEdgeCont.h:693
M_PI
#define M_PI
Definition: odrSpiral.cpp:40
NBEdgeCont::rename
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
Definition: NBEdgeCont.cpp:398
NBEdge::getJunctionPriority
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1843
NBEdge::setLaneWidth
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3271
NBTypeCont
A storage for available types of edges.
Definition: NBTypeCont.h:55
NBEdgeCont::myRoundabouts
std::set< EdgeSet > myRoundabouts
Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout)
Definition: NBEdgeCont.h:718
NBEdge::getSpeed
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:559
NBSign::SIGN_TYPE_STOP
Definition: NBSign.h:50
NBNode::getControllingTLS
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node)
Definition: NBNode.h:322
NBEdge::Lane
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:137
NBEdge::addSign
void addSign(NBSign sign)
add Sign
Definition: NBEdge.h:1303
NBEdgeCont::PostProcessConnection
A structure representing a connection between two lanes.
Definition: NBEdgeCont.h:617
NBEdgeCont::NBEdgeCont
NBEdgeCont(NBTypeCont &tc)
Constructor.
Definition: NBEdgeCont.cpp:57
NBNode::getIncomingEdges
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:259
NBEdge::Lane::oppositeID
std::string oppositeID
An opposite lane ID, if given.
Definition: NBEdge.h:164
NBEdgeCont::guessSpecialLanes
int guessSpecialLanes(SUMOVehicleClass svc, double width, double minSpeed, double maxSpeed, bool fromPermissions, const std::string &excludeOpt)
add sidwalks to edges within the given limits or permissions and return the number of edges affected
Definition: NBEdgeCont.cpp:1333
PositionVector::distances
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
Definition: PositionVector.cpp:1222
NBDistrictCont.h
NBEdgeCont::extract
void extract(NBDistrictCont &dc, NBEdge *edge, bool remember=false)
Removes the given edge from the container like erase but does not delete it.
Definition: NBEdgeCont.cpp:386
NBSign::SIGN_TYPE_PRIORITY
Definition: NBSign.h:53
NBEdgeCont::recheckLaneSpread
void recheckLaneSpread()
Rechecks whether the lane spread is proper.
Definition: NBEdgeCont.cpp:988
NBEdgeCont::formFactor
static double formFactor(const EdgeVector &loopEdges)
compute the form factor for a loop of edges
Definition: NBEdgeCont.cpp:1221
NBEdge::myLanes
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1595
IDSupplier::getNext
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:52
NBEdgeCont::Split::idAfter
std::string idAfter
The id for the edge after the split.
Definition: NBEdgeCont.h:219
NBNode::isSimpleContinuation
bool isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
Definition: NBNode.cpp:469
NBEdge::UNSPECIFIED_WIDTH
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:303
NBNode::removeDoubleEdges
void removeDoubleEdges()
remove duble edges
Definition: NBNode.cpp:1496
NBEdgeCont::computeEdgeShapes
void computeEdgeShapes(double smoothElevationThreshold=-1)
Computes the shapes of all edges stored in the container.
Definition: NBEdgeCont.cpp:855
NBEdgeCont::myEdgesSplit
int myEdgesSplit
the number of splits of edges during the building
Definition: NBEdgeCont.h:681
NBEdge::getFinalLength
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3704
NBEdge::getTypeID
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1061
NBContHelper::nextCW
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
Definition: NBContHelper.cpp:40
NBEdgeCont::joinLanes
int joinLanes(SVCPermissions perms)
join adjacent lanes with the given permissions
Definition: NBEdgeCont.cpp:1478
config.h
NBEdgeCont::addRoundabout
void addRoundabout(const EdgeSet &roundabout)
add user specified roundabout
Definition: NBEdgeCont.cpp:1240
GeomHelper.h
NBEdge::addRestrictedLane
void addRestrictedLane(double width, SUMOVehicleClass vclass)
add a lane of the given width, restricted to the given class and shift existing connections
Definition: NBEdge.cpp:3611
StringTokenizer.h
NBDistrictCont::removeFromSinksAndSources
void removeFromSinksAndSources(NBEdge *const e)
Removes the given edge from the lists of sources and sinks in all stored districts.
Definition: NBDistrictCont.cpp:98
VectorHelper::maxValue
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:90
Boundary::grow
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
NBEdgeCont::myVehicleClasses2Remove
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed)
Definition: NBEdgeCont.h:702
NBNode::invalidateTLS
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool removedConnections, bool addedConnections)
causes the traffic light to be computed anew
Definition: NBNode.cpp:385
NBEdgeCont::removeRoundabout
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
Definition: NBEdgeCont.cpp:1251
NBEdge::incLaneNo
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:3182
StringUtils::toLong
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
Definition: StringUtils.cpp:265
NBEdge::Lane::shape
PositionVector shape
The lane's shape.
Definition: NBEdge.h:142
NBEdgeCont::guessOpposites
void guessOpposites()
Sets opposite lane information for geometrically close edges.
Definition: NBEdgeCont.cpp:958
NBNode
Represents a single node (junction) during network building.
Definition: NBNode.h:68
NBTrafficLightLogicCont.h
NBEdgeCont::computeEdge2Edges
void computeEdge2Edges(bool noLeftMovers)
Computes for each edge the approached edges.
Definition: NBEdgeCont.cpp:762
NBPTStop
The representation of a single pt stop.
Definition: NBPTStop.h:45
NBEdge::Connection
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:184
NBEdge::setConnection
bool setConnection(int lane, NBEdge *destEdge, int destLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED)
Adds a connection to a certain lane of a certain edge.
Definition: NBEdge.cpp:1058
NBEdge::LANES2LANES_USER
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:117
NBEdgeCont::myRemoveEdgesAfterJoining
bool myRemoveEdgesAfterJoining
Whether edges shall be joined first, then removed.
Definition: NBEdgeCont.h:690
PositionVector::area
double area() const
Returns the area (0 for non-closed)
Definition: PositionVector.cpp:502
NBEdgeCont::Split
A structure which describes changes of lane number or speed along the road.
Definition: NBEdgeCont.h:206
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:77
NBEdge::getAngleAtNode
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1863
POSITION_EPS
#define POSITION_EPS
Definition: config.h:169
WRITE_ERROR
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:245
NBEdgeCont::Split::idBefore
std::string idBefore
The id for the edge before the split.
Definition: NBEdgeCont.h:217
NBEdge::getConnections
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:924
NBEdge::getFromNode
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:479
NBEdgeCont::myGuessedRoundabouts
std::set< EdgeSet > myGuessedRoundabouts
Edges marked as belonging to a roundabout after guessing.
Definition: NBEdgeCont.h:720
OptionsCont::getStringVector
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)
Definition: OptionsCont.cpp:921
NBEdgeCont::getRoundabouts
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
Definition: NBEdgeCont.cpp:1232
NBEdge::getCCWBoundaryLine
PositionVector getCCWBoundaryLine(const NBNode &n) const
get the outer boundary of this edge when going counter-clock-wise around the given node
Definition: NBEdge.cpp:2935
NBTrafficLightLogicCont::replaceRemoved
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
Definition: NBTrafficLightLogicCont.cpp:221
NBEdge::setGeometry
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:574
PositionVector::move2side
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
Definition: PositionVector.cpp:1086
NBCont.h
NBSign::SIGN_TYPE_YIELD
Definition: NBSign.h:49
Named::setID
void setID(const std::string &newID)
resets the id
Definition: Named.h:85
NBEdgeCont::getAllRouterEdges
RouterEdgeVector getAllRouterEdges() const
Definition: NBEdgeCont.cpp:1499
NBEdge::getLaneSpreadFunction
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge's lanes' lateral offset is computed.
Definition: NBEdge.h:762
NBNode::replaceIncoming
void replaceIncoming(NBEdge *which, NBEdge *by, int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
Definition: NBNode.cpp:1428
NBEdgeCont::Split::nameID
std::string nameID
the default node id
Definition: NBEdgeCont.h:221
NBHelpers::loadEdgesFromFile
static void loadEdgesFromFile(const std::string &file, std::set< std::string > &into)
Add edge ids defined in file (either ID or edge:ID per line) into the given set.
Definition: NBHelpers.cpp:88
Boundary::overlapsWith
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns whether the boundary overlaps with the given polygon.
Definition: Boundary.cpp:182
NBEdge::getTurnDestination
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3116
NBEdgeCont::clearControllingTLInformation
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:746
NBEdge::getID
const std::string & getID() const
Definition: NBEdge.h:1364