LCOV - code coverage report
Current view: top level - src/netimport - NIImporter_DlrNavteq.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 85.2 % 438 373
Test Date: 2024-11-20 15:55:46 Functions: 80.6 % 36 29

            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    NIImporter_DlrNavteq.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Jakob Erdmann
      17              : /// @author  Michael Behrisch
      18              : /// @date    Mon, 14.04.2008
      19              : ///
      20              : // Importer for networks stored in Elmar's format
      21              : /****************************************************************************/
      22              : #include <config.h>
      23              : 
      24              : #include <string>
      25              : #include <sstream>
      26              : #include <limits>
      27              : #include <utils/importio/LineHandler.h>
      28              : #include <utils/common/StringTokenizer.h>
      29              : #include <utils/common/MsgHandler.h>
      30              : #include <utils/common/UtilExceptions.h>
      31              : #include <utils/common/StringUtils.h>
      32              : #include <utils/common/ToString.h>
      33              : #include <utils/common/StringUtils.h>
      34              : #include <utils/options/OptionsCont.h>
      35              : #include <utils/importio/LineReader.h>
      36              : #include <utils/geom/GeoConvHelper.h>
      37              : #include <netbuild/NBNetBuilder.h>
      38              : #include <netbuild/NBNode.h>
      39              : #include <netbuild/NBNodeCont.h>
      40              : #include <netbuild/NBEdge.h>
      41              : #include <netbuild/NBEdgeCont.h>
      42              : #include <netbuild/NBTypeCont.h>
      43              : #include <netbuild/NBOwnTLDef.h>
      44              : #include <netimport/NINavTeqHelper.h>
      45              : #include "NILoader.h"
      46              : #include "NIImporter_DlrNavteq.h"
      47              : 
      48              : 
      49              : // ---------------------------------------------------------------------------
      50              : // static members
      51              : // ---------------------------------------------------------------------------
      52              : const std::string NIImporter_DlrNavteq::GEO_SCALE("1e-5");
      53              : const int NIImporter_DlrNavteq::EdgesHandler::MISSING_COLUMN = std::numeric_limits<int>::max();
      54              : const std::string NIImporter_DlrNavteq::UNDEFINED("-1");
      55              : bool NIImporter_DlrNavteq::keepLength = false;
      56              : 
      57              : // ===========================================================================
      58              : // method definitions
      59              : // ===========================================================================
      60              : // ---------------------------------------------------------------------------
      61              : // static methods
      62              : // ---------------------------------------------------------------------------
      63              : void
      64         1884 : NIImporter_DlrNavteq::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
      65              :     // check whether the option is set (properly)
      66         3768 :     if (!oc.isSet("dlr-navteq-prefix")) {
      67         1835 :         return;
      68              :     }
      69              :     time_t csTime;
      70           49 :     time(&csTime);
      71           49 :     keepLength = oc.getBool("dlr-navteq.keep-length");
      72              :     // parse file(s)
      73           49 :     LineReader lr;
      74              :     // load nodes
      75              :     std::map<std::string, PositionVector> myGeoms;
      76           98 :     PROGRESS_BEGIN_MESSAGE(TL("Loading nodes"));
      77           98 :     std::string file = oc.getString("dlr-navteq-prefix") + "_nodes_unsplitted.txt";
      78           49 :     NodesHandler handler1(nb.getNodeCont(), file, myGeoms);
      79           49 :     if (!lr.setFile(file)) {
      80            0 :         throw ProcessError(TLF("The file '%' could not be opened.", file));
      81              :     }
      82           49 :     lr.readAll(handler1);
      83           49 :     PROGRESS_DONE_MESSAGE();
      84              : 
      85              :     // load street names if given and wished
      86              :     std::map<std::string, std::string> streetNames; // nameID : name
      87           98 :     if (oc.getBool("output.street-names")) {
      88            6 :         file = oc.getString("dlr-navteq-prefix") + "_names.txt";
      89            3 :         if (lr.setFile(file)) {
      90            6 :             PROGRESS_BEGIN_MESSAGE(TL("Loading street names"));
      91            3 :             NamesHandler handler4(file, streetNames);
      92            3 :             lr.readAll(handler4);
      93            3 :             PROGRESS_DONE_MESSAGE();
      94            3 :         } else {
      95            0 :             WRITE_WARNINGF(TL("Output will not contain street names because the file '%' was not found"), file);
      96              :         }
      97              :     }
      98              : 
      99              :     // load edges
     100           98 :     PROGRESS_BEGIN_MESSAGE(TL("Loading edges"));
     101          147 :     file = oc.getString("dlr-navteq-prefix") + "_links_unsplitted.txt";
     102              :     // parse the file
     103           49 :     EdgesHandler handler2(nb.getNodeCont(), nb.getEdgeCont(), nb.getTypeCont(), file, myGeoms, streetNames);
     104           49 :     if (!lr.setFile(file)) {
     105            0 :         throw ProcessError(TLF("The file '%' could not be opened.", file));
     106              :     }
     107           49 :     lr.readAll(handler2);
     108           49 :     nb.getEdgeCont().recheckLaneSpread();
     109           49 :     PROGRESS_DONE_MESSAGE();
     110              : 
     111              :     // load traffic lights if given
     112           98 :     file = oc.getString("dlr-navteq-prefix") + "_traffic_signals.txt";
     113           49 :     if (lr.setFile(file)) {
     114           12 :         PROGRESS_BEGIN_MESSAGE(TL("Loading traffic lights"));
     115            4 :         TrafficlightsHandler handler3(nb.getNodeCont(), nb.getTLLogicCont(), nb.getEdgeCont(), file);
     116            4 :         lr.readAll(handler3);
     117            4 :         PROGRESS_DONE_MESSAGE();
     118            4 :     }
     119              : 
     120              :     // load prohibited manoeuvres if given
     121           98 :     file = oc.getString("dlr-navteq-prefix") + "_prohibited_manoeuvres.txt";
     122           49 :     if (lr.setFile(file)) {
     123            6 :         PROGRESS_BEGIN_MESSAGE(TL("Loading prohibited manoeuvres"));
     124            3 :         ProhibitionHandler handler6(nb.getEdgeCont(), file, csTime);
     125            3 :         lr.readAll(handler6);
     126            3 :         PROGRESS_DONE_MESSAGE();
     127            3 :     }
     128              : 
     129              :     // load connected lanes if given
     130           98 :     file = oc.getString("dlr-navteq-prefix") + "_connected_lanes.txt";
     131           49 :     if (lr.setFile(file)) {
     132           10 :         PROGRESS_BEGIN_MESSAGE(TL("Loading connected lanes"));
     133            5 :         ConnectedLanesHandler handler7(nb.getEdgeCont());
     134            5 :         lr.readAll(handler7);
     135            5 :         PROGRESS_DONE_MESSAGE();
     136            5 :     }
     137              : 
     138              :     // load time restrictions if given
     139           98 :     file = oc.getString("dlr-navteq-prefix") + "_links_timerestrictions.txt";
     140           49 :     if (lr.setFile(file)) {
     141            2 :         PROGRESS_BEGIN_MESSAGE(TL("Loading time restrictions"));
     142            2 :         if (!oc.isDefault("construction-date")) {
     143            2 :             csTime = readDate(oc.getString("construction-date"));
     144              :         }
     145            1 :         TimeRestrictionsHandler handler5(nb.getEdgeCont(), nb.getDistrictCont(), csTime);
     146            1 :         lr.readAll(handler5);
     147            1 :         handler5.printSummary();
     148            1 :         PROGRESS_DONE_MESSAGE();
     149            1 :     }
     150              : 
     151          147 : }
     152              : 
     153              : double
     154           60 : NIImporter_DlrNavteq::readVersion(const std::string& line, const std::string& file) {
     155              :     assert(line[0] == '#');
     156           60 :     const std::string marker = "extraction version: v";
     157           60 :     const std::string lowerCase = StringUtils::to_lower_case(line);
     158           60 :     if (lowerCase.find(marker) == std::string::npos) {
     159              :         return -1;
     160              :     }
     161           52 :     const int vStart = (int)(lowerCase.find(marker) + marker.size());
     162           52 :     const int vEnd = (int)line.find(" ", vStart);
     163              :     try {
     164           52 :         const double version = StringUtils::toDouble(line.substr(vStart, vEnd - vStart));
     165           52 :         if (version < 0) {
     166            0 :             throw ProcessError("Invalid version number '" + toString(version) + "' in file '" + file + "'.");
     167              :         }
     168              :         return version;
     169            0 :     } catch (NumberFormatException&) {
     170            0 :         throw ProcessError("Non-numerical value '" + line.substr(vStart, vEnd - vStart) + "' for version string in file '" + file + "'.");
     171            0 :     }
     172              : }
     173              : 
     174              : 
     175              : // ---------------------------------------------------------------------------
     176              : // definitions of NIImporter_DlrNavteq::NodesHandler-methods
     177              : // ---------------------------------------------------------------------------
     178           49 : NIImporter_DlrNavteq::NodesHandler::NodesHandler(NBNodeCont& nc,
     179              :         const std::string& file,
     180           49 :         std::map<std::string, PositionVector>& geoms)
     181           49 :     : myNodeCont(nc), myGeoms(geoms) {
     182              :     UNUSED_PARAMETER(file);
     183           49 : }
     184              : 
     185              : 
     186           49 : NIImporter_DlrNavteq::NodesHandler::~NodesHandler() {}
     187              : 
     188              : 
     189              : bool
     190          992 : NIImporter_DlrNavteq::NodesHandler::report(const std::string& result) {
     191          992 :     if (result[0] == '#') {
     192              :         return true;
     193              :     }
     194              :     std::string id;
     195              :     double x, y;
     196              :     int no_geoms, intermediate;
     197              :     // parse
     198          577 :     std::istringstream stream(result);
     199              :     // id
     200          577 :     stream >> id;
     201          577 :     if (stream.fail()) {
     202            0 :         throw ProcessError("Something is wrong with the following data line\n" + result);
     203              :     }
     204              :     // intermediate?
     205          577 :     stream >> intermediate;
     206          577 :     if (stream.fail()) {
     207            0 :         if (myNodeCont.size() == 0) { // be generous with extra data at beginning of file
     208              :             return true;
     209              :         }
     210            0 :         throw ProcessError(TLF("Non-numerical value for intermediate status in node %.", id));
     211              :     }
     212              :     // number of geometrical information
     213          577 :     stream >> no_geoms;
     214          577 :     if (stream.fail()) {
     215            0 :         throw ProcessError(TLF("Non-numerical value for number of geometries in node %.", id));
     216              :     }
     217              :     // geometrical information
     218          577 :     PositionVector geoms;
     219         1416 :     for (int i = 0; i < no_geoms; i++) {
     220              :         stream >> x;
     221          839 :         if (stream.fail()) {
     222            0 :             throw ProcessError(TLF("Non-numerical value for x-position in node %.", id));
     223              :         }
     224              :         stream >> y;
     225          839 :         if (stream.fail()) {
     226            0 :             throw ProcessError(TLF("Non-numerical value for y-position in node %.", id));
     227              :         }
     228          839 :         Position pos(x, y);
     229          839 :         if (!NBNetBuilder::transformCoordinate(pos, true)) {
     230            0 :             throw ProcessError(TLF("Unable to project coordinates for node %.", id));
     231              :         }
     232          839 :         geoms.push_back(pos);
     233              :     }
     234              : 
     235          577 :     if (intermediate == 0) {
     236          427 :         NBNode* n = new NBNode(id, geoms[0]);
     237          427 :         if (!myNodeCont.insert(n)) {
     238            1 :             delete n;
     239            2 :             if (OptionsCont::getOptions().getBool("ignore-errors")) {
     240            3 :                 WRITE_WARNINGF(TL("Could not add node '%'."), id);
     241              :             } else {
     242            0 :                 throw ProcessError(TLF("Could not add node '%'.", id));
     243              :             }
     244              :         }
     245              :     } else {
     246          150 :         myGeoms[id] = geoms;
     247              :     }
     248              :     return true;
     249          577 : }
     250              : 
     251              : 
     252              : // ---------------------------------------------------------------------------
     253              : // definitions of NIImporter_DlrNavteq::EdgesHandler-methods
     254              : // ---------------------------------------------------------------------------
     255           49 : NIImporter_DlrNavteq::EdgesHandler::EdgesHandler(NBNodeCont& nc, NBEdgeCont& ec,
     256              :         NBTypeCont& tc, const std::string& file,
     257              :         std::map<std::string, PositionVector>& geoms,
     258           49 :         std::map<std::string, std::string>& streetNames):
     259           49 :     myNodeCont(nc),
     260           49 :     myEdgeCont(ec),
     261           49 :     myTypeCont(tc),
     262           49 :     myGeoms(geoms),
     263           49 :     myStreetNames(streetNames),
     264           49 :     myVersion(0),
     265           49 :     myFile(file) {
     266           49 : }
     267              : 
     268              : 
     269           49 : NIImporter_DlrNavteq::EdgesHandler::~EdgesHandler() {}
     270              : 
     271              : 
     272              : bool
     273          984 : NIImporter_DlrNavteq::EdgesHandler::report(const std::string& result) {
     274              :     // parse version number from first comment line and initialize column definitions
     275          984 :     if (result[0] == '#') {
     276          321 :         if (!myColumns.empty()) {
     277              :             return true;
     278              :         }
     279           55 :         const double version = readVersion(result, myFile);
     280           55 :         if (version > 0) {
     281           49 :             myVersion = version;
     282              :             // init columns
     283              :             const int NUM_COLUMNS = 25; // @note arrays must match this size!
     284              :             const int MC = MISSING_COLUMN;
     285           49 :             if (myVersion < 3) {
     286           37 :                 const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, MC, 12, 13, 14, 15, 16, 17, 18, 19, 20, MC, MC, -21};
     287           37 :                 myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
     288           12 :             } else if (myVersion < 6) {
     289            3 :                 const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, MC, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -23};
     290            3 :                 myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
     291              :             } else {
     292            9 :                 const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
     293            9 :                 myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
     294              :             }
     295              :         }
     296           55 :         return true;
     297              :     }
     298          663 :     if (myColumns.empty()) {
     299            0 :         throw ProcessError(TLF("Missing version string in file '%'.", myFile));
     300              :     }
     301              :     // interpret link attributes
     302          663 :     StringTokenizer st(result, StringTokenizer::WHITECHARS);
     303          663 :     const std::string id = getColumn(st, LINK_ID);
     304              :     // form of way (for priority and permissions)
     305              :     int form_of_way;
     306              :     try {
     307          663 :         form_of_way = StringUtils::toInt(getColumn(st, FORM_OF_WAY));
     308            0 :     } catch (NumberFormatException&) {
     309            0 :         throw ProcessError(TLF("Non-numerical value for form_of_way of link '%'.", id));
     310            0 :     }
     311              :     // brunnel type (bridge/tunnel/ferry (for permissions)
     312              :     int brunnel_type;
     313              :     try {
     314          663 :         brunnel_type = StringUtils::toInt(getColumn(st, BRUNNEL_TYPE));
     315            0 :     } catch (NumberFormatException&) {
     316            0 :         throw ProcessError(TLF("Non-numerical value for brunnel_type of link '%'.", id));
     317            0 :     }
     318              :     // priority based on street_type / frc
     319              :     int priority;
     320              :     try {
     321          663 :         priority = -StringUtils::toInt(getColumn(st, FUNCTIONAL_ROAD_CLASS));
     322              :         // lower priority using form_of_way
     323          663 :         if (form_of_way == 11) {
     324              :             priority -= 1; // frontage road, very often with lowered curb
     325          661 :         } else if (form_of_way > 11) {
     326              :             priority -= 2; // parking/service access assume lowered curb
     327              :         }
     328            0 :     } catch (NumberFormatException&) {
     329            0 :         throw ProcessError(TLF("Non-numerical value for street_type of link '%'.", id));
     330            0 :     }
     331              :     // street name
     332              :     std::string streetName = getStreetNameFromIDs(
     333         1326 :                                  getColumn(st, NAME_ID1_REGIONAL),
     334         1326 :                                  getColumn(st, NAME_ID2_LOCAL));
     335              :     // try to get the nodes
     336          663 :     const std::string fromID = getColumn(st, NODE_ID_FROM);
     337          663 :     const std::string toID = getColumn(st, NODE_ID_TO);
     338          663 :     NBNode* from = myNodeCont.retrieve(fromID);
     339          663 :     NBNode* to = myNodeCont.retrieve(toID);
     340          663 :     if (from == nullptr) {
     341            0 :         throw ProcessError("The from-node '" + fromID + "' of link '" + id + "' could not be found");
     342              :     }
     343          663 :     if (to == nullptr) {
     344            0 :         throw ProcessError("The to-node '" + toID + "' of link '" + id + "' could not be found");
     345              :     }
     346              :     // speed
     347              :     double speed;
     348              :     try {
     349          663 :         speed = StringUtils::toInt(getColumn(st, SPEED_RESTRICTION, "-1")) / 3.6;
     350            0 :     } catch (NumberFormatException&) {
     351            0 :         throw ProcessError(TLF("Non-numerical value for the SPEED_RESTRICTION of link '%'.", id));
     352            0 :     }
     353          663 :     if (speed < 0) {
     354              :         // speed category as fallback
     355          686 :         speed = NINavTeqHelper::getSpeed(id, getColumn(st, SPEED_CATEGORY));
     356              :     }
     357              :     // number of lanes
     358              :     int numLanes;
     359              :     try {
     360              :         // EXTENDED_NUMBER_OF_LANES is prefered but may not be defined
     361          663 :         numLanes = StringUtils::toInt(getColumn(st, EXTENDED_NUMBER_OF_LANES, "-1"));
     362          663 :         if (numLanes == -1) {
     363         1326 :             numLanes = NINavTeqHelper::getLaneNumber(id, getColumn(st, NUMBER_OF_LANES), speed);
     364              :         }
     365            0 :     } catch (NumberFormatException&) {
     366            0 :         throw ProcessError(TLF("Non-numerical value for the number of lanes of link '%'.", id));
     367            0 :     }
     368              : 
     369         1989 :     const std::string navTeqTypeId = getColumn(st, VEHICLE_TYPE) + "_" + getColumn(st, FORM_OF_WAY);
     370              :     // build the edge
     371              :     NBEdge* e = nullptr;
     372          663 :     const std::string interID = getColumn(st, BETWEEN_NODE_ID);
     373          663 :     if (interID == "-1") {
     374         1020 :         e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, NBEdge::UNSPECIFIED_FRICTION, numLanes, priority,
     375         1020 :                        NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, LaneSpreadFunction::RIGHT, streetName);
     376              :     } else {
     377          153 :         PositionVector geoms = myGeoms[interID];
     378          306 :         if (getColumn(st, CONNECTION, "0") == "1") {
     379           70 :             geoms = geoms.reverse();
     380              :         }
     381          153 :         geoms.insert(geoms.begin(), from->getPosition());
     382          153 :         geoms.push_back(to->getPosition());
     383          153 :         const std::string origID = OptionsCont::getOptions().getBool("output.original-names") ? id : "";
     384          153 :         e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, NBEdge::UNSPECIFIED_FRICTION, numLanes, priority,
     385          612 :                        NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, geoms, LaneSpreadFunction::CENTER, streetName, origID);
     386          153 :     }
     387              : 
     388              :     //Import length or edges from input file
     389          663 :     if (keepLength) {
     390            8 :         const double length = StringUtils::toDouble(getColumn(st, LENGTH));
     391            8 :         e->setLoadedLength(length);
     392              :     }
     393              : 
     394              :     // NavTeq imports can be done with a typemap (if supplied), if not, the old defaults are used
     395          663 :     if (myTypeCont.knows(navTeqTypeId)) {
     396            8 :         e->setPermissions(myTypeCont.getEdgeTypePermissions(navTeqTypeId));
     397              :     } else {
     398              :         // add vehicle type information to the edge
     399          655 :         const SVCPermissions allPermissions = myTypeCont.getEdgeTypePermissions("");
     400          655 :         const SVCPermissions defaultPermissions = OptionsCont::getOptions().getBool("dlr-navteq.tolerant-permissions") ? allPermissions : 0;
     401          655 :         if (myVersion < 6.0) {
     402          656 :             NINavTeqHelper::addVehicleClasses(*e, getColumn(st, VEHICLE_TYPE), allPermissions, defaultPermissions);
     403              :         } else {
     404          654 :             NINavTeqHelper::addVehicleClassesV6(*e, getColumn(st, VEHICLE_TYPE), allPermissions, defaultPermissions);
     405              :         }
     406              :         // permission modifications based on form_of_way
     407          655 :         if (form_of_way == 14) { // pedestrian area (fussgaengerzone)
     408              :             // unfortunately, the veh_type string is misleading in this case
     409           31 :             e->disallowVehicleClass(-1, SVC_PASSENGER);
     410              :         }
     411              :         // permission modifications based on brunnel_type
     412          655 :         if (brunnel_type == 10) { // ferry
     413            0 :             e->setPermissions(SVC_SHIP, -1);
     414              :         }
     415              :     }
     416              : 
     417              :     // insert the edge to the network
     418          663 :     if (!myEdgeCont.insert(e)) {
     419            0 :         delete e;
     420            0 :         throw ProcessError(TLF("Could not add edge '%'.", id));
     421              :     }
     422              :     return true;
     423          663 : }
     424              : 
     425              : 
     426              : std::string
     427        10441 : NIImporter_DlrNavteq::EdgesHandler::getColumn(const StringTokenizer& st, ColumnName name, const std::string fallback) {
     428              :     assert(!myColumns.empty());
     429        10441 :     if (myColumns[name] == MISSING_COLUMN) {
     430          624 :         if (fallback == "") {
     431            0 :             throw ProcessError(TLF("Missing column %.", toString(name)));
     432              :         } else {
     433              :             return fallback;
     434              :         }
     435         9817 :     } else if (myColumns[name] >= 0) {
     436         9799 :         return st.get((int)(myColumns[name]));
     437              :     } else {
     438              :         // negative column number implies an optional column
     439           18 :         if ((int) st.size() <= -myColumns[name]) {
     440              :             // the column is not present
     441            9 :             if (fallback == "") {
     442            0 :                 throw ProcessError(TLF("Missing optional column % without default value.", toString(name)));
     443              :             } else {
     444              :                 return fallback;
     445              :             }
     446              :         } else {
     447            9 :             return st.get((int)(-myColumns[name]));
     448              :         }
     449              :     }
     450              : }
     451              : 
     452              : 
     453              : std::string
     454          663 : NIImporter_DlrNavteq::EdgesHandler::getStreetNameFromIDs(
     455              :     const std::string& regionalID, const std::string& localID) const {
     456          663 :     std::string result = "";
     457              :     bool hadRegional = false;
     458          663 :     if (myStreetNames.count(regionalID) > 0) {
     459              :         hadRegional = true;
     460           24 :         result += myStreetNames[regionalID];
     461              :     }
     462          663 :     if (myStreetNames.count(localID) > 0) {
     463           18 :         if (hadRegional) {
     464              :             result += " / ";
     465              :         }
     466           18 :         result += myStreetNames[localID];
     467              :     }
     468          663 :     return result;
     469              : }
     470              : 
     471              : // ---------------------------------------------------------------------------
     472              : // definitions of NIImporter_DlrNavteq::TrafficlightsHandler-methods
     473              : // ---------------------------------------------------------------------------
     474            4 : NIImporter_DlrNavteq::TrafficlightsHandler::TrafficlightsHandler(NBNodeCont& nc,
     475              :         NBTrafficLightLogicCont& tlc,
     476              :         NBEdgeCont& ne,
     477            4 :         const std::string& file) :
     478            4 :     myNodeCont(nc),
     479            4 :     myTLLogicCont(tlc),
     480            4 :     myEdgeCont(ne) {
     481              :     UNUSED_PARAMETER(file);
     482            4 : }
     483              : 
     484              : 
     485            4 : NIImporter_DlrNavteq::TrafficlightsHandler::~TrafficlightsHandler() {}
     486              : 
     487              : 
     488              : bool
     489           68 : NIImporter_DlrNavteq::TrafficlightsHandler::report(const std::string& result) {
     490              : // #ID     POICOL-TYPE     DESCRIPTION     LONGITUDE       LATITUDE        NAVTEQ_LINK_ID  NODEID
     491              : 
     492           68 :     if (result[0] == '#') {
     493              :         return true;
     494              :     }
     495           11 :     StringTokenizer st(result, StringTokenizer::WHITECHARS);
     496           11 :     const std::string edgeID = st.get(5);
     497           11 :     NBEdge* edge = myEdgeCont.retrieve(edgeID);
     498           11 :     if (edge == nullptr) {
     499            0 :         WRITE_WARNINGF(TL("The traffic light edge '%' could not be found."), edgeID);
     500              :     } else {
     501              :         NBNode* node = edge->getToNode();
     502           11 :         if (node->getType() != SumoXMLNodeType::TRAFFIC_LIGHT) {
     503            7 :             node->reinit(node->getPosition(), SumoXMLNodeType::TRAFFIC_LIGHT);
     504              :             // @note. There may be additional information somewhere in the GDF files about traffic light type ...
     505            7 :             TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type"));
     506              :             // @note actually we could use the navteq node ID here
     507            7 :             NBTrafficLightDefinition* tlDef = new NBOwnTLDef(node->getID(), node, 0, type);
     508            7 :             if (!myTLLogicCont.insert(tlDef)) {
     509              :                 // actually, nothing should fail here
     510            0 :                 delete tlDef;
     511            0 :                 throw ProcessError(TLF("Could not allocate tls for '%'.", node->getID()));
     512              :             }
     513              :         }
     514              :     }
     515              :     return true;
     516           11 : }
     517              : 
     518              : 
     519              : // ---------------------------------------------------------------------------
     520              : // definitions of NIImporter_DlrNavteq::NamesHandler-methods
     521              : // ---------------------------------------------------------------------------
     522            3 : NIImporter_DlrNavteq::NamesHandler::NamesHandler(
     523            3 :     const std::string& file, std::map<std::string, std::string>& streetNames) :
     524            3 :     myStreetNames(streetNames) {
     525              :     UNUSED_PARAMETER(file);
     526            3 : }
     527              : 
     528              : 
     529            3 : NIImporter_DlrNavteq::NamesHandler::~NamesHandler() {}
     530              : 
     531              : 
     532              : bool
     533           21 : NIImporter_DlrNavteq::NamesHandler::report(const std::string& result) {
     534              : // # NAME_ID    Name
     535           21 :     if (result[0] == '#') {
     536              :         return true;
     537              :     }
     538           15 :     StringTokenizer st(result, StringTokenizer::TAB);
     539           15 :     if (st.size() == 1) {
     540              :         return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
     541              :     }
     542              :     assert(st.size() >= 2);
     543           12 :     const std::string id = st.next();
     544           12 :     if (st.size() > 2) {
     545            4 :         const std::string permanent_id_info = st.next();
     546              :     }
     547           24 :     myStreetNames[id] = st.next();
     548              :     return true;
     549           15 : }
     550              : 
     551              : 
     552              : // ---------------------------------------------------------------------------
     553              : // definitions of NIImporter_DlrNavteq::TimeRestrictionsHandler-methods
     554              : // ---------------------------------------------------------------------------
     555            1 : NIImporter_DlrNavteq::TimeRestrictionsHandler::TimeRestrictionsHandler(NBEdgeCont& ec, NBDistrictCont& dc, time_t constructionTime):
     556            1 :     myEdgeCont(ec),
     557            1 :     myDistrictCont(dc),
     558            1 :     myConstructionTime(constructionTime),
     559            1 :     myCS_min(std::numeric_limits<time_t>::max()),
     560            1 :     myCS_max(std::numeric_limits<time_t>::min()),
     561            1 :     myConstructionEntries(0),
     562            1 :     myNotStarted(0),
     563            1 :     myUnderConstruction(0),
     564            1 :     myFinished(0),
     565            1 :     myRemovedEdges(0) {
     566            1 : }
     567              : 
     568              : 
     569            1 : NIImporter_DlrNavteq::TimeRestrictionsHandler::~TimeRestrictionsHandler() {}
     570              : 
     571              : 
     572              : bool
     573            5 : NIImporter_DlrNavteq::TimeRestrictionsHandler::report(const std::string& result) {
     574              : // # NAME_ID    Name
     575            5 :     if (result[0] == '#') {
     576              :         return true;
     577              :     }
     578            3 :     StringTokenizer st(result, StringTokenizer::WHITECHARS);
     579            3 :     const std::string id = st.next();
     580            3 :     const std::string type = st.next();
     581            3 :     const std::string directionOfFlow = st.next(); // can be ignored since unidirectional edge ids are referenced in the file
     582            3 :     const std::string throughTraffic = st.next();
     583            3 :     const std::string vehicleType = st.next();
     584            3 :     const std::string validityPeriod = st.next();
     585            3 :     const std::string warning = "Unrecognized TIME_REC '" + validityPeriod + "'";
     586            3 :     if (type == "CS") {
     587            3 :         myConstructionEntries++;
     588            3 :         if (validityPeriod.size() > 1024) {
     589            0 :             WRITE_WARNING(warning);
     590              :         }
     591              :         // construction
     592              :         char start[1024];
     593              :         char duration[1024];
     594              : 
     595              :         int matched;
     596              : 
     597            3 :         matched = sscanf(validityPeriod.c_str(), "[(%[^)]){%[^}]}]", start, duration);
     598            3 :         if (matched == 2) {
     599            6 :             time_t tStart = readTimeRec(start, "");
     600            6 :             time_t tEnd = readTimeRec(start, duration);
     601            3 :             myCS_min = MIN2(myCS_min, tStart);
     602            3 :             myCS_max = MAX2(myCS_max, tEnd);
     603              :             //std::cout << " start=" << start << " tStart=" << tStart<< " translation=" << asctime(localtime(&tStart)) << "";
     604              :             //std::cout << " duration=" << duration << " tEnd=" << tEnd << " translation=" << asctime(localtime(&tEnd)) << "\n";
     605            3 :             if (myConstructionTime < tEnd) {
     606            2 :                 NBEdge* edge = myEdgeCont.retrieve(id);
     607            2 :                 if (edge != nullptr) {
     608            2 :                     myRemovedEdges++;
     609            2 :                     myEdgeCont.extract(myDistrictCont, edge, true);
     610              :                 }
     611            2 :                 if (myConstructionTime < tStart) {
     612            1 :                     myNotStarted++;
     613              :                 } else {
     614            1 :                     myUnderConstruction++;
     615              :                 }
     616              :             } else {
     617            1 :                 myFinished++;
     618              :             }
     619              :         } else {
     620            0 :             WRITE_WARNING(warning);
     621              :         };
     622              :     }
     623              :     return true;
     624            3 : }
     625              : 
     626              : 
     627              : void
     628            1 : NIImporter_DlrNavteq::TimeRestrictionsHandler::printSummary() {
     629            1 :     if (myConstructionEntries > 0) {
     630              :         char buff[1024];
     631            1 :         std::ostringstream msg;
     632            1 :         strftime(buff, 1024, "%Y-%m-%d", localtime(&myCS_min));
     633            2 :         msg << "Parsed " << myConstructionEntries << " construction entries between " << buff;
     634            1 :         strftime(buff, 1024, "%Y-%m-%d", localtime(&myCS_max));
     635            1 :         msg << " and " << buff << ".\n";
     636            1 :         strftime(buff, 1024, "%Y-%m-%d", localtime(&myConstructionTime));
     637            2 :         msg << "Removed " << myRemovedEdges << " edges not yet constructed at " << buff << ".\n";
     638            1 :         msg << "   not yet started: " << myNotStarted << "\n";
     639            1 :         msg << "   under construction: " << myUnderConstruction << "\n";
     640            1 :         msg << "   finished: " << myFinished << "\n";
     641            1 :         WRITE_MESSAGE(msg.str());
     642            1 :     }
     643            1 : }
     644              : 
     645              : 
     646              : int
     647           48 : NIImporter_DlrNavteq::readPrefixedInt(const std::string& s, const std::string& prefix, int fallBack) {
     648           48 :     int result = fallBack;
     649              :     const size_t pos = s.find(prefix);
     650           48 :     if (pos != std::string::npos) {
     651           30 :         sscanf(s.substr(pos + prefix.size()).c_str(), "%i", &result);
     652              :     }
     653           48 :     return result;
     654              : }
     655              : 
     656              : 
     657              : time_t
     658            6 : NIImporter_DlrNavteq::readTimeRec(const std::string& start, const std::string& duration) {
     659              :     // http://www.cplusplus.com/reference/ctime/mktime/
     660              :     struct tm timeinfo;
     661            6 :     timeinfo.tm_hour = 0;
     662            6 :     timeinfo.tm_min = 0;
     663            6 :     timeinfo.tm_sec = 0;
     664            6 :     timeinfo.tm_year = 0;
     665            6 :     timeinfo.tm_mon = 0;
     666            6 :     timeinfo.tm_mday = 1;
     667            6 :     timeinfo.tm_wday = 0;
     668            6 :     timeinfo.tm_yday = 0;
     669            6 :     timeinfo.tm_isdst = 0;
     670              : 
     671            6 :     timeinfo.tm_year = readPrefixedInt(start, "y") + readPrefixedInt(duration, "y") - 1900;
     672            6 :     timeinfo.tm_mon = readPrefixedInt(start, "M") + readPrefixedInt(duration, "M") - 1;
     673            6 :     timeinfo.tm_mday = 7 * (readPrefixedInt(start, "w") + readPrefixedInt(duration, "w"));
     674            6 :     timeinfo.tm_mday += readPrefixedInt(start, "d") + readPrefixedInt(duration, "d");
     675              : 
     676            6 :     time_t result =  mktime(&timeinfo);
     677            6 :     return result;
     678              : }
     679              : 
     680              : 
     681              : time_t
     682            1 : NIImporter_DlrNavteq::readDate(const std::string& yyyymmdd) {
     683              :     struct tm timeinfo;
     684            1 :     timeinfo.tm_hour = 0;
     685            1 :     timeinfo.tm_min = 0;
     686            1 :     timeinfo.tm_sec = 0;
     687            1 :     timeinfo.tm_wday = 0;
     688            1 :     timeinfo.tm_yday = 0;
     689            1 :     timeinfo.tm_isdst = 0;
     690              : 
     691              :     if (yyyymmdd.size() == 10
     692            1 :             && yyyymmdd[4] == '-'
     693            2 :             && yyyymmdd[7] == '-') {
     694              :         try {
     695            1 :             timeinfo.tm_year = StringUtils::toInt(yyyymmdd.substr(0, 4)) - 1900;
     696            1 :             timeinfo.tm_mon = StringUtils::toInt(yyyymmdd.substr(5, 2)) - 1;
     697            1 :             timeinfo.tm_mday = StringUtils::toInt(yyyymmdd.substr(8, 2));
     698            1 :             return mktime(&timeinfo);
     699            0 :         } catch (...) {
     700            0 :         }
     701              :     }
     702            0 :     WRITE_ERRORF(TL("Could not parse YYYY-MM-DD date '%'"), yyyymmdd);
     703              :     time_t now;
     704            0 :     time(&now);
     705            0 :     return now;
     706              : }
     707              : 
     708              : // ---------------------------------------------------------------------------
     709              : // definitions of NIImporter_DlrNavteq::ProhibitionHandler-methods
     710              : // ---------------------------------------------------------------------------
     711            3 : NIImporter_DlrNavteq::ProhibitionHandler::ProhibitionHandler(
     712            3 :     NBEdgeCont& ec, const std::string& file, time_t constructionTime) :
     713            3 :     myEdgeCont(ec),
     714            3 :     myFile(file),
     715            3 :     myVersion(0),
     716            3 :     myConstructionTime(constructionTime) {
     717            3 : }
     718              : 
     719              : 
     720            3 : NIImporter_DlrNavteq::ProhibitionHandler::~ProhibitionHandler() {}
     721              : 
     722              : 
     723              : bool
     724          108 : NIImporter_DlrNavteq::ProhibitionHandler::report(const std::string& result) {
     725              : // # NAME_ID    Name
     726          108 :     if (result[0] == '#') {
     727           94 :         if (myVersion == 0) {
     728            5 :             const double version = readVersion(result, myFile);
     729            5 :             if (version > 0) {
     730            3 :                 myVersion = version;
     731              :             }
     732              :         }
     733           94 :         return true;
     734              :     }
     735           14 :     StringTokenizer st(result, StringTokenizer::TAB);
     736           14 :     if (st.size() == 1) {
     737              :         return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
     738              :     }
     739           14 :     if (myVersion >= 6) {
     740              :         assert(st.size() >= 7);
     741            7 :         const std::string id = st.next();
     742            7 :         const std::string permanent = st.next();
     743            7 :         const std::string validityPeriod = st.next();
     744            7 :         const std::string throughTraffic = st.next();
     745            7 :         const std::string vehicleType = st.next();
     746            7 :         if (validityPeriod != UNDEFINED) {
     747            0 :             WRITE_WARNINGF(TL("Ignoring temporary prohibited manoeuvre (%)."), validityPeriod);
     748              :             return true;
     749              :         }
     750              :     }
     751           14 :     const std::string startEdge = st.next();
     752           14 :     const std::string endEdge = st.get(st.size() - 1);
     753              : 
     754           14 :     NBEdge* from = myEdgeCont.retrieve(startEdge);
     755           14 :     if (from == nullptr) {
     756            0 :         WRITE_WARNINGF(TL("Ignoring prohibition from unknown start edge '%'."), startEdge);
     757            0 :         return true;
     758              :     }
     759           14 :     NBEdge* to = myEdgeCont.retrieve(endEdge);
     760           14 :     if (to == nullptr) {
     761            0 :         WRITE_WARNINGF(TL("Ignoring prohibition from unknown end edge '%'."), endEdge);
     762            0 :         return true;
     763              :     }
     764           14 :     from->removeFromConnections(to, -1, -1, true);
     765              :     return true;
     766           14 : }
     767              : 
     768              : 
     769              : // ---------------------------------------------------------------------------
     770              : // definitions of NIImporter_DlrNavteq::ConnectedLanesHandler-methods
     771              : // ---------------------------------------------------------------------------
     772            5 : NIImporter_DlrNavteq::ConnectedLanesHandler::ConnectedLanesHandler(
     773            5 :     NBEdgeCont& ec) :
     774            5 :     myEdgeCont(ec) {
     775            5 : }
     776              : 
     777              : 
     778            5 : NIImporter_DlrNavteq::ConnectedLanesHandler::~ConnectedLanesHandler() {}
     779              : 
     780              : 
     781              : bool
     782          820 : NIImporter_DlrNavteq::ConnectedLanesHandler::report(const std::string& result) {
     783          820 :     if (result[0] == '#') {
     784              :         return true;
     785              :     }
     786          650 :     StringTokenizer st(result, StringTokenizer::TAB);
     787          650 :     if (st.size() == 1) {
     788              :         return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
     789              :     }
     790              :     assert(st.size() >= 7);
     791          650 :     const std::string nodeID = st.next();
     792          650 :     const std::string vehicleType = st.next();
     793          650 :     const std::string fromLaneS = st.next();
     794          650 :     const std::string toLaneS = st.next();
     795          650 :     const std::string throughTraffic = st.next();
     796          650 :     const std::string startEdge = st.next();
     797          650 :     const std::string endEdge = st.get(st.size() - 1);
     798              : 
     799          650 :     NBEdge* from = myEdgeCont.retrieve(startEdge);
     800          650 :     if (from == nullptr) {
     801            0 :         WRITE_WARNINGF(TL("Ignoring prohibition from unknown start edge '%'."), startEdge);
     802            0 :         return true;
     803              :     }
     804          650 :     NBEdge* to = myEdgeCont.retrieve(endEdge);
     805          650 :     if (to == nullptr) {
     806            0 :         WRITE_WARNINGF(TL("Ignoring prohibition from unknown end edge '%'."), endEdge);
     807            0 :         return true;
     808              :     }
     809          650 :     int fromLane = StringUtils::toInt(fromLaneS) - 1; // one based
     810          650 :     if (fromLane < 0 || fromLane >= from->getNumLanes()) {
     811            0 :         WRITE_WARNINGF(TL("Ignoring invalid lane index '%' in connection from edge '%' with % lanes."), fromLaneS, startEdge, from->getNumLanes());
     812            0 :         return true;
     813              :     }
     814          650 :     int toLane = StringUtils::toInt(toLaneS) - 1; // one based
     815          650 :     if (toLane < 0 || toLane >= to->getNumLanes()) {
     816            0 :         WRITE_WARNINGF(TL("Ignoring invalid lane index '%' in connection to edge '%' with % lanes"), toLaneS, endEdge, to->getNumLanes());
     817            0 :         return true;
     818              :     }
     819         1300 :     if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::Lane2LaneInfoType::USER, true)) {
     820            0 :         if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
     821            0 :             WRITE_WARNINGF(TL("Could not set loaded connection from '%' to '%'."), from->getLaneID(fromLane), to->getLaneID(toLane));
     822              :         }
     823              :         // set as to be re-applied after network processing
     824              :         // if this connection runs across a node cluster it may not be possible to set this
     825            0 :         const bool warnOnly = st.size() > 7;
     826            0 :         myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, false, KEEPCLEAR_UNSPECIFIED,
     827              :                                             NBEdge::UNSPECIFIED_CONTPOS, NBEdge::UNSPECIFIED_VISIBILITY_DISTANCE,
     828              :                                             NBEdge::UNSPECIFIED_SPEED, NBEdge::UNSPECIFIED_FRICTION, NBEdge::UNSPECIFIED_LOADED_LENGTH, PositionVector::EMPTY, false, warnOnly);
     829              :     }
     830              :     // ensure that connections for other lanes are guessed if not specified
     831              :     from->declareConnectionsAsLoaded(NBEdge::EdgeBuildingStep::INIT);
     832          650 :     from->getLaneStruct(fromLane).connectionsDone = true;
     833          650 :     return true;
     834          650 : }
     835              : 
     836              : 
     837              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1