SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NBNetBuilder.cpp
Go to the documentation of this file.
1 /****************************************************************************/
12 // Instance responsible for building networks
13 /****************************************************************************/
14 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
15 // Copyright (C) 2001-2013 DLR (http://www.dlr.de/) and contributors
16 /****************************************************************************/
17 //
18 // This file is part of SUMO.
19 // SUMO is free software: you can redistribute it and/or modify
20 // it under the terms of the GNU General Public License as published by
21 // the Free Software Foundation, either version 3 of the License, or
22 // (at your option) any later version.
23 //
24 /****************************************************************************/
25 
26 
27 // ===========================================================================
28 // included modules
29 // ===========================================================================
30 #ifdef _MSC_VER
31 #include <windows_config.h>
32 #else
33 #include <config.h>
34 #endif
35 
36 #include <string>
37 #include <fstream>
38 #include "NBNetBuilder.h"
39 #include "NBNodeCont.h"
40 #include "NBEdgeCont.h"
42 #include "NBDistrictCont.h"
43 #include "NBDistrict.h"
44 #include "NBDistribution.h"
45 #include "NBRequest.h"
46 #include "NBTypeCont.h"
51 #include <utils/common/ToString.h>
53 #include "NBAlgorithms.h"
54 #include "NBAlgorithms_Ramps.h"
55 
56 
57 #ifdef CHECK_MEMORY_LEAKS
58 #include <foreign/nvwa/debug_new.h>
59 #endif // CHECK_MEMORY_LEAKS
60 
61 
62 // ===========================================================================
63 // method definitions
64 // ===========================================================================
66  myEdgeCont(myTypeCont),
67  myHaveSeenRoundabouts(false)
68 {}
69 
70 
72 
73 
74 void
76  // we possibly have to load the edges to keep
77  if (oc.isSet("keep-edges.input-file")) {
78  std::ifstream strm(oc.getString("keep-edges.input-file").c_str());
79  if (!strm.good()) {
80  throw ProcessError("Could not load names of edges too keep from '" + oc.getString("keep-edges.input-file") + "'.");
81  }
82  std::ostringstream oss;
83  bool first = true;
84  while (strm.good()) {
85  if (!first) {
86  oss << ',';
87  }
88  std::string name;
89  strm >> name;
90  oss << name;
91  first = false;
92  }
93  oc.set("keep-edges.explicit", oss.str());
94  }
95  // apply options to type control
96  myTypeCont.setDefaults(oc.getInt("default.lanenumber"), oc.getFloat("default.speed"), oc.getInt("default.priority"));
97  // apply options to edge control
99  // apply options to traffic light logics control
101 }
102 
103 
104 void
106  const std::set<std::string>& explicitTurnarounds,
107  bool removeUnwishedNodes) {
108  GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing();
109 
110 
111  // MODIFYING THE SETS OF NODES AND EDGES
112 
113  // Removes edges that are connecting the same node
114  PROGRESS_BEGIN_MESSAGE("Removing self-loops");
117  //
118  if (oc.exists("remove-edges.isolated") && oc.getBool("remove-edges.isolated")) {
119  PROGRESS_BEGIN_MESSAGE("Finding isolated roads");
122  }
123  //
124  if (oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload")) {
125  if (oc.isSet("keep-edges.explicit")) {
126  PROGRESS_BEGIN_MESSAGE("Removing unwished edges");
129  }
130  }
131  //
132  if (removeUnwishedNodes) {
133  unsigned int no = 0;
134  const bool removeGeometryNodes = oc.exists("geometry.remove") && oc.getBool("geometry.remove");
135  PROGRESS_BEGIN_MESSAGE("Removing empty nodes" + std::string(removeGeometryNodes ? " and geometry nodes" : ""));
138  WRITE_MESSAGE(" " + toString(no) + " nodes removed.");
139  }
140  // MOVE TO ORIGIN
141  if (!oc.getBool("offset.disable-normalization") && oc.isDefault("offset.x") && oc.isDefault("offset.y")) {
142  moveToOrigin(geoConvHelper);
143  }
144  geoConvHelper.computeFinal(); // information needed for location element fixed at this point
145 
146  if (oc.exists("geometry.min-dist") && oc.isSet("geometry.min-dist")) {
147  PROGRESS_BEGIN_MESSAGE("Reducing geometries");
148  myEdgeCont.reduceGeometries(oc.getFloat("geometry.min-dist"));
150  }
151  // @note: removing geometry can create similar edges so joinSimilarEdges must come afterwards
152  // @note: likewise splitting can destroy similarities so joinSimilarEdges must come before
153  PROGRESS_BEGIN_MESSAGE("Joining similar edges");
157  //
158  // join junctions
159  if (oc.exists("junctions.join-exclude") && oc.isSet("junctions.join-exclude")) {
160  myNodeCont.addJoinExclusion(oc.getStringVector("junctions.join-exclude"));
161  }
163  if (oc.getBool("junctions.join")) {
164  PROGRESS_BEGIN_MESSAGE("Joining junction clusters");
165  // preliminary geometry computations to determine the length of edges
166  // This depends on turning directions and sorting of edge list
167  // in case junctions are joined geometry computations have to be repeated
170  myNodeCont.computeNodeShapes(oc.getBool("lefthand"));
172  // preliminary roundabout computations to avoid destroying roundabouts
173  if (oc.getBool("roundabouts.guess") || (oc.isDefault("roundabouts.guess") && myHaveSeenRoundabouts)) {
174  assert(myRoundabouts.size() == 0);
176  for (std::vector<EdgeVector>::const_iterator it_round = myRoundabouts.begin();
177  it_round != myRoundabouts.end(); ++it_round) {
178  std::vector<std::string> nodeIDs;
179  for (EdgeVector::const_iterator it_edge = it_round->begin(); it_edge != it_round->end(); ++it_edge) {
180  nodeIDs.push_back((*it_edge)->getToNode()->getID());
181  }
182  myNodeCont.addJoinExclusion(nodeIDs);
183  }
184  myRoundabouts.clear();
185  }
186  numJoined += myNodeCont.joinJunctions(oc.getFloat("junctions.join-dist"), myDistrictCont, myEdgeCont, myTLLCont);
188  }
189  if (numJoined > 0) {
190  // bit of a misnomer since we're already done
191  WRITE_MESSAGE(" Joined " + toString(numJoined) + " junction cluster(s).");
192  }
193  //
194  if (oc.exists("geometry.split") && oc.getBool("geometry.split")) {
195  PROGRESS_BEGIN_MESSAGE("Splitting geometry edges");
198  }
199  // guess ramps
200  if ((oc.exists("ramps.guess") && oc.getBool("ramps.guess")) || (oc.exists("ramps.set") && oc.isSet("ramps.set"))) {
201  PROGRESS_BEGIN_MESSAGE("Guessing and setting on-/off-ramps");
205  }
206 
207  // check whether any not previously setable connections may be set now
209 
211 
212  // APPLY SPEED MODIFICATIONS
213  if (oc.exists("speed.offset")) {
214  const SUMOReal speedOffset = oc.getFloat("speed.offset");
215  const SUMOReal speedFactor = oc.getFloat("speed.factor");
216  if (speedOffset != 0 || speedFactor != 1) {
217  PROGRESS_BEGIN_MESSAGE("Applying speed modifications");
218  for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
219  (*i).second->setSpeed(-1, (*i).second->getSpeed() * speedFactor + speedOffset);
220  }
222  }
223  }
224 
225  // CONNECTIONS COMPUTATION
226  //
227  PROGRESS_BEGIN_MESSAGE("Computing turning directions");
230  //
231  PROGRESS_BEGIN_MESSAGE("Sorting nodes' edges");
234  //
235  PROGRESS_BEGIN_MESSAGE("Computing node types");
238  //
239  PROGRESS_BEGIN_MESSAGE("Computing priorities");
242  //
243  PROGRESS_BEGIN_MESSAGE("Computing approached edges");
244  myEdgeCont.computeEdge2Edges(oc.getBool("no-left-connections"));
246  //
247  if (oc.getBool("roundabouts.guess") || (oc.isDefault("roundabouts.guess") && myHaveSeenRoundabouts)) {
248  PROGRESS_BEGIN_MESSAGE("Guessing and setting roundabouts");
251  }
252  //
253  PROGRESS_BEGIN_MESSAGE("Computing approaching lanes");
256  //
257  PROGRESS_BEGIN_MESSAGE("Dividing of lanes on approached lanes");
261  //
262  PROGRESS_BEGIN_MESSAGE("Processing turnarounds");
263  if (!oc.getBool("no-turnarounds")) {
264  myEdgeCont.appendTurnarounds(oc.getBool("no-turnarounds.tls"));
265  } else {
266  myEdgeCont.appendTurnarounds(explicitTurnarounds, oc.getBool("no-turnarounds.tls"));
267  }
269  //
270  PROGRESS_BEGIN_MESSAGE("Rechecking of lane endings");
273 
274 
275  // GEOMETRY COMPUTATION
276  //
277  PROGRESS_BEGIN_MESSAGE("Computing node shapes");
278  myNodeCont.computeNodeShapes(oc.getBool("lefthand"));
280  //
281  PROGRESS_BEGIN_MESSAGE("Computing edge shapes");
284 
285 
286  // GUESS TLS POSITIONS
287  PROGRESS_BEGIN_MESSAGE("Assigning nodes to traffic lights");
288  if (oc.isSet("tls.set")) {
289  std::vector<std::string> tlControlledNodes = oc.getStringVector("tls.set");
291  for (std::vector<std::string>::const_iterator i = tlControlledNodes.begin(); i != tlControlledNodes.end(); ++i) {
292  NBNode* node = myNodeCont.retrieve(*i);
293  if (node == 0) {
294  WRITE_WARNING("Building a tl-logic for node '" + *i + "' is not possible." + "\n The node '" + *i + "' is not known.");
295  } else {
297  }
298  }
299  }
302  //
303  if (oc.getBool("tls.join")) {
304  PROGRESS_BEGIN_MESSAGE("Joining traffic light nodes");
305  myNodeCont.joinTLS(myTLLCont, oc.getFloat("tls.join-dist"));
307  }
308 
309 
310  // COMPUTING RIGHT-OF-WAY AND TRAFFIC LIGHT PROGRAMS
311  //
312  PROGRESS_BEGIN_MESSAGE("Computing traffic light control information");
315  //
316  PROGRESS_BEGIN_MESSAGE("Computing node logics");
319  //
320  PROGRESS_BEGIN_MESSAGE("Computing traffic light logics");
321  std::pair<unsigned int, unsigned int> numbers = myTLLCont.computeLogics(myEdgeCont, oc);
323  std::string progCount = "";
324  if (numbers.first != numbers.second) {
325  progCount = "(" + toString(numbers.second) + " programs) ";
326  }
327  WRITE_MESSAGE(" " + toString(numbers.first) + " traffic light(s) " + progCount + "computed.");
328  //
329  if (oc.isSet("street-sign-output")) {
330  PROGRESS_BEGIN_MESSAGE("Generating street signs");
333  }
334 
335  // FINISHING INNER EDGES
336  if (!oc.getBool("no-internal-links")) {
337  PROGRESS_BEGIN_MESSAGE("Building inner edges");
338  for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
339  (*i).second->sortOutgoingConnectionsByIndex();
340  }
341  for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
342  (*i).second->buildInnerEdges();
343  }
345  }
346 
347 
348  // report
349  WRITE_MESSAGE("-----------------------------------------------------");
350  WRITE_MESSAGE("Summary:");
352  WRITE_MESSAGE(" Network boundaries:");
353  WRITE_MESSAGE(" Original boundary : " + toString(geoConvHelper.getOrigBoundary()));
354  WRITE_MESSAGE(" Applied offset : " + toString(geoConvHelper.getOffsetBase()));
355  WRITE_MESSAGE(" Converted boundary : " + toString(geoConvHelper.getConvBoundary()));
356  WRITE_MESSAGE("-----------------------------------------------------");
358  // report on very large networks
359  if (MAX2(geoConvHelper.getConvBoundary().xmax(), geoConvHelper.getConvBoundary().ymax()) > 1000000 ||
360  MIN2(geoConvHelper.getConvBoundary().xmin(), geoConvHelper.getConvBoundary().ymin()) < -1000000) {
361  WRITE_WARNING("Network contains very large coordinates and will probably flicker in the GUI. Check for outlying nodes and make sure the network is shifted to the coordinate origin");
362  }
363 }
364 
365 
366 void
368  PROGRESS_BEGIN_MESSAGE("Moving network to origin");
369  // compute new boundary after network modifications have taken place
370  Boundary boundary;
371  for (std::map<std::string, NBNode*>::const_iterator it = myNodeCont.begin(); it != myNodeCont.end(); ++it) {
372  boundary.add(it->second->getPosition());
373  }
374  for (std::map<std::string, NBEdge*>::const_iterator it = myEdgeCont.begin(); it != myEdgeCont.end(); ++it) {
375  boundary.add(it->second->getGeometry().getBoxBoundary());
376  }
377  geoConvHelper.setConvBoundary(boundary);
378  const SUMOReal x = -boundary.xmin();
379  const SUMOReal y = -boundary.ymin();
380  for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
381  (*i).second->reshiftPosition(x, y);
382  }
383  for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
384  (*i).second->reshiftPosition(x, y);
385  }
386  for (std::map<std::string, NBDistrict*>::const_iterator i = myDistrictCont.begin(); i != myDistrictCont.end(); ++i) {
387  (*i).second->reshiftPosition(x, y);
388  }
389  geoConvHelper.moveConvertedBy(x, y);
391 }
392 
393 /****************************************************************************/