SUMO - Simulation of Urban MObility
|
00001 /****************************************************************************/ 00009 // Exporter writing networks using the SUMO format 00010 /****************************************************************************/ 00011 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/ 00012 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors 00013 /****************************************************************************/ 00014 // 00015 // This file is part of SUMO. 00016 // SUMO is free software: you can redistribute it and/or modify 00017 // it under the terms of the GNU General Public License as published by 00018 // the Free Software Foundation, either version 3 of the License, or 00019 // (at your option) any later version. 00020 // 00021 /****************************************************************************/ 00022 00023 00024 // =========================================================================== 00025 // included modules 00026 // =========================================================================== 00027 #ifdef _MSC_VER 00028 #include <windows_config.h> 00029 #else 00030 #include <config.h> 00031 #endif 00032 #include <cmath> 00033 #include <utils/options/OptionsCont.h> 00034 #include <utils/iodevices/OutputDevice.h> 00035 #include <utils/geom/GeoConvHelper.h> 00036 #include <utils/common/ToString.h> 00037 #include <utils/common/MsgHandler.h> 00038 #include <netbuild/NBEdge.h> 00039 #include <netbuild/NBEdgeCont.h> 00040 #include <netbuild/NBNode.h> 00041 #include <netbuild/NBNodeCont.h> 00042 #include <netbuild/NBNetBuilder.h> 00043 #include <netbuild/NBTrafficLightLogic.h> 00044 #include <netbuild/NBDistrict.h> 00045 #include "NWFrame.h" 00046 #include "NWWriter_SUMO.h" 00047 00048 #ifdef CHECK_MEMORY_LEAKS 00049 #include <foreign/nvwa/debug_new.h> 00050 #endif // CHECK_MEMORY_LEAKS 00051 00052 00053 00054 // =========================================================================== 00055 // method definitions 00056 // =========================================================================== 00057 // --------------------------------------------------------------------------- 00058 // static methods 00059 // --------------------------------------------------------------------------- 00060 void 00061 NWWriter_SUMO::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) { 00062 // check whether a matsim-file shall be generated 00063 if (!oc.isSet("output-file")) { 00064 return; 00065 } 00066 OutputDevice& device = OutputDevice::getDevice(oc.getString("output-file")); 00067 device.writeXMLHeader("net", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/net_file.xsd\""); // street names may contain non-ascii chars 00068 device.lf(); 00069 // get involved container 00070 const NBNodeCont& nc = nb.getNodeCont(); 00071 const NBEdgeCont& ec = nb.getEdgeCont(); 00072 const NBDistrictCont& dc = nb.getDistrictCont(); 00073 00074 // write network offsets and projection 00075 writeLocation(device); 00076 00077 // write inner lanes 00078 if (!oc.getBool("no-internal-links")) { 00079 bool hadAny = false; 00080 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { 00081 hadAny |= writeInternalEdges(device, *(*i).second); 00082 } 00083 if (hadAny) { 00084 device.lf(); 00085 } 00086 } 00087 00088 // write edges with lanes and connected edges 00089 bool noNames = !oc.getBool("output.street-names"); 00090 for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) { 00091 writeEdge(device, *(*i).second, noNames); 00092 } 00093 device.lf(); 00094 00095 // write tls logics 00096 writeTrafficLights(device, nb.getTLLogicCont()); 00097 00098 // write the nodes (junctions) 00099 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { 00100 writeJunction(device, *(*i).second); 00101 } 00102 device.lf(); 00103 const bool includeInternal = !oc.getBool("no-internal-links"); 00104 if (includeInternal) { 00105 // ... internal nodes if not unwanted 00106 bool hadAny = false; 00107 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { 00108 hadAny |= writeInternalNodes(device, *(*i).second); 00109 } 00110 if (hadAny) { 00111 device.lf(); 00112 } 00113 } 00114 00115 // write the successors of lanes 00116 unsigned int numConnections = 0; 00117 for (std::map<std::string, NBEdge*>::const_iterator it_edge = ec.begin(); it_edge != ec.end(); it_edge++) { 00118 NBEdge* from = it_edge->second; 00119 from->sortOutgoingConnectionsByIndex(); 00120 const std::vector<NBEdge::Connection> connections = from->getConnections(); 00121 numConnections += (unsigned int)connections.size(); 00122 for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) { 00123 writeConnection(device, *from, *it_c, includeInternal); 00124 } 00125 } 00126 if (numConnections > 0) { 00127 device.lf(); 00128 } 00129 if (includeInternal) { 00130 // ... internal successors if not unwanted 00131 bool hadAny = false; 00132 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { 00133 hadAny |= writeInternalConnections(device, *(*i).second); 00134 } 00135 if (hadAny) { 00136 device.lf(); 00137 } 00138 } 00139 // write loaded prohibitions 00140 for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) { 00141 writeProhibitions(device, i->second->getProhibitions()); 00142 } 00143 00144 // write roundabout information 00145 const std::vector<std::set<NBEdge*> > &roundabouts = nb.getRoundabouts(); 00146 for (std::vector<std::set<NBEdge*> >::const_iterator i = roundabouts.begin(); i != roundabouts.end(); ++i) { 00147 writeRoundabout(device, *i); 00148 } 00149 if (roundabouts.size() != 0) { 00150 device.lf(); 00151 } 00152 00153 // write the districts 00154 for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) { 00155 writeDistrict(device, *(*i).second); 00156 } 00157 if (dc.size() != 0) { 00158 device.lf(); 00159 } 00160 device.close(); 00161 } 00162 00163 00164 bool 00165 NWWriter_SUMO::writeInternalEdges(OutputDevice& into, const NBNode& n) { 00166 bool ret = false; 00167 const EdgeVector& incoming = n.getIncomingEdges(); 00168 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) { 00169 const std::vector<NBEdge::Connection> &elv = (*i)->getConnections(); 00170 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { 00171 if ((*k).toEdge == 0) { 00172 continue; 00173 } 00174 writeInternalEdge(into, (*k).id, (*k).vmax, (*k).shape); 00175 if ((*k).haveVia) { 00176 writeInternalEdge(into, (*k).viaID, (*k).viaVmax, (*k).viaShape); 00177 } 00178 ret = true; 00179 } 00180 } 00181 return ret; 00182 } 00183 00184 00185 void 00186 NWWriter_SUMO::writeInternalEdge(OutputDevice& into, const std::string& id, SUMOReal vmax, const PositionVector& shape) { 00187 SUMOReal length = MAX2(shape.length(), (SUMOReal)POSITION_EPS); // microsim needs positive length 00188 into.openTag(SUMO_TAG_EDGE); 00189 into.writeAttr(SUMO_ATTR_ID, id); 00190 into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_INTERNAL); 00191 into.closeOpener(); 00192 into.openTag(SUMO_TAG_LANE); 00193 into.writeAttr(SUMO_ATTR_ID, id + "_0"); 00194 into.writeAttr(SUMO_ATTR_INDEX, 0); 00195 into.writeAttr(SUMO_ATTR_SPEED, vmax); 00196 into.writeAttr(SUMO_ATTR_LENGTH, length); 00197 into.writeAttr(SUMO_ATTR_SHAPE, shape); 00198 into.closeTag(true); 00199 into.closeTag(); 00200 } 00201 00202 00203 void 00204 NWWriter_SUMO::writeEdge(OutputDevice& into, const NBEdge& e, bool noNames) { 00205 // write the edge's begin 00206 into.openTag(SUMO_TAG_EDGE).writeAttr(SUMO_ATTR_ID, e.getID()); 00207 into.writeAttr(SUMO_ATTR_FROM, e.getFromNode()->getID()); 00208 into.writeAttr(SUMO_ATTR_TO, e.getToNode()->getID()); 00209 if (!noNames && e.getStreetName() != "") { 00210 into.writeAttr(SUMO_ATTR_NAME, e.getStreetName()); 00211 } 00212 into.writeAttr(SUMO_ATTR_PRIORITY, e.getPriority()); 00213 if (e.getTypeName() != "") { 00214 into.writeAttr(SUMO_ATTR_TYPE, e.getTypeName()); 00215 } 00216 if (e.isMacroscopicConnector()) { 00217 into.writeAttr(SUMO_ATTR_FUNCTION, EDGEFUNC_CONNECTOR); 00218 } 00219 // write the spread type if not default ("right") 00220 if (e.getLaneSpreadFunction() != LANESPREAD_RIGHT) { 00221 into.writeAttr(SUMO_ATTR_SPREADTYPE, e.getLaneSpreadFunction()); 00222 } 00223 if (e.hasLoadedLength()) { 00224 into.writeAttr(SUMO_ATTR_LENGTH, e.getLoadedLength()); 00225 } 00226 if (!e.hasDefaultGeometry()) { 00227 into.writeAttr(SUMO_ATTR_SHAPE, e.getGeometry()); 00228 } 00229 into.closeOpener(); 00230 // write the lanes 00231 const std::vector<NBEdge::Lane> &lanes = e.getLanes(); 00232 SUMOReal length = e.getLoadedLength(); 00233 if (length <= 0) { 00234 length = (SUMOReal) .1; 00235 } 00236 for (unsigned int i = 0; i < (unsigned int) lanes.size(); i++) { 00237 writeLane(into, e.getID(), e.getLaneID(i), lanes[i], length, i); 00238 } 00239 // close the edge 00240 into.closeTag(); 00241 } 00242 00243 00244 void 00245 NWWriter_SUMO::writeLane(OutputDevice& into, const std::string& eID, const std::string& lID, const NBEdge::Lane& lane, SUMOReal length, unsigned int index) { 00246 // output the lane's attributes 00247 into.openTag(SUMO_TAG_LANE).writeAttr(SUMO_ATTR_ID, lID); 00248 // the first lane of an edge will be the depart lane 00249 into.writeAttr(SUMO_ATTR_INDEX, index); 00250 // write the list of allowed/disallowed vehicle classes 00251 writePermissions(into, lane.permissions); 00252 writePreferences(into, lane.preferred); 00253 // some further information 00254 if (lane.speed == 0) { 00255 WRITE_WARNING("Lane #" + toString(index) + " of edge '" + eID + "' has a maximum velocity of 0."); 00256 } else if (lane.speed < 0) { 00257 throw ProcessError("Negative velocity (" + toString(lane.speed) + " on edge '" + eID + "' lane#" + toString(index) + "."); 00258 } 00259 if (lane.offset > 0) { 00260 length = length - lane.offset; 00261 } 00262 into.writeAttr(SUMO_ATTR_SPEED, lane.speed); 00263 into.writeAttr(SUMO_ATTR_LENGTH, length); 00264 if (lane.offset > 0) { 00265 into.writeAttr(SUMO_ATTR_ENDOFFSET, lane.offset); 00266 } 00267 if (lane.width != NBEdge::UNSPECIFIED_WIDTH) { 00268 into.writeAttr(SUMO_ATTR_WIDTH, lane.width); 00269 } 00270 PositionVector shape = lane.shape; 00271 if (lane.offset > 0) { 00272 shape = shape.getSubpart(0, shape.length() - lane.offset); 00273 } 00274 into.writeAttr(SUMO_ATTR_SHAPE, shape); 00275 into.closeTag(true); 00276 } 00277 00278 00279 void 00280 NWWriter_SUMO::writeJunction(OutputDevice& into, const NBNode& n) { 00281 // write the attributes 00282 into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, n.getID()); 00283 into.writeAttr(SUMO_ATTR_TYPE, n.getType()); 00284 NWFrame::writePositionLong(n.getPosition(), into); 00285 // write the incoming lanes 00286 std::string incLanes; 00287 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00288 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) { 00289 unsigned int noLanes = (*i)->getNumLanes(); 00290 for (unsigned int j = 0; j < noLanes; j++) { 00291 incLanes += (*i)->getLaneID(j); 00292 if (i != incoming.end() - 1 || j < noLanes - 1) { 00293 incLanes += ' '; 00294 } 00295 } 00296 } 00297 into.writeAttr(SUMO_ATTR_INCLANES, incLanes); 00298 // write the internal lanes 00299 std::string intLanes; 00300 if (!OptionsCont::getOptions().getBool("no-internal-links")) { 00301 unsigned int l = 0; 00302 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) { 00303 const std::vector<NBEdge::Connection> &elv = (*i)->getConnections(); 00304 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { 00305 if ((*k).toEdge == 0) { 00306 continue; 00307 } 00308 if (l != 0) { 00309 intLanes += ' '; 00310 } 00311 if (!(*k).haveVia) { 00312 intLanes += (*k).id + "_0"; 00313 } else { 00314 intLanes += (*k).viaID + "_0"; 00315 } 00316 l++; 00317 } 00318 } 00319 } 00320 into.writeAttr(SUMO_ATTR_INTLANES, intLanes); 00321 // close writing 00322 into.writeAttr(SUMO_ATTR_SHAPE, n.getShape()); 00323 if (n.getType() == NODETYPE_DEAD_END) { 00324 into.closeTag(true); 00325 } else { 00326 into.closeOpener(); 00327 // write right-of-way logics 00328 n.writeLogic(into); 00329 into.closeTag(); 00330 } 00331 } 00332 00333 00334 bool 00335 NWWriter_SUMO::writeInternalNodes(OutputDevice& into, const NBNode& n) { 00336 bool ret = false; 00337 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00338 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) { 00339 const std::vector<NBEdge::Connection> &elv = (*i)->getConnections(); 00340 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { 00341 if ((*k).toEdge == 0 || !(*k).haveVia) { 00342 continue; 00343 } 00344 Position pos = (*k).shape[-1]; 00345 into.openTag(SUMO_TAG_JUNCTION).writeAttr(SUMO_ATTR_ID, (*k).viaID + "_0"); 00346 into.writeAttr(SUMO_ATTR_TYPE, NODETYPE_INTERNAL); 00347 NWFrame::writePositionLong(pos, into); 00348 std::string incLanes = (*k).id + "_0"; 00349 if ((*k).foeIncomingLanes.length() != 0) { 00350 incLanes += " " + (*k).foeIncomingLanes; 00351 } 00352 into.writeAttr(SUMO_ATTR_INCLANES, incLanes); 00353 into.writeAttr(SUMO_ATTR_INTLANES, (*k).foeInternalLanes); 00354 into.closeTag(true); 00355 ret = true; 00356 } 00357 } 00358 return ret; 00359 } 00360 00361 00362 void 00363 NWWriter_SUMO::writeConnection(OutputDevice& into, const NBEdge& from, const NBEdge::Connection& c, 00364 bool includeInternal, ConnectionStyle style) { 00365 assert(c.toEdge != 0); 00366 into.openTag(SUMO_TAG_CONNECTION); 00367 into.writeAttr(SUMO_ATTR_FROM, from.getID()); 00368 into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID()); 00369 into.writeAttr(SUMO_ATTR_FROM_LANE, c.fromLane); 00370 into.writeAttr(SUMO_ATTR_TO_LANE, c.toLane); 00371 00372 if (style != PLAIN) { 00373 if (includeInternal) { 00374 into.writeAttr(SUMO_ATTR_VIA, c.id + "_0"); 00375 } 00376 // set information about the controlling tl if any 00377 if (c.tlID != "") { 00378 into.writeAttr(SUMO_ATTR_TLID, c.tlID); 00379 into.writeAttr(SUMO_ATTR_TLLINKINDEX, c.tlLinkNo); 00380 } 00381 if (style == SUMONET) { 00382 // write the direction information 00383 LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge); 00384 assert(dir != LINKDIR_NODIR); 00385 into.writeAttr(SUMO_ATTR_DIR, toString(dir)); 00386 // write the state information 00387 std::string stateCode; 00388 if (c.tlID != "") { 00389 stateCode = toString(LINKSTATE_TL_OFF_BLINKING); 00390 } else { 00391 stateCode = from.getToNode()->stateCode(&from, c.toEdge, c.toLane, c.mayDefinitelyPass); 00392 } 00393 into.writeAttr(SUMO_ATTR_STATE, stateCode); 00394 } 00395 } 00396 into.closeTag(true); 00397 } 00398 00399 00400 bool 00401 NWWriter_SUMO::writeInternalConnections(OutputDevice& into, const NBNode& n) { 00402 bool ret = false; 00403 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00404 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) { 00405 NBEdge* from = *i; 00406 const std::vector<NBEdge::Connection> &connections = from->getConnections(); 00407 for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) { 00408 const NBEdge::Connection& c = *j; 00409 assert(c.toEdge != 0); 00410 if (c.haveVia) { 00411 // internal split 00412 writeInternalConnection(into, c.id, c.toEdge->getID(), c.toLane, c.viaID + "_0"); 00413 writeInternalConnection(into, c.viaID, c.toEdge->getID(), c.toLane, ""); 00414 } else { 00415 // no internal split 00416 writeInternalConnection(into, c.id, c.toEdge->getID(), c.toLane, ""); 00417 } 00418 ret = true; 00419 } 00420 } 00421 return ret; 00422 } 00423 00424 00425 void 00426 NWWriter_SUMO::writeInternalConnection(OutputDevice& into, 00427 const std::string& from, const std::string& to, int toLane, const std::string& via) { 00428 into.openTag(SUMO_TAG_CONNECTION); 00429 into.writeAttr(SUMO_ATTR_FROM, from); 00430 into.writeAttr(SUMO_ATTR_TO, to); 00431 into.writeAttr(SUMO_ATTR_FROM_LANE, 0); 00432 into.writeAttr(SUMO_ATTR_TO_LANE, toLane); 00433 if (via != "") { 00434 into.writeAttr(SUMO_ATTR_VIA, via); 00435 } 00436 into.writeAttr(SUMO_ATTR_DIR, "s"); 00437 into.writeAttr(SUMO_ATTR_STATE, "M"); 00438 into.closeTag(true); 00439 } 00440 00441 00442 void 00443 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::set<NBEdge*> &r) { 00444 std::set<std::string> nodes; 00445 for (std::set<NBEdge*>::const_iterator j = r.begin(); j != r.end(); ++j) { 00446 nodes.insert((*j)->getToNode()->getID()); 00447 } 00448 std::string nodeString; 00449 for (std::set<std::string>::const_iterator j = nodes.begin(); j != nodes.end(); ++j) { 00450 if (j != nodes.begin()) { 00451 nodeString += " "; 00452 } 00453 nodeString += *j; 00454 } 00455 into.openTag(SUMO_TAG_ROUNDABOUT).writeAttr(SUMO_ATTR_NODES, nodeString).closeTag(true); 00456 } 00457 00458 00459 void 00460 NWWriter_SUMO::writeDistrict(OutputDevice& into, const NBDistrict& d) { 00461 std::vector<SUMOReal> sourceW = d.getSourceWeights(); 00462 VectorHelper<SUMOReal>::normaliseSum(sourceW, 1.0); 00463 std::vector<SUMOReal> sinkW = d.getSinkWeights(); 00464 VectorHelper<SUMOReal>::normaliseSum(sinkW, 1.0); 00465 // write the head and the id of the district 00466 into.openTag(SUMO_TAG_TAZ).writeAttr(SUMO_ATTR_ID, d.getID()); 00467 if (d.getShape().size() > 0) { 00468 into.writeAttr(SUMO_ATTR_SHAPE, d.getShape()); 00469 } 00470 into.closeOpener(); 00471 size_t i; 00472 // write all sources 00473 const std::vector<NBEdge*> &sources = d.getSourceEdges(); 00474 for (i = 0; i < sources.size(); i++) { 00475 // write the head and the id of the source 00476 into.openTag(SUMO_TAG_TAZSOURCE).writeAttr(SUMO_ATTR_ID, sources[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sourceW[i]); 00477 into.closeTag(true); 00478 } 00479 // write all sinks 00480 const std::vector<NBEdge*> &sinks = d.getSinkEdges(); 00481 for (i = 0; i < sinks.size(); i++) { 00482 // write the head and the id of the sink 00483 into.openTag(SUMO_TAG_TAZSINK).writeAttr(SUMO_ATTR_ID, sinks[i]->getID()).writeAttr(SUMO_ATTR_WEIGHT, sinkW[i]); 00484 into.closeTag(true); 00485 } 00486 // write the tail 00487 into.closeTag(); 00488 } 00489 00490 00491 std::string 00492 NWWriter_SUMO::writeSUMOTime(SUMOTime steps) { 00493 SUMOReal time = STEPS2TIME(steps); 00494 if (time == std::floor(time)) { 00495 return toString(int(time)); 00496 } else { 00497 return toString(time); 00498 } 00499 } 00500 00501 00502 void 00503 NWWriter_SUMO::writeProhibitions(OutputDevice& into, const NBConnectionProhibits& prohibitions) { 00504 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) { 00505 NBConnection prohibited = (*j).first; 00506 const NBConnectionVector& prohibiting = (*j).second; 00507 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) { 00508 NBConnection prohibitor = *k; 00509 into.openTag(SUMO_TAG_PROHIBITION); 00510 into.writeAttr(SUMO_ATTR_PROHIBITOR, prohibitionConnection(prohibitor)); 00511 into.writeAttr(SUMO_ATTR_PROHIBITED, prohibitionConnection(prohibited)); 00512 into.closeTag(true); 00513 } 00514 } 00515 } 00516 00517 00518 std::string 00519 NWWriter_SUMO::prohibitionConnection(const NBConnection& c) { 00520 return c.getFrom()->getID() + "->" + c.getTo()->getID(); 00521 } 00522 00523 00524 void 00525 NWWriter_SUMO::writeTrafficLights(OutputDevice& into, const NBTrafficLightLogicCont& tllCont) { 00526 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed(); 00527 for (std::vector<NBTrafficLightLogic*>::iterator it = logics.begin(); it != logics.end(); it++) { 00528 into.openTag(SUMO_TAG_TLLOGIC); 00529 into.writeAttr(SUMO_ATTR_ID, (*it)->getID()); 00530 into.writeAttr(SUMO_ATTR_TYPE, toString(TLTYPE_STATIC)); 00531 into.writeAttr(SUMO_ATTR_PROGRAMID, (*it)->getProgramID()); 00532 into.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime((*it)->getOffset())); 00533 into.closeOpener(); 00534 // write the phases 00535 const std::vector<NBTrafficLightLogic::PhaseDefinition> &phases = (*it)->getPhases(); 00536 for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator j = phases.begin(); j != phases.end(); ++j) { 00537 into.openTag(SUMO_TAG_PHASE); 00538 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j->duration)); 00539 into.writeAttr(SUMO_ATTR_STATE, j->state); 00540 into.closeTag(true); 00541 } 00542 into.closeTag(); 00543 } 00544 if (logics.size() > 0) { 00545 into.lf(); 00546 } 00547 } 00548 00549 00550 void 00551 NWWriter_SUMO::writeLocation(OutputDevice& into) { 00552 const GeoConvHelper& geoConvHelper = GeoConvHelper::getFinal(); 00553 into.openTag(SUMO_TAG_LOCATION); 00554 into.writeAttr(SUMO_ATTR_NET_OFFSET, geoConvHelper.getOffsetBase()); 00555 into.writeAttr(SUMO_ATTR_CONV_BOUNDARY, geoConvHelper.getConvBoundary()); 00556 if (geoConvHelper.usingGeoProjection()) { 00557 into.setPrecision(GEO_OUTPUT_ACCURACY); 00558 } 00559 into.writeAttr(SUMO_ATTR_ORIG_BOUNDARY, geoConvHelper.getOrigBoundary()); 00560 if (geoConvHelper.usingGeoProjection()) { 00561 into.setPrecision(); 00562 } 00563 into.writeAttr(SUMO_ATTR_ORIG_PROJ, geoConvHelper.getProjString()); 00564 into.closeTag(true); 00565 into.lf(); 00566 } 00567 00568 00569 void 00570 NWWriter_SUMO::writePermissions(OutputDevice& into, SVCPermissions permissions) { 00571 if (permissions == SVCFreeForAll) { 00572 return; 00573 } else if (permissions == 0) { 00574 // special case: since all-empty encodes FreeForAll we must list all disallowed 00575 into.writeAttr(SUMO_ATTR_DISALLOW, getAllowedVehicleClassNames(SVCFreeForAll)); 00576 return; 00577 } else { 00578 std::pair<std::string, bool> encoding = getPermissionEncoding(permissions); 00579 if (encoding.second) { 00580 into.writeAttr(SUMO_ATTR_ALLOW, encoding.first); 00581 } else { 00582 into.writeAttr(SUMO_ATTR_DISALLOW, encoding.first); 00583 } 00584 } 00585 } 00586 00587 00588 void 00589 NWWriter_SUMO::writePreferences(OutputDevice& into, SVCPermissions preferred) { 00590 if (preferred == SVCFreeForAll || preferred == 0) { 00591 return; 00592 } else { 00593 into.writeAttr(SUMO_ATTR_PREFER, getAllowedVehicleClassNames(preferred)); 00594 } 00595 } 00596 /****************************************************************************/ 00597