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