LCOV - code coverage report
Current view: top level - src/netimport - NIImporter_ArcView.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 66.0 % 282 186
Test Date: 2026-08-23 15:49:09 Functions: 100.0 % 13 13

            Line data    Source code
       1              : /****************************************************************************/
       2              : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
       3              : // Copyright (C) 2001-2026 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_ArcView.cpp
      15              : /// @author  Daniel Krajzewicz
      16              : /// @author  Eric Nicolay
      17              : /// @author  Jakob Erdmann
      18              : /// @author  Thimor Bohn
      19              : /// @author  Michael Behrisch
      20              : /// @date    Sept 2002
      21              : ///
      22              : // Importer for networks stored in ArcView-shape format
      23              : /****************************************************************************/
      24              : #include <config.h>
      25              : 
      26              : #include <string>
      27              : #include <utils/common/MsgHandler.h>
      28              : #include <utils/common/ToString.h>
      29              : #include <utils/common/StringUtils.h>
      30              : #include <utils/common/StringUtils.h>
      31              : #include <utils/options/OptionsCont.h>
      32              : #include <utils/geom/GeomHelper.h>
      33              : #include <netbuild/NBNetBuilder.h>
      34              : #include <netbuild/NBHelpers.h>
      35              : #include <netbuild/NBEdge.h>
      36              : #include <netbuild/NBEdgeCont.h>
      37              : #include <netbuild/NBTypeCont.h>
      38              : #include <netbuild/NBNode.h>
      39              : #include <netbuild/NBNodeCont.h>
      40              : #include <netimport/NINavTeqHelper.h>
      41              : #include <utils/geom/GeoConvHelper.h>
      42              : #include <utils/common/FileHelpers.h>
      43              : #include "NILoader.h"
      44              : #include "NIImporter_ArcView.h"
      45              : 
      46              : #ifdef HAVE_GDAL
      47              : #ifdef _MSC_VER
      48              : #pragma warning(push)
      49              : #pragma warning(disable: 4435 5219 5220)
      50              : #endif
      51              : #if __GNUC__ > 3
      52              : #pragma GCC diagnostic push
      53              : #pragma GCC diagnostic ignored "-Wpedantic"
      54              : #endif
      55              : #include <gdal_version.h>
      56              : #include <ogrsf_frmts.h>
      57              : #if __GNUC__ > 3
      58              : #pragma GCC diagnostic pop
      59              : #endif
      60              : #ifdef _MSC_VER
      61              : #pragma warning(pop)
      62              : #endif
      63              : #endif
      64              : 
      65              : 
      66              : // ===========================================================================
      67              : // method definitions
      68              : // ===========================================================================
      69              : // ---------------------------------------------------------------------------
      70              : // static methods (interface in this case)
      71              : // ---------------------------------------------------------------------------
      72              : void
      73         2437 : NIImporter_ArcView::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
      74         4874 :     if (!oc.isSet("shapefile-prefix")) {
      75         2435 :         return;
      76              :     }
      77              :     // check whether the correct set of entries is given
      78              :     //  and compute all file names
      79            2 :     const std::string dbf_file = oc.getString("shapefile-prefix") + ".dbf";
      80            2 :     const std::string shp_file = oc.getString("shapefile-prefix") + ".shp";
      81            2 :     const std::string shx_file = oc.getString("shapefile-prefix") + ".shx";
      82            4 :     if (!StringUtils::startsWith(shp_file, "/vsi")) {
      83              :         // if we are not using a virtual file system, check whether the files do exist
      84            4 :         if (!FileHelpers::isReadable(dbf_file)) {
      85            0 :             WRITE_ERROR("File not accessible: " + dbf_file);
      86              :         }
      87            4 :         if (!FileHelpers::isReadable(shp_file)) {
      88            0 :             WRITE_ERROR("File not accessible: " + shp_file);
      89              :         }
      90            4 :         if (!FileHelpers::isReadable(shx_file)) {
      91            0 :             WRITE_ERROR("File not accessible: " + shx_file);
      92              :         }
      93              :     }
      94            2 :     if (MsgHandler::getErrorInstance()->wasInformed()) {
      95              :         return;
      96              :     }
      97              :     // load the arcview files
      98              :     NIImporter_ArcView loader(oc, nb.getNodeCont(), nb.getEdgeCont(), nb.getTypeCont(),
      99            2 :                               shp_file, oc.getBool("speed-in-kmh"));
     100            2 :     loader.load();
     101            2 : }
     102              : 
     103              : 
     104              : 
     105              : // ---------------------------------------------------------------------------
     106              : // loader methods
     107              : // ---------------------------------------------------------------------------
     108            2 : NIImporter_ArcView::NIImporter_ArcView(const OptionsCont& oc,
     109              :                                        NBNodeCont& nc,
     110              :                                        NBEdgeCont& ec,
     111              :                                        NBTypeCont& tc,
     112              :                                        const std::string& shp_name,
     113            2 :                                        bool speedInKMH)
     114            2 :     : myOptions(oc), mySHPName(shp_name),
     115            2 :       myNameAddition(0),
     116            2 :       myNodeCont(nc), myEdgeCont(ec), myTypeCont(tc),
     117            2 :       mySpeedInKMH(speedInKMH),
     118            2 :       myRunningEdgeID(0),
     119            2 :       myRunningNodeID(0) {
     120            2 : }
     121              : 
     122              : 
     123            2 : NIImporter_ArcView::~NIImporter_ArcView() {}
     124              : 
     125              : 
     126              : void
     127            2 : NIImporter_ArcView::load() {
     128              : #ifdef HAVE_GDAL
     129            6 :     PROGRESS_BEGIN_MESSAGE("Loading data from '" + mySHPName + "'");
     130              : #if GDAL_VERSION_MAJOR < 2
     131              :     OGRRegisterAll();
     132              :     OGRDataSource* poDS = OGRSFDriverRegistrar::Open(mySHPName.c_str(), FALSE);
     133              : #else
     134            2 :     GDALAllRegister();
     135            2 :     GDALDataset* poDS = (GDALDataset*)GDALOpenEx(mySHPName.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, NULL, NULL, NULL);
     136              : #endif
     137            2 :     if (poDS == NULL) {
     138            0 :         WRITE_ERRORF(TL("Could not open shape description '%'."), mySHPName);
     139            0 :         return;
     140              :     }
     141              : 
     142              :     // begin file parsing
     143            2 :     OGRLayer* poLayer = poDS->GetLayer(0);
     144            2 :     poLayer->ResetReading();
     145              : 
     146              :     // build coordinate transformation
     147              : #if GDAL_VERSION_MAJOR < 3
     148              :     OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
     149              : #else
     150            2 :     const OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
     151              : #endif
     152            2 :     OGRSpatialReference destTransf;
     153              :     // use wgs84 as destination
     154            2 :     destTransf.SetWellKnownGeogCS("WGS84");
     155              : #if GDAL_VERSION_MAJOR > 2
     156            4 :     if (myOptions.getBool("shapefile.traditional-axis-mapping") || origTransf != nullptr) {
     157            0 :         destTransf.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     158              :     }
     159              : #endif
     160            2 :     OGRCoordinateTransformation* poCT = origTransf == nullptr ? nullptr : OGRCreateCoordinateTransformation(origTransf, &destTransf);
     161            0 :     if (poCT == nullptr) {
     162            4 :         if (myOptions.getBool("shapefile.guess-projection")) {
     163            0 :             OGRSpatialReference origTransf2;
     164            0 :             origTransf2.SetWellKnownGeogCS("WGS84");
     165            0 :             poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
     166            0 :         }
     167              :     }
     168              : 
     169            2 :     const bool saveOrigIDs = OptionsCont::getOptions().getBool("output.original-names");
     170              :     OGRFeature* poFeature;
     171            2 :     poLayer->ResetReading();
     172              : 
     173            2 :     const double nodeJoinDist = myOptions.getFloat("shapefile.node-join-dist");
     174            2 :     const std::vector<std::string> params = myOptions.getStringVector("shapefile.add-params");
     175              : 
     176              :     int featureIndex = 0;
     177              :     bool warnNotUnique = true;
     178              :     bool warnMissingProjection = true;
     179            2 :     std::string idPrefix = ""; // prefix for non-unique street-id values
     180              :     std::map<std::string, int> idIndex; // running index to make street-id unique
     181          120 :     while ((poFeature = poLayer->GetNextFeature()) != NULL) {
     182              :         // read in edge attributes
     183          118 :         if (featureIndex == 0) {
     184            6 :             WRITE_MESSAGE("Available fields: " + toString(getFieldNames(poFeature)));
     185              :         }
     186              :         std::string id;
     187              :         std::string name;
     188              :         std::string from_node;
     189              :         std::string to_node;
     190          236 :         if (!getStringEntry(poFeature, "shapefile.street-id", "LINK_ID", true, id)) {
     191            0 :             WRITE_ERRORF(TL("Needed field '%' (street-id) is missing."), id);
     192              :             id = "";
     193              :         }
     194          118 :         if (id == "") {
     195            0 :             id = toString(myRunningEdgeID++);
     196              :         }
     197              : 
     198          118 :         getStringEntry(poFeature, "shapefile.name", "ST_NAME", true, name);
     199          354 :         name = StringUtils::replace(name, "&", "&amp;");
     200              : 
     201          236 :         if (!getStringEntry(poFeature, "shapefile.from-id", "REF_IN_ID", true, from_node)) {
     202            0 :             WRITE_ERRORF(TL("Needed field '%' (from node id) is missing."), from_node);
     203              :             from_node = "";
     204              :         }
     205          236 :         if (!getStringEntry(poFeature, "shapefile.to-id", "NREF_IN_ID", true, to_node)) {
     206            0 :             WRITE_ERRORF(TL("Needed field '%' (to node id) is missing."), to_node);
     207              :             to_node = "";
     208              :         }
     209              : 
     210          118 :         if (from_node == "" || to_node == "") {
     211          118 :             from_node = toString(myRunningNodeID++);
     212          236 :             to_node = toString(myRunningNodeID++);
     213              :         }
     214              : 
     215              :         std::string type;
     216          118 :         if (myOptions.isSet("shapefile.type-id") && poFeature->GetFieldIndex(myOptions.getString("shapefile.type-id").c_str()) >= 0) {
     217            0 :             type = poFeature->GetFieldAsString(myOptions.getString("shapefile.type-id").c_str());
     218          118 :         } else if (poFeature->GetFieldIndex("ST_TYP_AFT") >= 0) {
     219            0 :             type = poFeature->GetFieldAsString("ST_TYP_AFT");
     220              :         }
     221          236 :         if ((type != "" || myOptions.isSet("shapefile.type-id")) && !myTypeCont.knows(type)) {
     222            0 :             WRITE_WARNINGF(TL("Unknown type '%' for edge '%'"), type, id);
     223              :         }
     224          118 :         bool oneway = myTypeCont.knows(type) ? myTypeCont.getEdgeTypeIsOneWay(type) : false;
     225          118 :         double speed = getSpeed(*poFeature, id);
     226          118 :         int nolanes = getLaneNo(*poFeature, id, speed);
     227          118 :         int priority = getPriority(*poFeature, id);
     228          118 :         double width = getLaneWidth(*poFeature, id, nolanes);
     229          118 :         double length = getLength(*poFeature, id);
     230          118 :         if (nolanes <= 0 || speed <= 0) {
     231          236 :             if (myOptions.getBool("shapefile.use-defaults-on-failure")) {
     232          118 :                 nolanes = nolanes <= 0 ? myTypeCont.getEdgeTypeNumLanes(type) : nolanes;
     233          118 :                 speed = speed <= 0 ? myTypeCont.getEdgeTypeSpeed(type) : speed;
     234              :             } else {
     235            0 :                 const std::string lanesField = myOptions.isSet("shapefile.laneNumber") ? myOptions.getString("shapefile.laneNumber") : "nolanes";
     236            0 :                 const std::string speedField = myOptions.isSet("shapefile.speed") ? myOptions.getString("shapefile.speed") : "speed";
     237            0 :                 WRITE_ERRORF(TL("Required field '%' or '%' is missing (add fields or set option --shapefile.use-defaults-on-failure)."), lanesField, speedField);
     238            0 :                 WRITE_ERROR("Available fields: " + toString(getFieldNames(poFeature)));
     239            0 :                 OGRFeature::DestroyFeature(poFeature);
     240              :                 return;
     241              :             }
     242              :         }
     243          118 :         if (mySpeedInKMH) {
     244            0 :             speed /= 3.6;
     245              :         }
     246              : 
     247              : 
     248              :         // read in the geometry
     249          118 :         OGRGeometry* poGeometry = poFeature->GetGeometryRef();
     250          118 :         OGRwkbGeometryType gtype = poGeometry->getGeometryType();
     251          118 :         if (gtype != wkbLineString && gtype != wkbLineString25D) {
     252            0 :             OGRFeature::DestroyFeature(poFeature);
     253            0 :             WRITE_ERRORF(TL("Road geometry must be of type 'linestring' or 'linestring25D' (found '%')"), toString(gtype));
     254            0 :             return;
     255              :         }
     256              :         OGRLineString* cgeom = (OGRLineString*) poGeometry;
     257          118 :         if (poCT == nullptr && warnMissingProjection) {
     258              :             int outOfRange = 0;
     259           13 :             for (int j = 0; j < cgeom->getNumPoints(); j++) {
     260           11 :                 if (fabs(cgeom->getX(j)) > 180 || fabs(cgeom->getY(j)) > 90) {
     261            5 :                     outOfRange++;
     262              :                 }
     263              :             }
     264            2 :             if (2 * outOfRange > cgeom->getNumPoints()) {
     265            1 :                 WRITE_WARNING(TL("No coordinate system found and coordinates look already projected."));
     266            2 :                 GeoConvHelper::init("!", GeoConvHelper::getProcessing().getOffset(), GeoConvHelper::getProcessing().getOrigBoundary(), GeoConvHelper::getProcessing().getConvBoundary());
     267              :             } else {
     268            2 :                 WRITE_WARNING(TL("Could not find geo coordinate system, assuming WGS84."));
     269              :             }
     270              :             warnMissingProjection = false;
     271              :         }
     272          118 :         if (poCT != nullptr) {
     273              :             // try transform to wgs84
     274            0 :             cgeom->transform(poCT);
     275              :         }
     276              : 
     277          118 :         PositionVector shape;
     278          496 :         for (int j = 0; j < cgeom->getNumPoints(); j++) {
     279          378 :             Position pos(cgeom->getX(j), cgeom->getY(j), cgeom->getZ(j));
     280          378 :             if (!NBNetBuilder::transformCoordinate(pos)) {
     281            0 :                 WRITE_WARNINGF(TL("Unable to project coordinates for edge '%'."), id);
     282              :             }
     283          378 :             shape.push_back_noDoublePos(pos);
     284              :         }
     285              : 
     286              :         // build from-node
     287          118 :         NBNode* from = myNodeCont.retrieve(from_node);
     288          118 :         if (from == nullptr) {
     289          118 :             Position from_pos = shape[0];
     290          118 :             std::vector<NBNode*> cands = myNodeCont.retrieveByPos(from_pos, nodeJoinDist);
     291          118 :             if (!cands.empty()) {
     292           39 :                 from = cands.front();
     293              :             }
     294          118 :             if (from == nullptr) {
     295           79 :                 from = new NBNode(from_node, from_pos);
     296           79 :                 if (!myNodeCont.insert(from)) {
     297            0 :                     WRITE_ERRORF(TL("Node '%' could not be added"), from_node);
     298            0 :                     delete from;
     299              :                     continue;
     300              :                 }
     301              :             }
     302          118 :         }
     303              :         // build to-node
     304          118 :         NBNode* to = myNodeCont.retrieve(to_node);
     305          118 :         if (to == nullptr) {
     306          118 :             Position to_pos = shape[-1];
     307          118 :             std::vector<NBNode*> cands = myNodeCont.retrieveByPos(to_pos, nodeJoinDist);
     308          118 :             if (!cands.empty()) {
     309           39 :                 to = cands.front();
     310              :             }
     311          118 :             if (to == nullptr) {
     312           79 :                 to = new NBNode(to_node, to_pos);
     313           79 :                 if (!myNodeCont.insert(to)) {
     314            0 :                     WRITE_ERRORF(TL("Node '%' could not be added"), to_node);
     315            0 :                     delete to;
     316              :                     continue;
     317              :                 }
     318              :             }
     319          118 :         }
     320              : 
     321          118 :         if (from == to) {
     322            3 :             WRITE_WARNINGF(TL("Edge '%' connects identical nodes, skipping."), id);
     323            1 :             continue;
     324              :         }
     325              : 
     326              :         // retrieve the information whether the street is bi-directional
     327              :         std::string dir;
     328          117 :         int index = poFeature->GetDefnRef()->GetFieldIndex("DIR_TRAVEL");
     329          117 :         if (index >= 0 && poFeature->IsFieldSet(index)) {
     330            0 :             dir = poFeature->GetFieldAsString(index);
     331              :         }
     332          117 :         const std::string origID = saveOrigIDs ? id : "";
     333              :         // check for duplicate ids
     334          117 :         NBEdge* const existing = myEdgeCont.retrieve(id);
     335          117 :         NBEdge* const existingReverse = myEdgeCont.retrieve("-" + id);
     336          117 :         if (existing != nullptr || existingReverse != nullptr) {
     337            0 :             if ((existing != nullptr && existing->getGeometry() == shape)
     338            0 :                     || (existingReverse != nullptr && existingReverse->getGeometry() == shape.reverse())) {
     339            0 :                 WRITE_ERRORF(TL("Edge '%' is not unique."), (existing != nullptr ? id : existingReverse->getID()));
     340              :             } else {
     341              :                 if (idIndex.count(id) == 0) {
     342            0 :                     idIndex[id] = 0;
     343              :                 }
     344            0 :                 idIndex[id]++;
     345              :                 idPrefix = id;
     346            0 :                 id += "#" + toString(idIndex[id]);
     347            0 :                 if (warnNotUnique) {
     348            0 :                     WRITE_WARNINGF(TL("Edge '%' is not unique. Renaming subsequent edge to '%'."), idPrefix, id);
     349              :                     warnNotUnique = false;
     350              :                 }
     351              :             }
     352              :         }
     353              :         // add positive direction if wanted
     354          117 :         if (dir == "B" || dir == "F" || dir == "" || myOptions.getBool("shapefile.all-bidirectional")) {
     355          117 :             if (myEdgeCont.retrieve(id) == 0) {
     356          117 :                 LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LaneSpreadFunction::RIGHT : LaneSpreadFunction::CENTER;
     357          117 :                 if (spread == LaneSpreadFunction::RIGHT && OptionsCont::getOptions().getString("default.spreadtype") == toString(LaneSpreadFunction::ROADCENTER)) {
     358              :                     spread = LaneSpreadFunction::ROADCENTER;
     359              :                 }
     360          468 :                 NBEdge* edge = new NBEdge(id, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape, spread, name, origID);
     361          117 :                 edge->setPermissions(myTypeCont.getEdgeTypePermissions(type));
     362          117 :                 edge->setLoadedLength(length);
     363          117 :                 myEdgeCont.insert(edge);
     364          117 :                 checkSpread(edge);
     365          117 :                 addParams(edge, poFeature, params);
     366              :             } else {
     367            0 :                 WRITE_ERRORF(TL("Could not create edge '%'. An edge with the same id already exists."), id);
     368              :             }
     369              :         }
     370              :         // add negative direction if wanted
     371          234 :         if ((dir == "B" || dir == "T" || myOptions.getBool("shapefile.all-bidirectional")) && !oneway) {
     372            0 :             if (myEdgeCont.retrieve("-" + id) == 0) {
     373            0 :                 LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LaneSpreadFunction::RIGHT : LaneSpreadFunction::CENTER;
     374            0 :                 if (spread == LaneSpreadFunction::RIGHT && OptionsCont::getOptions().getString("default.spreadtype") == toString(LaneSpreadFunction::ROADCENTER)) {
     375              :                     spread = LaneSpreadFunction::ROADCENTER;
     376              :                 }
     377            0 :                 NBEdge* edge = new NBEdge("-" + id, to, from, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), spread, name, origID);
     378            0 :                 edge->setPermissions(myTypeCont.getEdgeTypePermissions(type));
     379            0 :                 edge->setLoadedLength(length);
     380            0 :                 myEdgeCont.insert(edge);
     381            0 :                 checkSpread(edge);
     382            0 :                 addParams(edge, poFeature, params);
     383              :             } else {
     384            0 :                 WRITE_ERRORF(TL("Could not create edge '-%'. An edge with the same id already exists."), id);
     385              :             }
     386              :         }
     387              :         //
     388          117 :         OGRFeature::DestroyFeature(poFeature);
     389          117 :         featureIndex++;
     390          118 :     }
     391              : #if GDAL_VERSION_MAJOR < 2
     392              :     OGRDataSource::DestroyDataSource(poDS);
     393              : #else
     394            2 :     GDALClose(poDS);
     395              : #endif
     396            2 :     PROGRESS_DONE_MESSAGE();
     397              : #else
     398              :     WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
     399              : #endif
     400            2 : }
     401              : 
     402              : #ifdef HAVE_GDAL
     403              : double
     404          118 : NIImporter_ArcView::getSpeed(OGRFeature& poFeature, const std::string& edgeid) {
     405          236 :     if (myOptions.isSet("shapefile.speed")) {
     406            0 :         int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.speed").c_str());
     407            0 :         if (index >= 0 && poFeature.IsFieldSet(index)) {
     408            0 :             const double speed = poFeature.GetFieldAsDouble(index);
     409            0 :             if (speed <= 0) {
     410            0 :                 WRITE_WARNING("invalid value for field: '"
     411              :                               + myOptions.getString("shapefile.speed")
     412              :                               + "': '" + std::string(poFeature.GetFieldAsString(index)) + "'");
     413              :             } else {
     414              :                 return speed;
     415              :             }
     416              :         }
     417              :     }
     418          236 :     if (myOptions.isSet("shapefile.type-id")) {
     419            0 :         return myTypeCont.getEdgeTypeSpeed(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str())));
     420              :     }
     421              :     // try to get definitions as to be found in SUMO-XML-definitions
     422              :     //  idea by John Michael Calandrino
     423          118 :     int index = poFeature.GetDefnRef()->GetFieldIndex("speed");
     424          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     425            0 :         return (double) poFeature.GetFieldAsDouble(index);
     426              :     }
     427          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("SPEED");
     428          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     429            0 :         return (double) poFeature.GetFieldAsDouble(index);
     430              :     }
     431              :     // try to get the NavTech-information
     432          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("SPEED_CAT");
     433          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     434            0 :         std::string def = poFeature.GetFieldAsString(index);
     435            0 :         return NINavTeqHelper::getSpeed(edgeid, def);
     436              :     }
     437              :     return -1;
     438              : }
     439              : 
     440              : 
     441              : double
     442          118 : NIImporter_ArcView::getLaneWidth(OGRFeature& poFeature, const std::string& edgeid, int laneNumber) {
     443          236 :     if (myOptions.isSet("shapefile.width")) {
     444            0 :         int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.width").c_str());
     445            0 :         if (index >= 0 && poFeature.IsFieldSet(index)) {
     446            0 :             const double width = poFeature.GetFieldAsDouble(index);
     447            0 :             if (width <= 0) {
     448            0 :                 WRITE_WARNING("invalid value for field: '"
     449              :                               + myOptions.getString("shapefile.width")
     450              :                               + "' of edge '" + edgeid
     451              :                               + "': '" + std::string(poFeature.GetFieldAsString(index)) + "'");
     452              :             } else {
     453            0 :                 return width / laneNumber;
     454              :             }
     455              :         }
     456              :     }
     457          236 :     if (myOptions.isSet("shapefile.type-id")) {
     458            0 :         return myTypeCont.getEdgeTypeWidth(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str())));
     459              :     }
     460          118 :     return NBEdge::UNSPECIFIED_WIDTH;
     461              : }
     462              : 
     463              : 
     464              : 
     465              : double
     466          118 : NIImporter_ArcView::getLength(OGRFeature& poFeature, const std::string& edgeid) {
     467          236 :     if (myOptions.isSet("shapefile.length")) {
     468            0 :         int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.length").c_str());
     469            0 :         if (index >= 0 && poFeature.IsFieldSet(index)) {
     470            0 :             const double length = poFeature.GetFieldAsDouble(index);
     471            0 :             if (length <= 0) {
     472            0 :                 WRITE_WARNING("invalid value for field: '"
     473              :                               + myOptions.getString("shapefile.length")
     474              :                               + "' of edge '" + edgeid
     475              :                               + "': '" + std::string(poFeature.GetFieldAsString(index)) + "'");
     476              :             } else {
     477              :                 return length;
     478              :             }
     479              :         }
     480              :     }
     481          118 :     return NBEdge::UNSPECIFIED_LOADED_LENGTH;
     482              : }
     483              : 
     484              : 
     485              : int
     486          118 : NIImporter_ArcView::getLaneNo(OGRFeature& poFeature, const std::string& edgeid,
     487              :                               double speed) {
     488          236 :     if (myOptions.isSet("shapefile.laneNumber")) {
     489            0 :         int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.laneNumber").c_str());
     490            0 :         if (index >= 0 && poFeature.IsFieldSet(index)) {
     491            0 :             const int laneNumber = poFeature.GetFieldAsInteger(index);
     492            0 :             if (laneNumber <= 0) {
     493            0 :                 WRITE_WARNING("invalid value for field '"
     494              :                               + myOptions.getString("shapefile.laneNumber")
     495              :                               + "': '" + std::string(poFeature.GetFieldAsString(index)) + "'");
     496              :             } else {
     497              :                 return laneNumber;
     498              :             }
     499              :         }
     500              :     }
     501          236 :     if (myOptions.isSet("shapefile.type-id")) {
     502            0 :         return (int) myTypeCont.getEdgeTypeNumLanes(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str())));
     503              :     }
     504              :     // try to get definitions as to be found in SUMO-XML-definitions
     505              :     //  idea by John Michael Calandrino
     506          118 :     int index = poFeature.GetDefnRef()->GetFieldIndex("nolanes");
     507          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     508            0 :         return (int) poFeature.GetFieldAsInteger(index);
     509              :     }
     510          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("NOLANES");
     511          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     512            0 :         return (int) poFeature.GetFieldAsInteger(index);
     513              :     }
     514          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("rnol");
     515          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     516            0 :         return (int) poFeature.GetFieldAsInteger(index);
     517              :     }
     518          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("LANE_CAT");
     519          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     520            0 :         std::string def = poFeature.GetFieldAsString(index);
     521            0 :         return NINavTeqHelper::getLaneNumber(edgeid, def, speed);
     522              :     }
     523              :     return 0;
     524              : }
     525              : 
     526              : 
     527              : int
     528          118 : NIImporter_ArcView::getPriority(OGRFeature& poFeature, const std::string& /*edgeid*/) {
     529          236 :     if (myOptions.isSet("shapefile.type-id")) {
     530            0 :         return myTypeCont.getEdgeTypePriority(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str())));
     531              :     }
     532              :     // try to get definitions as to be found in SUMO-XML-definitions
     533              :     //  idea by John Michael Calandrino
     534          118 :     int index = poFeature.GetDefnRef()->GetFieldIndex("priority");
     535          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     536            0 :         return poFeature.GetFieldAsInteger(index);
     537              :     }
     538          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("PRIORITY");
     539          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     540            0 :         return poFeature.GetFieldAsInteger(index);
     541              :     }
     542              :     // try to determine priority from NavTechs FUNC_CLASS attribute
     543          118 :     index = poFeature.GetDefnRef()->GetFieldIndex("FUNC_CLASS");
     544          118 :     if (index >= 0 && poFeature.IsFieldSet(index)) {
     545            0 :         return poFeature.GetFieldAsInteger(index);
     546              :     }
     547              :     return 0;
     548              : }
     549              : 
     550              : void
     551          117 : NIImporter_ArcView::checkSpread(NBEdge* e) {
     552          117 :     NBEdge* ret = e->getToNode()->getConnectionTo(e->getFromNode());
     553          117 :     if (ret != 0) {
     554            0 :         e->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
     555            0 :         ret->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
     556              :     }
     557          117 : }
     558              : 
     559              : bool
     560          472 : NIImporter_ArcView::getStringEntry(OGRFeature* poFeature, const std::string& optionName, const char* defaultName, bool prune, std::string& into) {
     561          472 :     std::string v(defaultName);
     562          472 :     if (myOptions.isSet(optionName)) {
     563          236 :         v = myOptions.getString(optionName);
     564              :     }
     565          472 :     if (poFeature->GetFieldIndex(v.c_str()) < 0) {
     566          354 :         if (myOptions.isSet(optionName)) {
     567              :             into = v;
     568              :             return false;
     569              :         }
     570              :         into = "";
     571              :         return true;
     572              :     }
     573          118 :     into = poFeature->GetFieldAsString((char*)v.c_str());
     574          118 :     if (prune) {
     575          236 :         into = StringUtils::prune(into);
     576              :     }
     577              :     return true;
     578              : }
     579              : 
     580              : std::vector<std::string>
     581            2 : NIImporter_ArcView::getFieldNames(OGRFeature* poFeature) const {
     582              :     std::vector<std::string> fields;
     583           12 :     for (int i = 0; i < poFeature->GetFieldCount(); i++) {
     584           16 :         fields.push_back(poFeature->GetFieldDefnRef(i)->GetNameRef());
     585              :     }
     586            2 :     return fields;
     587            0 : }
     588              : 
     589              : void
     590          117 : NIImporter_ArcView::addParams(NBEdge* edge, OGRFeature* poFeature, const std::vector<std::string>& params) const {
     591          117 :     for (const std::string& p : params) {
     592            0 :         int index = poFeature->GetDefnRef()->GetFieldIndex(p.c_str());
     593            0 :         if (index >= 0 && poFeature->IsFieldSet(index)) {
     594            0 :             edge->setParameter(p, poFeature->GetFieldAsString(index));
     595              :         }
     596              :     }
     597          117 : }
     598              : 
     599              : #endif
     600              : 
     601              : 
     602              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1