00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef _MSC_VER
00025 #include <windows_config.h>
00026 #else
00027 #include <config.h>
00028 #endif
00029
00030 #include <string>
00031 #include <fstream>
00032 #include "NBNetBuilder.h"
00033 #include "NBNodeCont.h"
00034 #include "NBEdgeCont.h"
00035 #include "NBTrafficLightLogicCont.h"
00036 #include "NBJunctionLogicCont.h"
00037 #include "NBDistrictCont.h"
00038 #include "NBDistribution.h"
00039 #include "NBRequest.h"
00040 #include "NBTypeCont.h"
00041 #include <utils/options/OptionsCont.h>
00042 #include <utils/common/MsgHandler.h>
00043 #include <utils/common/UtilExceptions.h>
00044 #include <utils/common/StringTokenizer.h>
00045 #include <utils/common/ToString.h>
00046 #include <utils/geom/GeoConvHelper.h>
00047 #include <utils/iodevices/OutputDevice.h>
00048 #include "NBJoinedEdgesMap.h"
00049
00050 #ifdef CHECK_MEMORY_LEAKS
00051 #include <foreign/nvwa/debug_new.h>
00052 #endif // CHECK_MEMORY_LEAKS
00053
00054
00055
00056
00057
00058 NBNetBuilder::NBNetBuilder() throw()
00059 : myEdgeCont(*this) {}
00060
00061
00062 NBNetBuilder::~NBNetBuilder() throw() {}
00063
00064
00065 void
00066 NBNetBuilder::applyOptions(OptionsCont &oc) throw(ProcessError) {
00067
00068 if (oc.isSet("keep-edges.input-file")) {
00069 std::ifstream strm(oc.getString("keep-edges.input-file").c_str());
00070 if (!strm.good()) {
00071 throw ProcessError("Could not load names of edges too keep from '" + oc.getString("keep-edges.input-file") + "'.");
00072 }
00073 std::ostringstream oss;
00074 bool first = true;
00075 while (strm.good()) {
00076 if (!first) {
00077 oss << ',';
00078 }
00079 std::string name;
00080 strm >> name;
00081 oss << name;
00082 first = false;
00083 }
00084 oc.set("keep-edges", oss.str());
00085 }
00086
00087 if (!oc.isSet("output")&&!oc.isSet("plain-output")&&!oc.isSet("map-output")) {
00088 throw ProcessError("No output defined.");
00089 }
00090
00091 myTypeCont.setDefaults(oc.getInt("lanenumber"), oc.getFloat("speed"), oc.getInt("priority"));
00092
00093 myEdgeCont.applyOptions(oc);
00094
00095 myTLLCont.applyOptions(oc);
00096 }
00097
00098
00099 void
00100 NBNetBuilder::buildLoaded() throw(IOError) {
00101
00102 OptionsCont &oc = OptionsCont::getOptions();
00103 compute(oc);
00104
00105 OutputDevice& device = OutputDevice::getDevice(oc.getString("output"));
00106 save(device, oc);
00107
00108 if (oc.isSet("map-output")) {
00109 OutputDevice& mdevice = OutputDevice::getDevice(oc.getString("map-output"));
00110 mdevice << gJoinedEdges;
00111 }
00112 }
00113
00114
00115 void
00116 NBNetBuilder::compute(OptionsCont &oc) throw(ProcessError) {
00117 int step = 1;
00118
00119
00120 inform(step, "Removing dummy edges.");
00121 myNodeCont.removeDummyEdges(myDistrictCont, myEdgeCont, myTLLCont);
00122
00123 inform(step, "Joining double connections.");
00124 gJoinedEdges.init(myEdgeCont);
00125 myNodeCont.recheckEdges(myDistrictCont, myTLLCont, myEdgeCont);
00126
00127 if (oc.getBool("remove-isolated")) {
00128 inform(step, "Finding isolated roads.");
00129 myNodeCont.removeIsolatedRoads(myDistrictCont, myEdgeCont, myTLLCont);
00130 }
00131
00132 if (oc.getBool("remove-geometry")) {
00133 inform(step, "Removing empty nodes and geometry nodes.");
00134 myNodeCont.removeUnwishedNodes(myDistrictCont, myEdgeCont, myTLLCont, oc.getBool("remove-geometry"));
00135 }
00136
00137 if (oc.getBool("keep-edges.postload")) {
00138 if (oc.isSet("keep-edges")) {
00139 inform(step, "Removing unwished edges.");
00140 myEdgeCont.removeUnwishedEdges(myDistrictCont);
00141 }
00142 }
00143 if (oc.isSet("keep-edges") || oc.isSet("remove-edges") || oc.getBool("keep-edges.postload") || oc.isSet("keep-edges.by-vclass") || oc.isSet("keep-edges.input-file")) {
00144 inform(step, "Rechecking nodes after edge removal.");
00145 myNodeCont.removeUnwishedNodes(myDistrictCont, myEdgeCont, myTLLCont, oc.getBool("remove-geometry"));
00146 }
00147
00148 if (oc.getBool("split-geometry")) {
00149 inform(step, "Splitting geometry edges.");
00150 myEdgeCont.splitGeometry(myNodeCont);
00151 }
00152
00153 if (!oc.getBool("disable-normalize-node-positions") && oc.isDefault("x-offset-to-apply") && oc.isDefault("y-offset-to-apply")) {
00154 inform(step, "Normalising node positions.");
00155 const SUMOReal x = -GeoConvHelper::getConvBoundary().xmin();
00156 const SUMOReal y = -GeoConvHelper::getConvBoundary().ymin();
00157 myNodeCont.reshiftNodePositions(x, y);
00158 myEdgeCont.reshiftEdgePositions(x, y);
00159 myDistrictCont.reshiftDistrictPositions(x, y);
00160 GeoConvHelper::moveConvertedBy(x, y);
00161 }
00162
00163 myEdgeCont.recomputeLaneShapes();
00164
00165 if (oc.getBool("guess-ramps")||oc.getBool("guess-obscure-ramps")||oc.isSet("ramp-guess.explicite")) {
00166 inform(step, "Guessing and setting on-/off-ramps.");
00167 myNodeCont.guessRamps(oc, myEdgeCont, myDistrictCont);
00168 }
00169
00170 inform(step, "Guessing and setting TLs.");
00171 if (oc.isSet("explicite-tls")) {
00172 std::vector<std::string> tlControlledNodes = oc.getStringVector("explicite-tls");
00173 for (std::vector<std::string>::const_iterator i=tlControlledNodes.begin(); i!=tlControlledNodes.end(); ++i) {
00174 NBNode *node = myNodeCont.retrieve(*i);
00175 if (node==0) {
00176 WRITE_WARNING("Building a tl-logic for node '" + *i + "' is not possible." + "\n The node '" + *i + "' is not known.");
00177 } else {
00178 myNodeCont.setAsTLControlled(node, myTLLCont);
00179 }
00180 }
00181 }
00182 myNodeCont.guessTLs(oc, myTLLCont);
00183
00184 if (oc.getBool("try-join-tls")) {
00185 myNodeCont.joinTLS(myTLLCont);
00186 }
00187
00188 inform(step, "Computing turning directions.");
00189 myEdgeCont.computeTurningDirections();
00190
00191 OutputDevice::createDeviceByOption("node-type-output", "pois");
00192 inform(step, "Sorting nodes' edges.");
00193 myNodeCont.sortNodesEdges(oc.getBool("lefthand"), myTypeCont);
00194
00195 if (oc.getBool("guess-roundabouts")) {
00196 inform(step, "Guessing and setting roundabouts.");
00197 myEdgeCont.guessRoundabouts(myRoundabouts);
00198 }
00199
00200 inform(step, "Computing approached edges.");
00201 myEdgeCont.computeEdge2Edges();
00202
00203 inform(step, "Computing approaching lanes.");
00204 myEdgeCont.computeLanes2Edges();
00205
00206 inform(step, "Dividing of lanes on approached lanes.");
00207 myNodeCont.computeLanes2Lanes();
00208 myEdgeCont.sortOutgoingLanesConnections();
00209
00210 if (!oc.getBool("no-turnarounds")) {
00211 inform(step, "Appending turnarounds.");
00212 myEdgeCont.appendTurnarounds(oc.getBool("no-tls-turnarounds"));
00213 }
00214
00215 inform(step, "Rechecking of lane endings.");
00216 myEdgeCont.recheckLanes();
00217
00218 if (oc.isSet("plain-output")) {
00219 myNodeCont.savePlain(oc.getString("plain-output") + ".nod.xml");
00220 myEdgeCont.savePlain(oc.getString("plain-output") + ".edg.xml", oc.getString("plain-output") + ".con.xml");
00221 }
00222
00223 inform(step, "Computing node shapes.");
00224 myNodeCont.computeNodeShapes(oc.getBool("lefthand"));
00225
00226 inform(step, "Computing edge shapes.");
00227 myEdgeCont.computeEdgeShapes();
00228
00229 inform(step, "Computing tls logics.");
00230 myTLLCont.setTLControllingInformation(myEdgeCont);
00231
00232 inform(step, "Computing node logics.");
00233 myNodeCont.computeLogics(myEdgeCont, myJunctionLogicCont, oc);
00234
00235 inform(step, "Computing traffic light logics.");
00236 myTLLCont.computeLogics(myEdgeCont, oc);
00237
00238 WRITE_MESSAGE("-----------------------------------------------------");
00239 WRITE_MESSAGE("Summary:");
00240 if (!gSuppressMessages) {
00241 myNodeCont.printBuiltNodesStatistics();
00242 }
00243 WRITE_MESSAGE(" Network boundaries:");
00244 WRITE_MESSAGE(" Original boundary : " + toString(GeoConvHelper::getOrigBoundary()));
00245 WRITE_MESSAGE(" Applied offset : " + toString(GeoConvHelper::getOffsetBase()));
00246 WRITE_MESSAGE(" Converted boundary : " + toString(GeoConvHelper::getConvBoundary()));
00247 WRITE_MESSAGE("-----------------------------------------------------");
00248 NBRequest::reportWarnings();
00249 }
00250
00251
00252 void
00253 NBNetBuilder::inform(int &step, const std::string &about) throw() {
00254 WRITE_MESSAGE("Computing step " + toString<int>(step)+ ": " + about);
00255 step++;
00256 }
00257
00258
00259
00260
00261 void
00262 NBNetBuilder::save(OutputDevice &device, OptionsCont &oc) throw(IOError) {
00263 device.writeXMLHeader("net");
00264 device << "\n";
00265
00266 device << " <location netOffset=\"" << GeoConvHelper::getOffsetBase() << "\""
00267 << " convBoundary=\"" << GeoConvHelper::getConvBoundary() << "\"";
00268 if (GeoConvHelper::usingGeoProjection()) {
00269 device.setPrecision(GEO_OUTPUT_ACCURACY);
00270 device << " origBoundary=\"" << GeoConvHelper::getOrigBoundary() << "\"";
00271 device.setPrecision();
00272 } else {
00273 device << " origBoundary=\"" << GeoConvHelper::getOrigBoundary() << "\"";
00274 }
00275 device << " projParameter=\"" << GeoConvHelper::getProjString() << "\"/>\n\n";
00276
00277
00278
00279 if (!oc.getBool("no-internal-links")) {
00280 myNodeCont.writeXMLInternalLinks(device);
00281 }
00282
00283
00284 myDistrictCont.writeXML(device);
00285
00286 myEdgeCont.writeXMLStep1(device);
00287
00288 myJunctionLogicCont.writeXML(device);
00289 myTLLCont.writeXML(device);
00290
00291 myNodeCont.writeXML(device);
00292
00293 if (!oc.getBool("no-internal-links")) {
00294 myNodeCont.writeXMLInternalNodes(device);
00295 }
00296
00297 myEdgeCont.writeXMLStep2(device, !oc.getBool("no-internal-links"));
00298 if (!oc.getBool("no-internal-links")) {
00299 myNodeCont.writeXMLInternalSuccInfos(device);
00300 }
00301
00302 for (std::vector<std::set<NBEdge*> >::iterator i=myRoundabouts.begin(); i!=myRoundabouts.end(); ++i) {
00303 std::vector<NBNode*> nodes;
00304 for (std::set<NBEdge*>::iterator j=(*i).begin(); j!=(*i).end(); ++j) {
00305 NBNode *n = (*j)->getToNode();
00306 if (find(nodes.begin(), nodes.end(), n)==nodes.end()) {
00307 nodes.push_back(n);
00308 }
00309 }
00310 sort(nodes.begin(), nodes.end(), by_id_sorter());
00311 device << " <roundabout nodes=\"";
00312 int k = 0;
00313 for (std::vector<NBNode*>::iterator j=nodes.begin(); j!=nodes.end(); ++j, ++k) {
00314 if (k!=0) {
00315 device << ' ';
00316 }
00317 device << (*j)->getID();
00318 }
00319 device << "\"/>\n";
00320 }
00321 if (myRoundabouts.size()!=0) {
00322 device << "\n";
00323 }
00324 device.close();
00325 }
00326
00327
00328
00329
00330 void
00331 NBNetBuilder::insertNetBuildOptions(OptionsCont &oc) {
00332
00333 oc.doRegister("output-file", 'o', new Option_FileName("net.net.xml"));
00334 oc.addSynonyme("output-file", "output");
00335 oc.addDescription("output-file", "Output", "The generated net will be written to FILE");
00336
00337 oc.doRegister("plain-output", new Option_FileName());
00338 oc.addDescription("plain-output", "Output", "Prefix of files to write nodes and edges to");
00339
00340 oc.doRegister("node-geometry-dump", new Option_FileName());
00341 oc.addDescription("node-geometry-dump", "Output", "Writes node corner positions to FILE");
00342
00343 oc.doRegister("map-output", 'M', new Option_FileName());
00344 oc.addDescription("map-output", "Output", "Writes joined edges information to FILE");
00345
00346 oc.doRegister("node-type-output", new Option_FileName());
00347 oc.addDescription("node-type-output", "Output", "Writes pois of node types to FILE");
00348
00349
00350
00351
00352 oc.doRegister("type", 'T', new Option_String("Unknown"));
00353 oc.addDescription("type", "Building Defaults", "The default name for an edges type");
00354
00355 oc.doRegister("lanenumber", 'L', new Option_Integer(1));
00356 oc.addDescription("lanenumber", "Building Defaults", "The default number of lanes in an edge");
00357
00358 oc.doRegister("speed", 'S', new Option_Float((SUMOReal) 13.9));
00359 oc.addDescription("speed", "Building Defaults", "The default speed on an edge (in m/s)");
00360
00361 oc.doRegister("priority", 'P', new Option_Integer(-1));
00362 oc.addDescription("priority", "Building Defaults", "The default priority of an edge");
00363
00364
00365
00366 oc.doRegister("flip-y", new Option_Bool(false));
00367 oc.addDescription("flip-y", "Processing", "Flips the y-coordinate along zero");
00368
00369 oc.doRegister("dismiss-vclasses", new Option_Bool(false));
00370 oc.addDescription("dismiss-vclasses", "Processing", "");
00371
00372 oc.doRegister("remove-geometry", 'R', new Option_Bool(false));
00373 oc.addDescription("remove-geometry", "Processing", "Removes geometry information from edges");
00374
00375 oc.doRegister("remove-isolated", new Option_Bool(false));
00376 oc.addDescription("remove-isolated", "Processing", "Removes isolated edges");
00377
00378 oc.doRegister("no-turnarounds", new Option_Bool(false));
00379 oc.addDescription("no-turnarounds", "Processing", "Disables building turnarounds");
00380 oc.doRegister("no-tls-turnarounds", new Option_Bool(false));
00381 oc.addDescription("no-tls-turnarounds", "Processing", "Disables building turnarounds at tls-controlled junctions");
00382
00383 oc.doRegister("no-internal-links", new Option_Bool(false));
00384 oc.addDescription("no-internal-links", "Processing", "Omits internal links");
00385
00386 oc.doRegister("split-geometry", new Option_Bool(false));
00387 oc.addDescription("split-geometry", "Processing", "Splits edges across geometry nodes");
00388
00389 oc.doRegister("disable-normalize-node-positions", new Option_Bool(false));
00390 oc.addDescription("disable-normalize-node-positions", "Processing", "Turn off normalizing node positions");
00391
00392 oc.doRegister("x-offset-to-apply", new Option_Float(0));
00393 oc.addDescription("x-offset-to-apply", "Processing", "Adds FLOAT to net x-positions");
00394
00395 oc.doRegister("y-offset-to-apply", new Option_Float(0));
00396 oc.addDescription("y-offset-to-apply", "Processing", "Adds FLOAT to net y-positions");
00397
00398 oc.doRegister("guess-roundabouts", new Option_Bool(false));
00399 oc.addDescription("guess-roundabouts", "Processing", "Enable roundabout-guessing");
00400
00401 oc.doRegister("lefthand", new Option_Bool(false));
00402 oc.addDescription("lefthand", "Processing", "Assumes left-hand traffic on the network");
00403
00404
00405
00406
00407 oc.doRegister("explicite-tls", new Option_String());
00408 oc.addDescription("explicite-tls", "TLS Building", "Interprets STR as list of junctions to be controlled by TLS");
00409
00410 oc.doRegister("explicite-no-tls", new Option_String());
00411 oc.addDescription("explicite-no-tls", "TLS Building", "Interprets STR as list of junctions to be not controlled by TLS");
00412
00413
00414 oc.doRegister("guess-tls", new Option_Bool(false));
00415 oc.addDescription("guess-tls", "TLS Building", "Turns on TLS guessing");
00416
00417 oc.doRegister("tls-guess.district-nodes", new Option_Bool(false));
00418 oc.addDescription("tls-guess.district-nodes", "TLS Building", "Sets district nodes as tls-controlled");
00419
00420 oc.doRegister("tls-guess.joining", new Option_Bool(false));
00421 oc.addDescription("tls-guess.joining", "TLS Building", "Includes node clusters into guess");
00422
00423 oc.doRegister("try-join-tls", new Option_Bool(false));
00424 oc.addDescription("try-join-tls", "TLS Building", "Tries to cluster tls-controlled nodes");
00425
00426
00427 oc.doRegister("min-decel", 'D', new Option_Float(3.0));
00428 oc.addDescription("min-decel", "TLS Building", "Defines smallest vehicle deceleration");
00429
00430 oc.doRegister("patch-small-tyellow", new Option_Bool(false));
00431 oc.addDescription("patch-small-tyellow", "TLS Building", "Given yellow times are patched even if being too short");
00432
00433 oc.doRegister("traffic-light-green", new Option_Integer());
00434 oc.addDescription("traffic-light-green", "TLS Building", "Use INT as green phase duration");
00435
00436 oc.doRegister("traffic-light-yellow", new Option_Integer());
00437 oc.addDescription("traffic-light-yellow", "TLS Building", "Set INT as fixed time for yellow phase durations");
00438
00439
00440 oc.doRegister("tl-logics.half-offset", new Option_String());
00441 oc.addDescription("tl-logics.half-offset", "TLS Building", "TLSs in STR will be shifted by half-phase");
00442
00443 oc.doRegister("tl-logics.quarter-offset", new Option_String());
00444 oc.addDescription("tl-logics.quarter-offset", "TLS Building", "TLSs in STR will be shifted by quarter-phase");
00445
00446
00447
00448 oc.doRegister("edges-min-speed", new Option_Float());
00449 oc.addDescription("edges-min-speed", "Edge Removal", "Remove edges with speed < FLOAT");
00450
00451 oc.doRegister("remove-edges", new Option_String());
00452 oc.addDescription("remove-edges", "Edge Removal", "Remove edges in STR");
00453
00454 oc.doRegister("keep-edges", new Option_String());
00455 oc.addDescription("keep-edges", "Edge Removal", "Remove edges not in STR");
00456
00457 oc.doRegister("keep-edges.input-file", new Option_FileName());
00458 oc.addDescription("keep-edges.input-file", "Edge Removal", "Removed edges not in FILE");
00459
00460 oc.doRegister("keep-edges.postload", new Option_Bool(false));
00461 oc.addDescription("keep-edges.postload", "Edge Removal", "Remove edges after joining");
00462
00463 oc.doRegister("keep-edges.in-boundary", new Option_String());
00464 oc.addDescription("keep-edges.in-boundary", "Edge Removal", "Keeps edges which are located within the given boundary");
00465
00466 oc.doRegister("remove-edges.by-vclass", new Option_String());
00467 oc.addDescription("remove-edges.by-vclass", "Edge Removal", "Remove edges where vclass def is not in STR");
00468
00469
00470
00471 oc.doRegister("keep-unregulated", new Option_Bool(false));
00472 oc.addDescription("keep-unregulated", "Unregulated Nodes", "All nodes will be not regulated");
00473
00474 oc.doRegister("keep-unregulated.nodes", new Option_String());
00475 oc.addDescription("keep-unregulated.nodes", "Unregulated Nodes", "Do not regulate nodes in STR");
00476
00477 oc.doRegister("keep-unregulated.district-nodes", new Option_Bool(false));
00478 oc.addDescription("keep-unregulated.district-nodes", "Unregulated Nodes", "Do not regulate district nodes");
00479
00480
00481
00482 oc.doRegister("guess-ramps", new Option_Bool(false));
00483 oc.addDescription("guess-ramps", "Ramp Guessing", "Enable ramp-guessing");
00484
00485 oc.doRegister("ramp-guess.max-ramp-speed", new Option_Float(-1));
00486 oc.addDescription("ramp-guess.max-ramp-speed", "Ramp Guessing", "Treat edges with speed > FLOAT as no ramps");
00487
00488 oc.doRegister("ramp-guess.min-highway-speed", new Option_Float((SUMOReal)(79/3.6)));
00489 oc.addDescription("ramp-guess.min-highway-speed", "Ramp Guessing", "Treat edges with speed < FLOAT as no highways");
00490
00491 oc.doRegister("ramp-guess.ramp-length", new Option_Float(100));
00492 oc.addDescription("ramp-guess.ramp-length", "Ramp Guessing", "Use FLOAT as ramp-length");
00493
00494 oc.doRegister("ramp-guess.explicite", new Option_String());
00495 oc.addDescription("ramp-guess.explicite", "Ramp Guessing", "Tries to handle the given edges as ramps");
00496
00497 oc.doRegister("guess-obscure-ramps", new Option_Bool(false));
00498 oc.addDescription("guess-obscure-ramps", "Ramp Guessing", "");
00499
00500 oc.doRegister("obscure-ramps.add-ramp", new Option_Bool(false));
00501 oc.addDescription("obscure-ramps.add-ramp", "Ramp Guessing", "");
00502
00503 oc.doRegister("obscure-ramps.min-highway-speed", new Option_Float((SUMOReal)(100/3.6)));
00504 oc.addDescription("obscure-ramps.min-highway-speed", "Ramp Guessing", "");
00505
00506
00507 }
00508
00509