SUMO - Simulation of Urban MObility
NWWriter_XML.cpp
Go to the documentation of this file.
00001 /****************************************************************************/
00009 // Exporter writing networks using XML (native input) 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 <algorithm>
00033 #include <utils/common/MsgHandler.h>
00034 #include <netbuild/NBEdge.h>
00035 #include <netbuild/NBEdgeCont.h>
00036 #include <netbuild/NBNode.h>
00037 #include <netbuild/NBNodeCont.h>
00038 #include <netbuild/NBNetBuilder.h>
00039 #include <utils/common/ToString.h>
00040 #include <utils/options/OptionsCont.h>
00041 #include <utils/iodevices/OutputDevice.h>
00042 #include <utils/geom/GeoConvHelper.h>
00043 #include "NWFrame.h"
00044 #include "NWWriter_SUMO.h"
00045 #include "NWWriter_XML.h"
00046 
00047 #ifdef CHECK_MEMORY_LEAKS
00048 #include <foreign/nvwa/debug_new.h>
00049 #endif // CHECK_MEMORY_LEAKS
00050 
00051 
00052 
00053 // ===========================================================================
00054 // method definitions
00055 // ===========================================================================
00056 // ---------------------------------------------------------------------------
00057 // static methods
00058 // ---------------------------------------------------------------------------
00059 void
00060 NWWriter_XML::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
00061     // check whether a matsim-file shall be generated
00062     if (oc.isSet("plain-output-prefix")) {
00063         writeNodes(oc, nb.getNodeCont());
00064         writeEdgesAndConnections(oc, nb.getNodeCont(), nb.getEdgeCont());
00065         writeTrafficLights(oc, nb.getTLLogicCont(), nb.getEdgeCont());
00066     }
00067     if (oc.isSet("junctions.join-output")) {
00068         writeJoinedJunctions(oc, nb.getNodeCont());
00069     }
00070 }
00071 
00072 
00073 void
00074 NWWriter_XML::writeNodes(const OptionsCont& oc, NBNodeCont& nc) {
00075     const GeoConvHelper& gch = GeoConvHelper::getFinal();
00076     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
00077     if (useGeo && !gch.usingGeoProjection()) {
00078         WRITE_WARNING("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined");
00079         useGeo = false;
00080     }
00081     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
00082 
00083     OutputDevice& device = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".nod.xml");
00084     device.writeXMLHeader("nodes", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/nodes_file.xsd\"");
00085 
00086     // write network offsets and projection to allow reconstruction of original coordinates
00087     if (!useGeo) {
00088         NWWriter_SUMO::writeLocation(device);
00089     }
00090 
00091     // write nodes
00092     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
00093         NBNode* n = (*i).second;
00094         device.openTag(SUMO_TAG_NODE);
00095         device.writeAttr(SUMO_ATTR_ID, n->getID());
00096         // write position
00097         Position pos = n->getPosition();
00098         if (useGeo) {
00099             gch.cartesian2geo(pos);
00100         }
00101         if (geoAccuracy) {
00102             device.setPrecision(GEO_OUTPUT_ACCURACY);
00103         }
00104         NWFrame::writePositionLong(pos, device);
00105         if (geoAccuracy) {
00106             device.setPrecision();
00107         }
00108 
00109         device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
00110         if (n->isTLControlled()) {
00111             const std::set<NBTrafficLightDefinition*> &tlss = n->getControllingTLS();
00112             // set may contain multiple programs for the same id.
00113             // make sure ids are unique and sorted
00114             std::set<std::string> tlsIDs;
00115             for (std::set<NBTrafficLightDefinition*>::const_iterator it_tl = tlss.begin(); it_tl != tlss.end(); it_tl++) {
00116                 tlsIDs.insert((*it_tl)->getID());
00117             }
00118             std::vector<std::string> sortedIDs(tlsIDs.begin(), tlsIDs.end());
00119             sort(sortedIDs.begin(), sortedIDs.end());
00120             device.writeAttr(SUMO_ATTR_TLID, sortedIDs);
00121         }
00122         device.closeTag(true);
00123     }
00124     device.close();
00125 }
00126 
00127 
00128 void
00129 NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, NBNodeCont& nc, NBEdgeCont& ec) {
00130     const GeoConvHelper& gch = GeoConvHelper::getFinal();
00131     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
00132     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
00133 
00134     OutputDevice& edevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".edg.xml");
00135     edevice.writeXMLHeader("edges", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/edges_file.xsd\"");
00136     OutputDevice& cdevice = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".con.xml");
00137     cdevice.writeXMLHeader("connections", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/connections_file.xsd\"");
00138     bool noNames = !oc.getBool("output.street-names");
00139     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
00140         // write the edge itself to the edges-files
00141         NBEdge* e = (*i).second;
00142         edevice.openTag(SUMO_TAG_EDGE);
00143         edevice.writeAttr(SUMO_ATTR_ID, e->getID());
00144         edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID());
00145         edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID());
00146         if (!noNames && e->getStreetName() != "") {
00147             edevice.writeAttr(SUMO_ATTR_NAME, e->getStreetName());
00148         }
00149         edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
00150         // write the type if given
00151         if (e->getTypeID() != "") {
00152             edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID());
00153         }
00154         edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
00155         if (!e->hasLaneSpecificSpeed()) {
00156             edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed());
00157         }
00158         // write non-default geometry
00159         if (!e->hasDefaultGeometry()) {
00160             PositionVector geom = e->getGeometry();
00161             if (useGeo) {
00162                 for (int i = 0; i < (int) geom.size(); i++) {
00163                     gch.cartesian2geo(geom[i]);
00164                 }
00165             }
00166             if (geoAccuracy) {
00167                 edevice.setPrecision(GEO_OUTPUT_ACCURACY);
00168             }
00169             edevice.writeAttr(SUMO_ATTR_SHAPE, geom);
00170             if (geoAccuracy) {
00171                 edevice.setPrecision();
00172             }
00173         }
00174         // write the spread type if not default ("right")
00175         if (e->getLaneSpreadFunction() != LANESPREAD_RIGHT) {
00176             edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()));
00177         }
00178         // write the length if it was specified
00179         if (e->hasLoadedLength()) {
00180             edevice.writeAttr(SUMO_ATTR_LENGTH, e->getLoadedLength());
00181         }
00182         // some attributes can be set by edge default or per lane. Write as default if possible (efficiency)
00183         if (e->getWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) {
00184             edevice.writeAttr(SUMO_ATTR_WIDTH, e->getWidth());
00185         }
00186         if (e->getOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificOffset()) {
00187             edevice.writeAttr(SUMO_ATTR_OFFSET, e->getOffset());
00188         }
00189         if (!e->needsLaneSpecificOutput()) {
00190             edevice.closeTag(true);
00191         } else {
00192             edevice << ">\n";
00193             for (unsigned int i = 0; i < e->getLanes().size(); ++i) {
00194                 const NBEdge::Lane& lane = e->getLanes()[i];
00195                 edevice.openTag(SUMO_TAG_LANE);
00196                 edevice.writeAttr(SUMO_ATTR_INDEX, i);
00197                 // write allowed lanes
00198                 NWWriter_SUMO::writePermissions(edevice, lane.permissions);
00199                 NWWriter_SUMO::writePreferences(edevice, lane.preferred);
00200                 // write other attributes
00201                 if (lane.width != NBEdge::UNSPECIFIED_WIDTH && e->hasLaneSpecificWidth()) {
00202                     edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width);
00203                 }
00204                 if (lane.offset != NBEdge::UNSPECIFIED_OFFSET && e->hasLaneSpecificOffset()) {
00205                     edevice.writeAttr(SUMO_ATTR_OFFSET, lane.offset);
00206                 }
00207                 if (e->hasLaneSpecificSpeed()) {
00208                     edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed);
00209                 }
00210                 edevice.closeTag(true);
00211             }
00212             edevice.closeTag();
00213         }
00214         // write this edge's connections to the connections-files
00215         e->sortOutgoingConnectionsByIndex();
00216         const std::vector<NBEdge::Connection> connections = e->getConnections();
00217         for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
00218             NWWriter_SUMO::writeConnection(cdevice, *e, *c, false, NWWriter_SUMO::PLAIN);
00219         }
00220         if (connections.size() > 0) {
00221             cdevice << "\n";
00222         }
00223     }
00224 
00225     // write loaded prohibitions to the connections-file
00226     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
00227         NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions());
00228     }
00229     edevice.close();
00230     cdevice.close();
00231 }
00232 
00233 
00234 void
00235 NWWriter_XML::writeTrafficLights(const OptionsCont& oc, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
00236     OutputDevice& device = OutputDevice::getDevice(oc.getString("plain-output-prefix") + ".tll.xml");
00237     device.writeXMLHeader("tlLogics", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/tllogic_file.xsd\"");
00238     NWWriter_SUMO::writeTrafficLights(device, tc);
00239     // we also need to remember the associations between tlLogics and connections
00240     // since the information in con.xml is insufficient
00241     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
00242         NBEdge* e = (*i).second;
00243         // write this edge's tl-controlled connections
00244         const std::vector<NBEdge::Connection> connections = e->getConnections();
00245         for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
00246             if (c->tlID != "") {
00247                 NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
00248             }
00249         }
00250     }
00251     device.close();
00252 }
00253 
00254 
00255 void
00256 NWWriter_XML::writeJoinedJunctions(const OptionsCont& oc, NBNodeCont& nc) {
00257     OutputDevice& device = OutputDevice::getDevice(oc.getString("junctions.join-output"));
00258     device.writeXMLHeader("nodes", SUMOSAXAttributes::ENCODING, NWFrame::MAJOR_VERSION + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"http://sumo.sf.net/xsd/nodes_file.xsd\"");
00259     const std::vector<std::set<std::string> >& clusters = nc.getJoinedClusters();
00260     for (std::vector<std::set<std::string> >::const_iterator it = clusters.begin(); it != clusters.end(); it++) {
00261         assert((*it).size() > 0);
00262         device.openTag(SUMO_TAG_JOIN);
00263         // prepare string
00264         std::ostringstream oss;
00265         for (std::set<std::string>::iterator it_id = it->begin(); it_id != it->end(); it_id++) {
00266             oss << *it_id << " ";
00267         }
00268         // remove final space
00269         std::string ids = oss.str();
00270         device.writeAttr(SUMO_ATTR_NODES, ids.substr(0, ids.size() - 1));
00271         device.closeTag(true);
00272     }
00273     device.close();
00274 }
00275 /****************************************************************************/
00276 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Friends Defines