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