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 << "\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 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines