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 /****************************************************************************/
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:47
~NBEdgeCont()
Destructor.
Definition: NBEdgeCont.cpp:66
LaneSpreadFunction getLaneSpreadFunction() const
Returns how this edge&#39;s lanes&#39; lateral offset is computed.
Definition: NBEdge.h:762
std::map< std::string, std::vector< PostProcessConnection > > myConnections
The list of connections to recheck.
Definition: NBEdgeCont.h:665
void invalidateConnections(bool reallowSetting=false)
invalidate current connections of edge
Definition: NBEdge.cpp:1363
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1595
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:533
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
bool isSimpleContinuation(bool checkLaneNumbers=true, bool checkWidth=false) const
check if node is a simple continuation
Definition: NBNode.cpp:469
double length2D() const
Returns the length.
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:184
void sortOutgoingLanesConnections()
Sorts all lanes of all edges within the container by their direction.
Definition: NBEdgeCont.cpp:754
void markRoundabouts()
mark edge priorities and prohibit turn-arounds for all roundabout edges
void setRoundabout()
update the type of this node as a roundabout
Definition: NBNode.cpp:3081
A class representing a single street sign.
Definition: NBSign.h:44
EdgeVector getGeneratedFrom(const std::string &id) const
Returns the edges which have been built by splitting the edge of the given id.
PositionVector shape
The lane&#39;s shape.
Definition: NBEdge.h:142
void append(const PositionVector &v, double sameThreshold=2.0)
void addSign(NBSign sign)
add Sign
Definition: NBEdge.h:1303
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:206
void reduceGeometries(const double minDist)
Definition: NBEdgeCont.cpp:727
SUMOVehicleClass
Definition of vehicle classes to differ between different lane usage and authority types...
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
NBNode * myTo
Definition: NBEdge.h:1533
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:315
A structure which describes changes of lane number or speed along the road.
Definition: NBEdgeCont.h:206
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3332
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
double getMaxGrade(double &maxJump) const
void markAsSplit(const NBNode *node)
mark a node as being created form a split
Definition: NBNodeCont.h:317
bool hasRestrictedLane(SUMOVehicleClass vclass) const
returns whether any lane already allows the given vclass exclusively
Definition: NBEdge.cpp:3600
A container for traffic light definitions and built programs.
int guessRoundabouts()
Determines which edges belong to roundabouts and increases their priority.
bool myRemoveEdgesAfterJoining
Whether edges shall be joined first, then removed.
Definition: NBEdgeCont.h:690
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3382
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1843
NBEdge * getOppositeByID(const std::string &edgeID) const
Returns the edge with negated id if it exists.
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:87
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:1607
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:1061
std::string nameID
the default node id
Definition: NBEdgeCont.h:221
const double SUMO_const_halfLaneAndOffset
Definition: StdDefs.h:55
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.
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
The representation of a single edge during network building.
Definition: NBEdge.h:86
const double SUMO_const_laneWidthAndOffset
Definition: StdDefs.h:54
void guessOpposites()
Sets opposite lane information for geometrically close edges.
Definition: NBEdgeCont.cpp:958
void removeRoundabout(const NBNode *node)
remove roundabout that contains the given node
bool isBidiRail(bool ignoreSpread=false) const
whether this edge is part of a bidirectional railway
Definition: NBEdge.cpp:683
A container for districts.
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:306
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
Definition: GeoConvHelper.h:92
void removeDoubleEdges()
remove duble edges
Definition: NBNode.cpp:1496
T MAX2(T a, T b)
Definition: StdDefs.h:80
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:3116
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
void setLoadedLength(double val)
set loaded lenght
Definition: NBEdge.cpp:3456
void generateStreetSigns()
assigns street signs to edges based on toNode types
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:644
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
Definition: NBEdgeCont.cpp:398
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:556
void recheckPostProcessConnections()
Try to set any stored connections.
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
std::string idAfter
The id for the edge after the split.
Definition: NBEdgeCont.h:219
std::vector< NBRouterEdge * > RouterEdgeVector
Definition: NBCont.h:43
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:196
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
The representation of a single pt stop.
Definition: NBPTStop.h:45
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1271
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns whether the boundary overlaps with the given polygon.
Definition: Boundary.cpp:182
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
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
void computeLanes2Edges()
Computes for each edge which lanes approach the next edges.
Definition: NBEdgeCont.cpp:770
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge&#39;s geometry
Definition: NBEdge.cpp:574
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:88
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:303
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:42
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
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
The connection was computed and validated.
Definition: NBEdge.h:130
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
void checkGeometries(const double maxAngle, const double minRadius, bool fix)
Definition: NBEdgeCont.cpp:735
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:264
void checkOverlap(double threshold, double zThreshold) const
check whether edges overlap
int joinLanes(SVCPermissions perms)
join adjacent lanes with the given permissions
double area() const
Returns the area (0 for non-closed)
void checkGrade(double threshold) const
check whether edges are to steep
PositionVector myPruningBoundary
Boundary within which an edge must be located in order to be kept.
Definition: NBEdgeCont.h:711
PositionVector shape
shape of Connection
Definition: NBEdge.h:239
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&#39;s lane and an approached one.
Definition: NBEdge.cpp:1014
double pos
The position of this change.
Definition: NBEdgeCont.h:211
NBEdgeCont(NBTypeCont &tc)
Constructor.
Definition: NBEdgeCont.cpp:57
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
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 ...
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:2161
RouterEdgeVector getAllRouterEdges() const
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:137
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void invalidateTLS(NBTrafficLightLogicCont &tlCont, bool removedConnections, bool addedConnections)
causes the traffic light to be computed anew
Definition: NBNode.cpp:385
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:990
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:3182
NBNode * node
The new node that is created for this split.
Definition: NBEdgeCont.h:215
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
Definition: NBEdgeCont.h:699
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:72
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
Definition: GeomHelper.cpp:90
double myEdgesMinSpeed
The minimum speed an edge may have in order to be kept (default: -1)
Definition: NBEdgeCont.h:687
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:117
std::set< NBEdge * > EdgeSet
container for unique edges
Definition: NBCont.h:50
void patchRoundabouts(NBEdge *orig, NBEdge *part1, NBEdge *part2, std::set< EdgeSet > &roundabouts)
fix roundabout information after splitting an edge
Definition: NBEdgeCont.cpp:670
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:52
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:152
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
Definition: NBEdgeCont.cpp:281
int offsetFactor
direction in which to apply the offset (used by netgenerate for lefthand networks) ...
Definition: NBEdgeCont.h:225
void removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
Definition: NBEdgeCont.cpp:699
void decLaneNo(int by)
decrement lane
Definition: NBEdge.cpp:3213
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.
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter ...
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:3125
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
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
A list of positions.
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
Definition: NBEdgeCont.cpp:72
void setOrigID(const std::string origID)
set origID for all lanes
Definition: NBEdge.cpp:3725
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
Definition: NBEdge.cpp:2810
void move2side(double amount, double maxExtension=100)
move position vector to side using certain ammount
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:312
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
Definition: NBEdgeCont.h:693
void computeEdge2Edges(bool noLeftMovers)
Computes for each edge the approached edges.
Definition: NBEdgeCont.cpp:762
void computeLaneShapes()
Computes the shapes of all lanes of all edges stored in the container.
Definition: NBEdgeCont.cpp:863
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
Definition: NBNode.h:269
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:746
const std::string & getID() const
Definition: NBEdge.h:1364
static double formFactor(const EdgeVector &loopEdges)
compute the form factor for a loop of edges
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
void processSplits(NBEdge *e, std::vector< Split > splits, NBNodeCont &nc, NBDistrictCont &dc, NBTrafficLightLogicCont &tlc)
Definition: NBEdgeCont.cpp:411
void splitGeometry(NBNodeCont &nc)
Splits edges into multiple if they have a complex geometry.
Definition: NBEdgeCont.cpp:716
EdgeCont myEdges
The instance of the dictionary (id->edge)
Definition: NBEdgeCont.h:672
#define POSITION_EPS
Definition: config.h:169
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.
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:301
SVCPermissions parseVehicleClasses(const std::string &allowedS)
Parses the given definition of allowed vehicle classes into the given containers Deprecated classes g...
std::vector< int > lanes
The lanes after this change.
Definition: NBEdgeCont.h:209
void clear()
Deletes all edges.
Definition: NBEdgeCont.cpp:137
EdgeCont myExtractedEdges
The extracted nodes which are kept for reference.
Definition: NBEdgeCont.h:675
The connection was given by the user.
Definition: NBEdge.h:128
std::set< EdgeSet > myGuessedRoundabouts
Edges marked as belonging to a roundabout after guessing.
Definition: NBEdgeCont.h:720
bool typeWasGuessed() const
return whether a priority road turns at this node
Definition: NBNode.h:768
std::set< EdgeSet > myRoundabouts
Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout) ...
Definition: NBEdgeCont.h:718
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
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3704
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again ...
Definition: NBEdge.cpp:2225
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:871
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:559
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed) ...
Definition: NBEdgeCont.h:702
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:680
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:245
const std::map< std::string, NBPTStop * > & getStops() const
Definition: NBPTStopCont.h:62
std::set< std::string > myTypes2Keep
Set of edges types which shall be kept.
Definition: NBEdgeCont.h:705
EdgeVector getAllEdges() const
return all edges
void setID(const std::string &newID)
resets the id
Definition: Named.h:85
double length() const
Returns the length.
PositionVector viaShape
shape of via
Definition: NBEdge.h:251
std::string oppositeID
An opposite lane ID, if given.
Definition: NBEdge.h:164
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
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:924
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
#define M_PI
Definition: odrSpiral.cpp:40
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
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
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
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, which
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:3308
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
bool myNeedGeoTransformedPruningBoundary
whether a geo transform has been applied to the pruning boundary
Definition: NBEdgeCont.h:714
A storage for options typed value containers)
Definition: OptionsCont.h:90
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:276
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:379
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
const std::string SUMO_PARAM_ORIGID
A structure representing a connection between two lanes.
Definition: NBEdgeCont.h:617
double speed
The speed after this change.
Definition: NBEdgeCont.h:213
Sorts splits by their position (increasing)
Definition: NBEdgeCont.h:725
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
void appendRailwayTurnarounds(const NBPTStopCont &sc)
Appends turnarounds to all bidiRail edges with stops.
Definition: NBEdgeCont.cpp:834
bool hasPostProcessConnection(const std::string &from, const std::string &to="")
The connection was computed.
Definition: NBEdge.h:126
const double SUMO_const_haltingSpeed
the speed threshold at which vehicles are considered as halting
Definition: StdDefs.h:61
const Position & getPosition() const
Definition: NBNode.h:251
Represents a single node (junction) during network building.
Definition: NBNode.h:68
void dismissVehicleClassInformation()
dimiss vehicle class information
Definition: NBEdge.cpp:3462
NBTypeCont & myTypeCont
The network builder; used to obtain type information.
Definition: NBEdgeCont.h:612
void recheckLaneSpread()
Rechecks whether the lane spread is proper.
Definition: NBEdgeCont.cpp:988
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
#define NUMERICAL_EPS
Definition: config.h:145
void computeEdgeShapes(double smoothElevationThreshold=-1)
Computes the shapes of all edges stored in the container.
Definition: NBEdgeCont.cpp:855
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:479
void removeFromSinksAndSources(NBEdge *const e)
Removes the given edge from the lists of sources and sinks in all stored districts.
std::set< std::string > myTypes2Remove
Set of edges types which shall be removed.
Definition: NBEdgeCont.h:708
void recheckLanes()
Rechecks whether all lanes have a successor for each of the stored edges.
Definition: NBEdgeCont.cpp:778
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:60
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
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:90
std::set< std::string > myIgnoredEdges
The ids of ignored edges.
Definition: NBEdgeCont.h:678
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...
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
void addRoundabout(const EdgeSet &roundabout)
add user specified roundabout
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:542
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:877
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:688
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string &prefix, NBPTStopCont &sc)
remap node IDs accoring to options –numerical-ids and –reserved-ids
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1533
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486
std::string idBefore
The id for the edge before the split.
Definition: NBEdgeCont.h:217
void appendTurnarounds(bool noTLSControlled, bool onlyDeadends, bool noGeometryLike)
Appends turnarounds to all edges stored in the container.
Definition: NBEdgeCont.cpp:818
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
Definition: NBEdge.cpp:1478
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:3271
bool ignoreFilterMatch(NBEdge *edge)
Returns true if this edge matches one of the removal criteria.
Definition: NBEdgeCont.cpp:173
A storage for available types of edges.
Definition: NBTypeCont.h:55
double offset
lateral offset to edge geometry
Definition: NBEdgeCont.h:223
int myEdgesSplit
the number of splits of edges during the building
Definition: NBEdgeCont.h:681
std::set< std::string > myEdges2Remove
Set of ids of edges which shall explicitly be removed.
Definition: NBEdgeCont.h:696