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