Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2025 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 2003 : NIImporter_ArcView::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
73 4006 : if (!oc.isSet("shapefile-prefix")) {
74 2001 : 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 : #if GDAL_VERSION_MAJOR < 3
147 : OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
148 : #else
149 2 : const OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
150 : #endif
151 2 : OGRSpatialReference destTransf;
152 : // use wgs84 as destination
153 2 : destTransf.SetWellKnownGeogCS("WGS84");
154 : #if GDAL_VERSION_MAJOR > 2
155 4 : if (myOptions.getBool("shapefile.traditional-axis-mapping") || origTransf != nullptr) {
156 0 : destTransf.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
157 : }
158 : #endif
159 2 : OGRCoordinateTransformation* poCT = origTransf == nullptr ? nullptr : OGRCreateCoordinateTransformation(origTransf, &destTransf);
160 0 : if (poCT == nullptr) {
161 4 : if (myOptions.getBool("shapefile.guess-projection")) {
162 0 : OGRSpatialReference origTransf2;
163 0 : origTransf2.SetWellKnownGeogCS("WGS84");
164 0 : poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
165 0 : }
166 : }
167 :
168 2 : const bool saveOrigIDs = OptionsCont::getOptions().getBool("output.original-names");
169 : OGRFeature* poFeature;
170 2 : poLayer->ResetReading();
171 :
172 2 : const double nodeJoinDist = myOptions.getFloat("shapefile.node-join-dist");
173 2 : 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 2 : 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 120 : while ((poFeature = poLayer->GetNextFeature()) != NULL) {
181 : // read in edge attributes
182 118 : if (featureIndex == 0) {
183 6 : 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 236 : if (!getStringEntry(poFeature, "shapefile.street-id", "LINK_ID", true, id)) {
190 0 : WRITE_ERRORF(TL("Needed field '%' (street-id) is missing."), id);
191 : id = "";
192 : }
193 118 : if (id == "") {
194 0 : id = toString(myRunningEdgeID++);
195 : }
196 :
197 118 : getStringEntry(poFeature, "shapefile.name", "ST_NAME", true, name);
198 354 : name = StringUtils::replace(name, "&", "&");
199 :
200 236 : if (!getStringEntry(poFeature, "shapefile.from-id", "REF_IN_ID", true, from_node)) {
201 0 : WRITE_ERRORF(TL("Needed field '%' (from node id) is missing."), from_node);
202 : from_node = "";
203 : }
204 236 : if (!getStringEntry(poFeature, "shapefile.to-id", "NREF_IN_ID", true, to_node)) {
205 0 : WRITE_ERRORF(TL("Needed field '%' (to node id) is missing."), to_node);
206 : to_node = "";
207 : }
208 :
209 118 : if (from_node == "" || to_node == "") {
210 118 : from_node = toString(myRunningNodeID++);
211 236 : to_node = toString(myRunningNodeID++);
212 : }
213 :
214 : std::string type;
215 118 : if (myOptions.isSet("shapefile.type-id") && poFeature->GetFieldIndex(myOptions.getString("shapefile.type-id").c_str()) >= 0) {
216 0 : type = poFeature->GetFieldAsString(myOptions.getString("shapefile.type-id").c_str());
217 118 : } else if (poFeature->GetFieldIndex("ST_TYP_AFT") >= 0) {
218 0 : type = poFeature->GetFieldAsString("ST_TYP_AFT");
219 : }
220 236 : if ((type != "" || myOptions.isSet("shapefile.type-id")) && !myTypeCont.knows(type)) {
221 0 : WRITE_WARNINGF(TL("Unknown type '%' for edge '%'"), type, id);
222 : }
223 118 : bool oneway = myTypeCont.knows(type) ? myTypeCont.getEdgeTypeIsOneWay(type) : false;
224 118 : double speed = getSpeed(*poFeature, id);
225 118 : int nolanes = getLaneNo(*poFeature, id, speed);
226 118 : int priority = getPriority(*poFeature, id);
227 118 : double width = getLaneWidth(*poFeature, id, nolanes);
228 118 : double length = getLength(*poFeature, id);
229 118 : if (nolanes <= 0 || speed <= 0) {
230 236 : if (myOptions.getBool("shapefile.use-defaults-on-failure")) {
231 118 : nolanes = nolanes <= 0 ? myTypeCont.getEdgeTypeNumLanes(type) : nolanes;
232 118 : speed = speed <= 0 ? myTypeCont.getEdgeTypeSpeed(type) : speed;
233 : } else {
234 0 : const std::string lanesField = myOptions.isSet("shapefile.laneNumber") ? myOptions.getString("shapefile.laneNumber") : "nolanes";
235 0 : const std::string speedField = myOptions.isSet("shapefile.speed") ? myOptions.getString("shapefile.speed") : "speed";
236 0 : WRITE_ERRORF(TL("Required field '%' or '%' is missing (add fields or set option --shapefile.use-defaults-on-failure)."), lanesField, speedField);
237 0 : WRITE_ERROR("Available fields: " + toString(getFieldNames(poFeature)));
238 0 : OGRFeature::DestroyFeature(poFeature);
239 : return;
240 : }
241 : }
242 118 : if (mySpeedInKMH) {
243 0 : speed /= 3.6;
244 : }
245 :
246 :
247 : // read in the geometry
248 118 : OGRGeometry* poGeometry = poFeature->GetGeometryRef();
249 118 : OGRwkbGeometryType gtype = poGeometry->getGeometryType();
250 118 : if (gtype != wkbLineString && gtype != wkbLineString25D) {
251 0 : OGRFeature::DestroyFeature(poFeature);
252 0 : WRITE_ERRORF(TL("Road geometry must be of type 'linestring' or 'linestring25D' (found '%')"), toString(gtype));
253 0 : return;
254 : }
255 : OGRLineString* cgeom = (OGRLineString*) poGeometry;
256 118 : if (poCT == nullptr && warnMissingProjection) {
257 : int outOfRange = 0;
258 13 : for (int j = 0; j < cgeom->getNumPoints(); j++) {
259 11 : if (fabs(cgeom->getX(j)) > 180 || fabs(cgeom->getY(j)) > 90) {
260 5 : outOfRange++;
261 : }
262 : }
263 2 : if (2 * outOfRange > cgeom->getNumPoints()) {
264 1 : WRITE_WARNING(TL("No coordinate system found and coordinates look already projected."));
265 2 : GeoConvHelper::init("!", GeoConvHelper::getProcessing().getOffset(), GeoConvHelper::getProcessing().getOrigBoundary(), GeoConvHelper::getProcessing().getConvBoundary());
266 : } else {
267 2 : WRITE_WARNING(TL("Could not find geo coordinate system, assuming WGS84."));
268 : }
269 : warnMissingProjection = false;
270 : }
271 118 : if (poCT != nullptr) {
272 : // try transform to wgs84
273 0 : cgeom->transform(poCT);
274 : }
275 :
276 118 : PositionVector shape;
277 496 : for (int j = 0; j < cgeom->getNumPoints(); j++) {
278 378 : Position pos(cgeom->getX(j), cgeom->getY(j), cgeom->getZ(j));
279 378 : if (!NBNetBuilder::transformCoordinate(pos)) {
280 0 : WRITE_WARNINGF(TL("Unable to project coordinates for edge '%'."), id);
281 : }
282 378 : shape.push_back_noDoublePos(pos);
283 : }
284 :
285 : // build from-node
286 118 : NBNode* from = myNodeCont.retrieve(from_node);
287 118 : if (from == nullptr) {
288 118 : Position from_pos = shape[0];
289 118 : std::vector<NBNode*> cands = myNodeCont.retrieveByPos(from_pos, nodeJoinDist);
290 118 : if (!cands.empty()) {
291 39 : from = cands.front();
292 : }
293 118 : if (from == nullptr) {
294 79 : from = new NBNode(from_node, from_pos);
295 79 : if (!myNodeCont.insert(from)) {
296 0 : WRITE_ERRORF(TL("Node '%' could not be added"), from_node);
297 0 : delete from;
298 : continue;
299 : }
300 : }
301 118 : }
302 : // build to-node
303 118 : NBNode* to = myNodeCont.retrieve(to_node);
304 118 : if (to == nullptr) {
305 118 : Position to_pos = shape[-1];
306 118 : std::vector<NBNode*> cands = myNodeCont.retrieveByPos(to_pos, nodeJoinDist);
307 118 : if (!cands.empty()) {
308 39 : to = cands.front();
309 : }
310 118 : if (to == nullptr) {
311 79 : to = new NBNode(to_node, to_pos);
312 79 : if (!myNodeCont.insert(to)) {
313 0 : WRITE_ERRORF(TL("Node '%' could not be added"), to_node);
314 0 : delete to;
315 : continue;
316 : }
317 : }
318 118 : }
319 :
320 118 : if (from == to) {
321 3 : WRITE_WARNINGF(TL("Edge '%' connects identical nodes, skipping."), id);
322 1 : continue;
323 : }
324 :
325 : // retrieve the information whether the street is bi-directional
326 : std::string dir;
327 117 : int index = poFeature->GetDefnRef()->GetFieldIndex("DIR_TRAVEL");
328 117 : if (index >= 0 && poFeature->IsFieldSet(index)) {
329 0 : dir = poFeature->GetFieldAsString(index);
330 : }
331 117 : const std::string origID = saveOrigIDs ? id : "";
332 : // check for duplicate ids
333 117 : NBEdge* const existing = myEdgeCont.retrieve(id);
334 117 : NBEdge* const existingReverse = myEdgeCont.retrieve("-" + id);
335 117 : if (existing != nullptr || existingReverse != nullptr) {
336 0 : if ((existing != nullptr && existing->getGeometry() == shape)
337 0 : || (existingReverse != nullptr && existingReverse->getGeometry() == shape.reverse())) {
338 0 : WRITE_ERRORF(TL("Edge '%' is not unique."), (existing != nullptr ? id : existingReverse->getID()));
339 : } else {
340 : if (idIndex.count(id) == 0) {
341 0 : idIndex[id] = 0;
342 : }
343 0 : idIndex[id]++;
344 : idPrefix = id;
345 0 : id += "#" + toString(idIndex[id]);
346 0 : if (warnNotUnique) {
347 0 : 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 117 : if (dir == "B" || dir == "F" || dir == "" || myOptions.getBool("shapefile.all-bidirectional")) {
354 117 : if (myEdgeCont.retrieve(id) == 0) {
355 117 : LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LaneSpreadFunction::RIGHT : LaneSpreadFunction::CENTER;
356 117 : if (spread == LaneSpreadFunction::RIGHT && OptionsCont::getOptions().getString("default.spreadtype") == toString(LaneSpreadFunction::ROADCENTER)) {
357 : spread = LaneSpreadFunction::ROADCENTER;
358 : }
359 468 : NBEdge* edge = new NBEdge(id, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape, spread, name, origID);
360 117 : edge->setPermissions(myTypeCont.getEdgeTypePermissions(type));
361 117 : edge->setLoadedLength(length);
362 117 : myEdgeCont.insert(edge);
363 117 : checkSpread(edge);
364 117 : addParams(edge, poFeature, params);
365 : } else {
366 0 : 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 234 : if ((dir == "B" || dir == "T" || myOptions.getBool("shapefile.all-bidirectional")) && !oneway) {
371 0 : if (myEdgeCont.retrieve("-" + id) == 0) {
372 0 : LaneSpreadFunction spread = dir == "B" || dir == "FALSE" ? LaneSpreadFunction::RIGHT : LaneSpreadFunction::CENTER;
373 0 : if (spread == LaneSpreadFunction::RIGHT && OptionsCont::getOptions().getString("default.spreadtype") == toString(LaneSpreadFunction::ROADCENTER)) {
374 : spread = LaneSpreadFunction::ROADCENTER;
375 : }
376 0 : NBEdge* edge = new NBEdge("-" + id, to, from, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, priority, width, NBEdge::UNSPECIFIED_OFFSET, shape.reverse(), spread, name, origID);
377 0 : edge->setPermissions(myTypeCont.getEdgeTypePermissions(type));
378 0 : edge->setLoadedLength(length);
379 0 : myEdgeCont.insert(edge);
380 0 : checkSpread(edge);
381 0 : addParams(edge, poFeature, params);
382 : } else {
383 0 : WRITE_ERRORF(TL("Could not create edge '-%'. An edge with the same id already exists."), id);
384 : }
385 : }
386 : //
387 117 : OGRFeature::DestroyFeature(poFeature);
388 117 : featureIndex++;
389 118 : }
390 : #if GDAL_VERSION_MAJOR < 2
391 : OGRDataSource::DestroyDataSource(poDS);
392 : #else
393 2 : GDALClose(poDS);
394 : #endif
395 2 : PROGRESS_DONE_MESSAGE();
396 : #else
397 : WRITE_ERROR(TL("SUMO was compiled without GDAL support."));
398 : #endif
399 2 : }
400 :
401 : #ifdef HAVE_GDAL
402 : double
403 118 : NIImporter_ArcView::getSpeed(OGRFeature& poFeature, const std::string& edgeid) {
404 236 : if (myOptions.isSet("shapefile.speed")) {
405 0 : int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.speed").c_str());
406 0 : if (index >= 0 && poFeature.IsFieldSet(index)) {
407 0 : const double speed = poFeature.GetFieldAsDouble(index);
408 0 : if (speed <= 0) {
409 0 : 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 236 : if (myOptions.isSet("shapefile.type-id")) {
418 0 : 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 118 : int index = poFeature.GetDefnRef()->GetFieldIndex("speed");
423 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
424 0 : return (double) poFeature.GetFieldAsDouble(index);
425 : }
426 118 : index = poFeature.GetDefnRef()->GetFieldIndex("SPEED");
427 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
428 0 : return (double) poFeature.GetFieldAsDouble(index);
429 : }
430 : // try to get the NavTech-information
431 118 : index = poFeature.GetDefnRef()->GetFieldIndex("SPEED_CAT");
432 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
433 0 : std::string def = poFeature.GetFieldAsString(index);
434 0 : return NINavTeqHelper::getSpeed(edgeid, def);
435 : }
436 : return -1;
437 : }
438 :
439 :
440 : double
441 118 : NIImporter_ArcView::getLaneWidth(OGRFeature& poFeature, const std::string& edgeid, int laneNumber) {
442 236 : if (myOptions.isSet("shapefile.width")) {
443 0 : int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.width").c_str());
444 0 : if (index >= 0 && poFeature.IsFieldSet(index)) {
445 0 : const double width = poFeature.GetFieldAsDouble(index);
446 0 : if (width <= 0) {
447 0 : WRITE_WARNING("invalid value for field: '"
448 : + myOptions.getString("shapefile.width")
449 : + "' of edge '" + edgeid
450 : + "': '" + std::string(poFeature.GetFieldAsString(index)) + "'");
451 : } else {
452 0 : return width / laneNumber;
453 : }
454 : }
455 : }
456 236 : if (myOptions.isSet("shapefile.type-id")) {
457 0 : return myTypeCont.getEdgeTypeWidth(poFeature.GetFieldAsString((char*)(myOptions.getString("shapefile.type-id").c_str())));
458 : }
459 118 : return NBEdge::UNSPECIFIED_WIDTH;
460 : }
461 :
462 :
463 :
464 : double
465 118 : NIImporter_ArcView::getLength(OGRFeature& poFeature, const std::string& edgeid) {
466 236 : if (myOptions.isSet("shapefile.length")) {
467 0 : int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.length").c_str());
468 0 : if (index >= 0 && poFeature.IsFieldSet(index)) {
469 0 : const double length = poFeature.GetFieldAsDouble(index);
470 0 : if (length <= 0) {
471 0 : 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 118 : return NBEdge::UNSPECIFIED_LOADED_LENGTH;
481 : }
482 :
483 :
484 : int
485 118 : NIImporter_ArcView::getLaneNo(OGRFeature& poFeature, const std::string& edgeid,
486 : double speed) {
487 236 : if (myOptions.isSet("shapefile.laneNumber")) {
488 0 : int index = poFeature.GetDefnRef()->GetFieldIndex(myOptions.getString("shapefile.laneNumber").c_str());
489 0 : if (index >= 0 && poFeature.IsFieldSet(index)) {
490 0 : const int laneNumber = poFeature.GetFieldAsInteger(index);
491 0 : if (laneNumber <= 0) {
492 0 : 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 236 : if (myOptions.isSet("shapefile.type-id")) {
501 0 : 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 118 : int index = poFeature.GetDefnRef()->GetFieldIndex("nolanes");
506 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
507 0 : return (int) poFeature.GetFieldAsInteger(index);
508 : }
509 118 : index = poFeature.GetDefnRef()->GetFieldIndex("NOLANES");
510 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
511 0 : return (int) poFeature.GetFieldAsInteger(index);
512 : }
513 118 : index = poFeature.GetDefnRef()->GetFieldIndex("rnol");
514 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
515 0 : return (int) poFeature.GetFieldAsInteger(index);
516 : }
517 118 : index = poFeature.GetDefnRef()->GetFieldIndex("LANE_CAT");
518 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
519 0 : std::string def = poFeature.GetFieldAsString(index);
520 0 : return NINavTeqHelper::getLaneNumber(edgeid, def, speed);
521 : }
522 : return 0;
523 : }
524 :
525 :
526 : int
527 118 : NIImporter_ArcView::getPriority(OGRFeature& poFeature, const std::string& /*edgeid*/) {
528 236 : if (myOptions.isSet("shapefile.type-id")) {
529 0 : 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 118 : int index = poFeature.GetDefnRef()->GetFieldIndex("priority");
534 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
535 0 : return poFeature.GetFieldAsInteger(index);
536 : }
537 118 : index = poFeature.GetDefnRef()->GetFieldIndex("PRIORITY");
538 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
539 0 : return poFeature.GetFieldAsInteger(index);
540 : }
541 : // try to determine priority from NavTechs FUNC_CLASS attribute
542 118 : index = poFeature.GetDefnRef()->GetFieldIndex("FUNC_CLASS");
543 118 : if (index >= 0 && poFeature.IsFieldSet(index)) {
544 0 : return poFeature.GetFieldAsInteger(index);
545 : }
546 : return 0;
547 : }
548 :
549 : void
550 117 : NIImporter_ArcView::checkSpread(NBEdge* e) {
551 117 : NBEdge* ret = e->getToNode()->getConnectionTo(e->getFromNode());
552 117 : if (ret != 0) {
553 0 : e->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
554 0 : ret->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
555 : }
556 117 : }
557 :
558 : bool
559 472 : NIImporter_ArcView::getStringEntry(OGRFeature* poFeature, const std::string& optionName, const char* defaultName, bool prune, std::string& into) {
560 472 : std::string v(defaultName);
561 472 : if (myOptions.isSet(optionName)) {
562 236 : v = myOptions.getString(optionName);
563 : }
564 472 : if (poFeature->GetFieldIndex(v.c_str()) < 0) {
565 354 : if (myOptions.isSet(optionName)) {
566 : into = v;
567 : return false;
568 : }
569 : into = "";
570 : return true;
571 : }
572 118 : into = poFeature->GetFieldAsString((char*)v.c_str());
573 118 : if (prune) {
574 236 : into = StringUtils::prune(into);
575 : }
576 : return true;
577 : }
578 :
579 : std::vector<std::string>
580 2 : NIImporter_ArcView::getFieldNames(OGRFeature* poFeature) const {
581 : std::vector<std::string> fields;
582 12 : for (int i = 0; i < poFeature->GetFieldCount(); i++) {
583 16 : fields.push_back(poFeature->GetFieldDefnRef(i)->GetNameRef());
584 : }
585 2 : return fields;
586 0 : }
587 :
588 : void
589 117 : NIImporter_ArcView::addParams(NBEdge* edge, OGRFeature* poFeature, const std::vector<std::string>& params) const {
590 117 : for (const std::string& p : params) {
591 0 : int index = poFeature->GetDefnRef()->GetFieldIndex(p.c_str());
592 0 : if (index >= 0 && poFeature->IsFieldSet(index)) {
593 0 : edge->setParameter(p, poFeature->GetFieldAsString(index));
594 : }
595 : }
596 117 : }
597 :
598 : #endif
599 :
600 :
601 : /****************************************************************************/
|