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