LCOV - code coverage report
Current view: top level - src/netwrite - NWWriter_XML.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 98.5 % 271 267
Test Date: 2026-10-12 15:53:19 Functions: 100.0 % 12 12

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 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_DlrNavteq.h"
      42              : #include "NWWriter_XML.h"
      43              : 
      44              : 
      45              : // ===========================================================================
      46              : // method definitions
      47              : // ===========================================================================
      48              : // ---------------------------------------------------------------------------
      49              : // static methods
      50              : // ---------------------------------------------------------------------------
      51              : void
      52         2198 : NWWriter_XML::writeNetwork(const OptionsCont& oc, const std::string& prefix, NBNetBuilder& nb) {
      53              :     // check whether plain-output files shall be generated
      54         2198 :     if (prefix != "") {
      55          187 :         const bool haveTypes = nb.getTypeCont().size() > 0;
      56          187 :         writeNodes(oc, prefix, nb.getNodeCont());
      57          185 :         if (haveTypes) {
      58           22 :             writeTypes(prefix, nb.getEdgeCont(), nb.getTypeCont());
      59              :         }
      60          185 :         writeEdgesAndConnections(oc, prefix, nb.getNodeCont(), nb.getEdgeCont());
      61          185 :         writeTrafficLights(prefix, nb.getTLLogicCont(), nb.getEdgeCont());
      62          185 :         writeConfig(oc, prefix, haveTypes);
      63              :     }
      64         2206 :     if (oc.isSet("junctions.join-output") && (oc.getString("junctions.join-output").size() > 0)) {
      65           10 :         writeJoinedJunctions(oc.getString("junctions.join-output"), nb.getNodeCont());
      66              :     }
      67         2198 :     if (oc.isSet("street-sign-output") && (oc.getString("street-sign-output").size() > 0)) {
      68            1 :         writeStreetSigns(oc, nb.getEdgeCont());
      69              :     }
      70         4471 :     if (oc.exists("ptstop-output") && oc.isSet("ptstop-output") && (oc.getString("ptstop-output").size() > 0)) {
      71           82 :         writePTStops(oc, nb.getPTStopCont());
      72              :     }
      73         4411 :     if (oc.exists("ptline-output") && oc.isSet("ptline-output") && (oc.getString("ptline-output").size() > 0)) {
      74           52 :         writePTLines(oc, nb.getPTLineCont());
      75              :     }
      76         4313 :     if (oc.exists("parking-output") && oc.isSet("parking-output") && (oc.getString("parking-output").size() > 0)) {
      77            3 :         writeParkingAreas(oc, nb.getParkingCont(), nb.getEdgeCont());
      78              :     }
      79         4309 :     if (oc.exists("taz-output") && oc.isSet("taz-output") && (oc.getString("taz-output").size() > 0)) {
      80            1 :         writeDistricts(oc, nb.getDistrictCont());
      81              :     }
      82         2196 : }
      83              : 
      84              : 
      85              : void
      86          185 : NWWriter_XML::writeConfig(const OptionsCont& oc, const std::string& prefix, bool haveTypes) {
      87          370 :     if (!oc.exists("node-files")) {
      88              :         // do not write configuration for netgen
      89            1 :         return;
      90              :     }
      91          184 :     const std::string ext = oc.getString("output.format");
      92          184 :     OptionsCont* tmp = oc.clone();
      93          552 :     tmp->set("node-files", prefix + ".nod." + ext);
      94          552 :     tmp->set("edge-files", prefix + ".edg." + ext);
      95          552 :     tmp->set("connection-files", prefix + ".con." + ext);
      96          552 :     tmp->set("tllogic-files", prefix + ".tll." + ext);
      97          184 :     if (haveTypes) {
      98           88 :         tmp->set("type-files", prefix + ".typ." + ext);
      99              :     }
     100          368 :     tmp->setDefault("sumo-net-file", "");
     101          368 :     tmp->setDefault("plain-output-prefix", "");
     102              : 
     103          184 :     const std::string configPath = prefix + ".netccfg";
     104          184 :     std::ofstream out(configPath.c_str());
     105          184 :     if (!out.good()) {
     106            0 :         delete tmp;
     107            0 :         throw ProcessError(TLF("Could not save configuration to '%'", configPath));
     108              :     } else {
     109          368 :         tmp->writeConfiguration(out, true, false, false);
     110              :     }
     111          184 :     delete tmp;
     112          184 : }
     113              : 
     114              : 
     115              : void
     116          187 : NWWriter_XML::writeNodes(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc) {
     117          187 :     const std::string ext = oc.getString("output.format");
     118              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     119          372 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
     120          187 :     if (useGeo && !gch.usingGeoProjection()) {
     121            0 :         WRITE_WARNING(TL("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"));
     122              :         useGeo = false;
     123              :     }
     124          187 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
     125              : 
     126          561 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".nod." + ext);
     127              :     std::map<SumoXMLAttr, std::string> attrs;
     128          185 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     129          370 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
     130              : 
     131              :     // write network offsets and projection to allow reconstruction of original coordinates
     132          185 :     if (!useGeo) {
     133          179 :         GeoConvHelper::writeLocation(device);
     134              :     }
     135              : 
     136              :     // write nodes
     137          370 :     TrafficLightType tlsDefaultType = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
     138         4962 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     139         4777 :         NBNode* n = (*i).second;
     140         4777 :         device.openTag(SUMO_TAG_NODE);
     141         4777 :         device.writeAttr(SUMO_ATTR_ID, n->getID());
     142              :         // write position
     143         4777 :         Position pos = n->getPosition();
     144         4777 :         if (useGeo) {
     145          158 :             gch.cartesian2geo(pos);
     146              :         }
     147         4777 :         if (geoAccuracy) {
     148          158 :             device.setPrecision(gPrecisionGeo);
     149              :         }
     150         4777 :         NWFrame::writePositionLong(pos, device);
     151         4777 :         if (geoAccuracy) {
     152          158 :             device.setPrecision();
     153              :         }
     154              : 
     155         4777 :         device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
     156              :         // std::set is already sorted, so the output is stable
     157              :         std::set<std::string> tlsIDs;
     158              :         std::set<std::string> controlledInnerEdges;
     159         4777 :         std::string tlType = "";
     160         4980 :         for (NBTrafficLightDefinition* tl : n->getControllingTLS()) {
     161              :             tlsIDs.insert(tl->getID());
     162          203 :             std::vector<std::string> cie = tl->getControlledInnerEdges();
     163              :             controlledInnerEdges.insert(cie.begin(), cie.end());
     164          203 :             if (tl->getType() != tlsDefaultType) {
     165          198 :                 tlType = toString(tl->getType());
     166              :             }
     167          203 :         }
     168         4777 :         device.writeOptionalAttr(SUMO_ATTR_TLID, tlsIDs, tlsIDs.empty());
     169         9554 :         device.writeOptionalAttr(SUMO_ATTR_TLTYPE, tlType, tlType == "");
     170         4777 :         device.writeOptionalAttr(SUMO_ATTR_CONTROLLED_INNER, controlledInnerEdges, controlledInnerEdges.empty());
     171         9554 :         NWWriter_SUMO::writeShape(device, gch, n->getShape(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy, n->hasCustomShape());
     172         9554 :         device.writeOptionalAttr(SUMO_ATTR_RADIUS, n->getRadius(), n->getRadius() == NBNode::UNSPECIFIED_RADIUS);
     173         9554 :         device.writeOptionalAttr<bool>(SUMO_ATTR_KEEP_CLEAR, n->getKeepClear(), n->getKeepClear());
     174         9554 :         device.writeOptionalAttr(SUMO_ATTR_RIGHT_OF_WAY, toString(n->getRightOfWay()), n->getRightOfWay() == RightOfWay::DEFAULT);
     175         9554 :         device.writeOptionalAttr(SUMO_ATTR_FRINGE, toString(n->getFringeType()), n->getFringeType() == FringeType::DEFAULT);
     176         9554 :         device.writeOptionalAttr(SUMO_ATTR_ROUNDABOUT, toString(n->getRoundaboutType()), n->getRoundaboutType() == RoundaboutType::DEFAULT);
     177         9554 :         device.writeOptionalAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(n->getName()), n->getName() == "");
     178         4777 :         n->writeParams(device);
     179         9554 :         device.closeTag();
     180              :     }
     181          185 :     device.close();
     182          185 : }
     183              : 
     184              : 
     185              : void
     186           22 : NWWriter_XML::writeTypes(const std::string& prefix, NBEdgeCont& ec, NBTypeCont& tc) {
     187           22 :     const std::string ext = OptionsCont::getOptions().getString("output.format");
     188           66 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".typ." + ext);
     189              :     std::map<SumoXMLAttr, std::string> attrs;
     190           22 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     191           44 :     device.writeXMLHeader(toString(SUMO_TAG_TYPES), "types_file.xsd", attrs);
     192           22 :     std::set<std::string> usedTypes = ec.getUsedTypes();
     193           22 :     tc.writeEdgeTypes(device, usedTypes);
     194           22 :     device.close();
     195           22 : }
     196              : 
     197              : 
     198              : void
     199          185 : NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc, NBEdgeCont& ec) {
     200          185 :     const std::string ext = oc.getString("output.format");
     201              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     202          369 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
     203          185 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
     204          370 :     const bool dlrNavteq = oc.exists("dlr-navteq.plain") && oc.getBool("dlr-navteq.plain");
     205              : 
     206              :     std::map<SumoXMLAttr, std::string> attrs;
     207          185 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     208          555 :     OutputDevice& edevice = OutputDevice::getDevice(prefix + ".edg." + ext);
     209          370 :     edevice.writeXMLHeader("edges", "edges_file.xsd", attrs);
     210          555 :     OutputDevice& cdevice = OutputDevice::getDevice(prefix + ".con." + ext);
     211          370 :     cdevice.writeXMLHeader("connections", "connections_file.xsd", attrs);
     212          185 :     const bool writeNames = oc.getBool("output.street-names");
     213          185 :     const bool writeLanes = oc.getBool("plain-output.lanes");
     214              : 
     215              :     // write network offsets and projection to allow reconstruction of original coordinates at least for geo-referenced networks
     216          185 :     if (!useGeo && gch.usingGeoProjection()) {
     217           28 :         GeoConvHelper::writeLocation(edevice);
     218              :     }
     219          370 :     LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
     220         8449 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     221              :         // write the edge itself to the edges-files
     222         8264 :         NBEdge* e = (*i).second;
     223         8264 :         edevice.openTag(SUMO_TAG_EDGE);
     224         8264 :         edevice.writeAttr(SUMO_ATTR_ID, e->getID());
     225         8264 :         edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID());
     226         8264 :         edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID());
     227        16528 :         edevice.writeOptionalAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName()), !writeNames || e->getStreetName() == "");
     228         8264 :         edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
     229              :         // write the type if given
     230        16528 :         edevice.writeOptionalAttr(SUMO_ATTR_TYPE, e->getTypeID(), e->getTypeID() == "");
     231        16528 :         edevice.writeOptionalAttr(SUMO_ATTR_ROUTINGTYPE, e->getRoutingType(), e->getRoutingType() == "");
     232         8264 :         edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
     233        16528 :         edevice.writeOptionalAttr(SUMO_ATTR_SPEED, e->getSpeed(), e->hasLaneSpecificSpeed());
     234        16525 :         edevice.writeOptionalAttr(SUMO_ATTR_FRICTION, e->getFriction(), e->getFriction() == NBEdge::UNSPECIFIED_FRICTION || e->hasLaneSpecificFriction());
     235              :         // write non-default geometry
     236         8264 :         NWWriter_SUMO::writeShape(edevice, gch, e->getGeometry(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy, !e->hasDefaultGeometry());
     237              :         // write the spread type if not default ("right")
     238        16528 :         edevice.writeOptionalAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()), e->getLaneSpreadFunction() == defaultSpread);
     239              :         // write the length if it was specified
     240        24789 :         edevice.writeOptionalAttr(SUMO_ATTR_LENGTH, e->getLoadedLength(), !e->hasLoadedLength());
     241              :         // some attributes can be set by edge default or per lane. Write as default if possible (efficiency)
     242        22175 :         edevice.writeOptionalAttr(SUMO_ATTR_WIDTH, e->getLaneWidth(), e->getLaneWidth() == NBEdge::UNSPECIFIED_WIDTH || e->hasLaneSpecificWidth());
     243        16521 :         edevice.writeOptionalAttr(SUMO_ATTR_ENDOFFSET, e->getEndOffset(), e->getEndOffset() == NBEdge::UNSPECIFIED_OFFSET || e->hasLaneSpecificEndOffset());
     244              :         // SVC_UNSPECIFIED is here a shortcut for do not write
     245         8264 :         writePermissions(edevice, e->hasLaneSpecificPermissions() ? SVC_UNSPECIFIED : e->getPermissions(0));
     246         8264 :         if (!e->hasLaneSpecificStopOffsets() && e->getEdgeStopOffset().isDefined()) {
     247            0 :             NWWriter_SUMO::writeStopOffsets(edevice, e->getEdgeStopOffset());
     248              :         }
     249         8264 :         edevice.writeOptionalAttr(SUMO_ATTR_DISTANCE, e->getDistance(), e->getDistance() == 0);
     250        16528 :         edevice.writeOptionalAttr(SUMO_ATTR_BIDI, e->getBidiEdge() == nullptr ? "" : e->getBidiEdge()->getID(), e->getBidiEdge() == nullptr);
     251         8264 :         if (dlrNavteq) {
     252           84 :             NWWriter_DlrNavteq::writeEdgeAttrs(edevice, e);
     253              :         }
     254         8264 :         if (e->needsLaneSpecificOutput() || writeLanes) {
     255              :             int idx = 0;
     256        14859 :             for (const NBEdge::Lane& lane : e->getLanes()) {
     257         9059 :                 edevice.openTag(SUMO_TAG_LANE);
     258         9059 :                 edevice.writeAttr(SUMO_ATTR_INDEX, idx++);
     259         9059 :                 writePermissions(edevice, e->hasLaneSpecificPermissions() || writeLanes ? lane.permissions : SVC_UNSPECIFIED);
     260         9059 :                 writePreferences(edevice, lane.preferred);
     261        15519 :                 edevice.writeOptionalAttr(SUMO_ATTR_WIDTH, lane.width, lane.width == NBEdge::UNSPECIFIED_WIDTH || !(e->hasLaneSpecificWidth() || writeLanes));
     262        18110 :                 edevice.writeOptionalAttr(SUMO_ATTR_ENDOFFSET, lane.endOffset, lane.endOffset == NBEdge::UNSPECIFIED_OFFSET || !(e->hasLaneSpecificEndOffset() || writeLanes));
     263         9084 :                 edevice.writeOptionalAttr(SUMO_ATTR_SPEED, lane.speed, !(e->hasLaneSpecificSpeed() || writeLanes));
     264        18118 :                 edevice.writeOptionalAttr(SUMO_ATTR_ACCELERATION, lane.accelRamp, !lane.accelRamp);
     265        18123 :                 NWWriter_SUMO::writeShape(edevice, gch, lane.customShape.size() > 0 ? lane.customShape : lane.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, lane.customShape.size() > 0 || writeLanes);
     266         9059 :                 edevice.writeOptionalAttr(SUMO_ATTR_TYPE, lane.type, lane.type == "");
     267         9059 :                 const bool changeLeft = (lane.changeLeft != SVCAll && lane.changeLeft != SVC_UNSPECIFIED && lane.changeLeft != SVC_IGNORING);
     268         9059 :                 edevice.writeOptionalAttr(SUMO_ATTR_CHANGE_LEFT, getVehicleClassNames(lane.changeLeft), !changeLeft);
     269         9059 :                 const bool changeRight = (lane.changeRight != SVCAll && lane.changeRight != SVC_UNSPECIFIED && lane.changeRight != SVC_IGNORING);
     270         9059 :                 edevice.writeOptionalAttr(SUMO_ATTR_CHANGE_RIGHT, getVehicleClassNames(lane.changeRight), !changeRight);
     271         9059 :                 if (lane.oppositeID != "") {
     272           47 :                     edevice.openTag(SUMO_TAG_NEIGH);
     273           47 :                     edevice.writeAttr(SUMO_ATTR_LANE, lane.oppositeID);
     274           94 :                     edevice.closeTag();
     275              :                 }
     276         9059 :                 lane.writeParams(edevice);
     277         9059 :                 NWWriter_SUMO::writeStopOffsets(edevice, lane.laneStopOffset);
     278        18118 :                 edevice.closeTag();
     279              :             }
     280              :         }
     281         8264 :         e->writeParams(edevice);
     282        16528 :         edevice.closeTag();
     283              :         // write this edge's connections to the connections-files
     284         8264 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     285         8264 :         if (connections.empty()) {
     286              :             // if there are no connections and this appears to be customized, preserve the information
     287         2596 :             const int numOutgoing = (int)e->getToNode()->getOutgoingEdges().size();
     288         2596 :             if (numOutgoing > 0) {
     289         1874 :                 const SVCPermissions inPerm = e->getPermissions();
     290              :                 SVCPermissions outPerm = 0;
     291         5464 :                 for (auto out : e->getToNode()->getOutgoingEdges()) {
     292         3590 :                     outPerm |= out->getPermissions();
     293              :                 }
     294         1874 :                 if ((inPerm & outPerm) != 0 && (inPerm & outPerm) != SVC_PEDESTRIAN) {
     295          182 :                     cdevice.openTag(SUMO_TAG_CONNECTION);
     296          182 :                     cdevice.writeAttr(SUMO_ATTR_FROM, e->getID());
     297          182 :                     cdevice.closeTag();
     298          182 :                     cdevice.lf();
     299              :                 }
     300              :             }
     301              :         } else {
     302        19676 :             for (NBEdge::Connection c : connections) {
     303        27914 :                 NWWriter_SUMO::writeConnection(cdevice, *e, c, false, dlrNavteq ? NWWriter_SUMO::PLAIN_NAVTEQ : NWWriter_SUMO::PLAIN, useGeo, geoAccuracy);
     304        14008 :             }
     305         5668 :             cdevice.lf();
     306              :         }
     307         8264 :     }
     308              :     // write roundabout information to the edges-files
     309          370 :     if (ec.getRoundabouts().size() > 0) {
     310            8 :         edevice.lf();
     311           16 :         NWWriter_SUMO::writeRoundabouts(edevice, ec.getRoundabouts(), ec);
     312              :     }
     313              : 
     314              :     // write loaded prohibitions to the connections-file
     315         4962 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     316         4777 :         NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions(), ec);
     317              :     }
     318              :     // write pedestrian crossings to the connections-file
     319         4962 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     320         4777 :         const std::vector<NBNode::Crossing*>& crossings = (*it_node).second->getCrossings();
     321         6098 :         for (auto c : crossings) {
     322         1321 :             cdevice.openTag(SUMO_TAG_CROSSING);
     323         1321 :             cdevice.writeAttr(SUMO_ATTR_NODE, (*it_node).second->getID());
     324         1321 :             cdevice.writeAttr(SUMO_ATTR_EDGES, c->edges);
     325         1321 :             cdevice.writeAttr(SUMO_ATTR_PRIORITY, c->priority);
     326         1321 :             cdevice.writeOptionalAttr(SUMO_ATTR_WIDTH, c->customWidth, c->customWidth == NBEdge::UNSPECIFIED_WIDTH);
     327         1321 :             cdevice.writeOptionalAttr(SUMO_ATTR_TLLINKINDEX, c->customTLIndex, c->customTLIndex == -1);
     328         2642 :             cdevice.writeOptionalAttr(SUMO_ATTR_TLLINKINDEX2, c->customTLIndex2, c->customTLIndex2 == -1);
     329         1321 :             NWWriter_SUMO::writeShape(cdevice, gch, c->customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, c->customShape.size() != 0);
     330         1321 :             NWWriter_SUMO::writeShape(cdevice, gch, c->outlineShape, SUMO_ATTR_OUTLINESHAPE, useGeo, geoAccuracy, c->outlineShape.size() != 0);
     331         1321 :             c->writeParams(cdevice);
     332         2642 :             cdevice.closeTag();
     333              :         }
     334         4777 :     }
     335              :     // write custom walkingarea shapes to the connections file
     336         4962 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     337         4784 :         for (const auto& wacs : it_node->second->getWalkingAreaCustomShapes()) {
     338            7 :             cdevice.openTag(SUMO_TAG_WALKINGAREA);
     339            7 :             cdevice.writeAttr(SUMO_ATTR_NODE, it_node->first);
     340            7 :             cdevice.writeAttr(SUMO_ATTR_EDGES, joinNamedToString(wacs.edges, " "));
     341            7 :             NWWriter_SUMO::writeShape(cdevice, gch, wacs.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy, wacs.shape.size() != 0);
     342            7 :             cdevice.writeOptionalAttr(SUMO_ATTR_WIDTH, wacs.width, wacs.width == NBEdge::UNSPECIFIED_WIDTH);
     343           14 :             cdevice.closeTag();
     344              :         }
     345              :     }
     346              : 
     347          185 :     edevice.close();
     348          185 :     cdevice.close();
     349          185 : }
     350              : 
     351              : 
     352              : void
     353          185 : NWWriter_XML::writeTrafficLights(const std::string& prefix, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
     354          370 :     const std::string ext = OptionsCont::getOptions().getString("output.format");
     355              :     std::map<SumoXMLAttr, std::string> attrs;
     356          185 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     357          555 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".tll." + ext);
     358          370 :     device.writeXMLHeader("tlLogics", "tllogic_file.xsd", attrs);
     359          185 :     const OptionsCont& oc = OptionsCont::getOptions();
     360          370 :     const bool dlrNavteq = oc.exists("dlr-navteq.plain") && oc.getBool("dlr-navteq.plain");
     361          368 :     NWWriter_SUMO::writeTrafficLights(device, tc, dlrNavteq ? NWWriter_SUMO::PLAIN_NAVTEQ : NWWriter_SUMO::PLAIN);
     362              :     // we also need to remember the associations between tlLogics and connections
     363              :     // since the information in con.xml is insufficient
     364         8449 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     365         8264 :         NBEdge* e = (*i).second;
     366              :         // write this edge's tl-controlled connections
     367         8264 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     368        22272 :         for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
     369        14008 :             if (c->tlID != "") {
     370         2301 :                 NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
     371              :             }
     372              :         }
     373         8264 :     }
     374          185 :     device.close();
     375          185 : }
     376              : 
     377              : 
     378              : void
     379            5 : NWWriter_XML::writeJoinedJunctions(const std::string& filename, NBNodeCont& nc) {
     380              :     std::map<SumoXMLAttr, std::string> attrs;
     381            5 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     382            5 :     OutputDevice& device = OutputDevice::getDevice(filename);
     383           10 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
     384           10 :     for (const std::set<std::string>& joined : nc.getJoinedClusters()) {
     385              :         assert(joined.size() > 0);
     386           10 :         device.openTag(SUMO_TAG_JOIN).writeAttr(SUMO_ATTR_NODES, joined).closeTag();
     387              :     }
     388            5 :     device.close();
     389            5 : }
     390              : 
     391              : 
     392              : void
     393            1 : NWWriter_XML::writeStreetSigns(const OptionsCont& oc, NBEdgeCont& ec) {
     394            2 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output"));
     395            2 :     device.writeXMLHeader("additional", "additional_file.xsd");
     396           23 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     397           22 :         NBEdge* e = (*i).second;
     398              :         const std::vector<NBSign>& signs =  e->getSigns();
     399           30 :         for (std::vector<NBSign>::const_iterator it = signs.begin(); it != signs.end(); ++it) {
     400            8 :             it->writeAsPOI(device, e);
     401              :         }
     402              :     }
     403            1 :     device.close();
     404            1 : }
     405              : 
     406              : 
     407              : void
     408           82 : NWWriter_XML::writePTStops(const OptionsCont& oc, NBPTStopCont& sc) {
     409          164 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptstop-output"));
     410          164 :     device.writeXMLHeader("additional", "additional_file.xsd");
     411          894 :     for (const auto& stopIt : sc.getStops()) {
     412          812 :         stopIt.second->write(device);
     413              :     }
     414           82 :     device.close();
     415           82 : }
     416              : 
     417              : 
     418           52 : void NWWriter_XML::writePTLines(const OptionsCont& oc, NBPTLineCont& lc) {
     419          104 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptline-output"));
     420          104 :     device.writeXMLHeader("ptLines", "ptlines_file.xsd");
     421          448 :     for (const auto& item : lc.getLines()) {
     422          396 :         item.second->write(device);
     423              :     }
     424           52 :     device.close();
     425           52 : }
     426              : 
     427              : 
     428            3 : void NWWriter_XML::writeParkingAreas(const OptionsCont& oc, NBParkingCont& pc, NBEdgeCont& ec) {
     429            6 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("parking-output"));
     430            6 :     device.writeXMLHeader("additional", "additional_file.xsd");
     431          297 :     for (NBParking& p : pc) {
     432          294 :         p.write(device, ec);
     433              :     }
     434            3 :     device.close();
     435            3 : }
     436              : 
     437              : 
     438              : void
     439            1 : NWWriter_XML::writeDistricts(const OptionsCont& oc, NBDistrictCont& dc) {
     440            2 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("taz-output"));
     441            2 :     device.writeXMLHeader("additional", "additional_file.xsd");
     442           30 :     for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
     443           29 :         NWWriter_SUMO::writeDistrict(device, *(*i).second);
     444              :     }
     445            1 : }
     446              : 
     447              : 
     448              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1