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 1884 : NIImporter_ArcView::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
73 3768 : if (!oc.isSet("shapefile-prefix")) {
74 1882 : 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, "&", "&");
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 : /****************************************************************************/
|