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
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:971
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
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
Definition: NBEdgeCont.cpp:287
void checkOverlap(double threshold, double zThreshold) const
check whether edges overlap
A class representing a single street sign.
Definition: NBSign.h:51
PositionVector shape
The lane&#39;s shape.
Definition: NBEdge.h:129
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
is a pedestrian
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:542
void append(const PositionVector &v, double sameThreshold=2.0)
void addSign(NBSign sign)
add Sign
Definition: NBEdge.h: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
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.
bool myNeedGeoTransformedPrunningBoundary
whether a geo transform has been applied to the pruning boundary
Definition: NBEdgeCont.h:656
double getLoadedLength() const
Returns the length was set explicitly or the computed length if it wasn&#39;t set.
Definition: NBEdge.h:490
double nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
return the nearest offest to point 2D
#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
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
double getTotalWidth() const
Returns the combined width of all lanes of this edge.
Definition: NBEdge.cpp:2831
const std::vector< NBEdge::Lane > & getLanes() const
Returns the lane definitions.
Definition: NBEdge.h:570
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
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
The representation of a single edge during network building.
Definition: NBEdge.h:71
void guessOpposites()
Sets opposite lane information for geometrically close edges.
Definition: NBEdgeCont.cpp:779
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
std::string getDescription(const NBEdge *parent) const
get string describing this connection
Definition: NBEdge.cpp:86
A container for districts.
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h: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
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:600
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given ...
Definition: NBEdge.cpp:2885
double getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:507
void generateStreetSigns()
assigns street signs to edges based on toNode types
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
Definition: NBEdgeCont.cpp:404
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:416
void recheckPostProcessConnections()
Try to set any stored connections.
Definition: NBEdgeCont.cpp: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
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1154
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
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
NBEdge * getByID(const std::string &edgeID) const
Returns the edge with id if it exists.
Definition: NBEdgeCont.cpp:830
PositionVector shape
shape of Connection
Definition: NBEdge.h:217
NBEdgeCont(NBTypeCont &tc)
Constructor.
Definition: NBEdgeCont.cpp:63
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
double getOverlapWith(const PositionVector &poly, double zThreshold) const
Returns the maximum overlaps between this and the given polygon (when not separated by at least zThre...
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:245
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
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:876
double area() const
Returns the area (0 for non-closed)
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
Definition: NBEdgeCont.h:641
const Position & getPosition() const
Definition: NBNode.h:232
std::vector< double > distances(const PositionVector &s, bool perpendicular=false) const
distances of all my points to s and all of s points to myself
static double nearest_offset_on_line_to_point2D(const Position &lineStart, const Position &lineEnd, const Position &p, bool perpendicular=true)
Definition: GeomHelper.cpp:96
double myEdgesMinSpeed
The minimum speed an edge may have in order to be kept (default: -1)
Definition: NBEdgeCont.h:629
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h: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 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:158
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:56
void removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
Definition: NBEdgeCont.cpp:553
void extract(NBDistrictCont &dc, NBEdge *edge, bool remember=false)
Removes the given edge from the container like erase but does not delete it.
Definition: NBEdgeCont.cpp:392
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
A list of positions.
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
Definition: NBEdgeCont.cpp:78
bool overlapsWith(const AbstractPoly &poly, double offset=0) const
Returns whether the boundary overlaps with the given polygon.
Definition: Boundary.cpp:189
void moveOutgoingConnectionsFrom(NBEdge *e, int laneOff)
move outgoing connection
Definition: NBEdge.cpp:2394
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
Definition: NBEdgeCont.h:635
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:257
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
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:413
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node) ...
Definition: NBNode.h:250
double length() const
Returns the length.
static double formFactor(const EdgeVector &loopEdges)
compute the form factor for a loop of edges
T MIN2(T a, T b)
Definition: StdDefs.h: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:176
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
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:75
The connection was given by the user.
Definition: NBEdge.h: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
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:1739
bool recheckLanes()
recheck whether all lanes within the edge are all right and optimises the connections once again ...
Definition: NBEdge.cpp:1854
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1556
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:692
double getMaxGrade() const
return the maximum grade of all segments as a fraction of zRange/length2D
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed) ...
Definition: NBEdgeCont.h:644
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:206
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2913
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 ...
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:434
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:481
void setID(const std::string &newID)
resets the id
Definition: Named.h:74
double length2D() const
Returns the length.
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:251
PositionVector viaShape
shape of via
Definition: NBEdge.h: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
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 ...
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:41
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:199
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:595
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
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
NBEdge * getOppositeByID(const std::string &edgeID) const
Returns the edge with negated id if it exists.
Definition: NBEdgeCont.cpp:823
Represents a single node (junction) during network building.
Definition: NBNode.h:75
void dismissVehicleClassInformation()
dimiss vehicle class information
Definition: NBEdge.cpp:2934
bool isSimpleContinuation(bool checkLaneNumbers=true) const
check if node is a simple continuation
Definition: NBNode.cpp:432
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
std::pair< PositionVector, PositionVector > splitAt(double where) const
Returns the two lists made when this list vector is splitted at the given point.
std::string getLaneID(int lane) const
get Lane ID (Secure)
Definition: NBEdge.cpp:2679
void checkGrade(double threshold) const
check whether edges are to steep
void removeFromSinksAndSources(NBEdge *const e)
Removes the given edge from the lists of sources and sinks in all stored districts.
std::set< std::string > myTypes2Remove
Set of edges types which shall be removed.
Definition: NBEdgeCont.h:650
void recheckLanes()
Rechecks whether all lanes have a successor for each of the stored edges.
Definition: NBEdgeCont.cpp:632
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:63
static T maxValue(const std::vector< T > &v)
Definition: VectorHelper.h:98
std::set< std::string > myIgnoredEdges
The ids of ignored edges.
Definition: NBEdgeCont.h:620
EdgeVector getGeneratedFrom(const std::string &id) const
Returns the edges which have been built by splitting the edge of the given id.
Definition: NBEdgeCont.cpp:879
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
void addRoundabout(const EdgeSet &roundabout)
add user specified roundabout
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:763
int remapIDs(bool numericaIDs, bool reservedIDs)
remap node IDs accoring to options –numerical-ids and –reserved-ids
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:834
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1353
NBEdge * getTurnDestination(bool possibleDestination=false) const
Definition: NBEdge.cpp:2670
const PositionVector & getLaneShape(int i) const
Returns the shape of the nth lane.
Definition: NBEdge.cpp:757
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void copyConnectionsFrom(NBEdge *src)
copy connections from antoher edge
Definition: NBEdge.cpp: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
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
int myEdgesSplit
the number of splits of edges during the building
Definition: NBEdgeCont.h:623
std::set< std::string > myEdges2Remove
Set of ids of edges which shall explicitly be removed.
Definition: NBEdgeCont.h:638
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:427