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-2017 German Aerospace Center (DLR) and others.
4 /****************************************************************************/
5 //
6 // This program and the accompanying materials
7 // are made available under the terms of the Eclipse Public License v2.0
8 // which accompanies this distribution, and is available at
9 // http://www.eclipse.org/legal/epl-v20.html
10 //
11 /****************************************************************************/
20 // Storage for edges, including some functionality operating on multiple edges
21 /****************************************************************************/
22 
23 
24 // ===========================================================================
25 // included modules
26 // ===========================================================================
27 #ifdef _MSC_VER
28 #include <windows_config.h>
29 #else
30 #include <config.h>
31 #endif
32 
33 #include <vector>
34 #include <string>
35 #include <cassert>
36 #include <algorithm>
37 #include <cmath>
38 #include <utils/geom/Boundary.h>
39 #include <utils/geom/GeomHelper.h>
42 #include <utils/common/ToString.h>
49 #include "NBNetBuilder.h"
50 #include "NBEdgeCont.h"
51 #include "NBNodeCont.h"
52 #include "NBHelpers.h"
53 #include "NBCont.h"
55 #include "NBDistrictCont.h"
56 #include "NBTypeCont.h"
57 
58 
59 // ===========================================================================
60 // method definitions
61 // ===========================================================================
63  myTypeCont(tc),
64  myEdgesSplit(0),
65  myVehicleClasses2Keep(0),
66  myVehicleClasses2Remove(0),
67  myNeedGeoTransformedPruningBoundary(false) {
68 }
69 
70 
72  clear();
73 }
74 
75 
76 void
78  // set edges dismiss/accept options
79  myEdgesMinSpeed = oc.getFloat("keep-edges.min-speed");
80  myRemoveEdgesAfterJoining = oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload");
81  // we possibly have to load the edges to keep/remove
82  if (oc.isSet("keep-edges.input-file")) {
83  NBHelpers::loadEdgesFromFile(oc.getString("keep-edges.input-file"), myEdges2Keep);
84  }
85  if (oc.isSet("remove-edges.input-file")) {
86  NBHelpers::loadEdgesFromFile(oc.getString("remove-edges.input-file"), myEdges2Remove);
87  }
88  if (oc.isSet("keep-edges.explicit")) {
89  const std::vector<std::string> edges = oc.getStringVector("keep-edges.explicit");
90  myEdges2Keep.insert(edges.begin(), edges.end());
91  }
92  if (oc.isSet("remove-edges.explicit")) {
93  const std::vector<std::string> edges = oc.getStringVector("remove-edges.explicit");
94  myEdges2Remove.insert(edges.begin(), edges.end());
95  }
96  if (oc.exists("keep-edges.by-vclass") && oc.isSet("keep-edges.by-vclass")) {
97  myVehicleClasses2Keep = parseVehicleClasses(oc.getStringVector("keep-edges.by-vclass"));
98  }
99  if (oc.exists("remove-edges.by-vclass") && oc.isSet("remove-edges.by-vclass")) {
100  myVehicleClasses2Remove = parseVehicleClasses(oc.getStringVector("remove-edges.by-vclass"));
101  }
102  if (oc.exists("keep-edges.by-type") && oc.isSet("keep-edges.by-type")) {
103  const std::vector<std::string> types = oc.getStringVector("keep-edges.by-type");
104  myTypes2Keep.insert(types.begin(), types.end());
105  }
106  if (oc.exists("remove-edges.by-type") && oc.isSet("remove-edges.by-type")) {
107  const std::vector<std::string> types = oc.getStringVector("remove-edges.by-type");
108  myTypes2Remove.insert(types.begin(), types.end());
109  }
110 
111  if (oc.isSet("keep-edges.in-boundary") || oc.isSet("keep-edges.in-geo-boundary")) {
112  std::vector<std::string> polyS = oc.getStringVector(oc.isSet("keep-edges.in-boundary") ?
113  "keep-edges.in-boundary" : "keep-edges.in-geo-boundary");
114  // !!! throw something if length<4 || length%2!=0?
115  std::vector<double> poly;
116  for (std::vector<std::string>::iterator i = polyS.begin(); i != polyS.end(); ++i) {
117  poly.push_back(TplConvert::_2double((*i).c_str())); // !!! may throw something anyhow...
118  }
119  if (poly.size() < 4) {
120  throw ProcessError("Invalid boundary: need at least 2 coordinates");
121  } else if (poly.size() % 2 != 0) {
122  throw ProcessError("Invalid boundary: malformed coordinate");
123  } else if (poly.size() == 4) {
124  // prunning boundary (box)
125  myPruningBoundary.push_back(Position(poly[0], poly[1]));
126  myPruningBoundary.push_back(Position(poly[2], poly[1]));
127  myPruningBoundary.push_back(Position(poly[2], poly[3]));
128  myPruningBoundary.push_back(Position(poly[0], poly[3]));
129  } else {
130  for (std::vector<double>::iterator j = poly.begin(); j != poly.end();) {
131  double x = *j++;
132  double y = *j++;
133  myPruningBoundary.push_back(Position(x, y));
134  }
135  }
136  myNeedGeoTransformedPruningBoundary = oc.isSet("keep-edges.in-geo-boundary");
137  }
138 }
139 
140 
141 void
143  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
144  delete((*i).second);
145  }
146  myEdges.clear();
147  for (EdgeCont::iterator i = myExtractedEdges.begin(); i != myExtractedEdges.end(); i++) {
148  delete((*i).second);
149  }
150  myExtractedEdges.clear();
151 }
152 
153 
154 
155 // ----- edge access methods
156 bool
157 NBEdgeCont::insert(NBEdge* edge, bool ignorePrunning) {
158  if (myEdges.count(edge->getID()) != 0) {
159  return false;
160  }
161  if (!ignorePrunning && ignoreFilterMatch(edge)) {
162  edge->getFromNode()->removeEdge(edge);
163  edge->getToNode()->removeEdge(edge);
164  myIgnoredEdges.insert(edge->getID());
165  delete edge;
166  } else {
168  if (oc.exists("dismiss-vclasses") && oc.getBool("dismiss-vclasses")) {
170  }
171  myEdges[edge->getID()] = edge;
172  }
173  return true;
174 }
175 
176 
177 bool
179  // remove edges which allow a speed below a set one (set using "keep-edges.min-speed")
180  if (edge->getSpeed() < myEdgesMinSpeed) {
181  return true;
182  }
183  // check whether the edge is a named edge to keep
184  if (!myRemoveEdgesAfterJoining && myEdges2Keep.size() != 0) {
185  if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) == myEdges2Keep.end()) {
186  // explicit whitelisting may be combined additively with other filters
188  && myTypes2Keep.size() == 0 && myTypes2Remove.size() == 0
189  && myPruningBoundary.size() == 0) {
190  return true;
191  }
192  } else {
193  // explicit whitelisting overrides other filters
194  return false;
195  }
196  }
197  // check whether the edge is a named edge to remove
198  if (myEdges2Remove.size() != 0) {
199  if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) {
200  return true;
201  }
202  }
203  // check whether the edge shall be removed because it does not allow any of the wished classes
204  if (myVehicleClasses2Keep != 0 && (myVehicleClasses2Keep & edge->getPermissions()) == 0) {
205  return true;
206  }
207  // check whether the edge shall be removed due to allowing unwished classes only
209  return true;
210  }
211  // check whether the edge shall be removed because it does not have one of the requested types
212  if (myTypes2Keep.size() != 0) {
213  if (myTypes2Keep.count(edge->getTypeID()) == 0) {
214  return true;
215  }
216  }
217  // check whether the edge shall be removed because it has one of the forbidden types
218  if (myTypes2Remove.size() != 0) {
219  if (myTypes2Remove.count(edge->getTypeID()) > 0) {
220  return true;
221  }
222  }
223  // check whether the edge is within the pruning boundary
224  if (myPruningBoundary.size() != 0) {
228  } else if (GeoConvHelper::getLoaded().usingGeoProjection()) {
229  // XXX what if input file with different projections are loaded?
230  for (int i = 0; i < (int) myPruningBoundary.size(); i++) {
232  }
233  } else {
234  WRITE_ERROR("Cannot prune edges using a geo-boundary because no projection has been loaded");
235  }
237  }
239  return true;
240  }
241  }
243  return true;
244  }
245  return false;
246 }
247 
248 
249 NBEdge*
250 NBEdgeCont::retrieve(const std::string& id, bool retrieveExtracted) const {
251  EdgeCont::const_iterator i = myEdges.find(id);
252  if (i == myEdges.end()) {
253  if (retrieveExtracted) {
254  i = myExtractedEdges.find(id);
255  if (i == myExtractedEdges.end()) {
256  return 0;
257  }
258  } else {
259  return 0;
260  }
261  }
262  return (*i).second;
263 }
264 
265 // FIXME: This can't work
266 /*
267 NBEdge*
268 NBEdgeCont::retrievePossiblySplit(const std::string& id, bool downstream) const {
269  NBEdge* edge = retrieve(id);
270  if (edge == 0) {
271  return 0;
272  }
273  const EdgeVector* candidates = downstream ? &edge->getToNode()->getOutgoingEdges() : &edge->getFromNode()->getIncomingEdges();
274  while (candidates->size() == 1) {
275  const std::string& nextID = candidates->front()->getID();
276  if (nextID.find(id) != 0 || nextID.size() <= id.size() + 1 || (nextID[id.size()] != '.' && nextID[id.size()] != '-')) {
277  break;
278  }
279  edge = candidates->front();
280  candidates = downstream ? &edge->getToNode()->getOutgoingEdges() : &edge->getFromNode()->getIncomingEdges();
281  }
282  return edge;
283 }*/
284 
285 NBEdge*
286 NBEdgeCont::retrievePossiblySplit(const std::string& id, bool downstream) const {
287  NBEdge* edge = retrieve(id);
288  if (edge != 0) {
289  return edge;
290  }
291  // NOTE: (TODO) for multiply split edges (e.g. 15[0][0]) one could try recursion
292  if ((retrieve(id + "[0]") != 0) && (retrieve(id + "[1]") != 0)) {
293  // Edge was split during the netbuilding process
294  if (downstream == true) {
295  return retrieve(id + "[1]");
296  } else {
297  return retrieve(id + "[0]");
298  }
299  }
300  return edge;
301 }
302 
303 
304 NBEdge*
305 NBEdgeCont::retrievePossiblySplit(const std::string& id, const std::string& hint, bool incoming) const {
306  // try to retrieve using the given name (iterative)
307  NBEdge* edge = retrieve(id);
308  if (edge != 0) {
309  return edge;
310  }
311  // now, we did not find it; we have to look over all possibilities
312  EdgeVector hints;
313  // check whether at least the hint was not splitted
314  NBEdge* hintedge = retrieve(hint);
315  if (hintedge == 0) {
316  hints = getGeneratedFrom(hint);
317  } else {
318  hints.push_back(hintedge);
319  }
320  EdgeVector candidates = getGeneratedFrom(id);
321  for (EdgeVector::iterator i = hints.begin(); i != hints.end(); i++) {
322  NBEdge* hintedge = (*i);
323  for (EdgeVector::iterator j = candidates.begin(); j != candidates.end(); j++) {
324  NBEdge* poss_searched = (*j);
325  NBNode* node = incoming
326  ? poss_searched->myTo : poss_searched->myFrom;
327  const EdgeVector& cont = incoming
328  ? node->getOutgoingEdges() : node->getIncomingEdges();
329  if (find(cont.begin(), cont.end(), hintedge) != cont.end()) {
330  return poss_searched;
331  }
332  }
333  }
334  return 0;
335 }
336 
337 
338 NBEdge*
339 NBEdgeCont::retrievePossiblySplit(const std::string& id, double pos) const {
340  // check whether the edge was not split, yet
341  NBEdge* edge = retrieve(id);
342  if (edge != 0) {
343  return edge;
344  }
345  int maxLength = 0;
346  std::string tid = id + "[";
347  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
348  if ((*i).first.find(tid) == 0) {
349  maxLength = MAX2(maxLength, (int)(*i).first.length());
350  }
351  }
352  // find the part of the edge which matches the position
353  double seen = 0;
354  std::vector<std::string> names;
355  names.push_back(id + "[1]");
356  names.push_back(id + "[0]");
357  while (names.size() > 0) {
358  // retrieve the first subelement (to follow)
359  std::string cid = names.back();
360  names.pop_back();
361  edge = retrieve(cid);
362  // The edge was splitted; check its subparts within the
363  // next step
364  if (edge == 0) {
365  if ((int)cid.length() + 3 < maxLength) {
366  names.push_back(cid + "[1]");
367  names.push_back(cid + "[0]");
368  }
369  }
370  // an edge with the name was found,
371  // check whether the position lies within it
372  else {
373  seen += edge->getLength();
374  if (seen >= pos) {
375  return edge;
376  }
377  }
378  }
379  return 0;
380 }
381 
382 
383 void
385  extract(dc, edge);
386  delete edge;
387 }
388 
389 
390 void
391 NBEdgeCont::extract(NBDistrictCont& dc, NBEdge* edge, bool remember) {
392  if (remember) {
393  myExtractedEdges[edge->getID()] = edge;
394  }
395  myEdges.erase(edge->getID());
396  edge->myFrom->removeEdge(edge);
397  edge->myTo->removeEdge(edge);
398  dc.removeFromSinksAndSources(edge);
399 }
400 
401 
402 void
403 NBEdgeCont::rename(NBEdge* edge, const std::string& newID) {
404  if (myEdges.count(newID) != 0) {
405  throw ProcessError("Attempt to rename edge using existing id '" + newID + "'");
406  }
407  myEdges.erase(edge->getID());
408  edge->setID(newID);
409  myEdges[newID] = edge;
410 }
411 
412 
413 // ----- explicit edge manipulation methods
414 bool
416  return splitAt(dc, edge, node, edge->getID() + "[0]", edge->getID() + "[1]",
417  (int) edge->myLanes.size(), (int) edge->myLanes.size());
418 }
419 
420 
421 bool
423  const std::string& firstEdgeName,
424  const std::string& secondEdgeName,
425  int noLanesFirstEdge, int noLanesSecondEdge,
426  const double speed,
427  const int changedLeft) {
428  double pos;
429  pos = edge->getGeometry().nearest_offset_to_point2D(node->getPosition());
430  if (pos <= 0) {
432  edge->myFrom->getPosition(), edge->myTo->getPosition(),
433  node->getPosition());
434  }
435  if (pos <= 0 || pos + POSITION_EPS > edge->getGeometry().length()) {
436  return false;
437  }
438  return splitAt(dc, edge, pos, node, firstEdgeName, secondEdgeName,
439  noLanesFirstEdge, noLanesSecondEdge, speed, changedLeft);
440 }
441 
442 
443 bool
445  NBEdge* edge, double pos, NBNode* node,
446  const std::string& firstEdgeName,
447  const std::string& secondEdgeName,
448  int noLanesFirstEdge, int noLanesSecondEdge,
449  const double speed,
450  const int changedLeft
451  ) {
452  // there must be at least some overlap between first and second edge
453  assert(changedLeft > -((int)noLanesFirstEdge));
454  assert(changedLeft < (int)noLanesSecondEdge);
455 
456  // build the new edges' geometries
457  std::pair<PositionVector, PositionVector> geoms =
458  edge->getGeometry().splitAt(pos);
459  if (geoms.first[-1] != node->getPosition()) {
460  geoms.first.pop_back();
461  geoms.first.push_back(node->getPosition());
462  }
463 
464  if (geoms.second[0] != node->getPosition()) {
465  geoms.second[0] = node->getPosition();
466  }
467  // build and insert the edges
468  NBEdge* one = new NBEdge(firstEdgeName, edge->myFrom, node, edge, geoms.first, noLanesFirstEdge);
469  NBEdge* two = new NBEdge(secondEdgeName, node, edge->myTo, edge, geoms.second, noLanesSecondEdge);
470  if (OptionsCont::getOptions().getBool("output.original-names")) {
471  const std::string origID = edge->getLaneStruct(0).getParameter(SUMO_PARAM_ORIGID, edge->getID());
472  if (firstEdgeName != origID) {
473  one->setOrigID(origID);
474  }
475  if (secondEdgeName != origID) {
476  two->setOrigID(origID);
477  }
478  }
479  two->copyConnectionsFrom(edge);
480  if (speed != -1.) {
481  two->setSpeed(-1, speed);
482  }
483  // replace information about this edge within the nodes
484  edge->myFrom->replaceOutgoing(edge, one, 0);
485  edge->myTo->replaceIncoming(edge, two, 0);
486  // patch tls
487  std::set<NBTrafficLightDefinition*> fromTLS = edge->myFrom->getControllingTLS();
488  for (std::set<NBTrafficLightDefinition*>::iterator i = fromTLS.begin(); i != fromTLS.end(); ++i) {
489  (*i)->replaceRemoved(edge, -1, one, -1);
490  }
491  std::set<NBTrafficLightDefinition*> toTLS = edge->myTo->getControllingTLS();
492  for (std::set<NBTrafficLightDefinition*>::iterator i = toTLS.begin(); i != toTLS.end(); ++i) {
493  (*i)->replaceRemoved(edge, -1, two, -1);
494  }
495  // the edge is now occuring twice in both nodes...
496  // clean up
497  edge->myFrom->removeDoubleEdges();
498  edge->myTo->removeDoubleEdges();
499  // add connections from the first to the second edge
500  // there will be as many connections as there are lanes on the second edge
501  // by default lanes will be added / discontinued on the right side
502  // (appropriate for highway on-/off-ramps)
503  const int offset = (int)one->getNumLanes() - (int)two->getNumLanes() + changedLeft;
504  for (int i2 = 0; i2 < (int)two->getNumLanes(); i2++) {
505  const int i1 = MIN2(MAX2((int)0, i2 + offset), (int)one->getNumLanes());
506  if (!one->addLane2LaneConnection(i1, two, i2, NBEdge::L2L_COMPUTED)) {
507  throw ProcessError("Could not set connection!");
508  }
509  }
511  if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) != myEdges2Keep.end()) {
512  myEdges2Keep.insert(one->getID());
513  myEdges2Keep.insert(two->getID());
514  }
515  if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) {
516  myEdges2Remove.insert(one->getID());
517  myEdges2Remove.insert(two->getID());
518  }
519  }
520  // erase the splitted edge
521  patchRoundabouts(edge, one, two, myRoundabouts);
522  patchRoundabouts(edge, one, two, myGuessedRoundabouts);
523  erase(dc, edge);
524  insert(one, true);
525  insert(two, true);
526  myEdgesSplit++;
527  return true;
528 }
529 
530 
531 void
532 NBEdgeCont::patchRoundabouts(NBEdge* orig, NBEdge* part1, NBEdge* part2, std::set<EdgeSet>& roundabouts) {
533  std::set<EdgeSet> addLater;
534  for (std::set<EdgeSet>::iterator it = roundabouts.begin(); it != roundabouts.end(); ++it) {
535  EdgeSet roundaboutSet = *it;
536  if (roundaboutSet.count(orig) > 0) {
537  roundaboutSet.erase(orig);
538  roundaboutSet.insert(part1);
539  roundaboutSet.insert(part2);
540  }
541  addLater.insert(roundaboutSet);
542  }
543  roundabouts.clear();
544  roundabouts.insert(addLater.begin(), addLater.end());
545 }
546 
547 
548 // ----- container access methods
549 std::vector<std::string>
551  std::vector<std::string> ret;
552  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
553  ret.push_back((*i).first);
554  }
555  return ret;
556 }
557 
558 
559 // ----- Adapting the input
560 void
562  EdgeVector toRemove;
563  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
564  NBEdge* edge = (*i).second;
565  if (!myEdges2Keep.count(edge->getID())) {
566  edge->getFromNode()->removeEdge(edge);
567  edge->getToNode()->removeEdge(edge);
568  toRemove.push_back(edge);
569  }
570  }
571  for (EdgeVector::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
572  erase(dc, *j);
573  }
574 }
575 
576 
577 void
579  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
580  if ((*i).second->getGeometry().size() < 3) {
581  continue;
582  }
583  (*i).second->splitGeometry(*this, nc);
584  }
585 }
586 
587 
588 void
589 NBEdgeCont::reduceGeometries(const double minDist) {
590  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
591  (*i).second->reduceGeometry(minDist);
592  }
593 }
594 
595 
596 void
597 NBEdgeCont::checkGeometries(const double maxAngle, const double minRadius, bool fix) {
598  if (maxAngle > 0 || minRadius > 0) {
599  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
600  (*i).second->checkGeometry(maxAngle, minRadius, fix);
601  }
602  }
603 }
604 
605 
606 // ----- processing methods
607 void
609  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); i++) {
610  (*i).second->clearControllingTLInformation();
611  }
612 }
613 
614 
615 void
617  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
618  (*i).second->sortOutgoingConnectionsByAngle();
619  }
620 }
621 
622 
623 void
624 NBEdgeCont::computeEdge2Edges(bool noLeftMovers) {
625  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
626  (*i).second->computeEdge2Edges(noLeftMovers);
627  }
628 }
629 
630 
631 void
633  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
634  (*i).second->computeLanes2Edges();
635  }
636 }
637 
638 
639 void
641  const bool fixOppositeLengths = OptionsCont::getOptions().getBool("opposites.guess.fix-lengths");
642  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
643  NBEdge* edge = i->second;
644  edge->recheckLanes();
645  // check opposites
646  if (edge->getNumLanes() > 0) {
647  const std::string& oppositeID = edge->getLanes().back().oppositeID;
648  if (oppositeID != "" && oppositeID != "-") {
649  NBEdge* oppEdge = retrieve(oppositeID.substr(0, oppositeID.rfind("_")));
650  if (oppEdge == 0 || oppEdge->getLaneID(oppEdge->getNumLanes() - 1) != oppositeID) {
651  WRITE_WARNING("Removing unknown opposite lane '" + oppositeID + "' for edge '" + edge->getID() + "'.");
652  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
653  continue;
654  }
655  if (fabs(oppEdge->getLoadedLength() - edge->getLoadedLength()) > POSITION_EPS) {
656  if (fixOppositeLengths) {
657  const double avgLength = 0.5 * (edge->getFinalLength() + oppEdge->getFinalLength());
658  WRITE_WARNING("Averaging edge lengths for lane '" + oppositeID + "' (length " + toString(oppEdge->getLoadedLength()) + ") and edge '" + edge->getID() + "' (length "
659  + toString(edge->getLoadedLength()) + ").");
660  edge->setLoadedLength(avgLength);
661  oppEdge->setLoadedLength(avgLength);
662  } else {
663  WRITE_ERROR("Opposite lane '" + oppositeID + "' (length " + toString(oppEdge->getLoadedLength()) + ") differs in length from edge '" + edge->getID() + "' (length "
664  + toString(edge->getLoadedLength()) + "). Set --opposites.guess.fix-lengths to fix this.");
665  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
666  continue;
667  }
668  }
669  if (oppEdge->getFromNode() != edge->getToNode() || oppEdge->getToNode() != edge->getFromNode()) {
670  WRITE_ERROR("Opposite lane '" + oppositeID + "' does not connect the same nodes as edge '" + edge->getID() + "'!");
671  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
672  }
673  }
674  }
675  }
676 }
677 
678 
679 void
680 NBEdgeCont::appendTurnarounds(bool noTLSControlled) {
681  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
682  (*i).second->appendTurnaround(noTLSControlled, true);
683  }
684 }
685 
686 
687 void
688 NBEdgeCont::appendTurnarounds(const std::set<std::string>& ids, bool noTLSControlled) {
689  for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
690  myEdges[*it]->appendTurnaround(noTLSControlled, false);
691  }
692 }
693 
694 
695 void
697  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
698  (*i).second->computeEdgeShape();
699  }
700 }
701 
702 
703 void
705  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
706  (*i).second->computeLaneShapes();
707  }
708 }
709 
710 
711 void
714  EdgeVector edges) {
715  // !!! Attention!
716  // No merging of the geometry to come is being done
717  // The connections are moved from one edge to another within
718  // the replacement where the edge is a node's incoming edge.
719 
720  // count the number of lanes, the speed and the id
721  int nolanes = 0;
722  double speed = 0;
723  int priority = 0;
724  std::string id;
725  sort(edges.begin(), edges.end(), NBContHelper::same_connection_edge_sorter());
726  // retrieve the connected nodes
727  NBEdge* tpledge = *(edges.begin());
728  NBNode* from = tpledge->getFromNode();
729  NBNode* to = tpledge->getToNode();
730  EdgeVector::const_iterator i;
731  for (i = edges.begin(); i != edges.end(); i++) {
732  // some assertions
733  assert((*i)->getFromNode() == from);
734  assert((*i)->getToNode() == to);
735  // ad the number of lanes the current edge has
736  nolanes += (*i)->getNumLanes();
737  // build the id
738  if (i != edges.begin()) {
739  id += "+";
740  }
741  id += (*i)->getID();
742  // compute the speed
743  speed += (*i)->getSpeed();
744  // build the priority
745  priority = MAX2(priority, (*i)->getPriority());
746  }
747  speed /= edges.size();
748  // build the new edge
749  NBEdge* newEdge = new NBEdge(id, from, to, "", speed, nolanes, priority,
751  tpledge->getStreetName(), tpledge->myLaneSpreadFunction);
752  // copy lane attributes
753  int laneIndex = 0;
754  for (i = edges.begin(); i != edges.end(); ++i) {
755  const std::vector<NBEdge::Lane>& lanes = (*i)->getLanes();
756  for (int j = 0; j < (int)lanes.size(); ++j) {
757  newEdge->setPermissions(lanes[j].permissions, laneIndex);
758  newEdge->setLaneWidth(laneIndex, lanes[j].width);
759  newEdge->setEndOffset(laneIndex, lanes[j].endOffset);
760  laneIndex++;
761  }
762  }
763  insert(newEdge, true);
764  // replace old edge by current within the nodes
765  // and delete the old
766  from->replaceOutgoing(edges, newEdge);
767  to->replaceIncoming(edges, newEdge);
768  // patch connections
769  // add edge2edge-information
770  for (i = edges.begin(); i != edges.end(); i++) {
771  EdgeVector ev = (*i)->getConnectedEdges();
772  for (EdgeVector::iterator j = ev.begin(); j != ev.end(); j++) {
773  newEdge->addEdge2EdgeConnection(*j);
774  }
775  }
776  // copy outgoing connections to the new edge
777  int currLane = 0;
778  for (i = edges.begin(); i != edges.end(); i++) {
779  newEdge->moveOutgoingConnectionsFrom(*i, currLane);
780  currLane += (*i)->getNumLanes();
781  }
782  // patch tl-information
783  currLane = 0;
784  for (i = edges.begin(); i != edges.end(); i++) {
785  int noLanes = (*i)->getNumLanes();
786  for (int j = 0; j < noLanes; j++, currLane++) {
787  // replace in traffic lights
788  tlc.replaceRemoved(*i, j, newEdge, currLane);
789  }
790  }
791  // delete joined edges
792  for (i = edges.begin(); i != edges.end(); i++) {
793  extract(dc, *i, true);
794  }
795 }
796 
797 
798 void
800  //@todo magic values
801  const double distanceThreshold = 7;
802  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
803  NBEdge* edge = i->second;
804  const int numLanes = edge->getNumLanes();
805  if (numLanes > 0) {
806  NBEdge::Lane& lastLane = edge->getLaneStruct(numLanes - 1);
807  if (lastLane.oppositeID == "") {
808  NBEdge* opposite = 0;
809  //double minOppositeDist = std::numeric_limits<double>::max();
810  for (EdgeVector::const_iterator j = edge->getToNode()->getOutgoingEdges().begin(); j != edge->getToNode()->getOutgoingEdges().end(); ++j) {
811  if ((*j)->getToNode() == edge->getFromNode() && !(*j)->getLanes().empty()) {
812  const double distance = VectorHelper<double>::maxValue(lastLane.shape.distances((*j)->getLanes().back().shape));
813  if (distance < distanceThreshold) {
814  //minOppositeDist = distance;
815  opposite = *j;
816  }
817  }
818  }
819  if (opposite != 0) {
820  lastLane.oppositeID = opposite->getLaneID(opposite->getNumLanes() - 1);
821  }
822  }
823  }
824  }
825 }
826 
827 
828 void
830  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
831  NBEdge* opposite = getOppositeByID(i->first);
832  if (opposite != 0) {
833  i->second->setLaneSpreadFunction(LANESPREAD_RIGHT);
835  } else {
836  i->second->setLaneSpreadFunction(LANESPREAD_CENTER);
837  }
838  }
839 }
840 
841 
842 NBEdge*
843 NBEdgeCont::getOppositeByID(const std::string& edgeID) const {
844  const std::string oppositeID = edgeID[0] == '-' ? edgeID.substr(1) : "-" + edgeID;
845  EdgeCont::const_iterator it = myEdges.find(oppositeID);
846  return it != myEdges.end() ? it->second : (NBEdge*)0;
847 }
848 
849 NBEdge*
850 NBEdgeCont::getByID(const std::string& edgeID) const {
851  EdgeCont::const_iterator it = myEdges.find(edgeID);
852  return it != myEdges.end() ? it->second : (NBEdge*)0;
853 }
854 
855 // ----- other
856 void
857 NBEdgeCont::addPostProcessConnection(const std::string& from, int fromLane, const std::string& to, int toLane, bool mayDefinitelyPass,
858  bool keepClear, double contPos, double visibility, double speed,
859  const PositionVector& customShape, bool warnOnly) {
860  myConnections.push_back(PostProcessConnection(from, fromLane, to, toLane, mayDefinitelyPass, keepClear, contPos, visibility, speed, customShape, warnOnly));
861 }
862 
863 
864 void
866  const bool warnOnly = OptionsCont::getOptions().exists("ignore-errors.connections") && OptionsCont::getOptions().getBool("ignore-errors.connections");
867  for (std::vector<PostProcessConnection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
868  NBEdge* from = retrievePossiblySplit((*i).from, true);
869  NBEdge* to = retrievePossiblySplit((*i).to, false);
870  if (from == 0 || to == 0 ||
871  !from->addLane2LaneConnection((*i).fromLane, to, (*i).toLane, NBEdge::L2L_USER, true, (*i).mayDefinitelyPass,
872  (*i).keepClear, (*i).contPos, (*i).visibility, (*i).speed, (*i).customShape)) {
873  const std::string msg = "Could not insert connection between '" + (*i).from + "' and '" + (*i).to + "' after build.";
874  if (warnOnly || (*i).warnOnly) {
875  WRITE_WARNING(msg);
876  } else {
877  WRITE_ERROR(msg);
878  }
879  }
880  }
881  // during loading we also kept some ambiguous connections in hope they might be valid after processing
882  // we need to make sure that all invalid connections are removed now
883  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); ++it) {
884  NBEdge* edge = it->second;
885  NBNode* to = edge->getToNode();
886  // make a copy because we may delete connections
887  std::vector<NBEdge::Connection> connections = edge->getConnections();
888  for (std::vector<NBEdge::Connection>::iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
889  NBEdge::Connection& c = *it_con;
890  if (c.toEdge != 0 && c.toEdge->getFromNode() != to) {
891  WRITE_WARNING("Found and removed invalid connection from edge '" + edge->getID() +
892  "' to edge '" + c.toEdge->getID() + "' via junction '" + to->getID() + "'.");
893  edge->removeFromConnections(c.toEdge);
894  }
895  }
896  }
897 }
898 
899 
901 NBEdgeCont::getGeneratedFrom(const std::string& id) const {
902  int len = (int)id.length();
903  EdgeVector ret;
904  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
905  std::string curr = (*i).first;
906  // the next check makes it possibly faster - we don not have
907  // to compare the names
908  if ((int)curr.length() <= len) {
909  continue;
910  }
911  // the name must be the same as the given id but something
912  // beginning with a '[' must be appended to it
913  if (curr.substr(0, len) == id && curr[len] == '[') {
914  ret.push_back((*i).second);
915  continue;
916  }
917  // ok, maybe the edge is a compound made during joining of edges
918  std::string::size_type pos = curr.find(id);
919  // surely not
920  if (pos == std::string::npos) {
921  continue;
922  }
923  // check leading char
924  if (pos > 0) {
925  if (curr[pos - 1] != ']' && curr[pos - 1] != '+') {
926  // actually, this is another id
927  continue;
928  }
929  }
930  if (pos + id.length() < curr.length()) {
931  if (curr[pos + id.length()] != '[' && curr[pos + id.length()] != '+') {
932  // actually, this is another id
933  continue;
934  }
935  }
936  ret.push_back((*i).second);
937  }
938  return ret;
939 }
940 
941 
942 int
944  myGuessedRoundabouts.clear();
945  std::set<NBEdge*> loadedRoundaboutEdges;
946  for (std::set<EdgeSet>::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
947  loadedRoundaboutEdges.insert(it->begin(), it->end());
948  }
949  // step 1: keep only those edges which have no turnarounds and which are not
950  // part of a loaded roundabout
951  std::set<NBEdge*> candidates;
952  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
953  NBEdge* e = (*i).second;
954  NBNode* const to = e->getToNode();
955  if (e->getTurnDestination() == 0 && to->getConnectionTo(e->getFromNode()) == 0 && loadedRoundaboutEdges.count(e) == 0) {
956  candidates.insert(e);
957  }
958  }
959 
960  // step 2:
961  std::set<NBEdge*> visited;
962  for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) {
963  EdgeVector loopEdges;
964  // start with a random edge (this doesn't have to be a roundabout edge)
965  // loop over connected edges (using always the leftmost one)
966  // and keep the list in loopEdges
967  // continue until we loop back onto a loopEdges and extract the loop
968  NBEdge* e = (*i);
969  if (visited.count(e) > 0) {
970  // already seen
971  continue;
972  }
973  loopEdges.push_back(e);
974  bool doLoop = true;
975  do {
976  visited.insert(e);
977  const EdgeVector& edges = e->getToNode()->getEdges();
978  if (edges.size() < 2) {
979  doLoop = false;
980  break;
981  }
982  if (e->getTurnDestination() != 0 || e->getToNode()->getConnectionTo(e->getFromNode()) != 0) {
983  // do not follow turn-arounds while in a (tentative) loop
984  doLoop = false;
985  break;
986  }
987  EdgeVector::const_iterator me = find(edges.begin(), edges.end(), e);
988  NBContHelper::nextCW(edges, me);
989  NBEdge* left = *me;
990  double angle = fabs(NBHelpers::relAngle(e->getAngleAtNode(e->getToNode()), left->getAngleAtNode(e->getToNode())));
991  if (angle >= 90) {
992  // roundabouts do not have sharp turns (or they wouldn't be called 'round')
993  doLoop = false;
994  break;
995  }
996  EdgeVector::const_iterator loopClosed = find(loopEdges.begin(), loopEdges.end(), left);
997  const int loopSize = (int)(loopEdges.end() - loopClosed);
998  if (loopSize > 0) {
999  // loop found
1000  if (loopSize < 3) {
1001  doLoop = false; // need at least 3 edges for a roundabout
1002  } else if (loopSize < (int)loopEdges.size()) {
1003  // remove initial edges not belonging to the loop
1004  EdgeVector(loopEdges.begin() + (loopEdges.size() - loopSize), loopEdges.end()).swap(loopEdges);
1005  }
1006  // count attachments to the outside. need at least 3 or a roundabout doesn't make much sense
1007  int attachments = 0;
1008  for (EdgeVector::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) {
1009  if ((*j)->getToNode()->getEdges().size() > 2) {
1010  attachments++;
1011  }
1012  }
1013  if (attachments < 3) {
1014  doLoop = false;
1015  }
1016  break;
1017  }
1018  if (visited.count(left) > 0) {
1019  doLoop = false;
1020  } else {
1021  // keep going
1022  loopEdges.push_back(left);
1023  e = left;
1024  }
1025  } while (doLoop);
1026  if (doLoop) {
1027  // check form factor to avoid elongated shapes (circle: 1, square: ~0.79)
1028  if (formFactor(loopEdges) > 0.6) {
1029  // collected edges are marked in markRoundabouts
1030  myGuessedRoundabouts.insert(EdgeSet(loopEdges.begin(), loopEdges.end()));
1031  }
1032  }
1033  }
1034  return (int)myGuessedRoundabouts.size();
1035 }
1036 
1037 
1038 double
1040  PositionVector points;
1041  for (EdgeVector::const_iterator it = loopEdges.begin(); it != loopEdges.end(); ++it) {
1042  points.append((*it)->getGeometry());
1043  }
1044  double circumference = points.length2D();
1045  return 4 * M_PI * points.area() / (circumference * circumference);
1046 }
1047 
1048 
1049 const std::set<EdgeSet>
1051  std::set<EdgeSet> result = myRoundabouts;
1052  result.insert(myGuessedRoundabouts.begin(), myGuessedRoundabouts.end());
1053  return result;
1054 }
1055 
1056 
1057 void
1059  if (roundabout.size() > 0) {
1060  if (find(myRoundabouts.begin(), myRoundabouts.end(), roundabout) != myRoundabouts.end()) {
1061  WRITE_WARNING("Ignoring duplicate roundabout: " + toString(roundabout));
1062  } else {
1063  myRoundabouts.insert(roundabout);
1064  }
1065  }
1066 }
1067 
1068 
1069 void
1071  const std::set<EdgeSet> roundabouts = getRoundabouts();
1072  for (std::set<EdgeSet>::const_iterator it = roundabouts.begin(); it != roundabouts.end(); ++it) {
1073  const EdgeSet roundaboutSet = *it;
1074  for (std::set<NBEdge*>::const_iterator j = roundaboutSet.begin(); j != roundaboutSet.end(); ++j) {
1075  // disable turnarounds on incoming edges
1076  NBNode* node = (*j)->getToNode();
1077  const EdgeVector& incoming = node->getIncomingEdges();
1078  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
1079  NBEdge* inEdge = *k;
1080  if (roundaboutSet.count(inEdge) > 0) {
1081  continue;
1082  }
1083  if ((inEdge)->getStep() >= NBEdge::LANES2LANES_USER) {
1084  continue;
1085  }
1086  inEdge->removeFromConnections(inEdge->getTurnDestination(), -1);
1087  }
1088  // let the connections to succeeding roundabout edge have a higher priority
1089  (*j)->setJunctionPriority(node, NBEdge::ROUNDABOUT);
1090  (*j)->setJunctionPriority((*j)->getFromNode(), NBEdge::ROUNDABOUT);
1091  node->setRoundabout();
1092  }
1093  }
1094 }
1095 
1096 void
1098  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
1099  NBEdge* e = i->second;
1100  const double offset = MAX2(0., e->getLength() - 3);
1101  if (e->getToNode()->isSimpleContinuation(false)) {
1102  // not a "real" junction?
1103  continue;
1104  }
1105  const SumoXMLNodeType nodeType = e->getToNode()->getType();
1106  switch (nodeType) {
1107  case NODETYPE_PRIORITY:
1108  // yield or major?
1109  if (e->getJunctionPriority(e->getToNode()) > 0) {
1111  } else {
1112  e->addSign(NBSign(NBSign::SIGN_TYPE_YIELD, offset));
1113  }
1114  break;
1116  // yield or major?
1117  if (e->getJunctionPriority(e->getToNode()) > 0) {
1119  } else {
1120  e->addSign(NBSign(NBSign::SIGN_TYPE_STOP, offset));
1121  }
1122  break;
1123  case NODETYPE_ALLWAY_STOP:
1125  break;
1128  break;
1129  default:
1130  break;
1131  }
1132  }
1133 }
1134 
1135 
1136 int
1137 NBEdgeCont::guessSidewalks(double width, double minSpeed, double maxSpeed, bool fromPermissions) {
1138  int sidewalksCreated = 0;
1139  const std::vector<std::string> edges = OptionsCont::getOptions().getStringVector("sidewalks.guess.exclude");
1140  std::set<std::string> exclude(edges.begin(), edges.end());
1141  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1142  NBEdge* edge = it->second;
1143  if (// not excluded
1144  exclude.count(edge->getID()) == 0
1145  // does not yet have a sidewalk
1146  && edge->getPermissions(0) != SVC_PEDESTRIAN
1147  && (
1148  // guess.from-permissions
1149  (fromPermissions && (edge->getPermissions() & SVC_PEDESTRIAN) != 0)
1150  // guess from speed
1151  || (!fromPermissions && edge->getSpeed() > minSpeed && edge->getSpeed() <= maxSpeed)
1152  )) {
1153  edge->addSidewalk(width);
1154  sidewalksCreated += 1;
1155  }
1156  }
1157  return sidewalksCreated;
1158 }
1159 
1160 
1161 int
1162 NBEdgeCont::remapIDs(bool numericaIDs, bool reservedIDs) {
1163  std::vector<std::string> avoid = getAllNames();
1164  std::set<std::string> reserve;
1165  if (reservedIDs) {
1166  NBHelpers::loadPrefixedIDsFomFile(OptionsCont::getOptions().getString("reserved-ids"), "edge:", reserve);
1167  avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1168  }
1169  IDSupplier idSupplier("", avoid);
1170  std::set<NBEdge*, Named::ComparatorIdLess> toChange;
1171  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1172  if (numericaIDs) {
1173  try {
1174  TplConvert::_str2long(it->first);
1175  } catch (NumberFormatException&) {
1176  toChange.insert(it->second);
1177  }
1178  }
1179  if (reservedIDs && reserve.count(it->first) > 0) {
1180  toChange.insert(it->second);
1181  }
1182  }
1183  const bool origNames = OptionsCont::getOptions().getBool("output.original-names");
1184  for (std::set<NBEdge*, Named::ComparatorIdLess>::iterator it = toChange.begin(); it != toChange.end(); ++it) {
1185  NBEdge* edge = *it;
1186  myEdges.erase(edge->getID());
1187  if (origNames) {
1188  edge->setOrigID(edge->getID());
1189  }
1190  edge->setID(idSupplier.getNext());
1191  myEdges[edge->getID()] = edge;
1192  }
1193  return (int)toChange.size();
1194 }
1195 
1196 
1197 void
1198 NBEdgeCont::checkOverlap(double threshold, double zThreshold) const {
1199  for (EdgeCont::const_iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1200  const NBEdge* e1 = it->second;
1201  Boundary b1 = e1->getGeometry().getBoxBoundary();
1202  b1.grow(e1->getTotalWidth());
1203  PositionVector outline1 = e1->getCCWBoundaryLine(*e1->getFromNode());
1204  outline1.append(e1->getCCWBoundaryLine(*e1->getToNode()));
1205  // check is symmetric. only check once per pair
1206  for (EdgeCont::const_iterator it2 = it; it2 != myEdges.end(); it2++) {
1207  const NBEdge* e2 = it2->second;
1208  if (e1 == e2) {
1209  continue;
1210  }
1211  Boundary b2 = e2->getGeometry().getBoxBoundary();
1212  b2.grow(e2->getTotalWidth());
1213  if (b1.overlapsWith(b2)) {
1214  PositionVector outline2 = e2->getCCWBoundaryLine(*e2->getFromNode());
1215  outline2.append(e2->getCCWBoundaryLine(*e2->getToNode()));
1216  const double overlap = outline1.getOverlapWith(outline2, zThreshold);
1217  if (overlap > threshold) {
1218  WRITE_WARNING("Edge '" + e1->getID() + "' overlaps with edge '" + e2->getID() + "' by " + toString(overlap) + ".");
1219  }
1220  }
1221  }
1222  }
1223 }
1224 
1225 
1226 void
1227 NBEdgeCont::checkGrade(double threshold) const {
1228  for (EdgeCont::const_iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1229  const NBEdge* edge = it->second;
1230  for (int i = 0; i < (int)edge->getNumLanes(); i++) {
1231  const double grade = edge->getLaneShape(i).getMaxGrade();
1232  if (grade > threshold) {
1233  WRITE_WARNING("Edge '" + edge->getID() + "' has a grade of " + toString(grade * 100) + "%.");
1234  break;
1235  }
1236  }
1237  const std::vector<NBEdge::Connection>& connections = edge->getConnections();
1238  for (std::vector<NBEdge::Connection>::const_iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
1239  const NBEdge::Connection& c = *it_con;
1240  const double grade = MAX2(c.shape.getMaxGrade(), c.viaShape.getMaxGrade());
1241  if (grade > threshold) {
1242  WRITE_WARNING("Connection '" + c.getDescription(edge) + "' has a grade of " + toString(grade * 100) + "%.");
1243  break;
1244  }
1245  }
1246  }
1247 }
1248 
1249 
1250 /****************************************************************************/
static double relAngle(double angle1, double angle2)
computes the relative angle between the two angles
Definition: NBHelpers.cpp:53
~NBEdgeCont()
Destructor.
Definition: NBEdgeCont.cpp:71
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1429
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) ...
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:249
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:982
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:161
void sortOutgoingLanesConnections()
Sorts all lanes of all edges within the container by their direction.
Definition: NBEdgeCont.cpp:616
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:2627
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
Definition: NBEdgeCont.cpp:286
void checkOverlap(double threshold, double zThreshold) const
check whether edges overlap
A class representing a single street sign.
Definition: NBSign.h:50
PositionVector shape
The lane&#39;s shape.
Definition: NBEdge.h:126
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
is a pedestrian
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:550
void append(const PositionVector &v, double sameThreshold=2.0)
void addSign(NBSign sign)
add Sign
Definition: NBEdge.h:1209
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:186
void reduceGeometries(const double minDist)
Definition: NBEdgeCont.cpp:589
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:112
NBNode * myTo
Definition: NBEdge.h:1376
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2950
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1611
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:489
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
A container for traffic light definitions and built programs.
int guessRoundabouts()
Determines which edges belong to roundabouts and increases their priority.
Definition: NBEdgeCont.cpp:943
bool myRemoveEdgesAfterJoining
Whether edges shall be joined first, then removed.
Definition: NBEdgeCont.h:644
void setSpeed(int lane, double speed)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2966
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:2935
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:569
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:90
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:1281
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:70
void guessOpposites()
Sets opposite lane information for geometrically close edges.
Definition: NBEdgeCont.cpp:799
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:2617
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:86
A container for districts.
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:257
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
Definition: GeoConvHelper.h:95
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1201
void removeDoubleEdges()
remove duble edges
Definition: NBNode.cpp:1170
T MAX2(T a, T b)
Definition: StdDefs.h:73
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:608
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:2997
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:506
void setLoadedLength(double val)
set loaded lenght
Definition: NBEdge.cpp:3040
void generateStreetSigns()
assigns street signs to edges based on toNode types
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
Definition: NBEdgeCont.cpp:403
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:415
void recheckPostProcessConnections()
Try to set any stored connections.
Definition: NBEdgeCont.cpp:865
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
static long long int _str2long(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter, which
Definition: TplConvert.h:243
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1177
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:94
void computeLanes2Edges()
Computes for each edge which lanes approach the next edges.
Definition: NBEdgeCont.cpp:632
void addSidewalk(double width)
add a pedestrian sidewalk of the given width and shift existing connctions
Definition: NBEdge.cpp:3152
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:254
A class that stores a 2D geometrical boundary.
Definition: Boundary.h:47
std::vector< PostProcessConnection > myConnections
The list of connections to recheck.
Definition: NBEdgeCont.h:619
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:1066
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:199
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:64
void checkGeometries(const double maxAngle, const double minRadius, bool fix)
Definition: NBEdgeCont.cpp:597
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
Definition: NBEdgeCont.cpp:850
PositionVector myPruningBoundary
Boundary within which an edge must be located in order to be kept.
Definition: NBEdgeCont.h:665
PositionVector shape
shape of Connection
Definition: NBEdge.h:219
NBEdgeCont(NBTypeCont &tc)
Constructor.
Definition: NBEdgeCont.cpp:62
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
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...
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:254
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:121
const std::string & getID() const
Returns the id.
Definition: Named.h:65
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:897
double area() const
Returns the area (0 for non-closed)
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
Definition: NBEdgeCont.h:653
const Position & getPosition() const
Definition: NBNode.h:241
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 double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
Definition: GeomHelper.cpp:95
double myEdgesMinSpeed
The minimum speed an edge may have in order to be kept (default: -1)
Definition: NBEdgeCont.h:641
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:101
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:532
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:58
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
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:302
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:157
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:55
void removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
Definition: NBEdgeCont.cpp:561
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:391
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:45
A list of positions.
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
Definition: NBEdgeCont.cpp:77
void setOrigID(const std::string origID)
set origID for all lanes
Definition: NBEdge.cpp:3282
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns whether the boundary overlaps with the given polygon.
Definition: Boundary.cpp:188
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
Definition: NBEdge.cpp:2477
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
Definition: NBEdgeCont.h:647
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:266
void computeEdge2Edges(bool noLeftMovers)
Computes for each edge the approached edges.
Definition: NBEdgeCont.cpp:624
void computeLaneShapes()
Computes the shapes of all lanes of all edges stored in the container.
Definition: NBEdgeCont.cpp:704
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:412
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
Definition: NBNode.h:259
double length() const
Returns the length.
static double formFactor(const EdgeVector &loopEdges)
compute the form factor for a loop of edges
T MIN2(T a, T b)
Definition: StdDefs.h:67
void splitGeometry(NBNodeCont &nc)
Splits edges into multiple if they have a complex geometry.
Definition: NBEdgeCont.cpp:578
EdgeCont myEdges
The instance of the dictionary (id->edge)
Definition: NBEdgeCont.h:626
#define POSITION_EPS
Definition: config.h:175
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...
void clear()
Deletes all edges.
Definition: NBEdgeCont.cpp:142
EdgeCont myExtractedEdges
The extracted nodes which are kept for reference.
Definition: NBEdgeCont.h:629
const std::string getParameter(const std::string &key, const std::string &defaultValue="") const
Returns the value for a given key.
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:74
The connection was given by the user.
Definition: NBEdge.h:112
std::set< EdgeSet > myGuessedRoundabouts
Edges marked as belonging to a roundabout after guessing.
Definition: NBEdgeCont.h:674
std::set< EdgeSet > myRoundabouts
Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout) ...
Definition: NBEdgeCont.h:672
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:1744
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again ...
Definition: NBEdge.cpp:1917
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1591
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:712
double getMaxGrade() const
return the maximum grade of all segments as a fraction of zRange/length2D
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed) ...
Definition: NBEdgeCont.h:656
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:205
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3025
std::set< std::string > myTypes2Keep
Set of edges types which shall be kept.
Definition: NBEdgeCont.h:659
int guessSidewalks(double width, double minSpeed, double maxSpeed, bool fromPermissions)
add sidwalks to edges within the given limits or permissions and return the number of edges affected ...
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:433
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:480
void setID(const std::string &newID)
resets the id
Definition: Named.h:73
double length2D() const
Returns the length.
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)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:921
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:250
PositionVector viaShape
shape of via
Definition: NBEdge.h:231
std::string oppositeID
An opposite lane ID, if given.
Definition: NBEdge.h:144
void appendTurnarounds(bool noTLSControlled)
Appends turnarounds to all edges stored in the container.
Definition: NBEdgeCont.cpp:680
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:1102
#define M_PI
Definition: odrSpiral.cpp:40
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:40
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 warnOnly=false)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:857
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:198
bool myNeedGeoTransformedPruningBoundary
whether a geo transform has been applied to the pruning boundary
Definition: NBEdgeCont.h:668
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:602
double getFinalLength() const
get length that will be assigned to the lanes in the final network
Definition: NBEdge.cpp:3269
A storage for options typed value containers)
Definition: OptionsCont.h:98
static double _2double(const E *const data)
converts a char-type array into the double value described by it
Definition: TplConvert.h:311
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:384
const std::string SUMO_PARAM_ORIGID
A structure representing a connection between two lanes.
Definition: NBEdgeCont.h:575
void computeEdgeShapes()
Computes the shapes of all edges stored in the container.
Definition: NBEdgeCont.cpp:696
The connection was computed.
Definition: NBEdge.h:110
NBEdge * getOppositeByID(const std::string &edgeID) const
Returns the edge with negated id if it exists.
Definition: NBEdgeCont.cpp:843
Represents a single node (junction) during network building.
Definition: NBNode.h:74
void dismissVehicleClassInformation()
dimiss vehicle class information
Definition: NBEdge.cpp:3046
bool isSimpleContinuation(bool checkLaneNumbers=true) const
check if node is a simple continuation
Definition: NBNode.cpp:431
NBTypeCont & myTypeCont
The network builder; used to obtain type information.
Definition: NBEdgeCont.h:570
void recheckLaneSpread()
Rechecks whether the lane spread is proper.
Definition: NBEdgeCont.cpp:829
std::pair< PositionVector, PositionVector > splitAt(double where) const
Returns the two lists made when this list vector is splitted at the given point.
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2783
void checkGrade(double threshold) const
check whether edges are to steep
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:662
void recheckLanes()
Rechecks whether all lanes have a successor for each of the stored edges.
Definition: NBEdgeCont.cpp:640
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:66
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:97
std::set< std::string > myIgnoredEdges
The ids of ignored edges.
Definition: NBEdgeCont.h:632
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:901
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
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:784
int remapIDs(bool numericaIDs, bool reservedIDs)
remap node IDs accoring to options –numerical-ids and –reserved-ids
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:845
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1376
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2774
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:778
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
Definition: NBEdge.cpp:1350
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2911
bool ignoreFilterMatch(NBEdge *edge)
Returns true if this edge matches one of the removal criteria.
Definition: NBEdgeCont.cpp:178
A storage for available types of edges.
Definition: NBTypeCont.h:61
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
int myEdgesSplit
the number of splits of edges during the building
Definition: NBEdgeCont.h:635
std::set< std::string > myEdges2Remove
Set of ids of edges which shall explicitly be removed.
Definition: NBEdgeCont.h:650
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:426