LCOV - code coverage report
Current view: top level - src/netwrite - NWWriter_DlrNavteq.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 96.8 % 311 301
Test Date: 2025-11-13 15:38:19 Functions: 100.0 % 16 16

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2012-2025 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_DlrNavteq.cpp
      15              : /// @author  Jakob Erdmann
      16              : /// @author  Michael Behrisch
      17              : /// @date    26.10.2012
      18              : ///
      19              : // Exporter writing networks using DlrNavteq (Elmar) format
      20              : /****************************************************************************/
      21              : #include <config.h>
      22              : #include <algorithm>
      23              : #include <ctime>
      24              : #include <cmath>
      25              : #include <utils/common/MsgHandler.h>
      26              : #include <netbuild/NBEdge.h>
      27              : #include <netbuild/NBEdgeCont.h>
      28              : #include <netbuild/NBNode.h>
      29              : #include <netbuild/NBNodeCont.h>
      30              : #include <netbuild/NBNetBuilder.h>
      31              : #include <utils/common/ToString.h>
      32              : #include <utils/common/IDSupplier.h>
      33              : #include <utils/common/StringUtils.h>
      34              : #include <utils/common/StringTokenizer.h>
      35              : #include <utils/options/OptionsCont.h>
      36              : #include <utils/iodevices/OutputDevice.h>
      37              : #include <utils/geom/GeoConvHelper.h>
      38              : #include "NWFrame.h"
      39              : #include "NWWriter_DlrNavteq.h"
      40              : 
      41              : 
      42              : // ---------------------------------------------------------------------------
      43              : // static members
      44              : // ---------------------------------------------------------------------------
      45              : const std::string NWWriter_DlrNavteq::UNDEFINED("-1");
      46              : 
      47              : // ---------------------------------------------------------------------------
      48              : // static methods
      49              : // ---------------------------------------------------------------------------
      50              : void
      51         1807 : NWWriter_DlrNavteq::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
      52              :     // check whether a matsim-file shall be generated
      53         3614 :     if (!oc.isSet("dlr-navteq-output")) {
      54         1796 :         return;
      55              :     }
      56              :     std::map<const NBEdge*, std::string> internalNodes;
      57           11 :     writeNodesUnsplitted(oc, nb.getNodeCont(), nb.getEdgeCont(), internalNodes);
      58           11 :     writeLinksUnsplitted(oc, nb.getEdgeCont(), internalNodes);
      59           11 :     writeTrafficSignals(oc, nb.getNodeCont());
      60           11 :     writeProhibitedManoeuvres(oc, nb.getNodeCont(), nb.getEdgeCont());
      61           11 :     writeConnectedLanes(oc, nb.getNodeCont());
      62              : }
      63              : 
      64              : 
      65           59 : void NWWriter_DlrNavteq::writeHeader(OutputDevice& device, const OptionsCont& oc) {
      66           59 :     device << "# Format matches Extraction version: V" << oc.getString("dlr-navteq.version") << " \n";
      67           59 :     std::stringstream tmp;
      68          118 :     oc.writeConfiguration(tmp, true, false, false);
      69           59 :     tmp.seekg(std::ios_base::beg);
      70              :     std::string line;
      71         2678 :     while (!tmp.eof()) {
      72         2619 :         std::getline(tmp, line);
      73         2619 :         device << "# " << line << "\n";
      74              :     }
      75           59 :     device << "#\n";
      76           59 : }
      77              : 
      78              : 
      79              : void
      80           11 : NWWriter_DlrNavteq::writeNodesUnsplitted(const OptionsCont& oc, const NBNodeCont& nc, const NBEdgeCont& ec, std::map<const NBEdge*, std::string>& internalNodes) {
      81              :     // For "real" nodes we simply use the node id.
      82              :     // For internal nodes (geometry vectors describing edge geometry in the parlance of this format)
      83              :     // we use the id of the edge and do not bother with
      84              :     // compression (each direction gets its own internal node).
      85           22 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt");
      86           11 :     writeHeader(device, oc);
      87              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
      88           11 :     const bool haveGeo = gch.usingGeoProjection();
      89           11 :     const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
      90           11 :     device.setPrecision(oc.getInt("dlr-navteq.precision"));
      91           11 :     if (!haveGeo) {
      92            6 :         WRITE_WARNING(TL("DlrNavteq node data will be written in (floating point) cartesian coordinates"));
      93              :     }
      94              :     // write format specifier
      95           11 :     device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2  ... xn  yn]\n";
      96              :     // write header
      97           11 :     Boundary boundary = gch.getConvBoundary();
      98           11 :     Position min(boundary.xmin(), boundary.ymin());
      99           11 :     Position max(boundary.xmax(), boundary.ymax());
     100           11 :     gch.cartesian2geo(min);
     101              :     min.mul(geoScale);
     102           11 :     gch.cartesian2geo(max);
     103              :     max.mul(geoScale);
     104           11 :     int multinodes = 0;
     105         1054 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     106         1043 :         if ((*i).second->getGeometry().size() > 2) {
     107          488 :             multinodes++;
     108              :         }
     109              :     }
     110           11 :     device << "# [xmin_region] " << min.x() << "\n";
     111           11 :     device << "# [xmax_region] " << max.x() << "\n";
     112           11 :     device << "# [ymin_region] " << min.y() << "\n";
     113           11 :     device << "# [ymax_region] " << max.y() << "\n";
     114           11 :     device << "# [elements_multinode] " << multinodes << "\n";
     115           11 :     device << "# [elements_normalnode] " << nc.size() << "\n";
     116           11 :     device << "# [xmin] " << min.x() << "\n";
     117           11 :     device << "# [xmax] " << max.x() << "\n";
     118           11 :     device << "# [ymin] " << min.y() << "\n";
     119           11 :     device << "# [ymax] " << max.y() << "\n";
     120              :     // write normal nodes
     121          561 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     122          550 :         NBNode* n = (*i).second;
     123          550 :         Position pos = n->getPosition();
     124          550 :         gch.cartesian2geo(pos);
     125              :         pos.mul(geoScale);
     126          550 :         device << n->getID() << "\t0\t1\t" << pos.x() << "\t" << pos.y() << "\n";
     127              :     }
     128              :     // write "internal" nodes
     129              :     std::vector<std::string> avoid;
     130              :     std::set<std::string> reservedNodeIDs;
     131           11 :     const bool numericalIDs = oc.getBool("numerical-ids");
     132           22 :     if (oc.isSet("reserved-ids")) {
     133            4 :         NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "node:", reservedNodeIDs); // backward compatibility
     134            4 :         NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "junction:", reservedNodeIDs); // selection format
     135              :     }
     136           11 :     if (numericalIDs) {
     137           11 :         avoid = nc.getAllNames();
     138           11 :         std::vector<std::string> avoid2 = ec.getAllNames();
     139           11 :         avoid.insert(avoid.end(), avoid2.begin(), avoid2.end());
     140           11 :         avoid.insert(avoid.end(), reservedNodeIDs.begin(), reservedNodeIDs.end());
     141           11 :     }
     142           22 :     IDSupplier idSupplier("", avoid);
     143         1054 :     for (const auto& edgeIt : ec) {
     144         1043 :         const NBEdge* const e = edgeIt.second;
     145              :         PositionVector geom = e->getGeometry();
     146         1043 :         if (geom.size() > 2) {
     147              :             // the import NIImporter_DlrNavteq checks for the presence of a
     148              :             // negated edge id to determine spread type. We may need to do some
     149              :             // shifting to make this consistent
     150          488 :             const bool hasOppositeID = ec.getOppositeByID(e->getID()) != nullptr;
     151          488 :             if (e->getLaneSpreadFunction() == LaneSpreadFunction::RIGHT && !hasOppositeID) {
     152              :                 // need to write center-line geometry instead
     153              :                 try {
     154          249 :                     geom.move2side(e->getTotalWidth() / 2);
     155            0 :                 } catch (InvalidArgument& exception) {
     156            0 :                     WRITE_WARNINGF(TL("Could not reconstruct shape for edge:'%' (%)."), e->getID(), exception.what());
     157            0 :                 }
     158          239 :             } else if (e->getLaneSpreadFunction() == LaneSpreadFunction::CENTER && hasOppositeID) {
     159              :                 // need to write left-border geometry instead
     160              :                 try {
     161            0 :                     geom.move2side(-e->getTotalWidth() / 2);
     162            0 :                 } catch (InvalidArgument& exception) {
     163            0 :                     WRITE_WARNINGF(TL("Could not reconstruct shape for edge:'%' (%)."), e->getID(), exception.what());
     164            0 :                 }
     165              :             }
     166              : 
     167          488 :             if (geom.size() > 2) { // move2side might have changed the number of nodes
     168          488 :                 std::string internalNodeID = e->getID();
     169          488 :                 if (internalNodeID == UNDEFINED
     170          488 :                         || (nc.retrieve(internalNodeID) != nullptr)
     171          488 :                         || reservedNodeIDs.count(internalNodeID) > 0
     172              :                    ) {
     173              :                     // need to invent a new name to avoid clashing with the id of a 'real' node or a reserved name
     174            3 :                     if (numericalIDs) {
     175            6 :                         internalNodeID = idSupplier.getNext();
     176              :                     } else {
     177              :                         internalNodeID += "_geometry";
     178              :                     }
     179              :                 }
     180          488 :                 internalNodes[e] = internalNodeID;
     181          488 :                 device << internalNodeID << "\t1\t" << geom.size() - 2;
     182         2099 :                 for (int ii = 1; ii < (int)geom.size() - 1; ++ii) {
     183         1611 :                     Position pos = geom[(int)ii];
     184         1611 :                     gch.cartesian2geo(pos);
     185              :                     pos.mul(geoScale);
     186         1611 :                     device << "\t" << pos.x() << "\t" << pos.y();
     187              :                 }
     188          488 :                 device << "\n";
     189              :             }
     190              :         }
     191         1043 :     }
     192           11 :     device.close();
     193           22 : }
     194              : 
     195              : 
     196              : void
     197           11 : NWWriter_DlrNavteq::writeLinksUnsplitted(const OptionsCont& oc, const NBEdgeCont& ec, const std::map<const NBEdge*, std::string>& internalNodes) {
     198           33 :     const int majorVersion = StringUtils::toInt(StringTokenizer(oc.getString("dlr-navteq.version"), ".").next());
     199              :     std::map<const std::string, std::string> nameIDs;
     200           22 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_links_unsplitted.txt");
     201           11 :     writeHeader(device, oc);
     202              :     // write format specifier
     203           11 :     device << "# LINK_ID\tNODE_ID_FROM\tNODE_ID_TO\tBETWEEN_NODE_ID\tLENGTH\tVEHICLE_TYPE\tFORM_OF_WAY\tBRUNNEL_TYPE\t"
     204           11 :            << "FUNCTIONAL_ROAD_CLASS\tSPEED_CATEGORY\tNUMBER_OF_LANES\tSPEED_LIMIT\tSPEED_RESTRICTION\t"
     205           11 :            << "NAME_ID1_REGIONAL\tNAME_ID2_LOCAL\tHOUSENUMBERS_RIGHT\tHOUSENUMBERS_LEFT\tZIP_CODE\t"
     206           11 :            << "AREA_ID\tSUBAREA_ID\tTHROUGH_TRAFFIC\tSPECIAL_RESTRICTIONS\tEXTENDED_NUMBER_OF_LANES\tISRAMP\tCONNECTION";
     207           11 :     if (majorVersion > 6) {
     208            1 :         device << "\tMAXHEIGHT\tMAXWIDTH\tMAXWEIGHT\tSURFACE";
     209              :     }
     210           11 :     device << "\n";
     211              :     // write edges
     212         1054 :     for (const auto& edgeIt : ec) {
     213         1043 :         const NBEdge* const e = edgeIt.second;
     214         1043 :         const int kph = speedInKph(e->getSpeed());
     215              :         const auto& internalIt = internalNodes.find(e);
     216         1043 :         const std::string& betweenNodeID = internalIt != internalNodes.end() ? internalIt->second : UNDEFINED;
     217              :         std::string nameID = UNDEFINED;
     218              :         std::string nameIDRegional = UNDEFINED;
     219         2086 :         if (oc.getBool("output.street-names")) {
     220              :             const std::string& name = e->getStreetName();
     221          912 :             if (name != "") {
     222              :                 if (nameIDs.count(name) == 0) {
     223           51 :                     const int tmp = (int)nameIDs.size();
     224          102 :                     nameIDs[name] = toString(tmp);
     225              :                 }
     226          366 :                 nameID = nameIDs[name];
     227              :             }
     228         1824 :             const std::string& name2 = e->getParameter("ref", "");
     229          912 :             if (name2 != "") {
     230              :                 if (nameIDs.count(name2) == 0) {
     231            4 :                     const int tmp = (int)nameIDs.size();
     232            8 :                     nameIDs[name2] = toString(tmp);
     233              :                 }
     234           44 :                 nameIDRegional = nameIDs[name2];
     235              :             }
     236              :         }
     237         1043 :         device << e->getID() << "\t"
     238         1043 :                << e->getFromNode()->getID() << "\t"
     239         1043 :                << e->getToNode()->getID() << "\t"
     240         1043 :                << betweenNodeID << "\t"
     241         1043 :                << getGraphLength(e) << "\t"
     242         1043 :                << getAllowedTypes(e->getPermissions()) << "\t"
     243         1043 :                << getFormOfWay(e) << "\t"
     244         1043 :                << getBrunnelType(e) << "\t"
     245         1043 :                << getRoadClass(e) << "\t"
     246         1043 :                << getSpeedCategory(kph) << "\t"
     247         1043 :                << getNavteqLaneCode(e->getNumLanes()) << "\t"
     248         1043 :                << getSpeedCategoryUpperBound(kph) << "\t"
     249         1043 :                << kph << "\t"
     250         1043 :                << nameIDRegional << "\t"
     251         1043 :                << nameID << "\t" // NAME_ID2_LOCAL
     252         1043 :                << UNDEFINED << "\t" // housenumbers_right
     253         1043 :                << UNDEFINED << "\t" // housenumbers_left
     254         4172 :                << getSinglePostalCode(e->getParameter("postal_code", UNDEFINED), e->getID()) << "\t" // ZIP_CODE
     255         1043 :                << UNDEFINED << "\t" // AREA_ID
     256         1043 :                << UNDEFINED << "\t" // SUBAREA_ID
     257         1043 :                << "1\t" // through_traffic (allowed)
     258         1043 :                << UNDEFINED << "\t" // special_restrictions
     259         1043 :                << UNDEFINED << "\t" // extended_number_of_lanes
     260         1043 :                << UNDEFINED << "\t" // isRamp
     261         1043 :                << "0"; // connection (between nodes always in order)
     262         1043 :         if (majorVersion > 6) {
     263          825 :             device << "\t" << e->getParameter("maxheight", UNDEFINED)
     264          825 :                    << "\t" << e->getParameter("maxwidth", UNDEFINED)
     265          825 :                    << "\t" << e->getParameter("maxweight", UNDEFINED)
     266          825 :                    << "\t" << e->getParameter("surface", UNDEFINED);
     267              :         }
     268         1043 :         device << "\n";
     269              :     }
     270           22 :     if (oc.getBool("output.street-names")) {
     271            8 :         OutputDevice& namesDevice = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_names.txt");
     272            4 :         writeHeader(namesDevice, oc);
     273              :         // write format specifier
     274            4 :         namesDevice << "# NAME_ID\tPERMANENT_ID_INFO\tName\n";
     275            4 :         namesDevice << "# [elements] " << nameIDs.size() << "\n";
     276           59 :         for (std::map<const std::string, std::string>::const_iterator i = nameIDs.begin(); i != nameIDs.end(); ++i) {
     277              :             namesDevice
     278           55 :                     << i->second << "\t"
     279          110 :                     << 0 << "\t"
     280           55 :                     << i->first << "\n";
     281              :         }
     282            4 :         namesDevice.close();
     283              :     }
     284           11 :     device.close();
     285           11 : }
     286              : 
     287              : 
     288              : std::string
     289         3557 : NWWriter_DlrNavteq::getAllowedTypes(SVCPermissions permissions) {
     290         3557 :     if (permissions == SVCAll) {
     291          625 :         return "100000000000";
     292              :     }
     293         2932 :     std::ostringstream oss;
     294         2932 :     oss << "0";
     295         4641 :     oss << ((permissions & SVC_PASSENGER)              > 0 ? 1 : 0);
     296         2932 :     oss << ((permissions & SVC_PASSENGER)              > 0 ? 1 : 0); // residential
     297         4641 :     oss << ((permissions & SVC_HOV)                    > 0 ? 1 : 0);
     298         4641 :     oss << ((permissions & SVC_EMERGENCY)              > 0 ? 1 : 0);
     299         4641 :     oss << ((permissions & SVC_TAXI)                   > 0 ? 1 : 0);
     300         4641 :     oss << ((permissions & (SVC_BUS | SVC_COACH))      > 0 ? 1 : 0);
     301         3702 :     oss << ((permissions & SVC_DELIVERY)               > 0 ? 1 : 0);
     302         4641 :     oss << ((permissions & (SVC_TRUCK | SVC_TRAILER))  > 0 ? 1 : 0);
     303         4586 :     oss << ((permissions & SVC_MOTORCYCLE)             > 0 ? 1 : 0);
     304         3383 :     oss << ((permissions & SVC_BICYCLE)                > 0 ? 1 : 0);
     305         3176 :     oss << ((permissions & SVC_PEDESTRIAN)             > 0 ? 1 : 0);
     306              :     return oss.str();
     307         2932 : }
     308              : 
     309              : 
     310              : int
     311         1743 : NWWriter_DlrNavteq::getRoadClass(const NBEdge* const edge) {
     312              :     // quoting the navteq manual:
     313              :     // As a general rule, Functional Road Class assignments have no direct
     314              :     // correlation with other road attributes like speed, controlled access, route type, etc.
     315              :     // if the network is based on OSM, we can use the highway types for determining FRC
     316              :     std::string type = edge->getTypeID();
     317         3486 :     if (StringUtils::startsWith(type, "highway.")) {
     318         3280 :         type = type.substr(8);
     319              :     }
     320         3486 :     if (StringUtils::startsWith(type, "motorway")) {
     321              :         return 0;
     322         3430 :     } else if (StringUtils::startsWith(type, "trunk")) {
     323              :         return 1;
     324         3430 :     } else if (StringUtils::startsWith(type, "primary")) {
     325              :         return 1;
     326         3286 :     } else if (StringUtils::startsWith(type, "secondary")) {
     327              :         return 2;
     328         3156 :     } else if (StringUtils::startsWith(type, "tertiary")) {
     329              :         return 3;
     330         1413 :     } else if (type == "unclassified") {
     331              :         return 3;
     332         1222 :     } else if (type == "living_street" || type == "residential" || type == "road" || type == "service" || type == "track" || type == "cycleway" || type == "path" || type == "footway") {
     333              :         return 4;
     334              :     }
     335              :     // as a fallback we do a simple speed / lane-count mapping anyway
     336              :     // the resulting functional road class layers probably won't be connected as required
     337          112 :     const int kph = speedInKph(edge->getSpeed());
     338          112 :     if ((kph) > 100) {
     339              :         return 0;
     340              :     }
     341          110 :     if ((kph) > 70) {
     342              :         return 1;
     343              :     }
     344           70 :     if ((kph) > 50) {
     345            0 :         return (edge->getNumLanes() > 1 ? 2 : 3);
     346              :     }
     347           70 :     if ((kph) > 30) {
     348              :         return 3;
     349              :     }
     350              :     return 4;
     351              : }
     352              : 
     353              : 
     354              : int
     355         1043 : NWWriter_DlrNavteq::getSpeedCategory(int kph) {
     356         1043 :     if ((kph) > 130) {
     357              :         return 1;
     358              :     }
     359         1041 :     if ((kph) > 100) {
     360              :         return 2;
     361              :     }
     362         1041 :     if ((kph) > 90) {
     363              :         return 3;
     364              :     }
     365         1001 :     if ((kph) > 70) {
     366              :         return 4;
     367              :     }
     368          920 :     if ((kph) > 50) {
     369              :         return 5;
     370              :     }
     371          918 :     if ((kph) > 30) {
     372              :         return 6;
     373              :     }
     374          483 :     if ((kph) > 10) {
     375          422 :         return 7;
     376              :     }
     377              :     return 8;
     378              : }
     379              : 
     380              : 
     381              : int
     382         1043 : NWWriter_DlrNavteq::getSpeedCategoryUpperBound(int kph) {
     383         1043 :     if ((kph) > 130) {
     384              :         return 131;
     385              :     }
     386         1041 :     if ((kph) > 100) {
     387              :         return 130;
     388              :     }
     389         1041 :     if ((kph) > 90) {
     390              :         return 100;
     391              :     }
     392         1001 :     if ((kph) > 70) {
     393              :         return 90;
     394              :     }
     395          920 :     if ((kph) > 50) {
     396              :         return 70;
     397              :     }
     398          918 :     if ((kph) > 30) {
     399              :         return 50;
     400              :     }
     401          483 :     if ((kph) > 10) {
     402          422 :         return 30;
     403              :     }
     404              :     return 10;
     405              : }
     406              : 
     407              : 
     408              : int
     409         1043 : NWWriter_DlrNavteq::getNavteqLaneCode(const int numLanes) {
     410         1043 :     const int code = (numLanes == 1 ? 1 :
     411          123 :                       (numLanes < 4 ?  2 : 3));
     412         1043 :     return numLanes * 10 + code;
     413              : }
     414              : 
     415              : 
     416              : int
     417         1043 : NWWriter_DlrNavteq::getBrunnelType(const NBEdge* const edge) {
     418         2086 :     if (edge->hasParameter("bridge")) {
     419              :         return 1;
     420         2054 :     } else if (edge->hasParameter("tunnel")) {
     421              :         return 4;
     422         1027 :     } else if (edge->getTypeID() == "route.ferry") {
     423            0 :         return 10;
     424              :     }
     425              :     return -1; // UNDEFINED
     426              : }
     427              : 
     428              : 
     429              : int
     430         1043 : NWWriter_DlrNavteq::getFormOfWay(const NBEdge* const edge) {
     431         1043 :     if (edge->getPermissions() == SVC_PEDESTRIAN) {
     432              :         return 15;
     433          952 :     } else if (edge->getJunctionPriority(edge->getToNode()) == NBEdge::JunctionPriority::ROUNDABOUT) {
     434              :         return 4;
     435          952 :     } else if (edge->getTypeID() == "highway.service") {
     436              :         return 14;
     437          712 :     } else if (edge->getTypeID().find("_link") != std::string::npos) {
     438            2 :         return 10;
     439              :     }
     440              :     return 3; // speed category 1-8;
     441              : }
     442              : 
     443              : 
     444              : double
     445         1043 : NWWriter_DlrNavteq::getGraphLength(const NBEdge* const edge) {
     446              :     PositionVector geom = edge->getGeometry();
     447         1043 :     geom.push_back_noDoublePos(edge->getToNode()->getPosition());
     448         1043 :     geom.push_front_noDoublePos(edge->getFromNode()->getPosition());
     449         2086 :     return geom.length();
     450         1043 : }
     451              : 
     452              : 
     453              : std::string
     454         1043 : NWWriter_DlrNavteq::getSinglePostalCode(const std::string& zipCode, const std::string edgeID) {
     455              :     // might be multiple codes
     456         1043 :     if (zipCode.find_first_of(" ,;") != std::string::npos) {
     457           72 :         WRITE_WARNINGF("ambiguous zip code '%' for edge '%'. (using first value)", zipCode, edgeID);
     458           72 :         StringTokenizer st(zipCode, " ,;", true);
     459           24 :         std::vector<std::string> ret = st.getVector();
     460              :         return ret[0];
     461         1043 :     } else if (zipCode.size() > 16) {
     462            0 :         WRITE_WARNINGF("long zip code '%' for edge '%'", zipCode, edgeID);
     463              :     }
     464              :     return zipCode;
     465              : }
     466              : 
     467              : void
     468           11 : NWWriter_DlrNavteq::writeTrafficSignals(const OptionsCont& oc, NBNodeCont& nc) {
     469           22 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_traffic_signals.txt");
     470           11 :     writeHeader(device, oc);
     471              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     472           11 :     const bool haveGeo = gch.usingGeoProjection();
     473           11 :     const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
     474           11 :     device.setPrecision(oc.getInt("dlr-navteq.precision"));
     475              :     // write format specifier
     476           11 :     device << "#Traffic signal related to LINK_ID and NODE_ID with location relative to driving direction.\n#column format like pointcollection.\n#DESCRIPTION->LOCATION: 1-rechts von LINK; 2-links von LINK; 3-oberhalb LINK -1-keineAngabe\n#RELATREC_ID\tPOICOL_TYPE\tDESCRIPTION\tLONGITUDE\tLATITUDE\tLINK_ID\n";
     477              :     // write record for every edge incoming to a tls controlled node
     478          561 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     479          550 :         NBNode* n = (*i).second;
     480          550 :         if (n->isTLControlled()) {
     481           14 :             Position pos = n->getPosition();
     482           14 :             gch.cartesian2geo(pos);
     483              :             pos.mul(geoScale);
     484              :             const EdgeVector& incoming = n->getIncomingEdges();
     485           65 :             for (EdgeVector::const_iterator it = incoming.begin(); it != incoming.end(); ++it) {
     486           51 :                 NBEdge* e = *it;
     487           51 :                 device << e->getID() << "\t"
     488           51 :                        << "12\t" // POICOL_TYPE
     489           51 :                        << "LSA;NODEIDS#" << n->getID() << "#;LOCATION#-1#;\t"
     490           51 :                        << pos.x() << "\t"
     491          102 :                        << pos.y() << "\t"
     492           51 :                        << e->getID() << "\n";
     493              :             }
     494              :         }
     495              :     }
     496           11 :     device.close();
     497           11 : }
     498              : 
     499              : 
     500              : void
     501           11 : NWWriter_DlrNavteq::writeProhibitedManoeuvres(const OptionsCont& oc, const NBNodeCont& nc, const NBEdgeCont& ec) {
     502           22 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_prohibited_manoeuvres.txt");
     503           11 :     writeHeader(device, oc);
     504              :     // need to invent id for relation
     505              :     std::set<std::string> reservedRelIDs;
     506           22 :     if (oc.isSet("reserved-ids")) {
     507            4 :         NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "rel:", reservedRelIDs);
     508              :     }
     509           11 :     std::vector<std::string> avoid = ec.getAllNames(); // already used for tls RELATREC_ID
     510           11 :     avoid.insert(avoid.end(), reservedRelIDs.begin(), reservedRelIDs.end());
     511           11 :     IDSupplier idSupplier("", avoid); // @note: use a global relRecIDsupplier if this is used more often
     512              :     // write format specifier
     513           11 :     device << "#No driving allowed from ID1 to ID2 or the complete chain from ID1 to IDn\n";
     514           11 :     device << "#RELATREC_ID\tPERMANENT_ID_INFO\tVALIDITY_PERIOD\tTHROUGH_TRAFFIC\tVEHICLE_TYPE\tNAVTEQ_LINK_ID1\t[NAVTEQ_LINK_ID2 ...]\n";
     515              :     // write record for every pair of incoming/outgoing edge that are not connected despite having common permissions
     516          561 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     517          550 :         NBNode* n = (*i).second;
     518              :         const EdgeVector& incoming = n->getIncomingEdges();
     519              :         const EdgeVector& outgoing = n->getOutgoingEdges();
     520         1593 :         for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
     521         1043 :             NBEdge* inEdge = *j;
     522         1043 :             const SVCPermissions inPerm = inEdge->getPermissions();
     523         3673 :             for (EdgeVector::const_iterator k = outgoing.begin(); k != outgoing.end(); ++k) {
     524         2630 :                 NBEdge* outEdge = *k;
     525         2630 :                 const SVCPermissions outPerm = outEdge->getPermissions();
     526         2630 :                 const SVCPermissions commonPerm = inPerm & outPerm;
     527         2630 :                 if (commonPerm != 0 && commonPerm != SVC_PEDESTRIAN && !inEdge->isConnectedTo(outEdge)) {
     528              :                     device
     529           16 :                             << idSupplier.getNext() << "\t"
     530            8 :                             << 1 << "\t" // permanent id
     531            8 :                             << UNDEFINED << "\t"
     532            8 :                             << 1 << "\t"
     533           16 :                             << getAllowedTypes(SVCAll) << "\t"
     534            8 :                             << inEdge->getID() << "\t" << outEdge->getID() << "\n";
     535              :                 }
     536              :             }
     537              :         }
     538              :     }
     539           11 :     device.close();
     540           22 : }
     541              : 
     542              : 
     543              : void
     544           11 : NWWriter_DlrNavteq::writeConnectedLanes(const OptionsCont& oc, NBNodeCont& nc) {
     545           22 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_connected_lanes.txt");
     546           11 :     writeHeader(device, oc);
     547              :     // write format specifier
     548           11 :     device << "#Lane connections related to LINK-IDs and NODE-ID.\n";
     549           11 :     device << "#column format like pointcollection.\n";
     550           11 :     device << "#NODE-ID\tVEHICLE-TYPE\tFROM_LANE\tTO_LANE\tTHROUGH_TRAFFIC\tLINK_IDs[2..*]\n";
     551              :     // write record for every connection
     552          561 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     553          550 :         NBNode* n = (*i).second;
     554              :         const EdgeVector& incoming = n->getIncomingEdges();
     555         1593 :         for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
     556         1043 :             NBEdge* from = *j;
     557         1043 :             const SVCPermissions fromPerm = from->getPermissions();
     558              :             const std::vector<NBEdge::Connection>& connections = from->getConnections();
     559         3549 :             for (std::vector<NBEdge::Connection>::const_iterator it_c = connections.begin(); it_c != connections.end(); it_c++) {
     560              :                 const NBEdge::Connection& c = *it_c;
     561              :                 device
     562         2506 :                         << n->getID() << "\t"
     563         5012 :                         << getAllowedTypes(fromPerm & c.toEdge->getPermissions()) << "\t"
     564         2506 :                         << c.fromLane + 1 << "\t" // one-based
     565         2506 :                         << c.toLane + 1 << "\t" // one-based
     566         5012 :                         << 1 << "\t" // no information regarding permissibility of through traffic
     567         2506 :                         << from->getID() << "\t"
     568         2506 :                         << c.toEdge->getID() << "\t"
     569         2506 :                         << "\n";
     570              :             }
     571              :         }
     572              :     }
     573           11 :     device.close();
     574           11 : }
     575              : 
     576              : 
     577              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1