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