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  myNeedGeoTransformedPrunningBoundary(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  myPrunningBoundary.push_back(Position(poly[0], poly[1]));
127  myPrunningBoundary.push_back(Position(poly[2], poly[1]));
128  myPrunningBoundary.push_back(Position(poly[2], poly[3]));
129  myPrunningBoundary.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  myPrunningBoundary.push_back(Position(x, y));
135  }
136  }
137  myNeedGeoTransformedPrunningBoundary = 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())) {
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  && myPrunningBoundary.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 prunning boundary
225  if (myPrunningBoundary.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) myPrunningBoundary.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  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
634  NBEdge* edge = i->second;
635  edge->recheckLanes();
636  // check opposites
637  if (edge->getNumLanes() > 0) {
638  const std::string& oppositeID = edge->getLanes().back().oppositeID;
639  if (oppositeID != "" && oppositeID != "-") {
640  NBEdge* oppEdge = retrieve(oppositeID.substr(0, oppositeID.rfind("_")));
641  if (oppEdge == 0 || oppEdge->getLaneID(oppEdge->getNumLanes() - 1) != oppositeID) {
642  WRITE_WARNING("Removing unknown opposite lane '" + oppositeID + "' for edge '" + edge->getID() + "'.");
643  edge->getLaneStruct(edge->getNumLanes() - 1).oppositeID = "";
644  continue;
645  }
646  if (fabs(oppEdge->getLoadedLength() - edge->getLoadedLength()) > POSITION_EPS) {
647  throw ProcessError("Opposite lane '" + oppositeID + "' (length " + toString(oppEdge->getLoadedLength()) + ") differs in length from edge '" + edge->getID() + "' (length "
648  + toString(edge->getLoadedLength()) + ")!");
649  }
650  if (oppEdge->getFromNode() != edge->getToNode() || oppEdge->getToNode() != edge->getFromNode()) {
651  throw ProcessError("Opposite lane '" + oppositeID + "' does not connect the same nodes as edge '" + edge->getID() + "'!");
652  }
653  }
654  }
655  }
656 }
657 
658 
659 void
660 NBEdgeCont::appendTurnarounds(bool noTLSControlled) {
661  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
662  (*i).second->appendTurnaround(noTLSControlled, true);
663  }
664 }
665 
666 
667 void
668 NBEdgeCont::appendTurnarounds(const std::set<std::string>& ids, bool noTLSControlled) {
669  for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
670  myEdges[*it]->appendTurnaround(noTLSControlled, false);
671  }
672 }
673 
674 
675 void
677  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
678  (*i).second->computeEdgeShape();
679  }
680 }
681 
682 
683 void
685  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
686  (*i).second->computeLaneShapes();
687  }
688 }
689 
690 
691 void
694  EdgeVector edges) {
695  // !!! Attention!
696  // No merging of the geometry to come is being done
697  // The connections are moved from one edge to another within
698  // the replacement where the edge is a node's incoming edge.
699 
700  // count the number of lanes, the speed and the id
701  int nolanes = 0;
702  double speed = 0;
703  int priority = 0;
704  std::string id;
705  sort(edges.begin(), edges.end(), NBContHelper::same_connection_edge_sorter());
706  // retrieve the connected nodes
707  NBEdge* tpledge = *(edges.begin());
708  NBNode* from = tpledge->getFromNode();
709  NBNode* to = tpledge->getToNode();
710  EdgeVector::const_iterator i;
711  for (i = edges.begin(); i != edges.end(); i++) {
712  // some assertions
713  assert((*i)->getFromNode() == from);
714  assert((*i)->getToNode() == to);
715  // ad the number of lanes the current edge has
716  nolanes += (*i)->getNumLanes();
717  // build the id
718  if (i != edges.begin()) {
719  id += "+";
720  }
721  id += (*i)->getID();
722  // compute the speed
723  speed += (*i)->getSpeed();
724  // build the priority
725  priority = MAX2(priority, (*i)->getPriority());
726  }
727  speed /= edges.size();
728  // build the new edge
729  NBEdge* newEdge = new NBEdge(id, from, to, "", speed, nolanes, priority,
731  tpledge->getStreetName(), tpledge->myLaneSpreadFunction);
732  // copy lane attributes
733  int laneIndex = 0;
734  for (i = edges.begin(); i != edges.end(); ++i) {
735  const std::vector<NBEdge::Lane>& lanes = (*i)->getLanes();
736  for (int j = 0; j < (int)lanes.size(); ++j) {
737  newEdge->setPermissions(lanes[j].permissions, laneIndex);
738  newEdge->setLaneWidth(laneIndex, lanes[j].width);
739  newEdge->setEndOffset(laneIndex, lanes[j].endOffset);
740  laneIndex++;
741  }
742  }
743  insert(newEdge, true);
744  // replace old edge by current within the nodes
745  // and delete the old
746  from->replaceOutgoing(edges, newEdge);
747  to->replaceIncoming(edges, newEdge);
748  // patch connections
749  // add edge2edge-information
750  for (i = edges.begin(); i != edges.end(); i++) {
751  EdgeVector ev = (*i)->getConnectedEdges();
752  for (EdgeVector::iterator j = ev.begin(); j != ev.end(); j++) {
753  newEdge->addEdge2EdgeConnection(*j);
754  }
755  }
756  // copy outgoing connections to the new edge
757  int currLane = 0;
758  for (i = edges.begin(); i != edges.end(); i++) {
759  newEdge->moveOutgoingConnectionsFrom(*i, currLane);
760  currLane += (*i)->getNumLanes();
761  }
762  // patch tl-information
763  currLane = 0;
764  for (i = edges.begin(); i != edges.end(); i++) {
765  int noLanes = (*i)->getNumLanes();
766  for (int j = 0; j < noLanes; j++, currLane++) {
767  // replace in traffic lights
768  tlc.replaceRemoved(*i, j, newEdge, currLane);
769  }
770  }
771  // delete joined edges
772  for (i = edges.begin(); i != edges.end(); i++) {
773  extract(dc, *i, true);
774  }
775 }
776 
777 
778 void
780  //@todo magic values
781  const double distanceThreshold = 7;
782  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
783  NBEdge* edge = i->second;
784  const int numLanes = edge->getNumLanes();
785  if (numLanes > 0) {
786  NBEdge::Lane& lastLane = edge->getLaneStruct(numLanes - 1);
787  if (lastLane.oppositeID == "") {
788  NBEdge* opposite = 0;
789  //double minOppositeDist = std::numeric_limits<double>::max();
790  for (EdgeVector::const_iterator j = edge->getToNode()->getOutgoingEdges().begin(); j != edge->getToNode()->getOutgoingEdges().end(); ++j) {
791  if ((*j)->getToNode() == edge->getFromNode() && !(*j)->getLanes().empty()) {
792  const double distance = VectorHelper<double>::maxValue(lastLane.shape.distances((*j)->getLanes().back().shape));
793  if (distance < distanceThreshold) {
794  //minOppositeDist = distance;
795  opposite = *j;
796  }
797  }
798  }
799  if (opposite != 0) {
800  lastLane.oppositeID = opposite->getLaneID(opposite->getNumLanes() - 1);
801  }
802  }
803  }
804  }
805 }
806 
807 
808 void
810  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
811  NBEdge* opposite = getOppositeByID(i->first);
812  if (opposite != 0) {
813  i->second->setLaneSpreadFunction(LANESPREAD_RIGHT);
815  } else {
816  i->second->setLaneSpreadFunction(LANESPREAD_CENTER);
817  }
818  }
819 }
820 
821 
822 NBEdge*
823 NBEdgeCont::getOppositeByID(const std::string& edgeID) const {
824  const std::string oppositeID = edgeID[0] == '-' ? edgeID.substr(1) : "-" + edgeID;
825  EdgeCont::const_iterator it = myEdges.find(oppositeID);
826  return it != myEdges.end() ? it->second : (NBEdge*)0;
827 }
828 
829 NBEdge*
830 NBEdgeCont::getByID(const std::string& edgeID) const {
831  EdgeCont::const_iterator it = myEdges.find(edgeID);
832  return it != myEdges.end() ? it->second : (NBEdge*)0;
833 }
834 
835 // ----- other
836 void
837 NBEdgeCont::addPostProcessConnection(const std::string& from, int fromLane, const std::string& to, int toLane, bool mayDefinitelyPass,
838  bool keepClear, double contPos, double visibility, bool warnOnly) {
839  myConnections.push_back(PostProcessConnection(from, fromLane, to, toLane, mayDefinitelyPass, keepClear, contPos, visibility, warnOnly));
840 }
841 
842 
843 void
845  const bool warnOnly = OptionsCont::getOptions().exists("ignore-errors.connections") && OptionsCont::getOptions().getBool("ignore-errors.connections");
846  for (std::vector<PostProcessConnection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
847  NBEdge* from = retrievePossiblySplit((*i).from, true);
848  NBEdge* to = retrievePossiblySplit((*i).to, false);
849  if (from == 0 || to == 0 ||
850  !from->addLane2LaneConnection((*i).fromLane, to, (*i).toLane, NBEdge::L2L_USER, true, (*i).mayDefinitelyPass, (*i).keepClear, (*i).contPos)) {
851  const std::string msg = "Could not insert connection between '" + (*i).from + "' and '" + (*i).to + "' after build.";
852  if (warnOnly || (*i).warnOnly) {
853  WRITE_WARNING(msg);
854  } else {
855  WRITE_ERROR(msg);
856  }
857  }
858  }
859  // during loading we also kept some ambiguous connections in hope they might be valid after processing
860  // we need to make sure that all invalid connections are removed now
861  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); ++it) {
862  NBEdge* edge = it->second;
863  NBNode* to = edge->getToNode();
864  // make a copy because we may delete connections
865  std::vector<NBEdge::Connection> connections = edge->getConnections();
866  for (std::vector<NBEdge::Connection>::iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
867  NBEdge::Connection& c = *it_con;
868  if (c.toEdge != 0 && c.toEdge->getFromNode() != to) {
869  WRITE_WARNING("Found and removed invalid connection from edge '" + edge->getID() +
870  "' to edge '" + c.toEdge->getID() + "' via junction '" + to->getID() + "'.");
871  edge->removeFromConnections(c.toEdge);
872  }
873  }
874  }
875 }
876 
877 
879 NBEdgeCont::getGeneratedFrom(const std::string& id) const {
880  int len = (int)id.length();
881  EdgeVector ret;
882  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
883  std::string curr = (*i).first;
884  // the next check makes it possibly faster - we don not have
885  // to compare the names
886  if ((int)curr.length() <= len) {
887  continue;
888  }
889  // the name must be the same as the given id but something
890  // beginning with a '[' must be appended to it
891  if (curr.substr(0, len) == id && curr[len] == '[') {
892  ret.push_back((*i).second);
893  continue;
894  }
895  // ok, maybe the edge is a compound made during joining of edges
896  std::string::size_type pos = curr.find(id);
897  // surely not
898  if (pos == std::string::npos) {
899  continue;
900  }
901  // check leading char
902  if (pos > 0) {
903  if (curr[pos - 1] != ']' && curr[pos - 1] != '+') {
904  // actually, this is another id
905  continue;
906  }
907  }
908  if (pos + id.length() < curr.length()) {
909  if (curr[pos + id.length()] != '[' && curr[pos + id.length()] != '+') {
910  // actually, this is another id
911  continue;
912  }
913  }
914  ret.push_back((*i).second);
915  }
916  return ret;
917 }
918 
919 
920 int
922  myGuessedRoundabouts.clear();
923  std::set<NBEdge*> loadedRoundaboutEdges;
924  for (std::set<EdgeSet>::const_iterator it = myRoundabouts.begin(); it != myRoundabouts.end(); ++it) {
925  loadedRoundaboutEdges.insert(it->begin(), it->end());
926  }
927  // step 1: keep only those edges which have no turnarounds and which are not
928  // part of a loaded roundabout
929  std::set<NBEdge*> candidates;
930  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
931  NBEdge* e = (*i).second;
932  NBNode* const to = e->getToNode();
933  if (e->getTurnDestination() == 0 && to->getConnectionTo(e->getFromNode()) == 0 && loadedRoundaboutEdges.count(e) == 0) {
934  candidates.insert(e);
935  }
936  }
937 
938  // step 2:
939  std::set<NBEdge*> visited;
940  for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) {
941  EdgeVector loopEdges;
942  // start with a random edge (this doesn't have to be a roundabout edge)
943  // loop over connected edges (using always the leftmost one)
944  // and keep the list in loopEdges
945  // continue until we loop back onto a loopEdges and extract the loop
946  NBEdge* e = (*i);
947  if (visited.count(e) > 0) {
948  // already seen
949  continue;
950  }
951  loopEdges.push_back(e);
952  bool doLoop = true;
953  do {
954  visited.insert(e);
955  const EdgeVector& edges = e->getToNode()->getEdges();
956  if (edges.size() < 2) {
957  doLoop = false;
958  break;
959  }
960  if (e->getTurnDestination() != 0 || e->getToNode()->getConnectionTo(e->getFromNode()) != 0) {
961  // do not follow turn-arounds while in a (tentative) loop
962  doLoop = false;
963  break;
964  }
965  EdgeVector::const_iterator me = find(edges.begin(), edges.end(), e);
966  NBContHelper::nextCW(edges, me);
967  NBEdge* left = *me;
968  double angle = fabs(NBHelpers::relAngle(e->getAngleAtNode(e->getToNode()), left->getAngleAtNode(e->getToNode())));
969  if (angle >= 90) {
970  // roundabouts do not have sharp turns (or they wouldn't be called 'round')
971  doLoop = false;
972  break;
973  }
974  EdgeVector::const_iterator loopClosed = find(loopEdges.begin(), loopEdges.end(), left);
975  const int loopSize = (int)(loopEdges.end() - loopClosed);
976  if (loopSize > 0) {
977  // loop found
978  if (loopSize < 3) {
979  doLoop = false; // need at least 3 edges for a roundabout
980  } else if (loopSize < (int)loopEdges.size()) {
981  // remove initial edges not belonging to the loop
982  EdgeVector(loopEdges.begin() + (loopEdges.size() - loopSize), loopEdges.end()).swap(loopEdges);
983  }
984  // count attachments to the outside. need at least 3 or a roundabout doesn't make much sense
985  int attachments = 0;
986  for (EdgeVector::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) {
987  if ((*j)->getToNode()->getEdges().size() > 2) {
988  attachments++;
989  }
990  }
991  if (attachments < 3) {
992  doLoop = false;
993  }
994  break;
995  }
996  if (visited.count(left) > 0) {
997  doLoop = false;
998  } else {
999  // keep going
1000  loopEdges.push_back(left);
1001  e = left;
1002  }
1003  } while (doLoop);
1004  if (doLoop) {
1005  // check form factor to avoid elongated shapes (circle: 1, square: ~0.79)
1006  if (formFactor(loopEdges) > 0.6) {
1007  // collected edges are marked in markRoundabouts
1008  myGuessedRoundabouts.insert(EdgeSet(loopEdges.begin(), loopEdges.end()));
1009  }
1010  }
1011  }
1012  return (int)myGuessedRoundabouts.size();
1013 }
1014 
1015 
1016 double
1018  PositionVector points;
1019  for (EdgeVector::const_iterator it = loopEdges.begin(); it != loopEdges.end(); ++it) {
1020  points.append((*it)->getGeometry());
1021  }
1022  double circumference = points.length2D();
1023  return 4 * M_PI * points.area() / (circumference * circumference);
1024 }
1025 
1026 
1027 const std::set<EdgeSet>
1029  std::set<EdgeSet> result = myRoundabouts;
1030  result.insert(myGuessedRoundabouts.begin(), myGuessedRoundabouts.end());
1031  return result;
1032 }
1033 
1034 
1035 void
1037  if (roundabout.size() > 0) {
1038  if (find(myRoundabouts.begin(), myRoundabouts.end(), roundabout) != myRoundabouts.end()) {
1039  WRITE_WARNING("Ignoring duplicate roundabout: " + toString(roundabout));
1040  } else {
1041  myRoundabouts.insert(roundabout);
1042  }
1043  }
1044 }
1045 
1046 
1047 void
1049  const std::set<EdgeSet> roundabouts = getRoundabouts();
1050  for (std::set<EdgeSet>::const_iterator it = roundabouts.begin(); it != roundabouts.end(); ++it) {
1051  const EdgeSet roundaboutSet = *it;
1052  for (std::set<NBEdge*>::const_iterator j = roundaboutSet.begin(); j != roundaboutSet.end(); ++j) {
1053  // disable turnarounds on incoming edges
1054  NBNode* node = (*j)->getToNode();
1055  const EdgeVector& incoming = node->getIncomingEdges();
1056  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
1057  NBEdge* inEdge = *k;
1058  if (roundaboutSet.count(inEdge) > 0) {
1059  continue;
1060  }
1061  if ((inEdge)->getStep() >= NBEdge::LANES2LANES_USER) {
1062  continue;
1063  }
1064  inEdge->removeFromConnections(inEdge->getTurnDestination(), -1);
1065  }
1066  // let the connections to succeeding roundabout edge have a higher priority
1067  (*j)->setJunctionPriority(node, NBEdge::ROUNDABOUT);
1068  (*j)->setJunctionPriority((*j)->getFromNode(), NBEdge::ROUNDABOUT);
1069  node->setRoundabout();
1070  }
1071  }
1072 }
1073 
1074 void
1076  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
1077  NBEdge* e = i->second;
1078  const double offset = MAX2(0., e->getLength() - 3);
1079  if (e->getToNode()->isSimpleContinuation(false)) {
1080  // not a "real" junction?
1081  continue;
1082  }
1083  const SumoXMLNodeType nodeType = e->getToNode()->getType();
1084  switch (nodeType) {
1085  case NODETYPE_PRIORITY:
1086  // yield or major?
1087  if (e->getJunctionPriority(e->getToNode()) > 0) {
1089  } else {
1090  e->addSign(NBSign(NBSign::SIGN_TYPE_YIELD, offset));
1091  }
1092  break;
1094  // yield or major?
1095  if (e->getJunctionPriority(e->getToNode()) > 0) {
1097  } else {
1098  e->addSign(NBSign(NBSign::SIGN_TYPE_STOP, offset));
1099  }
1100  break;
1101  case NODETYPE_ALLWAY_STOP:
1103  break;
1106  break;
1107  default:
1108  break;
1109  }
1110  }
1111 }
1112 
1113 
1114 int
1115 NBEdgeCont::guessSidewalks(double width, double minSpeed, double maxSpeed, bool fromPermissions) {
1116  int sidewalksCreated = 0;
1117  const std::vector<std::string> edges = OptionsCont::getOptions().getStringVector("sidewalks.guess.exclude");
1118  std::set<std::string> exclude(edges.begin(), edges.end());
1119  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1120  NBEdge* edge = it->second;
1121  if (// not excluded
1122  exclude.count(edge->getID()) == 0
1123  // does not yet have a sidewalk
1124  && edge->getPermissions(0) != SVC_PEDESTRIAN
1125  && (
1126  // guess.from-permissions
1127  (fromPermissions && (edge->getPermissions() & SVC_PEDESTRIAN) != 0)
1128  // guess from speed
1129  || (!fromPermissions && edge->getSpeed() > minSpeed && edge->getSpeed() <= maxSpeed)
1130  )) {
1131  edge->addSidewalk(width);
1132  sidewalksCreated += 1;
1133  }
1134  }
1135  return sidewalksCreated;
1136 }
1137 
1138 
1139 int
1140 NBEdgeCont::remapIDs(bool numericaIDs, bool reservedIDs) {
1141  std::vector<std::string> avoid = getAllNames();
1142  std::set<std::string> reserve;
1143  if (reservedIDs) {
1144  NBHelpers::loadPrefixedIDsFomFile(OptionsCont::getOptions().getString("reserved-ids"), "edge:", reserve);
1145  avoid.insert(avoid.end(), reserve.begin(), reserve.end());
1146  }
1147  IDSupplier idSupplier("", avoid);
1148  std::set<NBEdge*, Named::ComparatorIdLess> toChange;
1149  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1150  if (numericaIDs) {
1151  try {
1152  TplConvert::_str2long(it->first);
1153  } catch (NumberFormatException&) {
1154  toChange.insert(it->second);
1155  }
1156  }
1157  if (reservedIDs && reserve.count(it->first) > 0) {
1158  toChange.insert(it->second);
1159  }
1160  }
1161  for (std::set<NBEdge*, Named::ComparatorIdLess>::iterator it = toChange.begin(); it != toChange.end(); ++it) {
1162  NBEdge* edge = *it;
1163  myEdges.erase(edge->getID());
1164  edge->setID(idSupplier.getNext());
1165  myEdges[edge->getID()] = edge;
1166  }
1167  return (int)toChange.size();
1168 }
1169 
1170 
1171 void
1172 NBEdgeCont::checkOverlap(double threshold, double zThreshold) const {
1173  for (EdgeCont::const_iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1174  const NBEdge* e1 = it->second;
1175  Boundary b1 = e1->getGeometry().getBoxBoundary();
1176  b1.grow(e1->getTotalWidth());
1177  PositionVector outline1 = e1->getCCWBoundaryLine(*e1->getFromNode());
1178  outline1.append(e1->getCCWBoundaryLine(*e1->getToNode()));
1179  // check is symmetric. only check once per pair
1180  for (EdgeCont::const_iterator it2 = it; it2 != myEdges.end(); it2++) {
1181  const NBEdge* e2 = it2->second;
1182  if (e1 == e2) {
1183  continue;
1184  }
1185  Boundary b2 = e2->getGeometry().getBoxBoundary();
1186  b2.grow(e2->getTotalWidth());
1187  if (b1.overlapsWith(b2)) {
1188  PositionVector outline2 = e2->getCCWBoundaryLine(*e2->getFromNode());
1189  outline2.append(e2->getCCWBoundaryLine(*e2->getToNode()));
1190  const double overlap = outline1.getOverlapWith(outline2, zThreshold);
1191  if (overlap > threshold) {
1192  WRITE_WARNING("Edge '" + e1->getID() + "' overlaps with edge '" + e2->getID() + "' by " + toString(overlap) + ".");
1193  }
1194  }
1195  }
1196  }
1197 }
1198 
1199 
1200 void
1201 NBEdgeCont::checkGrade(double threshold) const {
1202  for (EdgeCont::const_iterator it = myEdges.begin(); it != myEdges.end(); it++) {
1203  const NBEdge* edge = it->second;
1204  for (int i = 0; i < (int)edge->getNumLanes(); i++) {
1205  const double grade = edge->getLaneShape(i).getMaxGrade();
1206  if (grade > threshold) {
1207  WRITE_WARNING("Edge '" + edge->getID() + "' has a grade of " + toString(grade * 100) + "%.");
1208  break;
1209  }
1210  }
1211  const std::vector<NBEdge::Connection>& connections = edge->getConnections();
1212  for (std::vector<NBEdge::Connection>::const_iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
1213  const NBEdge::Connection& c = *it_con;
1214  const double grade = MAX2(c.shape.getMaxGrade(), c.viaShape.getMaxGrade());
1215  if (grade > threshold) {
1216  WRITE_WARNING("Connection '" + c.getDescription(edge) + "' has a grade of " + toString(grade * 100) + "%.");
1217  break;
1218  }
1219  }
1220  }
1221 }
1222 
1223 /****************************************************************************/
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:837
~NBEdgeCont()
Destructor.
Definition: NBEdgeCont.cpp:72
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1406
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:481
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
Definition: NBEdgeCont.cpp:830
double length2D() const
Returns the length.
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:164
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:2536
A class representing a single street sign.
Definition: NBSign.h:51
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:879
PositionVector shape
The lane&#39;s shape.
Definition: NBEdge.h:129
is a pedestrian
void append(const PositionVector &v, double sameThreshold=2.0)
void addSign(NBSign sign)
add Sign
Definition: NBEdge.h:1186
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:187
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:1353
void setEndOffset(int lane, double offset)
set lane specific end-offset (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2846
bool myNeedGeoTransformedPrunningBoundary
whether a geo transform has been applied to the pruning boundary
Definition: NBEdgeCont.h:656
#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:921
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:2862
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1556
NBEdge * getOppositeByID(const std::string &edgeID) const
Returns the edge with negated id if it exists.
Definition: NBEdgeCont.cpp:823
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:1291
const std::string & getTypeID() const
get ID of type
Definition: NBEdge.h:971
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
The representation of a single edge during network building.
Definition: NBEdge.h:71
void guessOpposites()
Sets opposite lane information for geometrically close edges.
Definition: NBEdgeCont.cpp:779
A container for districts.
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:258
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:1174
void removeDoubleEdges()
remove duble edges
Definition: NBNode.cpp:1180
T MAX2(T a, T b)
Definition: StdDefs.h:70
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2670
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:2885
void generateStreetSigns()
assigns street signs to edges based on toNode types
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:570
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:844
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
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:199
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:66
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1154
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns whether the boundary overlaps with the given polygon.
Definition: Boundary.cpp:189
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
static void loadEdgesFromFile(const std::string &file, std::set< std::string > &into)
Add edge ids defined in file (either ID or edge:ID per line) into the given set.
Definition: NBHelpers.cpp: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:3011
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:86
std::pair< PositionVector, PositionVector > splitAt(double where) const
Returns the two lists made when this list vector is splitted at the given point.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:255
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:1076
#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
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:245
void checkOverlap(double threshold, double zThreshold) const
check whether edges overlap
double area() const
Returns the area (0 for non-closed)
void checkGrade(double threshold) const
check whether edges are to steep
PositionVector shape
shape of Connection
Definition: NBEdge.h:217
NBEdgeCont(NBTypeCont &tc)
Constructor.
Definition: NBEdgeCont.cpp:63
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:1739
An (internal) definition of a single lane of an edge.
Definition: NBEdge.h:124
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:876
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
Definition: NBEdgeCont.h:641
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:75
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: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:524
std::string getNext()
Returns the next id.
Definition: IDSupplier.cpp:59
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
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
Definition: NBEdgeCont.cpp:287
void removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
Definition: NBEdgeCont.cpp:553
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2679
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
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:413
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
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
Definition: NBEdge.cpp:2394
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
Definition: NBEdgeCont.h:635
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:684
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
Definition: NBNode.h:250
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:600
static double formFactor(const EdgeVector &loopEdges)
compute the form factor for a loop of edges
std::vector< std::string > getStringVector(const std::string &name) const
Returns the list of string-vector-value of the named option (only for Option_String) ...
T MIN2(T a, T b)
Definition: StdDefs.h:64
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:175
double getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge&#39;s geometry at the given node.
Definition: NBEdge.cpp:1576
const std::set< EdgeSet > getRoundabouts() const
Returns the determined roundabouts.
Boundary & grow(double by)
extends the boundary by the given amount
Definition: Boundary.cpp:234
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
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:662
std::set< EdgeSet > myRoundabouts
Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout) ...
Definition: NBEdgeCont.h:660
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2913
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again ...
Definition: NBEdge.cpp:1854
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:692
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:507
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed) ...
Definition: NBEdgeCont.h:644
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:595
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
PositionVector myPrunningBoundary
Boundary within which an edge must be located in order to be kept.
Definition: NBEdgeCont.h:653
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 ...
void setID(const std::string &newID)
resets the id
Definition: Named.h:74
double length() const
Returns the length.
PositionVector viaShape
shape of via
Definition: NBEdge.h:232
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:660
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:757
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:240
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:834
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:1112
SumoXMLNodeType
Numbers representing special SUMO-XML-attribute values for representing node- (junction-) types used ...
const std::set< NBTrafficLightDefinition * > & getControllingTLS() const
Returns the traffic lights that were assigned to this node (The set of tls that control this node) ...
Definition: NBNode.h:298
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:2831
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:251
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:297
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:257
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:900
void computeEdgeShapes()
Computes the shapes of all edges stored in the container.
Definition: NBEdgeCont.cpp:676
The connection was computed.
Definition: NBEdge.h:113
const Position & getPosition() const
Definition: NBNode.h:232
Represents a single node (junction) during network building.
Definition: NBNode.h:75
void dismissVehicleClassInformation()
dimiss vehicle class information
Definition: NBEdge.cpp:2934
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:809
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
double getMaxGrade() const
return the maximum grade of all segments as a fraction of zRange/length2D
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:427
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
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:2532
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
double getOverlapWith(const PositionVector &poly, double zThreshold) const
Returns the maximum overlaps between this and the given polygon (when not separated by at least zThre...
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
void addRoundabout(const EdgeSet &roundabout)
add user specified roundabout
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:490
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:763
int remapIDs(bool numericaIDs, bool reservedIDs)
remap node IDs accoring to options –numerical-ids and –reserved-ids
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:542
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1353
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:434
bool isSimpleContinuation(bool checkLaneNumbers=true) const
check if node is a simple continuation
Definition: NBNode.cpp:432
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
Definition: NBEdge.cpp:1319
void setLaneWidth(int lane, double width)
set lane specific width (negative lane implies set for all lanes)
Definition: NBEdge.cpp:2807
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
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