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