|
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 << "\n"; 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 << "\n"; 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 << "\n"; 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 << "\n"; 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 << "\n"; 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 << "\n"; 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 << "\n"; 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 << "\n"; 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 << "\n"; 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, toString(EDGEFUNC_INTERNAL)); 00191 into << ">\n"; 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, "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 << ">\n"; 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) << " id=\"" << lID << "\""; 00248 // the first lane of an edge will be the depart lane 00249 into << " index=\"" << index << "\""; 00250 // write the list of allowed/disallowed vehicle classes 00251 if (lane.allowed.size() > 0) { 00252 into << " allow=\"" << getVehicleClassNames(lane.allowed) << '\"'; 00253 } 00254 if (lane.notAllowed.size() > 0) { 00255 into << " disallow=\"" << getVehicleClassNames(lane.notAllowed) << '\"'; 00256 } 00257 if (lane.preferred.size() > 0) { 00258 into << " prefer=\"" << getVehicleClassNames(lane.preferred) << '\"'; 00259 } 00260 // some further information 00261 if (lane.speed == 0) { 00262 WRITE_WARNING("Lane #" + toString(index) + " of edge '" + eID + "' has a maximum velocity of 0."); 00263 } else if (lane.speed < 0) { 00264 throw ProcessError("Negative velocity (" + toString(lane.speed) + " on edge '" + eID + "' lane#" + toString(index) + "."); 00265 } 00266 if (lane.offset > 0) { 00267 length = length - lane.offset; 00268 } 00269 into.writeAttr(SUMO_ATTR_SPEED, lane.speed); 00270 into.writeAttr(SUMO_ATTR_LENGTH, length); 00271 if (lane.offset > 0) { 00272 into << " endOffset=\"" << lane.offset << '\"'; 00273 } 00274 if (lane.width != NBEdge::UNSPECIFIED_WIDTH) { 00275 into << " width=\"" << lane.width << '\"'; 00276 } 00277 PositionVector shape = lane.shape; 00278 if (lane.offset > 0) { 00279 shape = shape.getSubpart(0, shape.length() - lane.offset); 00280 } 00281 into << " shape=\"" << shape << "\""; 00282 into.closeTag(true); 00283 } 00284 00285 00286 void 00287 NWWriter_SUMO::writeJunction(OutputDevice& into, const NBNode& n) { 00288 // write the attributes 00289 into.openTag(SUMO_TAG_JUNCTION) << " id=\"" << n.getID() << '\"'; 00290 into.writeAttr(SUMO_ATTR_TYPE, n.getType()); 00291 NWFrame::writePositionLong(n.getPosition(), into); 00292 into << " incLanes=\""; 00293 // write the incoming lanes 00294 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00295 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) { 00296 unsigned int noLanes = (*i)->getNumLanes(); 00297 for (unsigned int j = 0; j < noLanes; j++) { 00298 into << (*i)->getLaneID(j); 00299 if (i != incoming.end() - 1 || j < noLanes - 1) { 00300 into << ' '; 00301 } 00302 } 00303 } 00304 into << "\""; 00305 // write the internal lanes 00306 into << " intLanes=\""; 00307 if (!OptionsCont::getOptions().getBool("no-internal-links")) { 00308 unsigned int l = 0; 00309 for (EdgeVector::const_iterator i = incoming.begin(); i != incoming.end(); i++) { 00310 const std::vector<NBEdge::Connection> &elv = (*i)->getConnections(); 00311 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { 00312 if ((*k).toEdge == 0) { 00313 continue; 00314 } 00315 if (l != 0) { 00316 into << ' '; 00317 } 00318 if (!(*k).haveVia) { 00319 into << (*k).id << "_0"; 00320 } else { 00321 into << (*k).viaID << "_0"; 00322 } 00323 l++; 00324 } 00325 } 00326 } 00327 into << "\""; 00328 // close writing 00329 into << " shape=\"" << n.getShape() << "\""; 00330 if (n.getType() == NODETYPE_DEAD_END) { 00331 into.closeTag(true); 00332 } else { 00333 into << ">\n"; 00334 // write right-of-way logics 00335 n.writeLogic(into); 00336 into.closeTag(); 00337 } 00338 } 00339 00340 00341 bool 00342 NWWriter_SUMO::writeInternalNodes(OutputDevice& into, const NBNode& n) { 00343 bool ret = false; 00344 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00345 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); i++) { 00346 const std::vector<NBEdge::Connection> &elv = (*i)->getConnections(); 00347 for (std::vector<NBEdge::Connection>::const_iterator k = elv.begin(); k != elv.end(); ++k) { 00348 if ((*k).toEdge == 0 || !(*k).haveVia) { 00349 continue; 00350 } 00351 Position pos = (*k).shape[-1]; 00352 into.openTag(SUMO_TAG_JUNCTION) << " id=\"" << (*k).viaID << "_0\""; 00353 into << " type=\"" << toString(NODETYPE_INTERNAL) << "\""; 00354 NWFrame::writePositionLong(pos, into); 00355 into << " incLanes=\""; 00356 std::string furtherIncoming = (*k).sourceNames; 00357 into << (*k).id << "_0"; 00358 if (furtherIncoming.length() != 0) { 00359 into << " " << furtherIncoming; 00360 } 00361 into << "\""; 00362 into << " intLanes=\"" << (*k).crossingNames << "\""; 00363 into.closeTag(true); 00364 ret = true; 00365 } 00366 } 00367 return ret; 00368 } 00369 00370 00371 void 00372 NWWriter_SUMO::writeConnection(OutputDevice& into, const NBEdge& from, const NBEdge::Connection& c, 00373 bool includeInternal, ConnectionStyle style) { 00374 assert(c.toEdge != 0); 00375 into.openTag(SUMO_TAG_CONNECTION); 00376 into.writeAttr(SUMO_ATTR_FROM, from.getID()); 00377 into.writeAttr(SUMO_ATTR_TO, c.toEdge->getID()); 00378 into.writeAttr(SUMO_ATTR_FROM_LANE, c.fromLane); 00379 into.writeAttr(SUMO_ATTR_TO_LANE, c.toLane); 00380 00381 if (style != PLAIN) { 00382 if (includeInternal) { 00383 into.writeAttr(SUMO_ATTR_VIA, c.id + "_0"); 00384 } 00385 // set information about the controlling tl if any 00386 if (c.tlID != "") { 00387 into.writeAttr(SUMO_ATTR_TLID, c.tlID); 00388 into.writeAttr(SUMO_ATTR_TLLINKINDEX, c.tlLinkNo); 00389 } 00390 if (style == SUMONET) { 00391 // write the direction information 00392 LinkDirection dir = from.getToNode()->getDirection(&from, c.toEdge); 00393 assert(dir != LINKDIR_NODIR); 00394 into.writeAttr(SUMO_ATTR_DIR, toString(dir)); 00395 // write the state information 00396 std::string stateCode; 00397 if (c.tlID != "") { 00398 stateCode = toString(LINKSTATE_TL_OFF_BLINKING); 00399 } else { 00400 stateCode = from.getToNode()->stateCode(&from, c.toEdge, c.toLane, c.mayDefinitelyPass); 00401 } 00402 into.writeAttr(SUMO_ATTR_STATE, stateCode); 00403 } 00404 } 00405 into.closeTag(true); 00406 } 00407 00408 00409 bool 00410 NWWriter_SUMO::writeInternalConnections(OutputDevice& into, const NBNode& n) { 00411 bool ret = false; 00412 const std::vector<NBEdge*> &incoming = n.getIncomingEdges(); 00413 for (std::vector<NBEdge*>::const_iterator i = incoming.begin(); i != incoming.end(); ++i) { 00414 NBEdge* from = *i; 00415 const std::vector<NBEdge::Connection> &connections = from->getConnections(); 00416 for (std::vector<NBEdge::Connection>::const_iterator j = connections.begin(); j != connections.end(); ++j) { 00417 const NBEdge::Connection& c = *j; 00418 assert(c.toEdge != 0); 00419 if (c.haveVia) { 00420 // internal split 00421 writeInternalConnection(into, c.id, c.toEdge->getID(), c.toLane, c.viaID + "_0"); 00422 writeInternalConnection(into, c.viaID, c.toEdge->getID(), c.toLane, ""); 00423 } else { 00424 // no internal split 00425 writeInternalConnection(into, c.id, c.toEdge->getID(), c.toLane, ""); 00426 } 00427 ret = true; 00428 } 00429 } 00430 return ret; 00431 } 00432 00433 00434 void 00435 NWWriter_SUMO::writeInternalConnection(OutputDevice& into, 00436 const std::string& from, const std::string& to, int toLane, const std::string& via) { 00437 into.openTag(SUMO_TAG_CONNECTION); 00438 into.writeAttr(SUMO_ATTR_FROM, from); 00439 into.writeAttr(SUMO_ATTR_TO, to); 00440 into.writeAttr(SUMO_ATTR_FROM_LANE, 0); 00441 into.writeAttr(SUMO_ATTR_TO_LANE, toLane); 00442 if (via != "") { 00443 into.writeAttr(SUMO_ATTR_VIA, via); 00444 } 00445 into.writeAttr(SUMO_ATTR_DIR, "s"); 00446 into.writeAttr(SUMO_ATTR_STATE, "M"); 00447 into.closeTag(true); 00448 } 00449 00450 00451 void 00452 NWWriter_SUMO::writeRoundabout(OutputDevice& into, const std::set<NBEdge*> &r) { 00453 std::vector<NBNode*> nodes; 00454 for (std::set<NBEdge*>::const_iterator j = r.begin(); j != r.end(); ++j) { 00455 NBNode* n = (*j)->getToNode(); 00456 if (find(nodes.begin(), nodes.end(), n) == nodes.end()) { 00457 nodes.push_back(n); 00458 } 00459 } 00460 sort(nodes.begin(), nodes.end(), NBNode::nodes_by_id_sorter()); 00461 into.openTag(SUMO_TAG_ROUNDABOUT) << " nodes=\""; 00462 int k = 0; 00463 for (std::vector<NBNode*>::iterator j = nodes.begin(); j != nodes.end(); ++j, ++k) { 00464 if (k != 0) { 00465 into << ' '; 00466 } 00467 into << (*j)->getID(); 00468 } 00469 into << "\""; 00470 into.closeTag(true); 00471 } 00472 00473 00474 void 00475 NWWriter_SUMO::writeDistrict(OutputDevice& into, const NBDistrict& d) { 00476 std::vector<SUMOReal> sourceW = d.getSourceWeights(); 00477 VectorHelper<SUMOReal>::normaliseSum(sourceW, 1.0); 00478 std::vector<SUMOReal> sinkW = d.getSinkWeights(); 00479 VectorHelper<SUMOReal>::normaliseSum(sinkW, 1.0); 00480 // write the head and the id of the district 00481 into.openTag(SUMO_TAG_TAZ) << " id=\"" << d.getID() << "\""; 00482 if (d.getShape().size() > 0) { 00483 into << " shape=\"" << d.getShape() << "\""; 00484 } 00485 into << ">\n"; 00486 size_t i; 00487 // write all sources 00488 const std::vector<NBEdge*> &sources = d.getSourceEdges(); 00489 for (i = 0; i < sources.size(); i++) { 00490 // write the head and the id of the source 00491 into.openTag(SUMO_TAG_TAZSOURCE) << " id=\"" << sources[i]->getID() << "\" weight=\"" << sourceW[i] << "\""; 00492 into.closeTag(true); 00493 } 00494 // write all sinks 00495 const std::vector<NBEdge*> &sinks = d.getSinkEdges(); 00496 for (i = 0; i < sinks.size(); i++) { 00497 // write the head and the id of the sink 00498 into.openTag(SUMO_TAG_TAZSINK) << " id=\"" << sinks[i]->getID() << "\" weight=\"" << sinkW[i] << "\""; 00499 into.closeTag(true); 00500 } 00501 // write the tail 00502 into.closeTag(); 00503 } 00504 00505 00506 std::string 00507 NWWriter_SUMO::writeSUMOTime(SUMOTime steps) { 00508 SUMOReal time = STEPS2TIME(steps); 00509 if (time == std::floor(time)) { 00510 return toString(int(time)); 00511 } else { 00512 return toString(time); 00513 } 00514 } 00515 00516 00517 void 00518 NWWriter_SUMO::writeProhibitions(OutputDevice& into, const NBConnectionProhibits& prohibitions) { 00519 for (NBConnectionProhibits::const_iterator j = prohibitions.begin(); j != prohibitions.end(); j++) { 00520 NBConnection prohibited = (*j).first; 00521 const NBConnectionVector& prohibiting = (*j).second; 00522 for (NBConnectionVector::const_iterator k = prohibiting.begin(); k != prohibiting.end(); k++) { 00523 NBConnection prohibitor = *k; 00524 into.openTag(SUMO_TAG_PROHIBITION); 00525 into.writeAttr(SUMO_ATTR_PROHIBITOR, prohibitionConnection(prohibitor)); 00526 into.writeAttr(SUMO_ATTR_PROHIBITED, prohibitionConnection(prohibited)); 00527 into.closeTag(true); 00528 } 00529 } 00530 } 00531 00532 00533 std::string 00534 NWWriter_SUMO::prohibitionConnection(const NBConnection& c) { 00535 return c.getFrom()->getID() + "->" + c.getTo()->getID(); 00536 } 00537 00538 00539 void 00540 NWWriter_SUMO::writeTrafficLights(OutputDevice& into, const NBTrafficLightLogicCont& tllCont) { 00541 std::vector<NBTrafficLightLogic*> logics = tllCont.getComputed(); 00542 for (std::vector<NBTrafficLightLogic*>::iterator it = logics.begin(); it != logics.end(); it++) { 00543 into.openTag(SUMO_TAG_TLLOGIC); 00544 into.writeAttr(SUMO_ATTR_ID, (*it)->getID()); 00545 into.writeAttr(SUMO_ATTR_TYPE, toString(TLTYPE_STATIC)); 00546 into.writeAttr(SUMO_ATTR_PROGRAMID, (*it)->getProgramID()); 00547 into.writeAttr(SUMO_ATTR_OFFSET, writeSUMOTime((*it)->getOffset())); 00548 into << ">\n"; 00549 // write the phases 00550 const std::vector<NBTrafficLightLogic::PhaseDefinition> &phases = (*it)->getPhases(); 00551 for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator j = phases.begin(); j != phases.end(); ++j) { 00552 into.openTag(SUMO_TAG_PHASE); 00553 into.writeAttr(SUMO_ATTR_DURATION, writeSUMOTime(j->duration)); 00554 into.writeAttr(SUMO_ATTR_STATE, j->state); 00555 into.closeTag(true); 00556 } 00557 into.closeTag(); 00558 } 00559 if (logics.size() > 0) { 00560 into << "\n"; 00561 } 00562 } 00563 00564 00565 void 00566 NWWriter_SUMO::writeLocation(OutputDevice& into) { 00567 const GeoConvHelper& geoConvHelper = GeoConvHelper::getFinal(); 00568 into.openTag(SUMO_TAG_LOCATION); 00569 into.writeAttr(SUMO_ATTR_NET_OFFSET, geoConvHelper.getOffsetBase()); 00570 into.writeAttr(SUMO_ATTR_CONV_BOUNDARY, geoConvHelper.getConvBoundary()); 00571 if (geoConvHelper.usingGeoProjection()) { 00572 into.setPrecision(GEO_OUTPUT_ACCURACY); 00573 } 00574 into.writeAttr(SUMO_ATTR_ORIG_BOUNDARY, geoConvHelper.getOrigBoundary()); 00575 if (geoConvHelper.usingGeoProjection()) { 00576 into.setPrecision(); 00577 } 00578 into.writeAttr(SUMO_ATTR_ORIG_PROJ, geoConvHelper.getProjString()); 00579 into.closeTag(true); 00580 into << "\n"; 00581 } 00582 00583 /****************************************************************************/ 00584