LCOV - code coverage report
Current view: top level - src/netwrite - NWWriter_XML.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 283 288 98.3 %
Date: 2024-04-30 15:40:33 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /****************************************************************************/
       2             : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3             : // Copyright (C) 2001-2024 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        1830 : NWWriter_XML::writeNetwork(const OptionsCont& oc, const std::string& prefix, NBNetBuilder& nb) {
      52             :     // check whether plain-output files shall be generated
      53        1830 :     if (prefix != "") {
      54         192 :         writeNodes(oc, prefix, nb.getNodeCont());
      55         190 :         if (nb.getTypeCont().size() > 0) {
      56          18 :             writeTypes(prefix, nb.getEdgeCont(), nb.getTypeCont());
      57             :         }
      58         190 :         writeEdgesAndConnections(oc, prefix, nb.getNodeCont(), nb.getEdgeCont());
      59         190 :         writeTrafficLights(prefix, nb.getTLLogicCont(), nb.getEdgeCont());
      60             :     }
      61        3656 :     if (oc.isSet("junctions.join-output")) {
      62          15 :         writeJoinedJunctions(oc.getString("junctions.join-output"), nb.getNodeCont());
      63             :     }
      64        3656 :     if (oc.isSet("street-sign-output")) {
      65           1 :         writeStreetSigns(oc, nb.getEdgeCont());
      66             :     }
      67        5242 :     if (oc.exists("ptstop-output") && oc.isSet("ptstop-output")) {
      68          66 :         writePTStops(oc, nb.getPTStopCont());
      69             :     }
      70        5262 :     if (oc.exists("ptline-output") && oc.isSet("ptline-output")) {
      71          46 :         writePTLines(oc, nb.getPTLineCont());
      72             :     }
      73             : 
      74        5306 :     if (oc.exists("parking-output") && oc.isSet("parking-output")) {
      75           2 :         writeParkingAreas(oc, nb.getParkingCont(), nb.getEdgeCont());
      76             :     }
      77        5307 :     if (oc.exists("taz-output") && oc.isSet("taz-output")) {
      78           1 :         writeDistricts(oc, nb.getDistrictCont());
      79             :     }
      80        1828 : }
      81             : 
      82             : 
      83             : void
      84         192 : NWWriter_XML::writeNodes(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc) {
      85             :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
      86         568 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
      87         192 :     if (useGeo && !gch.usingGeoProjection()) {
      88           0 :         WRITE_WARNING(TL("Ignoring option \"proj.plain-geo\" because no geo-conversion has been defined"));
      89             :         useGeo = false;
      90             :     }
      91         192 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
      92             : 
      93         382 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".nod.xml");
      94             :     std::map<SumoXMLAttr, std::string> attrs;
      95         190 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
      96         380 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
      97             : 
      98             :     // write network offsets and projection to allow reconstruction of original coordinates
      99         190 :     if (!useGeo) {
     100         184 :         GeoConvHelper::writeLocation(device);
     101             :     }
     102             : 
     103             :     // write nodes
     104         570 :     TrafficLightType tlsDefaultType = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
     105        1677 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     106        1487 :         NBNode* n = (*i).second;
     107        1487 :         device.openTag(SUMO_TAG_NODE);
     108             :         device.writeAttr(SUMO_ATTR_ID, n->getID());
     109             :         // write position
     110        1487 :         Position pos = n->getPosition();
     111        1487 :         if (useGeo) {
     112         106 :             gch.cartesian2geo(pos);
     113             :         }
     114        1487 :         if (geoAccuracy) {
     115         106 :             device.setPrecision(gPrecisionGeo);
     116             :         }
     117        1487 :         NWFrame::writePositionLong(pos, device);
     118        1487 :         if (geoAccuracy) {
     119         106 :             device.setPrecision();
     120             :         }
     121             : 
     122        2974 :         device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
     123        1487 :         if (n->isTLControlled()) {
     124             :             // set may contain multiple programs for the same id.
     125             :             // make sure ids are unique and sorted
     126             :             std::set<std::string> tlsIDs;
     127             :             std::set<std::string> controlledInnerEdges;
     128         135 :             std::string tlType = "";
     129         271 :             for (NBTrafficLightDefinition* tl : n->getControllingTLS()) {
     130             :                 tlsIDs.insert(tl->getID());
     131         136 :                 std::vector<std::string> cie = tl->getControlledInnerEdges();
     132             :                 controlledInnerEdges.insert(cie.begin(), cie.end());
     133         136 :                 if (tl->getType() != tlsDefaultType) {
     134           8 :                     tlType = toString(tl->getType());
     135             :                 }
     136         136 :             }
     137         135 :             std::vector<std::string> sortedIDs(tlsIDs.begin(), tlsIDs.end());
     138         135 :             sort(sortedIDs.begin(), sortedIDs.end());
     139             :             device.writeAttr(SUMO_ATTR_TLID, sortedIDs);
     140         135 :             if (tlType != "") {
     141             :                 device.writeAttr(SUMO_ATTR_TLTYPE, tlType);
     142             :             }
     143         135 :             if (controlledInnerEdges.size() > 0) {
     144           8 :                 std::vector<std::string> sortedCIEs(controlledInnerEdges.begin(), controlledInnerEdges.end());
     145           8 :                 sort(sortedCIEs.begin(), sortedCIEs.end());
     146           8 :                 device.writeAttr(SUMO_ATTR_CONTROLLED_INNER, joinToString(sortedCIEs, " "));
     147           8 :             }
     148         135 :         }
     149        1487 :         if (n->hasCustomShape()) {
     150          28 :             writeShape(device, gch, n->getShape(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     151             :         }
     152        1487 :         if (n->getRadius() != NBNode::UNSPECIFIED_RADIUS) {
     153          18 :             device.writeAttr(SUMO_ATTR_RADIUS, n->getRadius());
     154             :         }
     155        1487 :         if (!n->getKeepClear()) {
     156           0 :             device.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, n->getKeepClear());
     157             :         }
     158        1487 :         if (n->getRightOfWay() != RightOfWay::DEFAULT) {
     159           0 :             device.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n->getRightOfWay()));
     160             :         }
     161        1487 :         if (n->getFringeType() != FringeType::DEFAULT) {
     162           0 :             device.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n->getFringeType()));
     163             :         }
     164        1487 :         if (n->getName() != "") {
     165           8 :             device.writeAttr<std::string>(SUMO_ATTR_NAME, StringUtils::escapeXML(n->getName()));
     166             :         }
     167        1487 :         n->writeParams(device);
     168        2974 :         device.closeTag();
     169             :     }
     170         190 :     device.close();
     171         190 : }
     172             : 
     173             : 
     174             : void
     175          18 : NWWriter_XML::writeTypes(const std::string& prefix, NBEdgeCont& ec, NBTypeCont& tc) {
     176          36 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".typ.xml");
     177             :     std::map<SumoXMLAttr, std::string> attrs;
     178          18 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     179          36 :     device.writeXMLHeader("types", "types_file.xsd", attrs);
     180          18 :     std::set<std::string> usedTypes = ec.getUsedTypes();
     181          18 :     tc.writeEdgeTypes(device, usedTypes);
     182          18 :     device.close();
     183          18 : }
     184             : 
     185             : 
     186             : void
     187         190 : NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc, NBEdgeCont& ec) {
     188             :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     189         564 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
     190         190 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
     191             : 
     192             :     std::map<SumoXMLAttr, std::string> attrs;
     193         190 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     194         380 :     OutputDevice& edevice = OutputDevice::getDevice(prefix + ".edg.xml");
     195         380 :     edevice.writeXMLHeader("edges", "edges_file.xsd", attrs);
     196         380 :     OutputDevice& cdevice = OutputDevice::getDevice(prefix + ".con.xml");
     197         570 :     cdevice.writeXMLHeader("connections", "connections_file.xsd", attrs);
     198         190 :     const bool writeNames = oc.getBool("output.street-names");
     199         190 :     const bool writeLanes = oc.getBool("plain-output.lanes");
     200             : 
     201             :     // write network offsets and projection to allow reconstruction of original coordinates at least for geo-referenced networks
     202         190 :     if (!useGeo && gch.usingGeoProjection()) {
     203          22 :         GeoConvHelper::writeLocation(edevice);
     204             :     }
     205         570 :     LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
     206        2540 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     207             :         // write the edge itself to the edges-files
     208        2350 :         NBEdge* e = (*i).second;
     209        2350 :         edevice.openTag(SUMO_TAG_EDGE);
     210        2350 :         edevice.writeAttr(SUMO_ATTR_ID, e->getID());
     211             :         edevice.writeAttr(SUMO_ATTR_FROM, e->getFromNode()->getID());
     212             :         edevice.writeAttr(SUMO_ATTR_TO, e->getToNode()->getID());
     213        2771 :         if (writeNames && e->getStreetName() != "") {
     214         604 :             edevice.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName()));
     215             :         }
     216        4700 :         edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
     217             :         // write the type if given
     218        2350 :         if (e->getTypeID() != "") {
     219             :             edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID());
     220             :         }
     221        2350 :         edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
     222        2350 :         if (!e->hasLaneSpecificSpeed()) {
     223        4694 :             edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed());
     224             :         }
     225        2350 :         if (!e->hasLaneSpecificFriction()) {
     226        2346 :             if (e->getFriction() != NBEdge::UNSPECIFIED_FRICTION) {
     227           6 :                 edevice.writeAttr(SUMO_ATTR_FRICTION, e->getFriction());
     228             :             }
     229             :         }
     230             :         // write non-default geometry
     231        2350 :         if (!e->hasDefaultGeometry()) {
     232         785 :             writeShape(edevice, gch, e->getGeometry(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     233             :         }
     234             :         // write the spread type if not default ("right")
     235        2350 :         if (e->getLaneSpreadFunction() != defaultSpread) {
     236        1112 :             edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()));
     237             :         }
     238             :         // write the length if it was specified
     239        2350 :         if (e->hasLoadedLength()) {
     240           8 :             edevice.writeAttr(SUMO_ATTR_LENGTH, e->getLoadedLength());
     241             :         }
     242             :         // some attributes can be set by edge default or per lane. Write as default if possible (efficiency)
     243        2350 :         if (e->getLaneWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) {
     244         586 :             edevice.writeAttr(SUMO_ATTR_WIDTH, e->getLaneWidth());
     245             :         }
     246        2350 :         if (e->getEndOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificEndOffset()) {
     247          14 :             edevice.writeAttr(SUMO_ATTR_ENDOFFSET, e->getEndOffset());
     248             :         }
     249        2350 :         if (!e->hasLaneSpecificPermissions()) {
     250        2093 :             writePermissions(edevice, e->getPermissions(0));
     251             :         }
     252        2350 :         if (!e->hasLaneSpecificStopOffsets() && e->getEdgeStopOffset().isDefined()) {
     253           0 :             NWWriter_SUMO::writeStopOffsets(edevice, e->getEdgeStopOffset());
     254             :         }
     255        2350 :         if (e->getDistance() != 0) {
     256           4 :             edevice.writeAttr(SUMO_ATTR_DISTANCE, e->getDistance());
     257             :         }
     258        2350 :         if (e->getBidiEdge() != 0) {
     259          30 :             edevice.writeAttr(SUMO_ATTR_BIDI, e->getBidiEdge()->getID());
     260             :         }
     261        2350 :         if (e->needsLaneSpecificOutput() || writeLanes) {
     262             :             int idx = 0;
     263        1566 :             for (const NBEdge::Lane& lane : e->getLanes()) {
     264        1185 :                 edevice.openTag(SUMO_TAG_LANE);
     265        1185 :                 edevice.writeAttr(SUMO_ATTR_INDEX, idx++);
     266             :                 // write allowed lanes
     267        1185 :                 if (e->hasLaneSpecificPermissions() || writeLanes) {
     268         941 :                     writePermissions(edevice, lane.permissions);
     269             :                 }
     270        1185 :                 writePreferences(edevice, lane.preferred);
     271             :                 // write other attributes
     272        1185 :                 if (lane.width != NBEdge::UNSPECIFIED_WIDTH && (e->hasLaneSpecificWidth() || writeLanes)) {
     273         436 :                     edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width);
     274             :                 }
     275        1185 :                 if (lane.endOffset != NBEdge::UNSPECIFIED_OFFSET && (e->hasLaneSpecificEndOffset() || writeLanes)) {
     276           8 :                     edevice.writeAttr(SUMO_ATTR_ENDOFFSET, lane.endOffset);
     277             :                 }
     278        1185 :                 if (e->hasLaneSpecificSpeed() || writeLanes) {
     279          25 :                     edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed);
     280             :                 }
     281        1185 :                 if (lane.accelRamp) {
     282           1 :                     edevice.writeAttr(SUMO_ATTR_ACCELERATION, lane.accelRamp);
     283             :                 }
     284        1185 :                 if (lane.customShape.size() > 0 || writeLanes) {
     285          42 :                     writeShape(edevice, gch, lane.customShape.size() > 0 ? lane.customShape : lane.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     286             :                 }
     287        1185 :                 if (lane.type != "") {
     288             :                     edevice.writeAttr(SUMO_ATTR_TYPE, lane.type);
     289             :                 }
     290        1185 :                 if (lane.changeLeft != SVCAll && lane.changeLeft != SVC_UNSPECIFIED && lane.changeLeft != SVC_IGNORING) {
     291           6 :                     edevice.writeAttr(SUMO_ATTR_CHANGE_LEFT, getVehicleClassNames(lane.changeLeft));
     292             :                 }
     293        1185 :                 if (lane.changeRight != SVCAll && lane.changeRight != SVC_UNSPECIFIED && lane.changeRight != SVC_IGNORING) {
     294           7 :                     edevice.writeAttr(SUMO_ATTR_CHANGE_RIGHT, getVehicleClassNames(lane.changeRight));
     295             :                 }
     296        1185 :                 if (lane.oppositeID != "") {
     297          85 :                     edevice.openTag(SUMO_TAG_NEIGH);
     298             :                     edevice.writeAttr(SUMO_ATTR_LANE, lane.oppositeID);
     299         170 :                     edevice.closeTag();
     300             :                 }
     301        1185 :                 lane.writeParams(edevice);
     302        1185 :                 NWWriter_SUMO::writeStopOffsets(edevice, lane.laneStopOffset);
     303        2370 :                 edevice.closeTag();
     304             :             }
     305             :         }
     306        2350 :         e->writeParams(edevice);
     307        4700 :         edevice.closeTag();
     308             :         // write this edge's connections to the connections-files
     309        2350 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     310        2350 :         if (connections.empty()) {
     311             :             // if there are no connections and this appears to be customized, preserve the information
     312         428 :             const int numOutgoing = (int)e->getToNode()->getOutgoingEdges().size();
     313         428 :             if (numOutgoing > 0) {
     314         269 :                 const SVCPermissions inPerm = e->getPermissions();
     315             :                 SVCPermissions outPerm = 0;
     316         689 :                 for (auto out : e->getToNode()->getOutgoingEdges()) {
     317         420 :                     outPerm |= out->getPermissions();
     318             :                 }
     319         269 :                 if ((inPerm & outPerm) != 0 && (inPerm & outPerm) != SVC_PEDESTRIAN) {
     320         118 :                     cdevice.openTag(SUMO_TAG_CONNECTION);
     321         118 :                     cdevice.writeAttr(SUMO_ATTR_FROM, e->getID());
     322         118 :                     cdevice.closeTag();
     323         118 :                     cdevice << "\n";
     324             :                 }
     325             :             }
     326             :         } else {
     327        6671 :             for (NBEdge::Connection c : connections) {
     328        4749 :                 if (useGeo) {
     329         414 :                     for (Position& p : c.customShape) {
     330           3 :                         gch.cartesian2geo(p);
     331             :                     }
     332             :                 }
     333        4749 :                 NWWriter_SUMO::writeConnection(cdevice, *e, c, false, NWWriter_SUMO::PLAIN, geoAccuracy);
     334        4749 :             }
     335        1922 :             cdevice << "\n";
     336             :         }
     337        2350 :     }
     338             :     // write roundabout information to the edges-files
     339         380 :     if (ec.getRoundabouts().size() > 0) {
     340           6 :         edevice.lf();
     341          12 :         NWWriter_SUMO::writeRoundabouts(edevice, ec.getRoundabouts(), ec);
     342             :     }
     343             : 
     344             :     // write loaded prohibitions to the connections-file
     345        1677 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     346        1487 :         NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions());
     347             :     }
     348             :     // write pedestrian crossings to the connections-file
     349        1677 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     350        1487 :         const std::vector<NBNode::Crossing*>& crossings = (*it_node).second->getCrossings();
     351        1567 :         for (auto c : crossings) {
     352          80 :             cdevice.openTag(SUMO_TAG_CROSSING);
     353          80 :             cdevice.writeAttr(SUMO_ATTR_NODE, (*it_node).second->getID());
     354          80 :             cdevice.writeAttr(SUMO_ATTR_EDGES, c->edges);
     355          80 :             cdevice.writeAttr(SUMO_ATTR_PRIORITY, c->priority);
     356          80 :             if (c->customWidth != NBEdge::UNSPECIFIED_WIDTH) {
     357          42 :                 cdevice.writeAttr(SUMO_ATTR_WIDTH, c->customWidth);
     358             :             }
     359          80 :             if (c->customTLIndex != -1) {
     360          28 :                 cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX, c->customTLIndex);
     361             :             }
     362          80 :             if (c->customTLIndex2 != -1) {
     363           4 :                 cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX2, c->customTLIndex2);
     364             :             }
     365          80 :             if (c->customShape.size() != 0) {
     366           4 :                 writeShape(cdevice, gch, c->customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     367             :             }
     368          80 :             if (c->outlineShape.size() != 0) {
     369          80 :                 writeShape(cdevice, gch, c->outlineShape, SUMO_ATTR_OUTLINESHAPE, useGeo, geoAccuracy);
     370             :             }
     371          80 :             c->writeParams(cdevice);
     372         160 :             cdevice.closeTag();
     373             :         }
     374             :     }
     375             :     // write custom walkingarea shapes to the connections file
     376        1677 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     377        1494 :         for (const auto& wacs : it_node->second->getWalkingAreaCustomShapes()) {
     378           7 :             cdevice.openTag(SUMO_TAG_WALKINGAREA);
     379           7 :             cdevice.writeAttr(SUMO_ATTR_NODE, it_node->first);
     380          14 :             cdevice.writeAttr(SUMO_ATTR_EDGES, joinNamedToString(wacs.edges, " "));
     381           7 :             if (wacs.shape.size() != 0) {
     382           6 :                 writeShape(cdevice, gch, wacs.shape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     383             :             }
     384           7 :             if (wacs.width != NBEdge::UNSPECIFIED_WIDTH) {
     385           1 :                 cdevice.writeAttr(SUMO_ATTR_WIDTH, wacs.width);
     386             :             }
     387          14 :             cdevice.closeTag();
     388             :         }
     389             :     }
     390             : 
     391         190 :     edevice.close();
     392         190 :     cdevice.close();
     393         190 : }
     394             : 
     395             : 
     396             : void
     397         190 : NWWriter_XML::writeTrafficLights(const std::string& prefix, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
     398             :     std::map<SumoXMLAttr, std::string> attrs;
     399         190 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     400         380 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".tll.xml");
     401         570 :     device.writeXMLHeader("tlLogics", "tllogic_file.xsd", attrs);
     402         190 :     NWWriter_SUMO::writeTrafficLights(device, tc);
     403             :     // we also need to remember the associations between tlLogics and connections
     404             :     // since the information in con.xml is insufficient
     405        2540 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     406        2350 :         NBEdge* e = (*i).second;
     407             :         // write this edge's tl-controlled connections
     408        2350 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     409        7099 :         for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
     410        4749 :             if (c->tlID != "") {
     411        1373 :                 NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
     412             :             }
     413             :         }
     414        2350 :     }
     415         190 :     device.close();
     416         190 : }
     417             : 
     418             : 
     419             : void
     420           5 : NWWriter_XML::writeJoinedJunctions(const std::string& filename, NBNodeCont& nc) {
     421             :     std::map<SumoXMLAttr, std::string> attrs;
     422           5 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     423           5 :     OutputDevice& device = OutputDevice::getDevice(filename);
     424          10 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
     425             :     const std::vector<std::set<std::string> >& clusters = nc.getJoinedClusters();
     426          10 :     for (std::vector<std::set<std::string> >::const_iterator it = clusters.begin(); it != clusters.end(); it++) {
     427             :         assert((*it).size() > 0);
     428           5 :         device.openTag(SUMO_TAG_JOIN);
     429             :         // prepare string
     430           5 :         std::ostringstream oss;
     431          29 :         for (std::set<std::string>::const_iterator it_id = it->begin(); it_id != it->end(); it_id++) {
     432          24 :             oss << *it_id << " ";
     433             :         }
     434             :         // remove final space
     435             :         std::string ids = oss.str();
     436           5 :         device.writeAttr(SUMO_ATTR_NODES, ids.substr(0, ids.size() - 1));
     437          10 :         device.closeTag();
     438           5 :     }
     439           5 :     device.close();
     440           5 : }
     441             : 
     442             : 
     443             : void
     444           1 : NWWriter_XML::writeStreetSigns(const OptionsCont& oc, NBEdgeCont& ec) {
     445           3 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output"));
     446           3 :     device.writeXMLHeader("additional", "additional_file.xsd");
     447          23 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     448          22 :         NBEdge* e = (*i).second;
     449             :         const std::vector<NBSign>& signs =  e->getSigns();
     450          30 :         for (std::vector<NBSign>::const_iterator it = signs.begin(); it != signs.end(); ++it) {
     451           8 :             it->writeAsPOI(device, e);
     452             :         }
     453             :     }
     454           1 :     device.close();
     455           1 : }
     456             : 
     457             : 
     458             : void
     459          66 : NWWriter_XML::writePTStops(const OptionsCont& oc, NBPTStopCont& sc) {
     460         132 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptstop-output"));
     461         198 :     device.writeXMLHeader("additional", "additional_file.xsd");
     462         999 :     for (const auto& stopIt : sc.getStops()) {
     463         933 :         stopIt.second->write(device);
     464             :     }
     465          66 :     device.close();
     466          66 : }
     467             : 
     468             : 
     469          46 : void NWWriter_XML::writePTLines(const OptionsCont& oc, NBPTLineCont& lc) {
     470          92 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptline-output"));
     471         138 :     device.writeXMLHeader("ptLines", "ptlines_file.xsd");
     472         483 :     for (const auto& item : lc.getLines()) {
     473         437 :         item.second->write(device);
     474             :     }
     475          46 :     device.close();
     476          46 : }
     477             : 
     478             : 
     479           2 : void NWWriter_XML::writeParkingAreas(const OptionsCont& oc, NBParkingCont& pc, NBEdgeCont& ec) {
     480           4 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("parking-output"));
     481           6 :     device.writeXMLHeader("additional", "additional_file.xsd");
     482         276 :     for (NBParking& p : pc) {
     483         274 :         p.write(device, ec);
     484             :     }
     485           2 :     device.close();
     486           2 : }
     487             : 
     488             : 
     489             : void
     490           1 : NWWriter_XML::writeDistricts(const OptionsCont& oc, NBDistrictCont& dc) {
     491           2 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("taz-output"));
     492           3 :     device.writeXMLHeader("additional", "additional_file.xsd");
     493          30 :     for (std::map<std::string, NBDistrict*>::const_iterator i = dc.begin(); i != dc.end(); i++) {
     494          29 :         NWWriter_SUMO::writeDistrict(device, *(*i).second);
     495             :     }
     496           1 : }
     497             : 
     498             : 
     499             : void
     500         910 : NWWriter_XML::writeShape(OutputDevice& out, const GeoConvHelper& gch, PositionVector shape, SumoXMLAttr attr, bool useGeo, bool geoAccuracy) {
     501         910 :     if (useGeo) {
     502         322 :         for (int i = 0; i < (int) shape.size(); i++) {
     503         259 :             gch.cartesian2geo(shape[i]);
     504             :         }
     505             :     }
     506         910 :     if (geoAccuracy) {
     507          63 :         out.setPrecision(gPrecisionGeo);
     508             :     }
     509             :     out.writeAttr(attr, shape);
     510         910 :     if (geoAccuracy) {
     511          63 :         out.setPrecision();
     512             :     }
     513         910 : }
     514             : 
     515             : 
     516             : /****************************************************************************/

Generated by: LCOV version 1.14