LCOV - code coverage report
Current view: top level - src/netimport - NIImporter_ArcView.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 177 272 65.1 %
Date: 2024-05-02 15:31:40 Functions: 13 13 100.0 %

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

Generated by: LCOV version 1.14