SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-sim.org/
13 // Copyright (C) 2001-2014 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 <iostream>
39 #include <fstream>
40 #include <iomanip>
41 #include <utils/geom/Boundary.h>
42 #include <utils/geom/GeomHelper.h>
45 #include <utils/common/ToString.h>
48 #include "NBNetBuilder.h"
49 #include "NBEdgeCont.h"
50 #include "NBNodeCont.h"
51 #include "NBHelpers.h"
52 #include "NBCont.h"
54 #include "NBDistrictCont.h"
55 #include <cmath>
56 #include "NBTypeCont.h"
60 
61 #ifdef CHECK_MEMORY_LEAKS
62 #include <foreign/nvwa/debug_new.h>
63 #endif // CHECK_MEMORY_LEAKS
64 
65 
66 // ===========================================================================
67 // method definitions
68 // ===========================================================================
70  myTypeCont(tc),
71  myEdgesSplit(0),
72  myVehicleClasses2Keep(0),
73  myVehicleClasses2Remove(0),
74  myNeedGeoTransformedPrunningBoundary(false)
75 {}
76 
77 
79  clear();
80 }
81 
82 
83 void
85  myAmLeftHanded = oc.getBool("lefthand");
86  // set edges dismiss/accept options
87  myEdgesMinSpeed = oc.isSet("keep-edges.min-speed") ? oc.getFloat("keep-edges.min-speed") : -1;
88  myRemoveEdgesAfterJoining = oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload");
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<SUMOReal> poly;
117  for (std::vector<std::string>::iterator i = polyS.begin(); i != polyS.end(); ++i) {
118  poly.push_back(TplConvert::_2SUMOReal((*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<SUMOReal>::iterator j = poly.begin(); j != poly.end();) {
132  SUMOReal x = *j++;
133  SUMOReal y = *j++;
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 (myAmLeftHanded) {
160  edge->setLeftHanded();
161  }
162  if (myEdges.count(edge->getID())) {
163  return false;
164  }
165  if (!ignorePrunning && ignoreFilterMatch(edge)) {
166  edge->getFromNode()->removeEdge(edge);
167  edge->getToNode()->removeEdge(edge);
168  myIgnoredEdges.insert(edge->getID());
169  delete edge;
170  } else {
172  if (oc.exists("dismiss-vclasses") && oc.getBool("dismiss-vclasses")) {
174  }
175  myEdges[edge->getID()] = edge;
176  }
177  return true;
178 }
179 
180 
181 bool
183  // remove edges which allow a speed below a set one (set using "keep-edges.min-speed")
184  if (edge->getSpeed() < myEdgesMinSpeed) {
185  return true;
186  }
187  // check whether the edge is a named edge to keep
188  if (!myRemoveEdgesAfterJoining && myEdges2Keep.size() != 0) {
189  if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) == myEdges2Keep.end()) {
190  return true;
191  }
192  }
193  // check whether the edge is a named edge to remove
194  if (myEdges2Remove.size() != 0) {
195  if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) {
196  return true;
197  }
198  }
199  // check whether the edge shall be removed because it does not allow any of the wished classes
200  if (myVehicleClasses2Keep != 0 && (myVehicleClasses2Keep & edge->getPermissions()) == 0) {
201  return true;
202  }
203  // check whether the edge shall be removed due to allowing unwished classes only
205  return true;
206  }
207  // check whether the edge shall be removed because it does not have one of the requested types
208  if (myTypes2Keep.size() != 0) {
209  if (myTypes2Keep.count(edge->getTypeID()) == 0) {
210  return true;
211  }
212  }
213  // check whether the edge shall be removed because it has one of the forbidden types
214  if (myTypes2Remove.size() != 0) {
215  if (myTypes2Remove.count(edge->getTypeID()) > 0) {
216  return true;
217  }
218  }
219  // check whether the edge is within the prunning boundary
220  if (myPrunningBoundary.size() != 0) {
224  } else if (GeoConvHelper::getLoaded().usingGeoProjection()) {
225  // XXX what if input file with different projections are loaded?
226  for (int i = 0; i < (int) myPrunningBoundary.size(); i++) {
228  }
229  } else {
230  WRITE_ERROR("Cannot prune edges using a geo-boundary because no projection has been loaded");
231  }
232  }
234  return true;
235  }
236  }
238  return true;
239  }
240  return false;
241 }
242 
243 
244 NBEdge*
245 NBEdgeCont::retrieve(const std::string& id, bool retrieveExtracted) const {
246  EdgeCont::const_iterator i = myEdges.find(id);
247  if (i == myEdges.end()) {
248  if (retrieveExtracted) {
249  i = myExtractedEdges.find(id);
250  if (i == myExtractedEdges.end()) {
251  return 0;
252  }
253  } else {
254  return 0;
255  }
256  }
257  return (*i).second;
258 }
259 
260 
261 NBEdge*
262 NBEdgeCont::retrievePossiblySplit(const std::string& id, bool downstream) const {
263  NBEdge* edge = retrieve(id);
264  if (edge == 0) {
265  return 0;
266  }
267  const EdgeVector* candidates = downstream ? &edge->getToNode()->getOutgoingEdges() : &edge->getFromNode()->getIncomingEdges();
268  while (candidates->size() == 1) {
269  const std::string& nextID = candidates->front()->getID();
270  if (nextID.find(id) != 0 || nextID.size() <= id.size() + 1 || (nextID[id.size()] != '.' && nextID[id.size()] != '-')) {
271  break;
272  }
273  edge = candidates->front();
274  candidates = downstream ? &edge->getToNode()->getOutgoingEdges() : &edge->getFromNode()->getIncomingEdges();
275  }
276  return edge;
277 }
278 
279 
280 NBEdge*
281 NBEdgeCont::retrievePossiblySplit(const std::string& id, const std::string& hint, bool incoming) const {
282  // try to retrieve using the given name (iterative)
283  NBEdge* edge = retrieve(id);
284  if (edge != 0) {
285  return edge;
286  }
287  // now, we did not find it; we have to look over all possibilities
288  EdgeVector hints;
289  // check whether at least the hint was not splitted
290  NBEdge* hintedge = retrieve(hint);
291  if (hintedge == 0) {
292  hints = getGeneratedFrom(hint);
293  } else {
294  hints.push_back(hintedge);
295  }
296  EdgeVector candidates = getGeneratedFrom(id);
297  for (EdgeVector::iterator i = hints.begin(); i != hints.end(); i++) {
298  NBEdge* hintedge = (*i);
299  for (EdgeVector::iterator j = candidates.begin(); j != candidates.end(); j++) {
300  NBEdge* poss_searched = (*j);
301  NBNode* node = incoming
302  ? poss_searched->myTo : poss_searched->myFrom;
303  const EdgeVector& cont = incoming
304  ? node->getOutgoingEdges() : node->getIncomingEdges();
305  if (find(cont.begin(), cont.end(), hintedge) != cont.end()) {
306  return poss_searched;
307  }
308  }
309  }
310  return 0;
311 }
312 
313 
314 NBEdge*
315 NBEdgeCont::retrievePossiblySplit(const std::string& id, SUMOReal pos) const {
316  // check whether the edge was not split, yet
317  NBEdge* edge = retrieve(id);
318  if (edge != 0) {
319  return edge;
320  }
321  size_t maxLength = 0;
322  std::string tid = id + "[";
323  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
324  if ((*i).first.find(tid) == 0) {
325  maxLength = MAX2(maxLength, (*i).first.length());
326  }
327  }
328  // find the part of the edge which matches the position
329  SUMOReal seen = 0;
330  std::vector<std::string> names;
331  names.push_back(id + "[1]");
332  names.push_back(id + "[0]");
333  while (names.size() > 0) {
334  // retrieve the first subelement (to follow)
335  std::string cid = names.back();
336  names.pop_back();
337  edge = retrieve(cid);
338  // The edge was splitted; check its subparts within the
339  // next step
340  if (edge == 0) {
341  if (cid.length() + 3 < maxLength) {
342  names.push_back(cid + "[1]");
343  names.push_back(cid + "[0]");
344  }
345  }
346  // an edge with the name was found,
347  // check whether the position lies within it
348  else {
349  seen += edge->getLength();
350  if (seen >= pos) {
351  return edge;
352  }
353  }
354  }
355  return 0;
356 }
357 
358 
359 void
361  extract(dc, edge);
362  delete edge;
363 }
364 
365 
366 void
367 NBEdgeCont::extract(NBDistrictCont& dc, NBEdge* edge, bool remember) {
368  if (remember) {
369  myExtractedEdges[edge->getID()] = edge;
370  }
371  myEdges.erase(edge->getID());
372  edge->myFrom->removeEdge(edge);
373  edge->myTo->removeEdge(edge);
374  dc.removeFromSinksAndSources(edge);
375 }
376 
377 
378 void
379 NBEdgeCont::rename(NBEdge* edge, const std::string& newID) {
380  if (myEdges.count(newID) != 0) {
381  throw ProcessError("Attempt to rename edge using existing id '" + newID + "'");
382  }
383  myEdges.erase(edge->getID());
384  edge->setID(newID);
385  myEdges[newID] = edge;
386 }
387 
388 
389 // ----- explicit edge manipulation methods
390 bool
392  return splitAt(dc, edge, node, edge->getID() + "[0]", edge->getID() + "[1]",
393  (unsigned int) edge->myLanes.size(), (unsigned int) edge->myLanes.size());
394 }
395 
396 
397 bool
399  const std::string& firstEdgeName,
400  const std::string& secondEdgeName,
401  unsigned int noLanesFirstEdge, unsigned int noLanesSecondEdge) {
402  SUMOReal pos;
403  pos = edge->getGeometry().nearest_offset_to_point2D(node->getPosition());
404  if (pos <= 0) {
406  edge->myFrom->getPosition(), edge->myTo->getPosition(),
407  node->getPosition());
408  }
409  if (pos <= 0 || pos + POSITION_EPS > edge->getGeometry().length()) {
410  return false;
411  }
412  return splitAt(dc, edge, pos, node, firstEdgeName, secondEdgeName,
413  noLanesFirstEdge, noLanesSecondEdge);
414 }
415 
416 
417 bool
419  NBEdge* edge, SUMOReal pos, NBNode* node,
420  const std::string& firstEdgeName,
421  const std::string& secondEdgeName,
422  unsigned int noLanesFirstEdge, unsigned int noLanesSecondEdge) {
423  // build the new edges' geometries
424  std::pair<PositionVector, PositionVector> geoms =
425  edge->getGeometry().splitAt(pos);
426  if (geoms.first[-1] != node->getPosition()) {
427  geoms.first.pop_back();
428  geoms.first.push_back(node->getPosition());
429  }
430 
431  if (geoms.second[0] != node->getPosition()) {
432  geoms.second.pop_front();
433  geoms.second.push_front(node->getPosition());
434  }
435  // build and insert the edges
436  NBEdge* one = new NBEdge(firstEdgeName, edge->myFrom, node, edge, geoms.first, noLanesFirstEdge);
437  NBEdge* two = new NBEdge(secondEdgeName, node, edge->myTo, edge, geoms.second, noLanesSecondEdge);
438  two->copyConnectionsFrom(edge);
439  // replace information about this edge within the nodes
440  edge->myFrom->replaceOutgoing(edge, one, 0);
441  edge->myTo->replaceIncoming(edge, two, 0);
442  // the edge is now occuring twice in both nodes...
443  // clean up
444  edge->myFrom->removeDoubleEdges();
445  edge->myTo->removeDoubleEdges();
446  // add connections from the first to the second edge
447  // check special case:
448  // one in, one out, the outgoing has one lane more
449  if (noLanesFirstEdge == noLanesSecondEdge - 1) {
450  for (unsigned int i = 0; i < one->getNumLanes(); i++) {
451  if (!one->addLane2LaneConnection(i, two, i + 1, NBEdge::L2L_COMPUTED)) { // !!! Bresenham, here!!!
452  throw ProcessError("Could not set connection!");
453  }
454  }
456  } else {
457  for (unsigned int i = 0; i < one->getNumLanes() && i < two->getNumLanes(); i++) {
458  if (!one->addLane2LaneConnection(i, two, i, NBEdge::L2L_COMPUTED)) {// !!! Bresenham, here!!!
459  throw ProcessError("Could not set connection!");
460  }
461  }
462  }
464  if (find(myEdges2Keep.begin(), myEdges2Keep.end(), edge->getID()) != myEdges2Keep.end()) {
465  myEdges2Keep.insert(one->getID());
466  myEdges2Keep.insert(two->getID());
467  }
468  if (find(myEdges2Remove.begin(), myEdges2Remove.end(), edge->getID()) != myEdges2Remove.end()) {
469  myEdges2Remove.insert(one->getID());
470  myEdges2Remove.insert(two->getID());
471  }
472  }
473  // erase the splitted edge
474  erase(dc, edge);
475  insert(one, true);
476  insert(two, true);
477  myEdgesSplit++;
478  return true;
479 }
480 
481 
482 
483 // ----- container access methods
484 std::vector<std::string>
486  std::vector<std::string> ret;
487  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
488  ret.push_back((*i).first);
489  }
490  return ret;
491 }
492 
493 
494 // ----- Adapting the input
495 void
497  EdgeVector toRemove;
498  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
499  NBEdge* edge = (*i).second;
500  if (!myEdges2Keep.count(edge->getID())) {
501  edge->getFromNode()->removeEdge(edge);
502  edge->getToNode()->removeEdge(edge);
503  toRemove.push_back(edge);
504  }
505  }
506  for (EdgeVector::iterator j = toRemove.begin(); j != toRemove.end(); ++j) {
507  erase(dc, *j);
508  }
509 }
510 
511 
512 void
514  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
515  if ((*i).second->getGeometry().size() < 3) {
516  continue;
517  }
518  (*i).second->splitGeometry(*this, nc);
519  }
520 }
521 
522 
523 void
525  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
526  (*i).second->reduceGeometry(minDist);
527  }
528 }
529 
530 
531 void
532 NBEdgeCont::checkGeometries(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix) {
533  if (maxAngle > 0 || minRadius > 0) {
534  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
535  (*i).second->checkGeometry(maxAngle, minRadius, fix);
536  }
537  }
538 }
539 
540 
541 // ----- processing methods
542 void
544  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); i++) {
545  (*i).second->clearControllingTLInformation();
546  }
547 }
548 
549 
550 void
552  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
553  (*i).second->sortOutgoingConnectionsByAngle();
554  }
555 }
556 
557 
558 void
559 NBEdgeCont::computeEdge2Edges(bool noLeftMovers) {
560  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
561  (*i).second->computeEdge2Edges(noLeftMovers);
562  }
563 }
564 
565 
566 void
567 NBEdgeCont::computeLanes2Edges(const bool buildCrossingsAndWalkingAreas) {
568  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
569  (*i).second->computeLanes2Edges(buildCrossingsAndWalkingAreas);
570  }
571 }
572 
573 
574 void
575 NBEdgeCont::recheckLanes(const bool buildCrossingsAndWalkingAreas) {
576  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
577  (*i).second->recheckLanes(buildCrossingsAndWalkingAreas);
578  }
579 }
580 
581 
582 void
583 NBEdgeCont::appendTurnarounds(bool noTLSControlled) {
584  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
585  (*i).second->appendTurnaround(noTLSControlled);
586  }
587 }
588 
589 
590 void
591 NBEdgeCont::appendTurnarounds(const std::set<std::string>& ids, bool noTLSControlled) {
592  for (std::set<std::string>::const_iterator it = ids.begin(); it != ids.end(); it++) {
593  myEdges[*it]->appendTurnaround(noTLSControlled);
594  }
595 }
596 
597 
598 void
600  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); i++) {
601  (*i).second->computeEdgeShape();
602  }
603 }
604 
605 
606 void
608  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
609  (*i).second->computeLaneShapes();
610  }
611 }
612 
613 
614 void
617  EdgeVector edges) {
618  // !!! Attention!
619  // No merging of the geometry to come is being done
620  // The connections are moved from one edge to another within
621  // the replacement where the edge is a node's incoming edge.
622 
623  // count the number of lanes, the speed and the id
624  unsigned int nolanes = 0;
625  SUMOReal speed = 0;
626  int priority = 0;
627  std::string id;
628  sort(edges.begin(), edges.end(), NBContHelper::same_connection_edge_sorter());
629  // retrieve the connected nodes
630  NBEdge* tpledge = *(edges.begin());
631  NBNode* from = tpledge->getFromNode();
632  NBNode* to = tpledge->getToNode();
633  EdgeVector::const_iterator i;
634  for (i = edges.begin(); i != edges.end(); i++) {
635  // some assertions
636  assert((*i)->getFromNode() == from);
637  assert((*i)->getToNode() == to);
638  // ad the number of lanes the current edge has
639  nolanes += (*i)->getNumLanes();
640  // build the id
641  if (i != edges.begin()) {
642  id += "+";
643  }
644  id += (*i)->getID();
645  // compute the speed
646  speed += (*i)->getSpeed();
647  // build the priority
648  priority = MAX2(priority, (*i)->getPriority());
649  }
650  speed /= edges.size();
651  // build the new edge
652  // @bug new edge does not know about allowed vclass of old edges
653  // @bug both the width and the offset are not regarded
654  NBEdge* newEdge = new NBEdge(id, from, to, "", speed, nolanes, priority,
656  tpledge->getStreetName(), tpledge->myLaneSpreadFunction);
657  insert(newEdge, true);
658  // replace old edge by current within the nodes
659  // and delete the old
660  from->replaceOutgoing(edges, newEdge);
661  to->replaceIncoming(edges, newEdge);
662  // patch connections
663  // add edge2edge-information
664  for (i = edges.begin(); i != edges.end(); i++) {
665  EdgeVector ev = (*i)->getConnectedEdges();
666  for (EdgeVector::iterator j = ev.begin(); j != ev.end(); j++) {
667  newEdge->addEdge2EdgeConnection(*j);
668  }
669  }
670  // move lane2lane-connections
671  unsigned int currLane = 0;
672  for (i = edges.begin(); i != edges.end(); i++) {
673  newEdge->moveOutgoingConnectionsFrom(*i, currLane);
674  currLane += (*i)->getNumLanes();
675  }
676  // patch tl-information
677  currLane = 0;
678  for (i = edges.begin(); i != edges.end(); i++) {
679  unsigned int noLanes = (*i)->getNumLanes();
680  for (unsigned int j = 0; j < noLanes; j++, currLane++) {
681  // replace in traffic lights
682  tlc.replaceRemoved(*i, j, newEdge, currLane);
683  }
684  }
685  // delete joined edges
686  for (i = edges.begin(); i != edges.end(); i++) {
687  erase(dc, *i);
688  }
689 }
690 
691 
692 void
694  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
695  std::string oppositeID;
696  if ((*i).first[0] == '-') {
697  oppositeID = (*i).first.substr(1);
698  } else {
699  oppositeID = "-" + (*i).first;
700  }
701  if (myEdges.find(oppositeID) != myEdges.end()) {
702  (*i).second->setLaneSpreadFunction(LANESPREAD_RIGHT);
703  myEdges.find(oppositeID)->second->setLaneSpreadFunction(LANESPREAD_RIGHT);
704  } else {
705  (*i).second->setLaneSpreadFunction(LANESPREAD_CENTER);
706  }
707  }
708 }
709 
710 
711 
712 // ----- other
713 void
714 NBEdgeCont::addPostProcessConnection(const std::string& from, int fromLane, const std::string& to, int toLane, bool mayDefinitelyPass) {
715  myConnections.push_back(PostProcessConnection(from, fromLane, to, toLane, mayDefinitelyPass));
716 }
717 
718 
719 void
721  for (std::vector<PostProcessConnection>::const_iterator i = myConnections.begin(); i != myConnections.end(); ++i) {
722  NBEdge* from = retrievePossiblySplit((*i).from, true);
723  NBEdge* to = retrievePossiblySplit((*i).to, false);
724  if (from != 0 && to != 0) {
725  if (!from->addLane2LaneConnection((*i).fromLane, to, (*i).toLane, NBEdge::L2L_USER, false, (*i).mayDefinitelyPass)) {
726  WRITE_WARNING("Could not insert connection between '" + (*i).from + "' and '" + (*i).to + "' after build.");
727  }
728  }
729  }
730  // during loading we also kept some ambiguous connections in hope they might be valid after processing
731  // we need to make sure that all invalid connections are removed now
732  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); ++it) {
733  NBEdge* edge = it->second;
734  NBNode* to = edge->getToNode();
735  // make a copy because we may delete connections
736  std::vector<NBEdge::Connection> connections = edge->getConnections();
737  for (std::vector<NBEdge::Connection>::iterator it_con = connections.begin(); it_con != connections.end(); ++it_con) {
738  NBEdge::Connection& c = *it_con;
739  if (c.toEdge != 0 && c.toEdge->getFromNode() != to) {
740  WRITE_WARNING("Found and removed invalid connection from " + edge->getID() +
741  " to " + c.toEdge->getID() + " via " + to->getID());
742  edge->removeFromConnections(c.toEdge);
743  }
744  }
745  }
746 }
747 
748 
750 NBEdgeCont::getGeneratedFrom(const std::string& id) const {
751  size_t len = id.length();
752  EdgeVector ret;
753  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
754  std::string curr = (*i).first;
755  // the next check makes it possibly faster - we don not have
756  // to compare the names
757  if (curr.length() <= len) {
758  continue;
759  }
760  // the name must be the same as the given id but something
761  // beginning with a '[' must be appended to it
762  if (curr.substr(0, len) == id && curr[len] == '[') {
763  ret.push_back((*i).second);
764  continue;
765  }
766  // ok, maybe the edge is a compound made during joining of edges
767  size_t pos = curr.find(id);
768  // surely not
769  if (pos == std::string::npos) {
770  continue;
771  }
772  // check leading char
773  if (pos > 0) {
774  if (curr[pos - 1] != ']' && curr[pos - 1] != '+') {
775  // actually, this is another id
776  continue;
777  }
778  }
779  if (pos + id.length() < curr.length()) {
780  if (curr[pos + id.length()] != '[' && curr[pos + id.length()] != '+') {
781  // actually, this is another id
782  continue;
783  }
784  }
785  ret.push_back((*i).second);
786  }
787  return ret;
788 }
789 
790 
791 void
792 NBEdgeCont::guessRoundabouts(std::vector<EdgeVector>& marked) {
793  // step 1: keep only those edges which have no turnarounds
794  std::set<NBEdge*> candidates;
795  for (EdgeCont::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
796  NBEdge* e = (*i).second;
797  NBNode* const to = e->getToNode();
798  if (e->getTurnDestination() == 0 && to->getConnectionTo(e->getFromNode()) == 0) {
799  candidates.insert(e);
800  }
801  }
802 
803  // step 2:
804  std::set<NBEdge*> visited;
805  for (std::set<NBEdge*>::const_iterator i = candidates.begin(); i != candidates.end(); ++i) {
806  EdgeVector loopEdges;
807  // start with a random edge (this doesn't have to be a roundabout edge)
808  // loop over connected edges (using always the leftmost one)
809  // and keep the list in loopEdges
810  // continue until we loop back onto a loopEdges and extract the loop
811  NBEdge* e = (*i);
812  if (visited.count(e) > 0) {
813  // already seen
814  continue;
815  }
816  loopEdges.push_back(e);
817  bool doLoop = true;
818  do {
819  visited.insert(e);
820  const EdgeVector& edges = e->getToNode()->getEdges();
821  if (edges.size() < 2) {
822  doLoop = false;
823  break;
824  }
825  if (e->getTurnDestination() != 0 || e->getToNode()->getConnectionTo(e->getFromNode()) != 0) {
826  // do not follow turn-arounds while in a (tentative) loop
827  doLoop = false;
828  break;
829  }
830  EdgeVector::const_iterator me = find(edges.begin(), edges.end(), e);
831  NBContHelper::nextCW(edges, me);
832  NBEdge* left = *me;
833  SUMOReal angle = fabs(NBHelpers::relAngle(e->getAngleAtNode(e->getToNode()), left->getAngleAtNode(e->getToNode())));
834  if (angle >= 90) {
835  // roundabouts do not have sharp turns (or they wouldn't be called 'round')
836  doLoop = false;
837  break;
838  }
839  EdgeVector::const_iterator loopClosed = find(loopEdges.begin(), loopEdges.end(), left);
840  const size_t loopSize = loopEdges.end() - loopClosed;
841  if (loopSize > 0) {
842  // loop found
843  if (loopSize < 3) {
844  doLoop = false; // need at least 3 edges for a roundabout
845  } else if (loopSize < loopEdges.size()) {
846  // remove initial edges not belonging to the loop
847  EdgeVector(loopEdges.begin() + (loopEdges.size() - loopSize), loopEdges.end()).swap(loopEdges);
848  }
849  // count attachments to the outside. need at least 3 or a roundabout doesn't make much sense
850  int attachments = 0;
851  for (EdgeVector::const_iterator j = loopEdges.begin(); j != loopEdges.end(); ++j) {
852  if ((*j)->getToNode()->getEdges().size() > 2) {
853  attachments++;
854  }
855  }
856  if (attachments < 3) {
857  doLoop = false;
858  }
859  break;
860  }
861  if (visited.count(left) > 0) {
862  doLoop = false;
863  } else {
864  // keep going
865  loopEdges.push_back(left);
866  e = left;
867  }
868  } while (doLoop);
869  // mark collected edges in the case a loop (roundabout) was found
870  if (doLoop) {
871  std::set<NBEdge*> loopEdgesSet(loopEdges.begin(), loopEdges.end());
872  for (std::set<NBEdge*>::const_iterator j = loopEdgesSet.begin(); j != loopEdgesSet.end(); ++j) {
873  // disable turnarounds on incoming edges
874  NBNode* node = (*j)->getToNode();
875  const EdgeVector& incoming = node->getIncomingEdges();
876  for (EdgeVector::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
877  NBEdge* inEdge = *k;
878  if (loopEdgesSet.count(inEdge) > 0) {
879  continue;
880  }
881  if ((inEdge)->getStep() >= NBEdge::LANES2LANES_USER) {
882  continue;
883  }
884  inEdge->removeFromConnections(inEdge->getTurnDestination(), -1);
885  }
886  // let the connections to succeeding roundabout edge have a higher priority
887  (*j)->setJunctionPriority(node, 1000);
888  node->setRoundabout();
889  }
890  marked.push_back(loopEdges);
891  }
892  }
893 }
894 
895 
896 void
898  for (EdgeCont::iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
899  NBEdge* e = i->second;
900  // is this a "real" junction?
901  // XXX nyi
902  //continue
903  const SUMOReal offset = e->getLength() - 3;
904  switch (e->getToNode()->getType()) {
905  case NODETYPE_PRIORITY:
906  // yield or major?
907  if (e->getJunctionPriority(e->getToNode()) > 0) {
909  } else {
911  }
912  break;
914  // yield or major?
915  if (e->getJunctionPriority(e->getToNode()) > 0) {
917  } else {
919  }
920  break;
923  break;
926  break;
927  default:
928  break;
929  }
930  }
931 }
932 
933 
934 int
936  int sidewalksCreated = 0;
937  for (EdgeCont::iterator it = myEdges.begin(); it != myEdges.end(); it++) {
938  NBEdge* edge = it->second;
939  if (edge->getSpeed() > minSpeed && edge->getSpeed() <= maxSpeed && edge->getPermissions(0) != SVC_PEDESTRIAN) {
940  edge->addSidewalk(width);
941  sidewalksCreated += 1;
942  }
943  }
944  return sidewalksCreated;
945 }
946 
947 
948 /****************************************************************************/
~NBEdgeCont()
Destructor.
Definition: NBEdgeCont.cpp:78
std::vector< Lane > myLanes
Lane information.
Definition: NBEdge.h:1259
void replaceIncoming(NBEdge *which, NBEdge *by, unsigned int laneOff)
Replaces occurences of the first edge within the list of incoming by the second Connections are remap...
Definition: NBNode.cpp:851
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's incoming edges.
Definition: NBNode.h:244
const std::string & getTypeID() const
Definition: NBEdge.h:885
A structure which describes a connection between edges or lanes.
Definition: NBEdge.h:148
void sortOutgoingLanesConnections()
Sorts all lanes of all edges within the container by their direction.
Definition: NBEdgeCont.cpp:551
bool myAmLeftHanded
Whether the network is left-handed.
Definition: NBEdgeCont.h:570
void setRoundabout()
update the type of this node as a roundabout
Definition: NBNode.cpp:1992
NBEdge * retrievePossiblySplit(const std::string &id, bool downstream) const
Tries to retrieve an edge, even if it is splitted.
Definition: NBEdgeCont.cpp:262
static const SUMOReal UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:201
A class representing a single street sign.
Definition: NBSign.h:51
bool x2cartesian_const(Position &from) const
Converts the given coordinate into a cartesian using the previous initialisation. ...
is a pedestrian
SUMOReal nearest_offset_to_point2D(const Position &p, bool perpendicular=true) const
std::vector< std::string > getAllNames() const
Returns all ids of known edges.
Definition: NBEdgeCont.cpp:485
static bool transformCoordinates(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
void addSign(NBSign sign)
Definition: NBEdge.h:1049
NBEdge * toEdge
The edge the connections yields in.
Definition: NBEdge.h:164
NBNode * myTo
Definition: NBEdge.h:1210
static SUMOReal _2SUMOReal(const E *const data)
Definition: TplConvert.h:223
bool myNeedGeoTransformedPrunningBoundary
whether a geo transform has been applied to the pruning boundary
Definition: NBEdgeCont.h:604
A container for traffic light definitions and built programs.
bool myRemoveEdgesAfterJoining
Whether edges shall be joined first, then removed.
Definition: NBEdgeCont.h:580
void moveOutgoingConnectionsFrom(NBEdge *e, unsigned int laneOff)
Definition: NBEdge.cpp:1697
void addSidewalk(SUMOReal width)
add a pedestrian sidewalk of the given width and shift existing connctions
Definition: NBEdge.cpp:2237
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:97
void removeEdge(NBEdge *edge, bool removeFromConnections=true)
Removes edge from this node and optionally removes connections as well.
Definition: NBNode.cpp:1031
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
A container for districts.
static GeoConvHelper & getLoaded()
the coordinate transformation that was loaded fron an input file
bool addLane2LaneConnection(unsigned int fromLane, NBEdge *dest, unsigned int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:628
void removeDoubleEdges()
Definition: NBNode.cpp:919
T MAX2(T a, T b)
Definition: StdDefs.h:72
void clearControllingTLInformation() const
Clears information about controlling traffic lights for all connenections of all edges.
Definition: NBEdgeCont.cpp:543
void generateStreetSigns()
assigns street signs to edges based on toNode types
Definition: NBEdgeCont.cpp:897
void rename(NBEdge *edge, const std::string &newID)
Renames the edge. Throws exception if newID already exists.
Definition: NBEdgeCont.cpp:379
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:391
void recheckPostProcessConnections()
Try to set any stored connections.
Definition: NBEdgeCont.cpp:720
SUMOReal getFloat(const std::string &name) const
Returns the SUMOReal-value of the named option (only for Option_Float)
static void nextCW(const EdgeVector &edges, EdgeVector::const_iterator &from)
unsigned int myEdgesSplit
the number of splits of edges during the building
Definition: NBEdgeCont.h:567
static const SUMOReal UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:203
std::vector< PostProcessConnection > myConnections
The list of connections to recheck.
Definition: NBEdgeCont.h:551
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:200
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:67
void checkGeometries(const SUMOReal maxAngle, const SUMOReal minRadius, bool fix)
Definition: NBEdgeCont.cpp:532
void guessRoundabouts(std::vector< EdgeVector > &marked)
Determines which edges belong to roundabouts and increases their priority.
Definition: NBEdgeCont.cpp:792
NBEdgeCont(NBTypeCont &tc)
Constructor.
Definition: NBEdgeCont.cpp:69
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges.
Definition: NBNode.h:252
const std::string & getID() const
Returns the id.
Definition: Named.h:60
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:604
bool overlapsWith(const AbstractPoly &poly, SUMOReal offset=0) const
Returns whether the boundary overlaps with the given polygon.
Definition: Boundary.cpp:156
static SUMOReal nearest_offset_on_line_to_point2D(const Position &l1, const Position &l2, const Position &p, bool perpendicular=true)
Definition: GeomHelper.cpp:251
SVCPermissions myVehicleClasses2Keep
Set of vehicle types which must be allowed on edges in order to keep them.
Definition: NBEdgeCont.h:589
const Position & getPosition() const
Returns the position of this node.
Definition: NBNode.h:232
void reduceGeometries(const SUMOReal minDist)
Definition: NBEdgeCont.cpp:524
void computeLanes2Edges(const bool buildCrossingsAndWalkingAreas)
Computes for each edge which lanes approach the next edges.
Definition: NBEdgeCont.cpp:567
Lanes to lanes - relationships are loaded; no recheck is necessary/wished.
Definition: NBEdge.h:103
bool usingGeoProjection() const
Returns whether a transformation from geo to metric coordinates will be performed.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:158
void removeUnwishedEdges(NBDistrictCont &dc)
Removes unwished edges (not in keep-edges)
Definition: NBEdgeCont.cpp:496
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:367
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:46
void applyOptions(OptionsCont &oc)
Initialises the storage by applying given options.
Definition: NBEdgeCont.cpp:84
unsigned int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:344
std::set< std::string > myEdges2Keep
Set of ids of edges which shall explicitly be kept.
Definition: NBEdgeCont.h:583
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:269
void computeEdge2Edges(bool noLeftMovers)
Computes for each edge the approached edges.
Definition: NBEdgeCont.cpp:559
void computeLaneShapes()
Computes the shapes of all lanes of all edges stored in the container.
Definition: NBEdgeCont.cpp:607
void setLeftHanded()
Marks this edge to be left-handed.
Definition: NBEdge.h:333
const EdgeVector & getEdges() const
Returns all edges which participate in this node.
Definition: NBNode.h:260
void splitGeometry(NBNodeCont &nc)
Splits edges into multiple if they have a complex geometry.
Definition: NBEdgeCont.cpp:513
EdgeCont myEdges
The instance of the dictionary (id->edge)
Definition: NBEdgeCont.h:558
#define POSITION_EPS
Definition: config.h:186
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:561
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:80
The connection was given by the user.
Definition: NBEdge.h:114
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:839
NBEdge * getConnectionTo(NBNode *n) const
Definition: NBNode.cpp:1410
int getJunctionPriority(const NBNode *const node) const
Returns the junction priority (normalised for the node currently build)
Definition: NBEdge.cpp:1142
void joinSameNodeConnectingEdges(NBDistrictCont &dc, NBTrafficLightLogicCont &tlc, EdgeVector edges)
Joins the given edges because they connect the same nodes.
Definition: NBEdgeCont.cpp:615
std::pair< PositionVector, PositionVector > splitAt(SUMOReal where) const
Returns the two lists made when this list vector is splitted at the given point.
SVCPermissions myVehicleClasses2Remove
Set of vehicle types which need not be supported (edges which allow ONLY these are removed) ...
Definition: NBEdgeCont.h:592
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:205
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:2156
PositionVector myPrunningBoundary
Boundary within which an edge must be located in order to be kept.
Definition: NBEdgeCont.h:601
SUMOReal length() const
Returns the length.
void push_back(const PositionVector &p)
Appends all positions from the given vector.
std::set< std::string > myTypes2Keep
Set of edges types which shall be kept.
Definition: NBEdgeCont.h:595
Boundary & grow(SUMOReal by)
extends the boundary by the given amount
Definition: Boundary.cpp:200
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:368
SUMOReal myEdgesMinSpeed
The minimum speed an edge may have in order to be kept (default: -1)
Definition: NBEdgeCont.h:577
void setID(const std::string &newID)
resets the id
Definition: Named.h:68
void replaceOutgoing(NBEdge *which, NBEdge *by, unsigned int laneOff)
Replaces occurences of the first edge within the list of outgoing by the second Connections are remap...
Definition: NBNode.cpp:815
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
void appendTurnarounds(bool noTLSControlled)
Appends turnarounds to all edges stored in the container.
Definition: NBEdgeCont.cpp:583
std::vector< NBEdge * > EdgeVector
Definition: NBCont.h:38
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:122
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:521
A storage for options typed value containers)
Definition: OptionsCont.h:108
void recheckLanes(const bool buildCrossingsAndWalkingAreas)
Rechecks whether all lanes have a successor for each of the stored edges.
Definition: NBEdgeCont.cpp:575
void erase(NBDistrictCont &dc, NBEdge *edge)
Removes the given edge from the container (deleting it)
Definition: NBEdgeCont.cpp:360
A structure representing a connection between two lanes.
Definition: NBEdgeCont.h:526
void computeEdgeShapes()
Computes the shapes of all edges stored in the container.
Definition: NBEdgeCont.cpp:599
The connection was computed.
Definition: NBEdge.h:112
Represents a single node (junction) during network building.
Definition: NBNode.h:75
void dismissVehicleClassInformation()
Definition: NBEdge.cpp:2177
NBTypeCont & myTypeCont
The network builder; used to obtain type information.
Definition: NBEdgeCont.h:521
void recheckLaneSpread()
Rechecks whether the lane spread is proper.
Definition: NBEdgeCont.cpp:693
NBEdge * getTurnDestination() const
Definition: NBEdge.cpp:1952
#define SUMOReal
Definition: config.h:215
static SUMOReal relAngle(SUMOReal angle1, SUMOReal angle2)
Definition: NBHelpers.cpp:63
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:598
SUMOReal getSpeed() const
Returns the speed allowed on this edge.
Definition: NBEdge.h:428
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:64
std::set< std::string > myIgnoredEdges
The ids of ignored edges.
Definition: NBEdgeCont.h:564
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:750
int guessSidewalks(SUMOReal width, SUMOReal minSpeed, SUMOReal maxSpeed)
add sidwalks to edges within the given limits and return the number of edges affected ...
Definition: NBEdgeCont.cpp:935
void replaceRemoved(NBEdge *removed, int removedLane, NBEdge *by, int byLane)
Replaces occurences of the removed edge/lane in all definitions by the given edge.
Boundary getBoxBoundary() const
Returns a boundary enclosing this list of lines.
const std::vector< Connection > & getConnections() const
Returns the connections.
Definition: NBEdge.h:747
void addPostProcessConnection(const std::string &from, int fromLane, const std::string &to, int toLane, bool mayDefinitelyPass)
Adds a connection which could not be set during loading.
Definition: NBEdgeCont.cpp:714
NBNode * myFrom
The source and the destination node.
Definition: NBEdge.h:1210
bool exists(const std::string &name) const
Returns the information whether the named option is known.
void copyConnectionsFrom(NBEdge *src)
Definition: NBEdge.cpp:944
bool ignoreFilterMatch(NBEdge *edge)
Returns true if this edge matches one of the removal criteria.
Definition: NBEdgeCont.cpp:182
A storage for available types of edges.
Definition: NBTypeCont.h:56
SUMOReal getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:403
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
SUMOReal getAngleAtNode(const NBNode *const node) const
Returns the angle of the edge's geometry at the given node.
Definition: NBEdge.cpp:1162
std::set< std::string > myEdges2Remove
Set of ids of edges which shall explicitly be removed.
Definition: NBEdgeCont.h:586
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:360