LCOV - code coverage report
Current view: top level - src/netwrite - NWWriter_XML.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 98.3 % 289 284
Test Date: 2024-11-22 15:46:21 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-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         1689 : NWWriter_XML::writeNetwork(const OptionsCont& oc, const std::string& prefix, NBNetBuilder& nb) {
      52              :     // check whether plain-output files shall be generated
      53         1689 :     if (prefix != "") {
      54          164 :         writeNodes(oc, prefix, nb.getNodeCont());
      55          162 :         if (nb.getTypeCont().size() > 0) {
      56           14 :             writeTypes(prefix, nb.getEdgeCont(), nb.getTypeCont());
      57              :         }
      58          162 :         writeEdgesAndConnections(oc, prefix, nb.getNodeCont(), nb.getEdgeCont());
      59          162 :         writeTrafficLights(prefix, nb.getTLLogicCont(), nb.getEdgeCont());
      60              :     }
      61         3374 :     if (oc.isSet("junctions.join-output")) {
      62           10 :         writeJoinedJunctions(oc.getString("junctions.join-output"), nb.getNodeCont());
      63              :     }
      64         3374 :     if (oc.isSet("street-sign-output")) {
      65            1 :         writeStreetSigns(oc, nb.getEdgeCont());
      66              :     }
      67         3290 :     if (oc.exists("ptstop-output") && oc.isSet("ptstop-output")) {
      68           64 :         writePTStops(oc, nb.getPTStopCont());
      69              :     }
      70         3290 :     if (oc.exists("ptline-output") && oc.isSet("ptline-output")) {
      71           45 :         writePTLines(oc, nb.getPTLineCont());
      72              :     }
      73              : 
      74         3290 :     if (oc.exists("parking-output") && oc.isSet("parking-output")) {
      75            2 :         writeParkingAreas(oc, nb.getParkingCont(), nb.getEdgeCont());
      76              :     }
      77         3290 :     if (oc.exists("taz-output") && oc.isSet("taz-output")) {
      78            1 :         writeDistricts(oc, nb.getDistrictCont());
      79              :     }
      80         1687 : }
      81              : 
      82              : 
      83              : void
      84          164 : NWWriter_XML::writeNodes(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc) {
      85              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
      86          327 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
      87          164 :     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          164 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
      92              : 
      93          326 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".nod.xml");
      94              :     std::map<SumoXMLAttr, std::string> attrs;
      95          162 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
      96          324 :     device.writeXMLHeader("nodes", "nodes_file.xsd", attrs);
      97              : 
      98              :     // write network offsets and projection to allow reconstruction of original coordinates
      99          162 :     if (!useGeo) {
     100          158 :         GeoConvHelper::writeLocation(device);
     101              :     }
     102              : 
     103              :     // write nodes
     104          324 :     TrafficLightType tlsDefaultType = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
     105         1332 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     106         1170 :         NBNode* n = (*i).second;
     107         1170 :         device.openTag(SUMO_TAG_NODE);
     108              :         device.writeAttr(SUMO_ATTR_ID, n->getID());
     109              :         // write position
     110         1170 :         Position pos = n->getPosition();
     111         1170 :         if (useGeo) {
     112           99 :             gch.cartesian2geo(pos);
     113              :         }
     114         1170 :         if (geoAccuracy) {
     115           99 :             device.setPrecision(gPrecisionGeo);
     116              :         }
     117         1170 :         NWFrame::writePositionLong(pos, device);
     118         1170 :         if (geoAccuracy) {
     119           99 :             device.setPrecision();
     120              :         }
     121              : 
     122         2340 :         device.writeAttr(SUMO_ATTR_TYPE, toString(n->getType()));
     123         1170 :         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          101 :             std::string tlType = "";
     129          203 :             for (NBTrafficLightDefinition* tl : n->getControllingTLS()) {
     130              :                 tlsIDs.insert(tl->getID());
     131          102 :                 std::vector<std::string> cie = tl->getControlledInnerEdges();
     132              :                 controlledInnerEdges.insert(cie.begin(), cie.end());
     133          102 :                 if (tl->getType() != tlsDefaultType) {
     134            8 :                     tlType = toString(tl->getType());
     135              :                 }
     136          102 :             }
     137          101 :             std::vector<std::string> sortedIDs(tlsIDs.begin(), tlsIDs.end());
     138          101 :             sort(sortedIDs.begin(), sortedIDs.end());
     139              :             device.writeAttr(SUMO_ATTR_TLID, sortedIDs);
     140          101 :             if (tlType != "") {
     141              :                 device.writeAttr(SUMO_ATTR_TLTYPE, tlType);
     142              :             }
     143          101 :             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          101 :         }
     149         1170 :         if (n->hasCustomShape()) {
     150           28 :             writeShape(device, gch, n->getShape(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     151              :         }
     152         1170 :         if (n->getRadius() != NBNode::UNSPECIFIED_RADIUS) {
     153           16 :             device.writeAttr(SUMO_ATTR_RADIUS, n->getRadius());
     154              :         }
     155         1170 :         if (!n->getKeepClear()) {
     156            0 :             device.writeAttr<bool>(SUMO_ATTR_KEEP_CLEAR, n->getKeepClear());
     157              :         }
     158         1170 :         if (n->getRightOfWay() != RightOfWay::DEFAULT) {
     159            0 :             device.writeAttr<std::string>(SUMO_ATTR_RIGHT_OF_WAY, toString(n->getRightOfWay()));
     160              :         }
     161         1170 :         if (n->getFringeType() != FringeType::DEFAULT) {
     162            0 :             device.writeAttr<std::string>(SUMO_ATTR_FRINGE, toString(n->getFringeType()));
     163              :         }
     164         1170 :         if (n->getName() != "") {
     165            8 :             device.writeAttr<std::string>(SUMO_ATTR_NAME, StringUtils::escapeXML(n->getName()));
     166              :         }
     167         1170 :         n->writeParams(device);
     168         2340 :         device.closeTag();
     169              :     }
     170          162 :     device.close();
     171          162 : }
     172              : 
     173              : 
     174              : void
     175           14 : NWWriter_XML::writeTypes(const std::string& prefix, NBEdgeCont& ec, NBTypeCont& tc) {
     176           28 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".typ.xml");
     177              :     std::map<SumoXMLAttr, std::string> attrs;
     178           14 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     179           28 :     device.writeXMLHeader("types", "types_file.xsd", attrs);
     180           14 :     std::set<std::string> usedTypes = ec.getUsedTypes();
     181           14 :     tc.writeEdgeTypes(device, usedTypes);
     182           14 :     device.close();
     183           14 : }
     184              : 
     185              : 
     186              : void
     187          162 : NWWriter_XML::writeEdgesAndConnections(const OptionsCont& oc, const std::string& prefix, NBNodeCont& nc, NBEdgeCont& ec) {
     188              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     189          324 :     bool useGeo = oc.exists("proj.plain-geo") && oc.getBool("proj.plain-geo");
     190          162 :     const bool geoAccuracy = useGeo || gch.usingInverseGeoProjection();
     191              : 
     192              :     std::map<SumoXMLAttr, std::string> attrs;
     193          162 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     194          324 :     OutputDevice& edevice = OutputDevice::getDevice(prefix + ".edg.xml");
     195          324 :     edevice.writeXMLHeader("edges", "edges_file.xsd", attrs);
     196          324 :     OutputDevice& cdevice = OutputDevice::getDevice(prefix + ".con.xml");
     197          324 :     cdevice.writeXMLHeader("connections", "connections_file.xsd", attrs);
     198          162 :     const bool writeNames = oc.getBool("output.street-names");
     199          162 :     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          162 :     if (!useGeo && gch.usingGeoProjection()) {
     203           20 :         GeoConvHelper::writeLocation(edevice);
     204              :     }
     205          324 :     LaneSpreadFunction defaultSpread = SUMOXMLDefinitions::LaneSpreadFunctions.get(oc.getString("default.spreadtype"));
     206         1975 :     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         1813 :         NBEdge* e = (*i).second;
     209         1813 :         edevice.openTag(SUMO_TAG_EDGE);
     210         1813 :         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         1813 :         if (writeNames && e->getStreetName() != "") {
     214          592 :             edevice.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(e->getStreetName()));
     215              :         }
     216         3626 :         edevice.writeAttr(SUMO_ATTR_PRIORITY, e->getPriority());
     217              :         // write the type if given
     218         1813 :         if (e->getTypeID() != "") {
     219              :             edevice.writeAttr(SUMO_ATTR_TYPE, e->getTypeID());
     220              :         }
     221         1813 :         edevice.writeAttr(SUMO_ATTR_NUMLANES, e->getNumLanes());
     222         1813 :         if (!e->hasLaneSpecificSpeed()) {
     223         3620 :             edevice.writeAttr(SUMO_ATTR_SPEED, e->getSpeed());
     224              :         }
     225         1813 :         if (!e->hasLaneSpecificFriction()) {
     226         1809 :             if (e->getFriction() != NBEdge::UNSPECIFIED_FRICTION) {
     227            6 :                 edevice.writeAttr(SUMO_ATTR_FRICTION, e->getFriction());
     228              :             }
     229              :         }
     230              :         // write non-default geometry
     231         1813 :         if (!e->hasDefaultGeometry()) {
     232          574 :             writeShape(edevice, gch, e->getGeometry(), SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     233              :         }
     234              :         // write the spread type if not default ("right")
     235         1813 :         if (e->getLaneSpreadFunction() != defaultSpread) {
     236          818 :             edevice.writeAttr(SUMO_ATTR_SPREADTYPE, toString(e->getLaneSpreadFunction()));
     237              :         }
     238              :         // write the length if it was specified
     239         1813 :         if (e->hasLoadedLength()) {
     240            6 :             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         1813 :         if (e->getLaneWidth() != NBEdge::UNSPECIFIED_WIDTH && !e->hasLaneSpecificWidth()) {
     244          454 :             edevice.writeAttr(SUMO_ATTR_WIDTH, e->getLaneWidth());
     245              :         }
     246         1813 :         if (e->getEndOffset() != NBEdge::UNSPECIFIED_OFFSET && !e->hasLaneSpecificEndOffset()) {
     247           14 :             edevice.writeAttr(SUMO_ATTR_ENDOFFSET, e->getEndOffset());
     248              :         }
     249         1813 :         if (!e->hasLaneSpecificPermissions()) {
     250         1568 :             writePermissions(edevice, e->getPermissions(0));
     251              :         }
     252         1813 :         if (!e->hasLaneSpecificStopOffsets() && e->getEdgeStopOffset().isDefined()) {
     253            0 :             NWWriter_SUMO::writeStopOffsets(edevice, e->getEdgeStopOffset());
     254              :         }
     255         1813 :         if (e->getDistance() != 0) {
     256            4 :             edevice.writeAttr(SUMO_ATTR_DISTANCE, e->getDistance());
     257              :         }
     258         1813 :         if (e->getBidiEdge() != 0) {
     259           30 :             edevice.writeAttr(SUMO_ATTR_BIDI, e->getBidiEdge()->getID());
     260              :         }
     261         1813 :         if (e->needsLaneSpecificOutput() || writeLanes) {
     262              :             int idx = 0;
     263         1398 :             for (const NBEdge::Lane& lane : e->getLanes()) {
     264         1068 :                 edevice.openTag(SUMO_TAG_LANE);
     265         1068 :                 edevice.writeAttr(SUMO_ATTR_INDEX, idx++);
     266              :                 // write allowed lanes
     267         1068 :                 if (e->hasLaneSpecificPermissions() || writeLanes) {
     268          901 :                     writePermissions(edevice, lane.permissions);
     269              :                 }
     270         1068 :                 writePreferences(edevice, lane.preferred);
     271              :                 // write other attributes
     272         1068 :                 if (lane.width != NBEdge::UNSPECIFIED_WIDTH && (e->hasLaneSpecificWidth() || writeLanes)) {
     273          416 :                     edevice.writeAttr(SUMO_ATTR_WIDTH, lane.width);
     274              :                 }
     275         1068 :                 if (lane.endOffset != NBEdge::UNSPECIFIED_OFFSET && (e->hasLaneSpecificEndOffset() || writeLanes)) {
     276            8 :                     edevice.writeAttr(SUMO_ATTR_ENDOFFSET, lane.endOffset);
     277              :                 }
     278         1068 :                 if (e->hasLaneSpecificSpeed() || writeLanes) {
     279           25 :                     edevice.writeAttr(SUMO_ATTR_SPEED, lane.speed);
     280              :                 }
     281         1068 :                 if (lane.accelRamp) {
     282            1 :                     edevice.writeAttr(SUMO_ATTR_ACCELERATION, lane.accelRamp);
     283              :                 }
     284         1068 :                 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         1068 :                 if (lane.type != "") {
     288              :                     edevice.writeAttr(SUMO_ATTR_TYPE, lane.type);
     289              :                 }
     290         1068 :                 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         1068 :                 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         1068 :                 if (lane.oppositeID != "") {
     297           47 :                     edevice.openTag(SUMO_TAG_NEIGH);
     298              :                     edevice.writeAttr(SUMO_ATTR_LANE, lane.oppositeID);
     299           94 :                     edevice.closeTag();
     300              :                 }
     301         1068 :                 lane.writeParams(edevice);
     302         1068 :                 NWWriter_SUMO::writeStopOffsets(edevice, lane.laneStopOffset);
     303         2136 :                 edevice.closeTag();
     304              :             }
     305              :         }
     306         1813 :         e->writeParams(edevice);
     307         3626 :         edevice.closeTag();
     308              :         // write this edge's connections to the connections-files
     309         1813 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     310         1813 :         if (connections.empty()) {
     311              :             // if there are no connections and this appears to be customized, preserve the information
     312          341 :             const int numOutgoing = (int)e->getToNode()->getOutgoingEdges().size();
     313          341 :             if (numOutgoing > 0) {
     314          217 :                 const SVCPermissions inPerm = e->getPermissions();
     315              :                 SVCPermissions outPerm = 0;
     316          537 :                 for (auto out : e->getToNode()->getOutgoingEdges()) {
     317          320 :                     outPerm |= out->getPermissions();
     318              :                 }
     319          217 :                 if ((inPerm & outPerm) != 0 && (inPerm & outPerm) != SVC_PEDESTRIAN) {
     320          112 :                     cdevice.openTag(SUMO_TAG_CONNECTION);
     321          112 :                     cdevice.writeAttr(SUMO_ATTR_FROM, e->getID());
     322          112 :                     cdevice.closeTag();
     323          112 :                     cdevice << "\n";
     324              :                 }
     325              :             }
     326              :         } else {
     327         5125 :             for (NBEdge::Connection c : connections) {
     328         3653 :                 if (useGeo) {
     329          404 :                     for (Position& p : c.customShape) {
     330            3 :                         gch.cartesian2geo(p);
     331              :                     }
     332              :                 }
     333         3653 :                 NWWriter_SUMO::writeConnection(cdevice, *e, c, false, NWWriter_SUMO::PLAIN, geoAccuracy);
     334         3653 :             }
     335         1472 :             cdevice << "\n";
     336              :         }
     337         1813 :     }
     338              :     // write roundabout information to the edges-files
     339          324 :     if (ec.getRoundabouts().size() > 0) {
     340            4 :         edevice.lf();
     341            8 :         NWWriter_SUMO::writeRoundabouts(edevice, ec.getRoundabouts(), ec);
     342              :     }
     343              : 
     344              :     // write loaded prohibitions to the connections-file
     345         1332 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     346         1170 :         NWWriter_SUMO::writeProhibitions(cdevice, i->second->getProhibitions());
     347              :     }
     348              :     // write pedestrian crossings to the connections-file
     349         1332 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     350         1170 :         const std::vector<NBNode::Crossing*>& crossings = (*it_node).second->getCrossings();
     351         1247 :         for (auto c : crossings) {
     352           77 :             cdevice.openTag(SUMO_TAG_CROSSING);
     353           77 :             cdevice.writeAttr(SUMO_ATTR_NODE, (*it_node).second->getID());
     354           77 :             cdevice.writeAttr(SUMO_ATTR_EDGES, c->edges);
     355           77 :             cdevice.writeAttr(SUMO_ATTR_PRIORITY, c->priority);
     356           77 :             if (c->customWidth != NBEdge::UNSPECIFIED_WIDTH) {
     357           39 :                 cdevice.writeAttr(SUMO_ATTR_WIDTH, c->customWidth);
     358              :             }
     359           77 :             if (c->customTLIndex != -1) {
     360           24 :                 cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX, c->customTLIndex);
     361              :             }
     362           77 :             if (c->customTLIndex2 != -1) {
     363            4 :                 cdevice.writeAttr(SUMO_ATTR_TLLINKINDEX2, c->customTLIndex2);
     364              :             }
     365           77 :             if (c->customShape.size() != 0) {
     366            4 :                 writeShape(cdevice, gch, c->customShape, SUMO_ATTR_SHAPE, useGeo, geoAccuracy);
     367              :             }
     368           77 :             if (c->outlineShape.size() != 0) {
     369           77 :                 writeShape(cdevice, gch, c->outlineShape, SUMO_ATTR_OUTLINESHAPE, useGeo, geoAccuracy);
     370              :             }
     371           77 :             c->writeParams(cdevice);
     372          154 :             cdevice.closeTag();
     373              :         }
     374         1170 :     }
     375              :     // write custom walkingarea shapes to the connections file
     376         1332 :     for (std::map<std::string, NBNode*>::const_iterator it_node = nc.begin(); it_node != nc.end(); ++it_node) {
     377         1177 :         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          162 :     edevice.close();
     392          162 :     cdevice.close();
     393          162 : }
     394              : 
     395              : 
     396              : void
     397          162 : NWWriter_XML::writeTrafficLights(const std::string& prefix, NBTrafficLightLogicCont& tc, NBEdgeCont& ec) {
     398              :     std::map<SumoXMLAttr, std::string> attrs;
     399          162 :     attrs[SUMO_ATTR_VERSION] = toString(NETWORK_VERSION);
     400          324 :     OutputDevice& device = OutputDevice::getDevice(prefix + ".tll.xml");
     401          324 :     device.writeXMLHeader("tlLogics", "tllogic_file.xsd", attrs);
     402          162 :     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         1975 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     406         1813 :         NBEdge* e = (*i).second;
     407              :         // write this edge's tl-controlled connections
     408         1813 :         const std::vector<NBEdge::Connection> connections = e->getConnections();
     409         5466 :         for (std::vector<NBEdge::Connection>::const_iterator c = connections.begin(); c != connections.end(); ++c) {
     410         3653 :             if (c->tlID != "") {
     411         1065 :                 NWWriter_SUMO::writeConnection(device, *e, *c, false, NWWriter_SUMO::TLL);
     412              :             }
     413              :         }
     414         1813 :     }
     415          162 :     device.close();
     416          162 : }
     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            2 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("street-sign-output"));
     446            2 :     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           64 : NWWriter_XML::writePTStops(const OptionsCont& oc, NBPTStopCont& sc) {
     460          128 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptstop-output"));
     461          128 :     device.writeXMLHeader("additional", "additional_file.xsd");
     462          829 :     for (const auto& stopIt : sc.getStops()) {
     463          765 :         stopIt.second->write(device);
     464              :     }
     465           64 :     device.close();
     466           64 : }
     467              : 
     468              : 
     469           45 : void NWWriter_XML::writePTLines(const OptionsCont& oc, NBPTLineCont& lc) {
     470           90 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("ptline-output"));
     471           90 :     device.writeXMLHeader("ptLines", "ptlines_file.xsd");
     472          404 :     for (const auto& item : lc.getLines()) {
     473          359 :         item.second->write(device);
     474              :     }
     475           45 :     device.close();
     476           45 : }
     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            4 :     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            2 :     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          696 : NWWriter_XML::writeShape(OutputDevice& out, const GeoConvHelper& gch, PositionVector shape, SumoXMLAttr attr, bool useGeo, bool geoAccuracy) {
     501          696 :     if (useGeo) {
     502          322 :         for (int i = 0; i < (int) shape.size(); i++) {
     503          259 :             gch.cartesian2geo(shape[i]);
     504              :         }
     505              :     }
     506          696 :     if (geoAccuracy) {
     507           63 :         out.setPrecision(gPrecisionGeo);
     508              :     }
     509              :     out.writeAttr(attr, shape);
     510          696 :     if (geoAccuracy) {
     511           63 :         out.setPrecision();
     512              :     }
     513          696 : }
     514              : 
     515              : 
     516              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1