LCOV - code coverage report
Current view: top level - src/netwrite - NWWriter_XML.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 98.1 % 324 318
Test Date: 2026-01-01 15:49:29 Functions: 100.0 % 13 13

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.
       4              : // This program and the accompanying materials are made available under the
       5              : // terms of the Eclipse Public License 2.0 which is available at
       6              : // https://www.eclipse.org/legal/epl-2.0/
       7              : // This Source Code may also be made available under the following Secondary
       8              : // Licenses when the conditions for such availability set forth in the Eclipse
       9              : // Public License 2.0 are satisfied: GNU General Public License, version 2
      10              : // or later which is available at
      11              : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
      12              : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
      13              : /****************************************************************************/
      14              : /// @file    NWWriter_XML.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @author  Leonhard Luecken
      19              : /// @date    Tue, 11.05.2011
      20              : ///
      21              : // Exporter writing networks using XML (native input) format
      22              : /****************************************************************************/
      23              : #include <config.h>
      24              : #include <algorithm>
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <utils/common/ToString.h>
      27              : #include <utils/common/StringUtils.h>
      28              : #include <utils/options/OptionsCont.h>
      29              : #include <utils/iodevices/OutputDevice.h>
      30              : #include <utils/geom/GeoConvHelper.h>
      31              : #include <netbuild/NBEdge.h>
      32              : #include <netbuild/NBEdgeCont.h>
      33              : #include <netbuild/NBNode.h>
      34              : #include <netbuild/NBNodeCont.h>
      35              : #include <netbuild/NBNetBuilder.h>
      36              : #include <netbuild/NBPTLineCont.h>
      37              : #include <netbuild/NBPTStop.h>
      38              : #include <netbuild/NBParking.h>
      39              : #include "NWFrame.h"
      40              : #include "NWWriter_SUMO.h"
      41              : #include "NWWriter_XML.h"
      42              : 
      43              : 
      44              : // ===========================================================================
      45              : // method definitions
      46              : // ===========================================================================
      47              : // ---------------------------------------------------------------------------
      48              : // static methods
      49              : // ---------------------------------------------------------------------------
      50              : void
      51         1807 : NWWriter_XML::writeNetwork(const OptionsCont& oc, const std::string& prefix, NBNetBuilder& nb) {
      52              :     // check whether plain-output files shall be generated
      53         1807 :     if (prefix != "") {
      54          175 :         const bool haveTypes = nb.getTypeCont().size() > 0;
      55          175 :         writeNodes(oc, prefix, nb.getNodeCont());
      56          173 :         if (haveTypes) {
      57           16 :             writeTypes(prefix, nb.getEdgeCont(), nb.getTypeCont());
      58              :         }
      59          173 :         writeEdgesAndConnections(oc, prefix, nb.getNodeCont(), nb.getEdgeCont());
      60          173 :         writeTrafficLights(prefix, nb.getTLLogicCont(), nb.getEdgeCont());
      61          173 :         writeConfig(oc, prefix, haveTypes);
      62              :     }
      63         1815 :     if (oc.isSet("junctions.join-output") && (oc.getString("junctions.join-output").size() > 0)) {
      64           10 :         writeJoinedJunctions(oc.getString("junctions.join-output"), nb.getNodeCont());
      65              :     }
      66         1807 :     if (oc.isSet("street-sign-output") && (oc.getString("street-sign-output").size() > 0)) {
      67            1 :         writeStreetSigns(oc, nb.getEdgeCont());
      68              :     }
      69         3669 :     if (oc.exists("ptstop-output") && oc.isSet("ptstop-output") && (oc.getString("ptstop-output").size() > 0)) {
      70           72 :         writePTStops(oc, nb.getPTStopCont());
      71              :     }
      72         3617 :     if (oc.exists("ptline-output") && oc.isSet("ptline-output") && (oc.getString("ptline-output").size() > 0)) {
      73           46 :         writePTLines(oc, nb.getPTLineCont());
      74              :     }
      75         3531 :     if (oc.exists("parking-output") && oc.isSet("parking-output") && (oc.getString("parking-output").size() > 0)) {
      76            3 :         writeParkingAreas(oc, nb.getParkingCont(), nb.getEdgeCont());
      77              :     }
      78         3527 :     if (oc.exists("taz-output") && oc.isSet("taz-output") && (oc.getString("taz-output").size() > 0)) {
      79            1 :         writeDistricts(oc, nb.getDistrictCont());
      80              :     }
      81         1805 : }
      82              : 
      83              : 
      84              : void
      85          173 : NWWriter_XML::writeConfig(const OptionsCont& oc, const std::string& prefix, bool haveTypes) {
      86          346 :     if (!oc.exists("node-files")) {
      87              :         // do not write configuration for netgen
      88            1 :         return;
      89              :     }
      90          172 :     OptionsCont* tmp = oc.clone();
      91          344 :     tmp->set("node-files", prefix + ".nod.xml");
      92          344 :     tmp->set("edge-files", prefix + ".edg.xml");
      93          344 :     tmp->set("connection-files", prefix + ".con.xml");
      94          344 :     tmp->set("tllogic-files", prefix + ".tll.xml");
      95          172 :     if (haveTypes) {
      96           32 :         tmp->set("type-files", prefix + ".typ.xml");
      97              :     }
      98          344 :     tmp->setDefault("sumo-net-file", "");
      99          344 :     tmp->setDefault("plain-output-prefix", "");
     100              : 
     101          172 :     const std::string configPath = prefix + ".netccfg";
     102          172 :     std::ofstream out(configPath.c_str());
     103          172 :     if (!out.good()) {
     104            0 :         delete tmp;
     105            0 :         throw ProcessError(TLF("Could not save configuration to '%'", configPath));
     106              :     } else {
     107          344 :         tmp->writeConfiguration(out, true, false, false);
     108              :     }
     109          172 :     delete tmp;
     110          172 : }
     111              : 
     112              : 
     113              : void
     114          175 : NWWriter_XML::writeNodes(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc) {
     115              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     116          348 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
     117          175 :     if (useGeo && !gch.usingGeoProjection()) {
     118            0 :         WRITE_WARNING(TL("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"));
     119              :         useGeo = false;
     120              :     }
     121          175 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
     122              : 
     123          348 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".nod.xml");
     124              :     std::map<SumoXMLAttr, std::string> attrs;
     125          173 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     126          346 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
     127              : 
     128              :     // write network offsets and projection to allow reconstruction of original coordinates
     129          173 :     if (!useGeo) {
     130          169 :         GeoConvHelper::writeLocation(device);
     131              :     }
     132              : 
     133              :     // write nodes
     134          346 :     TrafficLightType tlsDefaultType = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
     135         1399 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     136         1226 :         NBNode* n = (*i).second;
     137         1226 :         device.openTag(SUMO_TAG_NODE);
     138         1226 :         device.writeAttr(SUMO_ATTR_ID, n->getID());
     139              :         // write position
     140         1226 :         Position pos = n->getPosition();
     141         1226 :         if (useGeo) {
     142           99 :             gch.cartesian2geo(pos);
     143              :         }
     144         1226 :         if (geoAccuracy) {
     145           99 :             device.setPrecision(gPrecisionGeo);
     146              :         }
     147         1226 :         NWFrame::writePositionLong(pos, device);
     148         1226 :         if (geoAccuracy) {
     149           99 :             device.setPrecision();
     150              :         }
     151              : 
     152         2452 :         device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
     153         1226 :         if (n->isTLControlled()) {
     154              :             // set may contain multiple programs for the same id.
     155              :             // make sure ids are unique and sorted
     156              :             std::set<std::string> tlsIDs;
     157              :             std::set<std::string> controlledInnerEdges;
     158          101 :             std::string tlType = "";
     159          203 :             for (NBTrafficLightDefinition* tl : n->getControllingTLS()) {
     160              :                 tlsIDs.insert(tl->getID());
     161          102 :                 std::vector<std::string> cie = tl->getControlledInnerEdges();
     162              :                 controlledInnerEdges.insert(cie.begin(), cie.end());
     163          102 :                 if (tl->getType() != tlsDefaultType) {
     164            8 :                     tlType = toString(tl->getType());
     165              :                 }
     166          102 :             }
     167          101 :             std::vector<std::string> sortedIDs(tlsIDs.begin(), tlsIDs.end());
     168          101 :             sort(sortedIDs.begin(), sortedIDs.end());
     169          101 :             device.writeAttr(SUMO_ATTR_TLID, sortedIDs);
     170          101 :             if (tlType != "") {
     171            4 :                 device.writeAttr(SUMO_ATTR_TLTYPE, tlType);
     172              :             }
     173          101 :             if (controlledInnerEdges.size() > 0) {
     174            8 :                 std::vector<std::string> sortedCIEs(controlledInnerEdges.begin(), controlledInnerEdges.end());
     175            8 :                 sort(sortedCIEs.begin(), sortedCIEs.end());
     176            8 :                 device.writeAttr(SUMO_ATTR_CONTROLLED_INNER, joinToString(sortedCIEs, " "));
     177            8 :             }
     178          101 :         }
     179         1226 :         if (n->hasCustomShape()) {
     180           28 :             writeShape(device, gch, n->getShape(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     181              :         }
     182         1226 :         if (n->getRadius() != NBNode::UNSPECIFIED_RADIUS) {
     183            8 :             device.writeAttr(SUMO_ATTR_RADIUS, n->getRadius());
     184              :         }
     185         1226 :         if (!n->getKeepClear()) {
     186            0 :             device.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, n->getKeepClear());
     187              :         }
     188         1226 :         if (n->getRightOfWay() != RightOfWay::DEFAULT) {
     189            0 :             device.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n->getRightOfWay()));
     190              :         }
     191         1226 :         if (n->getFringeType() != FringeType::DEFAULT) {
     192            8 :             device.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n->getFringeType()));
     193              :         }
     194         1226 :         if (n->getRoundaboutType() != RoundaboutType::DEFAULT) {
     195            2 :             device.writeAttr<std::string>(SUMO_ATTR_ROUNDABOUT, toString(n->getRoundaboutType()));
     196              :         }
     197         1226 :         if (n->getName() != "") {
     198            8 :             device.writeAttr<std::string>(SUMO_ATTR_NAME, StringUtils::escapeXML(n->getName()));
     199              :         }
     200         1226 :         n->writeParams(device);
     201         2452 :         device.closeTag();
     202              :     }
     203          173 :     device.close();
     204          173 : }
     205              : 
     206              : 
     207              : void
     208           16 : NWWriter_XML::writeTypes(const std::string& prefix, NBEdgeCont& ec, NBTypeCont& tc) {
     209           32 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".typ.xml");
     210              :     std::map<SumoXMLAttr, std::string> attrs;
     211           16 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     212           32 :     device.writeXMLHeader(toString(SUMO_TAG_TYPES), "types_file.xsd", attrs);
     213           16 :     std::set<std::string> usedTypes = ec.getUsedTypes();
     214           16 :     tc.writeEdgeTypes(device, usedTypes);
     215           16 :     device.close();
     216           16 : }
     217              : 
     218              : 
     219              : void
     220          173 : NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc, NBEdgeCont& ec) {
     221              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     222          345 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
     223          173 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
     224              : 
     225              :     std::map<SumoXMLAttr, std::string> attrs;
     226          173 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     227          346 :     OutputDevice& edevice = OutputDevice::getDevice(prefix + ".edg.xml");
     228          346 :     edevice.writeXMLHeader("edges", "edges_file.xsd", attrs);
     229          346 :     OutputDevice& cdevice = OutputDevice::getDevice(prefix + ".con.xml");
     230          346 :     cdevice.writeXMLHeader("connections", "connections_file.xsd", attrs);
     231          173 :     const bool writeNames = oc.getBool("output.street-names");
     232          173 :     const bool writeLanes = oc.getBool("plain-output.lanes");
     233              : 
     234              :     // write network offsets and projection to allow reconstruction of original coordinates at least for geo-referenced networks
     235          173 :     if (!useGeo && gch.usingGeoProjection()) {
     236           22 :         GeoConvHelper::writeLocation(edevice);
     237              :     }
     238          346 :     LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
     239         2059 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     240              :         // write the edge itself to the edges-files
     241         1886 :         NBEdge* e = (*i).second;
     242         1886 :         edevice.openTag(SUMO_TAG_EDGE);
     243         1886 :         edevice.writeAttr(SUMO_ATTR_ID, e->getID());
     244         1886 :         edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID());
     245         1886 :         edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID());
     246         1886 :         if (writeNames && e->getStreetName() != "") {
     247          592 :             edevice.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName()));
     248              :         }
     249         1886 :         edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
     250              :         // write the type if given
     251         1886 :         if (e->getTypeID() != "") {
     252          779 :             edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID());
     253              :         }
     254         1886 :         if (e->getRoutingType() != "") {
     255            2 :             edevice.writeAttr(SUMO_ATTR_ROUTINGTYPE, e->getRoutingType());
     256              :         }
     257         1886 :         edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
     258         1886 :         if (!e->hasLaneSpecificSpeed()) {
     259         1883 :             edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed());
     260              :         }
     261         1886 :         if (!e->hasLaneSpecificFriction()) {
     262         1882 :             if (e->getFriction() != NBEdge::UNSPECIFIED_FRICTION) {
     263            3 :                 edevice.writeAttr(SUMO_ATTR_FRICTION, e->getFriction());
     264              :             }
     265              :         }
     266              :         // write non-default geometry
     267         1886 :         if (!e->hasDefaultGeometry()) {
     268          591 :             writeShape(edevice, gch, e->getGeometry(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     269              :         }
     270              :         // write the spread type if not default ("right")
     271         1886 :         if (e->getLaneSpreadFunction() != defaultSpread) {
     272          836 :             edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()));
     273              :         }
     274              :         // write the length if it was specified
     275         1886 :         if (e->hasLoadedLength()) {
     276            3 :             edevice.writeAttr(SUMO_ATTR_LENGTH, e->getLoadedLength());
     277              :         }
     278              :         // some attributes can be set by edge default or per lane. Write as default if possible (efficiency)
     279         1886 :         if (e->getLaneWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) {
     280          227 :             edevice.writeAttr(SUMO_ATTR_WIDTH, e->getLaneWidth());
     281              :         }
     282         1886 :         if (e->getEndOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificEndOffset()) {
     283            7 :             edevice.writeAttr(SUMO_ATTR_ENDOFFSET, e->getEndOffset());
     284              :         }
     285         1886 :         if (!e->hasLaneSpecificPermissions()) {
     286         1613 :             writePermissions(edevice, e->getPermissions(0));
     287              :         }
     288         1886 :         if (!e->hasLaneSpecificStopOffsets() && e->getEdgeStopOffset().isDefined()) {
     289            0 :             NWWriter_SUMO::writeStopOffsets(edevice, e->getEdgeStopOffset());
     290              :         }
     291         1886 :         if (e->getDistance() != 0) {
     292            2 :             edevice.writeAttr(SUMO_ATTR_DISTANCE, e->getDistance());
     293              :         }
     294         1886 :         if (e->getBidiEdge() != 0) {
     295           30 :             edevice.writeAttr(SUMO_ATTR_BIDI, e->getBidiEdge()->getID());
     296              :         }
     297         1886 :         if (e->needsLaneSpecificOutput() || writeLanes) {
     298              :             int idx = 0;
     299         1530 :             for (const NBEdge::Lane& lane : e->getLanes()) {
     300         1172 :                 edevice.openTag(SUMO_TAG_LANE);
     301         1172 :                 edevice.writeAttr(SUMO_ATTR_INDEX, idx++);
     302              :                 // write allowed lanes
     303         1172 :                 if (e->hasLaneSpecificPermissions() || writeLanes) {
     304         1005 :                     writePermissions(edevice, lane.permissions);
     305              :                 }
     306         1172 :                 writePreferences(edevice, lane.preferred);
     307              :                 // write other attributes
     308         1172 :                 if (lane.width != NBEdge::UNSPECIFIED_WIDTH && (e->hasLaneSpecificWidth() || writeLanes)) {
     309          468 :                     edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width);
     310              :                 }
     311         1172 :                 if (lane.endOffset != NBEdge::UNSPECIFIED_OFFSET && (e->hasLaneSpecificEndOffset() || writeLanes)) {
     312            8 :                     edevice.writeAttr(SUMO_ATTR_ENDOFFSET, lane.endOffset);
     313              :                 }
     314         1172 :                 if (e->hasLaneSpecificSpeed() || writeLanes) {
     315           25 :                     edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed);
     316              :                 }
     317         1172 :                 if (lane.accelRamp) {
     318            1 :                     edevice.writeAttr(SUMO_ATTR_ACCELERATION, lane.accelRamp);
     319              :                 }
     320         1172 :                 if (lane.customShape.size() > 0 || writeLanes) {
     321           42 :                     writeShape(edevice, gch, lane.customShape.size() > 0 ? lane.customShape : lane.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     322              :                 }
     323         1172 :                 if (lane.type != "") {
     324            3 :                     edevice.writeAttr(SUMO_ATTR_TYPE, lane.type);
     325              :                 }
     326         1172 :                 if (lane.changeLeft != SVCAll && lane.changeLeft != SVC_UNSPECIFIED && lane.changeLeft != SVC_IGNORING) {
     327            6 :                     edevice.writeAttr(SUMO_ATTR_CHANGE_LEFT, getVehicleClassNames(lane.changeLeft));
     328              :                 }
     329         1172 :                 if (lane.changeRight != SVCAll && lane.changeRight != SVC_UNSPECIFIED && lane.changeRight != SVC_IGNORING) {
     330            7 :                     edevice.writeAttr(SUMO_ATTR_CHANGE_RIGHT, getVehicleClassNames(lane.changeRight));
     331              :                 }
     332         1172 :                 if (lane.oppositeID != "") {
     333           47 :                     edevice.openTag(SUMO_TAG_NEIGH);
     334           47 :                     edevice.writeAttr(SUMO_ATTR_LANE, lane.oppositeID);
     335           94 :                     edevice.closeTag();
     336              :                 }
     337         1172 :                 lane.writeParams(edevice);
     338         1172 :                 NWWriter_SUMO::writeStopOffsets(edevice, lane.laneStopOffset);
     339         2344 :                 edevice.closeTag();
     340              :             }
     341              :         }
     342         1886 :         e->writeParams(edevice);
     343         3772 :         edevice.closeTag();
     344              :         // write this edge's connections to the connections-files
     345         1886 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     346         1886 :         if (connections.empty()) {
     347              :             // if there are no connections and this appears to be customized, preserve the information
     348          355 :             const int numOutgoing = (int)e->getToNode()->getOutgoingEdges().size();
     349          355 :             if (numOutgoing > 0) {
     350          227 :                 const SVCPermissions inPerm = e->getPermissions();
     351              :                 SVCPermissions outPerm = 0;
     352          557 :                 for (auto out : e->getToNode()->getOutgoingEdges()) {
     353          330 :                     outPerm |= out->getPermissions();
     354              :                 }
     355          227 :                 if ((inPerm & outPerm) != 0 && (inPerm & outPerm) != SVC_PEDESTRIAN) {
     356          122 :                     cdevice.openTag(SUMO_TAG_CONNECTION);
     357          122 :                     cdevice.writeAttr(SUMO_ATTR_FROM, e->getID());
     358          122 :                     cdevice.closeTag();
     359          122 :                     cdevice << "\n";
     360              :                 }
     361              :             }
     362              :         } else {
     363         5297 :             for (NBEdge::Connection c : connections) {
     364         3766 :                 if (useGeo) {
     365          404 :                     for (Position& p : c.customShape) {
     366            3 :                         gch.cartesian2geo(p);
     367              :                     }
     368              :                 }
     369         3766 :                 NWWriter_SUMO::writeConnection(cdevice, *e, c, false, NWWriter_SUMO::PLAIN, geoAccuracy);
     370         3766 :             }
     371         1531 :             cdevice << "\n";
     372              :         }
     373         1886 :     }
     374              :     // write roundabout information to the edges-files
     375          346 :     if (ec.getRoundabouts().size() > 0) {
     376            6 :         edevice.lf();
     377           12 :         NWWriter_SUMO::writeRoundabouts(edevice, ec.getRoundabouts(), ec);
     378              :     }
     379              : 
     380              :     // write loaded prohibitions to the connections-file
     381         1399 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     382         1226 :         NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions(), ec);
     383              :     }
     384              :     // write pedestrian crossings to the connections-file
     385         1399 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     386         1226 :         const std::vector<NBNode::Crossing*>& crossings = (*it_node).second->getCrossings();
     387         1311 :         for (auto c : crossings) {
     388           85 :             cdevice.openTag(SUMO_TAG_CROSSING);
     389           85 :             cdevice.writeAttr(SUMO_ATTR_NODE, (*it_node).second->getID());
     390           85 :             cdevice.writeAttr(SUMO_ATTR_EDGES, c->edges);
     391           85 :             cdevice.writeAttr(SUMO_ATTR_PRIORITY, c->priority);
     392           85 :             if (c->customWidth != NBEdge::UNSPECIFIED_WIDTH) {
     393           39 :                 cdevice.writeAttr(SUMO_ATTR_WIDTH, c->customWidth);
     394              :             }
     395           85 :             if (c->customTLIndex != -1) {
     396           24 :                 cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX, c->customTLIndex);
     397              :             }
     398           85 :             if (c->customTLIndex2 != -1) {
     399            4 :                 cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX2, c->customTLIndex2);
     400              :             }
     401           85 :             if (c->customShape.size() != 0) {
     402            4 :                 writeShape(cdevice, gch, c->customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     403              :             }
     404           85 :             if (c->outlineShape.size() != 0) {
     405           85 :                 writeShape(cdevice, gch, c->outlineShape, SUMO_ATTR_OUTLINESHAPE, useGeo, geoAccuracy);
     406              :             }
     407           85 :             c->writeParams(cdevice);
     408          170 :             cdevice.closeTag();
     409              :         }
     410         1226 :     }
     411              :     // write custom walkingarea shapes to the connections file
     412         1399 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     413         1233 :         for (const auto& wacs : it_node->second->getWalkingAreaCustomShapes()) {
     414            7 :             cdevice.openTag(SUMO_TAG_WALKINGAREA);
     415            7 :             cdevice.writeAttr(SUMO_ATTR_NODE, it_node->first);
     416           14 :             cdevice.writeAttr(SUMO_ATTR_EDGES, joinNamedToString(wacs.edges, " "));
     417            7 :             if (wacs.shape.size() != 0) {
     418            6 :                 writeShape(cdevice, gch, wacs.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     419              :             }
     420            7 :             if (wacs.width != NBEdge::UNSPECIFIED_WIDTH) {
     421            1 :                 cdevice.writeAttr(SUMO_ATTR_WIDTH, wacs.width);
     422              :             }
     423           14 :             cdevice.closeTag();
     424              :         }
     425              :     }
     426              : 
     427          173 :     edevice.close();
     428          173 :     cdevice.close();
     429          173 : }
     430              : 
     431              : 
     432              : void
     433          173 : NWWriter_XML::writeTrafficLights(const std::string& prefix, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
     434              :     std::map<SumoXMLAttr, std::string> attrs;
     435          173 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     436          346 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".tll.xml");
     437          346 :     device.writeXMLHeader("tlLogics", "tllogic_file.xsd", attrs);
     438          173 :     NWWriter_SUMO::writeTrafficLights(device, tc);
     439              :     // we also need to remember the associations between tlLogics and connections
     440              :     // since the information in con.xml is insufficient
     441         2059 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     442         1886 :         NBEdge* e = (*i).second;
     443              :         // write this edge's tl-controlled connections
     444         1886 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     445         5652 :         for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
     446         3766 :             if (c->tlID != "") {
     447         1065 :                 NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
     448              :             }
     449              :         }
     450         1886 :     }
     451          173 :     device.close();
     452          173 : }
     453              : 
     454              : 
     455              : void
     456            5 : NWWriter_XML::writeJoinedJunctions(const std::string& filename, NBNodeCont& nc) {
     457              :     std::map<SumoXMLAttr, std::string> attrs;
     458            5 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     459            5 :     OutputDevice& device = OutputDevice::getDevice(filename);
     460           10 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
     461              :     const std::vector<std::set<std::string> >& clusters = nc.getJoinedClusters();
     462           10 :     for (std::vector<std::set<std::string> >::const_iterator it = clusters.begin(); it != clusters.end(); it++) {
     463              :         assert((*it).size() > 0);
     464            5 :         device.openTag(SUMO_TAG_JOIN);
     465              :         // prepare string
     466            5 :         std::ostringstream oss;
     467           29 :         for (std::set<std::string>::const_iterator it_id = it->begin(); it_id != it->end(); it_id++) {
     468           24 :             oss << *it_id << " ";
     469              :         }
     470              :         // remove final space
     471              :         std::string ids = oss.str();
     472            5 :         device.writeAttr(SUMO_ATTR_NODES, ids.substr(0, ids.size() - 1));
     473           10 :         device.closeTag();
     474            5 :     }
     475            5 :     device.close();
     476            5 : }
     477              : 
     478              : 
     479              : void
     480            1 : NWWriter_XML::writeStreetSigns(const OptionsCont& oc, NBEdgeCont& ec) {
     481            2 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output"));
     482            2 :     device.writeXMLHeader("additional", "additional_file.xsd");
     483           23 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     484           22 :         NBEdge* e = (*i).second;
     485              :         const std::vector<NBSign>& signs =  e->getSigns();
     486           30 :         for (std::vector<NBSign>::const_iterator it = signs.begin(); it != signs.end(); ++it) {
     487            8 :             it->writeAsPOI(device, e);
     488              :         }
     489              :     }
     490            1 :     device.close();
     491            1 : }
     492              : 
     493              : 
     494              : void
     495           72 : NWWriter_XML::writePTStops(const OptionsCont& oc, NBPTStopCont& sc) {
     496          144 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptstop-output"));
     497          144 :     device.writeXMLHeader("additional", "additional_file.xsd");
     498          816 :     for (const auto& stopIt : sc.getStops()) {
     499          744 :         stopIt.second->write(device);
     500              :     }
     501           72 :     device.close();
     502           72 : }
     503              : 
     504              : 
     505           46 : void NWWriter_XML::writePTLines(const OptionsCont& oc, NBPTLineCont& lc) {
     506           92 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptline-output"));
     507           92 :     device.writeXMLHeader("ptLines", "ptlines_file.xsd");
     508          427 :     for (const auto& item : lc.getLines()) {
     509          381 :         item.second->write(device);
     510              :     }
     511           46 :     device.close();
     512           46 : }
     513              : 
     514              : 
     515            3 : void NWWriter_XML::writeParkingAreas(const OptionsCont& oc, NBParkingCont& pc, NBEdgeCont& ec) {
     516            6 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("parking-output"));
     517            6 :     device.writeXMLHeader("additional", "additional_file.xsd");
     518          297 :     for (NBParking& p : pc) {
     519          294 :         p.write(device, ec);
     520              :     }
     521            3 :     device.close();
     522            3 : }
     523              : 
     524              : 
     525              : void
     526            1 : NWWriter_XML::writeDistricts(const OptionsCont& oc, NBDistrictCont& dc) {
     527            2 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("taz-output"));
     528            2 :     device.writeXMLHeader("additional", "additional_file.xsd");
     529           30 :     for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
     530           29 :         NWWriter_SUMO::writeDistrict(device, *(*i).second);
     531              :     }
     532            1 : }
     533              : 
     534              : 
     535              : void
     536          721 : NWWriter_XML::writeShape(OutputDevice& out, const GeoConvHelper& gch, PositionVector shape, SumoXMLAttr attr, bool useGeo, bool geoAccuracy) {
     537          721 :     if (useGeo) {
     538          322 :         for (int i = 0; i < (int) shape.size(); i++) {
     539          259 :             gch.cartesian2geo(shape[i]);
     540              :         }
     541              :     }
     542          721 :     if (geoAccuracy) {
     543           63 :         out.setPrecision(gPrecisionGeo);
     544              :     }
     545          721 :     out.writeAttr(attr, shape);
     546          721 :     if (geoAccuracy) {
     547           63 :         out.setPrecision();
     548              :     }
     549          721 : }
     550              : 
     551              : 
     552              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1