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