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

Generated by: LCOV version 2.0-1