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

Generated by: LCOV version 2.0-1