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

Generated by: LCOV version 2.0-1