SUMO - Simulation of Urban MObility

NWWriter_SUMO.cpp

Go to the documentation of this file.
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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines