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: 2024-11-22 15:46:21 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-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_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         1689 : NWWriter_DlrNavteq::writeNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
      52              :     // check whether a matsim-file shall be generated
      53         3378 :     if (!oc.isSet("dlr-navteq-output")) {
      54         1680 :         return;
      55              :     }
      56              :     std::map<const NBEdge*, std::string> internalNodes;
      57            9 :     writeNodesUnsplitted(oc, nb.getNodeCont(), nb.getEdgeCont(), internalNodes);
      58            9 :     writeLinksUnsplitted(oc, nb.getEdgeCont(), internalNodes);
      59            9 :     writeTrafficSignals(oc, nb.getNodeCont());
      60            9 :     writeProhibitedManoeuvres(oc, nb.getNodeCont(), nb.getEdgeCont());
      61            9 :     writeConnectedLanes(oc, nb.getNodeCont());
      62              : }
      63              : 
      64              : 
      65           49 : void NWWriter_DlrNavteq::writeHeader(OutputDevice& device, const OptionsCont& oc) {
      66           49 :     device << "# Format matches Extraction version: V" << oc.getString("dlr-navteq.version") << " \n";
      67           49 :     std::stringstream tmp;
      68           98 :     oc.writeConfiguration(tmp, true, false, false);
      69           49 :     tmp.seekg(std::ios_base::beg);
      70              :     std::string line;
      71         2292 :     while (!tmp.eof()) {
      72         2243 :         std::getline(tmp, line);
      73         2243 :         device << "# " << line << "\n";
      74              :     }
      75           49 :     device << "#\n";
      76           49 : }
      77              : 
      78              : 
      79              : void
      80            9 : 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           18 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_nodes_unsplitted.txt");
      86            9 :     writeHeader(device, oc);
      87              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
      88            9 :     const bool haveGeo = gch.usingGeoProjection();
      89            9 :     const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
      90            9 :     device.setPrecision(oc.getInt("dlr-navteq.precision"));
      91            9 :     if (!haveGeo) {
      92            2 :         WRITE_WARNING(TL("DlrNavteq node data will be written in (floating point) cartesian coordinates"));
      93              :     }
      94              :     // write format specifier
      95            9 :     device << "# NODE_ID\tIS_BETWEEN_NODE\tamount_of_geocoordinates\tx1\ty1\t[x2 y2  ... xn  yn]\n";
      96              :     // write header
      97            9 :     Boundary boundary = gch.getConvBoundary();
      98            9 :     Position min(boundary.xmin(), boundary.ymin());
      99            9 :     Position max(boundary.xmax(), boundary.ymax());
     100            9 :     gch.cartesian2geo(min);
     101              :     min.mul(geoScale);
     102            9 :     gch.cartesian2geo(max);
     103              :     max.mul(geoScale);
     104            9 :     int multinodes = 0;
     105         1050 :     for (std::map<std::string, NBEdge*>::const_iterator i = ec.begin(); i != ec.end(); ++i) {
     106         1041 :         if ((*i).second->getGeometry().size() > 2) {
     107          486 :             multinodes++;
     108              :         }
     109              :     }
     110            9 :     device << "# [xmin_region] " << min.x() << "\n";
     111            9 :     device << "# [xmax_region] " << max.x() << "\n";
     112            9 :     device << "# [ymin_region] " << min.y() << "\n";
     113            9 :     device << "# [ymax_region] " << max.y() << "\n";
     114            9 :     device << "# [elements_multinode] " << multinodes << "\n";
     115            9 :     device << "# [elements_normalnode] " << nc.size() << "\n";
     116            9 :     device << "# [xmin] " << min.x() << "\n";
     117            9 :     device << "# [xmax] " << max.x() << "\n";
     118            9 :     device << "# [ymin] " << min.y() << "\n";
     119            9 :     device << "# [ymax] " << max.y() << "\n";
     120              :     // write normal nodes
     121          555 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     122          546 :         NBNode* n = (*i).second;
     123          546 :         Position pos = n->getPosition();
     124          546 :         gch.cartesian2geo(pos);
     125              :         pos.mul(geoScale);
     126          546 :         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            9 :     const bool numericalIDs = oc.getBool("numerical-ids");
     132           18 :     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            9 :     if (numericalIDs) {
     137            9 :         avoid = nc.getAllNames();
     138            9 :         std::vector<std::string> avoid2 = ec.getAllNames();
     139            9 :         avoid.insert(avoid.end(), avoid2.begin(), avoid2.end());
     140            9 :         avoid.insert(avoid.end(), reservedNodeIDs.begin(), reservedNodeIDs.end());
     141            9 :     }
     142           18 :     IDSupplier idSupplier("", avoid);
     143         1050 :     for (const auto& edgeIt : ec) {
     144         1041 :         const NBEdge* const e = edgeIt.second;
     145              :         PositionVector geom = e->getGeometry();
     146         1041 :         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          486 :             const bool hasOppositeID = ec.getOppositeByID(e->getID()) != nullptr;
     151          486 :             if (e->getLaneSpreadFunction() == LaneSpreadFunction::RIGHT && !hasOppositeID) {
     152              :                 // need to write center-line geometry instead
     153              :                 try {
     154          247 :                     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          486 :             if (geom.size() > 2) { // move2side might have changed the number of nodes
     168          486 :                 std::string internalNodeID = e->getID();
     169          486 :                 if (internalNodeID == UNDEFINED
     170          486 :                         || (nc.retrieve(internalNodeID) != nullptr)
     171          486 :                         || 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            1 :                     if (numericalIDs) {
     175            2 :                         internalNodeID = idSupplier.getNext();
     176              :                     } else {
     177              :                         internalNodeID += "_geometry";
     178              :                     }
     179              :                 }
     180          486 :                 internalNodes[e] = internalNodeID;
     181          486 :                 device << internalNodeID << "\t1\t" << geom.size() - 2;
     182         2095 :                 for (int ii = 1; ii < (int)geom.size() - 1; ++ii) {
     183         1609 :                     Position pos = geom[(int)ii];
     184         1609 :                     gch.cartesian2geo(pos);
     185              :                     pos.mul(geoScale);
     186         1609 :                     device << "\t" << pos.x() << "\t" << pos.y();
     187              :                 }
     188          486 :                 device << "\n";
     189              :             }
     190              :         }
     191         1041 :     }
     192            9 :     device.close();
     193           18 : }
     194              : 
     195              : 
     196              : void
     197            9 : NWWriter_DlrNavteq::writeLinksUnsplitted(const OptionsCont& oc, const NBEdgeCont& ec, const std::map<const NBEdge*, std::string>& internalNodes) {
     198           27 :     const int majorVersion = StringUtils::toInt(StringTokenizer(oc.getString("dlr-navteq.version"), ".").next());
     199              :     std::map<const std::string, std::string> nameIDs;
     200           18 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_links_unsplitted.txt");
     201            9 :     writeHeader(device, oc);
     202              :     // write format specifier
     203            9 :     device << "# LINK_ID\tNODE_ID_FROM\tNODE_ID_TO\tBETWEEN_NODE_ID\tLENGTH\tVEHICLE_TYPE\tFORM_OF_WAY\tBRUNNEL_TYPE\t"
     204            9 :            << "FUNCTIONAL_ROAD_CLASS\tSPEED_CATEGORY\tNUMBER_OF_LANES\tSPEED_LIMIT\tSPEED_RESTRICTION\t"
     205            9 :            << "NAME_ID1_REGIONAL\tNAME_ID2_LOCAL\tHOUSENUMBERS_RIGHT\tHOUSENUMBERS_LEFT\tZIP_CODE\t"
     206            9 :            << "AREA_ID\tSUBAREA_ID\tTHROUGH_TRAFFIC\tSPECIAL_RESTRICTIONS\tEXTENDED_NUMBER_OF_LANES\tISRAMP\tCONNECTION";
     207            9 :     if (majorVersion > 6) {
     208            1 :         device << "\tMAXHEIGHT\tMAXWIDTH\tMAXWEIGHT\tSURFACE";
     209              :     }
     210            9 :     device << "\n";
     211              :     // write edges
     212         1050 :     for (const auto& edgeIt : ec) {
     213         1041 :         const NBEdge* const e = edgeIt.second;
     214         1041 :         const int kph = speedInKph(e->getSpeed());
     215              :         const auto& internalIt = internalNodes.find(e);
     216         1041 :         const std::string& betweenNodeID = internalIt != internalNodes.end() ? internalIt->second : UNDEFINED;
     217              :         std::string nameID = UNDEFINED;
     218              :         std::string nameIDRegional = UNDEFINED;
     219         2082 :         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         1041 :         device << e->getID() << "\t"
     238         1041 :                << e->getFromNode()->getID() << "\t"
     239         1041 :                << e->getToNode()->getID() << "\t"
     240         1041 :                << betweenNodeID << "\t"
     241         1041 :                << getGraphLength(e) << "\t"
     242         1041 :                << getAllowedTypes(e->getPermissions()) << "\t"
     243         1041 :                << getFormOfWay(e) << "\t"
     244         1041 :                << getBrunnelType(e) << "\t"
     245         1041 :                << getRoadClass(e) << "\t"
     246         1041 :                << getSpeedCategory(kph) << "\t"
     247         1041 :                << getNavteqLaneCode(e->getNumLanes()) << "\t"
     248         1041 :                << getSpeedCategoryUpperBound(kph) << "\t"
     249         1041 :                << kph << "\t"
     250         1041 :                << nameIDRegional << "\t"
     251         1041 :                << nameID << "\t" // NAME_ID2_LOCAL
     252         1041 :                << UNDEFINED << "\t" // housenumbers_right
     253         1041 :                << UNDEFINED << "\t" // housenumbers_left
     254         4164 :                << getSinglePostalCode(e->getParameter("postal_code", UNDEFINED), e->getID()) << "\t" // ZIP_CODE
     255         1041 :                << UNDEFINED << "\t" // AREA_ID
     256         1041 :                << UNDEFINED << "\t" // SUBAREA_ID
     257         1041 :                << "1\t" // through_traffic (allowed)
     258         1041 :                << UNDEFINED << "\t" // special_restrictions
     259         1041 :                << UNDEFINED << "\t" // extended_number_of_lanes
     260         1041 :                << UNDEFINED << "\t" // isRamp
     261         1041 :                << "0"; // connection (between nodes always in order)
     262         1041 :         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         1041 :         device << "\n";
     269              :     }
     270           18 :     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            9 :     device.close();
     285            9 : }
     286              : 
     287              : 
     288              : std::string
     289         3555 : NWWriter_DlrNavteq::getAllowedTypes(SVCPermissions permissions) {
     290         3555 :     if (permissions == SVCAll) {
     291          625 :         return "100000000000";
     292              :     }
     293         2930 :     std::ostringstream oss;
     294         2930 :     oss << "0";
     295         4637 :     oss << ((permissions & SVC_PASSENGER)              > 0 ? 1 : 0);
     296         2930 :     oss << ((permissions & SVC_PASSENGER)              > 0 ? 1 : 0); // residential
     297         4637 :     oss << ((permissions & SVC_HOV)                    > 0 ? 1 : 0);
     298         4637 :     oss << ((permissions & SVC_EMERGENCY)              > 0 ? 1 : 0);
     299         4637 :     oss << ((permissions & SVC_TAXI)                   > 0 ? 1 : 0);
     300         4637 :     oss << ((permissions & (SVC_BUS | SVC_COACH))      > 0 ? 1 : 0);
     301         3698 :     oss << ((permissions & SVC_DELIVERY)               > 0 ? 1 : 0);
     302         4637 :     oss << ((permissions & (SVC_TRUCK | SVC_TRAILER))  > 0 ? 1 : 0);
     303         4582 :     oss << ((permissions & SVC_MOTORCYCLE)             > 0 ? 1 : 0);
     304         3379 :     oss << ((permissions & SVC_BICYCLE)                > 0 ? 1 : 0);
     305         3174 :     oss << ((permissions & SVC_PEDESTRIAN)             > 0 ? 1 : 0);
     306              :     return oss.str();
     307         2930 : }
     308              : 
     309              : 
     310              : int
     311         1741 : 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         3482 :     if (StringUtils::startsWith(type, "highway.")) {
     318         3280 :         type = type.substr(8);
     319              :     }
     320         3482 :     if (StringUtils::startsWith(type, "motorway")) {
     321              :         return 0;
     322         3426 :     } else if (StringUtils::startsWith(type, "trunk")) {
     323              :         return 1;
     324         3426 :     } else if (StringUtils::startsWith(type, "primary")) {
     325              :         return 1;
     326         3282 :     } else if (StringUtils::startsWith(type, "secondary")) {
     327              :         return 2;
     328         3152 :     } else if (StringUtils::startsWith(type, "tertiary")) {
     329              :         return 3;
     330         1411 :     } else if (type == "unclassified") {
     331              :         return 3;
     332         1220 :     } 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          110 :     const int kph = speedInKph(edge->getSpeed());
     338          110 :     if ((kph) > 100) {
     339              :         return 0;
     340              :     }
     341          108 :     if ((kph) > 70) {
     342              :         return 1;
     343              :     }
     344           68 :     if ((kph) > 50) {
     345            0 :         return (edge->getNumLanes() > 1 ? 2 : 3);
     346              :     }
     347           68 :     if ((kph) > 30) {
     348              :         return 3;
     349              :     }
     350              :     return 4;
     351              : }
     352              : 
     353              : 
     354              : int
     355         1041 : NWWriter_DlrNavteq::getSpeedCategory(int kph) {
     356         1041 :     if ((kph) > 130) {
     357              :         return 1;
     358              :     }
     359         1039 :     if ((kph) > 100) {
     360              :         return 2;
     361              :     }
     362         1039 :     if ((kph) > 90) {
     363              :         return 3;
     364              :     }
     365          999 :     if ((kph) > 70) {
     366              :         return 4;
     367              :     }
     368          918 :     if ((kph) > 50) {
     369              :         return 5;
     370              :     }
     371          916 :     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         1041 : NWWriter_DlrNavteq::getSpeedCategoryUpperBound(int kph) {
     383         1041 :     if ((kph) > 130) {
     384              :         return 131;
     385              :     }
     386         1039 :     if ((kph) > 100) {
     387              :         return 130;
     388              :     }
     389         1039 :     if ((kph) > 90) {
     390              :         return 100;
     391              :     }
     392          999 :     if ((kph) > 70) {
     393              :         return 90;
     394              :     }
     395          918 :     if ((kph) > 50) {
     396              :         return 70;
     397              :     }
     398          916 :     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         1041 : NWWriter_DlrNavteq::getNavteqLaneCode(const int numLanes) {
     410         1041 :     const int code = (numLanes == 1 ? 1 :
     411          123 :                       (numLanes < 4 ?  2 : 3));
     412         1041 :     return numLanes * 10 + code;
     413              : }
     414              : 
     415              : 
     416              : int
     417         1041 : NWWriter_DlrNavteq::getBrunnelType(const NBEdge* const edge) {
     418         2082 :     if (edge->hasParameter("bridge")) {
     419              :         return 1;
     420         2050 :     } else if (edge->hasParameter("tunnel")) {
     421              :         return 4;
     422         1025 :     } else if (edge->getTypeID() == "route.ferry") {
     423            0 :         return 10;
     424              :     }
     425              :     return -1; // UNDEFINED
     426              : }
     427              : 
     428              : 
     429              : int
     430         1041 : NWWriter_DlrNavteq::getFormOfWay(const NBEdge* const edge) {
     431         1041 :     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         1041 : NWWriter_DlrNavteq::getGraphLength(const NBEdge* const edge) {
     446              :     PositionVector geom = edge->getGeometry();
     447         1041 :     geom.push_back_noDoublePos(edge->getToNode()->getPosition());
     448         1041 :     geom.push_front_noDoublePos(edge->getFromNode()->getPosition());
     449         2082 :     return geom.length();
     450         1041 : }
     451              : 
     452              : 
     453              : std::string
     454         1041 : NWWriter_DlrNavteq::getSinglePostalCode(const std::string& zipCode, const std::string edgeID) {
     455              :     // might be multiple codes
     456         1041 :     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         1041 :     } 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            9 : NWWriter_DlrNavteq::writeTrafficSignals(const OptionsCont& oc, NBNodeCont& nc) {
     469           18 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_traffic_signals.txt");
     470            9 :     writeHeader(device, oc);
     471              :     const GeoConvHelper& gch = GeoConvHelper::getFinal();
     472            9 :     const bool haveGeo = gch.usingGeoProjection();
     473            9 :     const double geoScale = pow(10.0f, haveGeo ? 5 : 2); // see NIImporter_DlrNavteq::GEO_SCALE
     474            9 :     device.setPrecision(oc.getInt("dlr-navteq.precision"));
     475              :     // write format specifier
     476            9 :     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          555 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     479          546 :         NBNode* n = (*i).second;
     480          546 :         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            9 :     device.close();
     497            9 : }
     498              : 
     499              : 
     500              : void
     501            9 : NWWriter_DlrNavteq::writeProhibitedManoeuvres(const OptionsCont& oc, const NBNodeCont& nc, const NBEdgeCont& ec) {
     502           18 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_prohibited_manoeuvres.txt");
     503            9 :     writeHeader(device, oc);
     504              :     // need to invent id for relation
     505              :     std::set<std::string> reservedRelIDs;
     506           18 :     if (oc.isSet("reserved-ids")) {
     507            4 :         NBHelpers::loadPrefixedIDsFomFile(oc.getString("reserved-ids"), "rel:", reservedRelIDs);
     508              :     }
     509            9 :     std::vector<std::string> avoid = ec.getAllNames(); // already used for tls RELATREC_ID
     510            9 :     avoid.insert(avoid.end(), reservedRelIDs.begin(), reservedRelIDs.end());
     511            9 :     IDSupplier idSupplier("", avoid); // @note: use a global relRecIDsupplier if this is used more often
     512              :     // write format specifier
     513            9 :     device << "#No driving allowed from ID1 to ID2 or the complete chain from ID1 to IDn\n";
     514            9 :     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          555 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     517          546 :         NBNode* n = (*i).second;
     518              :         const EdgeVector& incoming = n->getIncomingEdges();
     519              :         const EdgeVector& outgoing = n->getOutgoingEdges();
     520         1587 :         for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
     521         1041 :             NBEdge* inEdge = *j;
     522         1041 :             const SVCPermissions inPerm = inEdge->getPermissions();
     523         3671 :             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            9 :     device.close();
     540           18 : }
     541              : 
     542              : 
     543              : void
     544            9 : NWWriter_DlrNavteq::writeConnectedLanes(const OptionsCont& oc, NBNodeCont& nc) {
     545           18 :     OutputDevice& device = OutputDevice::getDevice(oc.getString("dlr-navteq-output") + "_connected_lanes.txt");
     546            9 :     writeHeader(device, oc);
     547              :     // write format specifier
     548            9 :     device << "#Lane connections related to LINK-IDs and NODE-ID.\n";
     549            9 :     device << "#column format like pointcollection.\n";
     550            9 :     device << "#NODE-ID\tVEHICLE-TYPE\tFROM_LANE\tTO_LANE\tTHROUGH_TRAFFIC\tLINK_IDs[2..*]\n";
     551              :     // write record for every connection
     552          555 :     for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
     553          546 :         NBNode* n = (*i).second;
     554              :         const EdgeVector& incoming = n->getIncomingEdges();
     555         1587 :         for (EdgeVector::const_iterator j = incoming.begin(); j != incoming.end(); ++j) {
     556         1041 :             NBEdge* from = *j;
     557         1041 :             const SVCPermissions fromPerm = from->getPermissions();
     558              :             const std::vector<NBEdge::Connection>& connections = from->getConnections();
     559         3547 :             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            9 :     device.close();
     574            9 : }
     575              : 
     576              : 
     577              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1