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_VISUM.cpp
15 : /// @author Daniel Krajzewicz
16 : /// @author Jakob Erdmann
17 : /// @author Sascha Krieg
18 : /// @author Michael Behrisch
19 : /// @date Fri, 19 Jul 2002
20 : ///
21 : // A VISUM network importer
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <string>
26 : #include <utils/common/MsgHandler.h>
27 : #include <utils/common/StringUtils.h>
28 : #include <utils/common/ToString.h>
29 : #include <utils/common/StringUtils.h>
30 : #include <utils/options/OptionsCont.h>
31 : #include <utils/geom/GeoConvHelper.h>
32 : #include <netbuild/NBDistrict.h>
33 : #include <netbuild/NBNetBuilder.h>
34 : #include <netbuild/NBPTStop.h>
35 : #include "NILoader.h"
36 : #include "NIImporter_VISUM.h"
37 :
38 :
39 : StringBijection<NIImporter_VISUM::VISUM_KEY>::Entry NIImporter_VISUM::KEYS_DE[] = {
40 : { "VSYS", VISUM_SYS },
41 : { "STRECKENTYP", VISUM_LINKTYPE },
42 : { "KNOTEN", VISUM_NODE },
43 : { "BEZIRK", VISUM_DISTRICT },
44 : { "PUNKT", VISUM_POINT },
45 : { "STRECKE", VISUM_LINK },
46 : { "V0IV", VISUM_V0 },
47 : { "VSYSSET", VISUM_TYPES },
48 : { "RANG", VISUM_RANK },
49 : { "KAPIV", VISUM_CAPACITY },
50 : { "XKOORD", VISUM_XCOORD },
51 : { "YKOORD", VISUM_YCOORD },
52 : { "ID", VISUM_ID },
53 : { "CODE", VISUM_CODE },
54 : { "VONKNOTNR", VISUM_FROMNODE },
55 : { "NACHKNOTNR", VISUM_TONODE },
56 : { "TYPNR", VISUM_TYPE },
57 : { "TYP", VISUM_TYP },
58 : { "ANBINDUNG", VISUM_DISTRICT_CONNECTION },
59 : { "BEZNR", VISUM_SOURCE_DISTRICT },
60 : { "KNOTNR", VISUM_FROMNODENO },
61 : { "RICHTUNG", VISUM_DIRECTION },
62 : { "FLAECHEID", VISUM_SURFACEID },
63 : { "TFLAECHEID", VISUM_FACEID },
64 : { "VONPUNKTID", VISUM_FROMPOINTID },
65 : { "NACHPUNKTID", VISUM_TOPOINTID },
66 : { "KANTE", VISUM_EDGE },
67 : { "ABBIEGER", VISUM_TURN },
68 : { "UEBERKNOTNR", VISUM_VIANODENO },
69 : { "ANZFAHRSTREIFEN", VISUM_NUMLANES },
70 : { "INDEX", VISUM_INDEX },
71 : { "STRECKENPOLY", VISUM_LINKPOLY },
72 : { "FLAECHENELEMENT", VISUM_SURFACEITEM },
73 : { "TEILFLAECHENELEMENT", VISUM_FACEITEM },
74 : { "KANTEID", VISUM_EDGEID },
75 : { "Q", VISUM_ORIGIN },
76 : { "Z", VISUM_DESTINATION },
77 : { "HALTEPUNKT", VISUM_STOPPOINT },
78 : { "NAME", VISUM_NAME },
79 : { "STRNR", VISUM_LINKNO },
80 : { "RELPOS", VISUM_RELPOS },
81 : { "KATNR", VISUM_CATID },
82 : { "ZWISCHENPUNKT", VISUM_EDGEITEM },
83 : { "POIKATEGORIE", VISUM_POICATEGORY },
84 : { "NR", VISUM_NO } // must be the last one
85 : };
86 :
87 :
88 :
89 : StringBijection<NIImporter_VISUM::VISUM_KEY> NIImporter_VISUM::KEYS(NIImporter_VISUM::KEYS_DE, VISUM_NO);
90 :
91 : // ===========================================================================
92 : // method definitions
93 : // ===========================================================================
94 : // ---------------------------------------------------------------------------
95 : // static methods (interface in this case)
96 : // ---------------------------------------------------------------------------
97 : void
98 2003 : NIImporter_VISUM::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
99 : // check whether the option is set (properly)
100 4006 : if (!oc.isSet("visum-file")) {
101 1995 : return;
102 : }
103 : // build the handler
104 16 : NIImporter_VISUM loader(nb, oc.getString("visum-file"),
105 16 : NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")),
106 16 : oc.getBool("visum.use-type-priority"),
107 24 : oc.getString("visum.language-file"));
108 8 : loader.load();
109 8 : }
110 :
111 :
112 :
113 : // ---------------------------------------------------------------------------
114 : // loader methods
115 : // ---------------------------------------------------------------------------
116 8 : NIImporter_VISUM::NIImporter_VISUM(NBNetBuilder& nb,
117 : const std::string& file,
118 : NBCapacity2Lanes capacity2Lanes,
119 : bool useVisumPrio,
120 8 : const std::string& languageFile) :
121 8 : myNetBuilder(nb), myFileName(file),
122 8 : myCapacity2Lanes(capacity2Lanes), myUseVisumPrio(useVisumPrio) {
123 8 : if (languageFile != "") {
124 0 : loadLanguage(languageFile);
125 : }
126 :
127 : // the order of process is important!
128 : // set1
129 8 : addParser(KEYS.getString(VISUM_SYS), &NIImporter_VISUM::parse_VSysTypes);
130 8 : addParser(KEYS.getString(VISUM_LINKTYPE), &NIImporter_VISUM::parse_Types);
131 8 : addParser(KEYS.getString(VISUM_NODE), &NIImporter_VISUM::parse_Nodes);
132 8 : addParser(KEYS.getString(VISUM_DISTRICT), &NIImporter_VISUM::parse_Districts);
133 8 : addParser(KEYS.getString(VISUM_POINT), &NIImporter_VISUM::parse_Point);
134 :
135 : // set2
136 : // two types of "strecke"
137 8 : addParser(KEYS.getString(VISUM_LINK), &NIImporter_VISUM::parse_Edges);
138 8 : addParser(KEYS.getString(VISUM_EDGE), &NIImporter_VISUM::parse_Kante);
139 :
140 : // set3
141 16 : if (OptionsCont::getOptions().getBool("visum.no-connectors")) {
142 8 : addParser(KEYS.getString(VISUM_DISTRICT_CONNECTION), &NIImporter_VISUM::parse_Connectors);
143 : } else {
144 0 : addParser(KEYS.getString(VISUM_DISTRICT_CONNECTION), &NIImporter_VISUM::parse_Connectors_legacy);
145 : }
146 : // two types of "abbieger"
147 8 : addParser("ABBIEGEBEZIEHUNG", &NIImporter_VISUM::parse_Turns);
148 8 : addParser(KEYS.getString(VISUM_TURN), &NIImporter_VISUM::parse_Turns);
149 :
150 8 : addParser(KEYS.getString(VISUM_LINKPOLY), &NIImporter_VISUM::parse_EdgePolys);
151 8 : addParser("FAHRSTREIFEN", &NIImporter_VISUM::parse_Lanes);
152 8 : addParser(KEYS.getString(VISUM_SURFACEITEM), &NIImporter_VISUM::parse_PartOfArea);
153 :
154 :
155 : // set4
156 : // two types of lsa
157 8 : addParser("LSA", &NIImporter_VISUM::parse_TrafficLights);
158 8 : addParser("SIGNALANLAGE", &NIImporter_VISUM::parse_TrafficLights);
159 : // two types of knotenzulsa
160 8 : addParser("KNOTENZULSA", &NIImporter_VISUM::parse_NodesToTrafficLights);
161 8 : addParser("LSAZUKNOTEN", &NIImporter_VISUM::parse_NodesToTrafficLights);
162 8 : addParser("SIGNALANLAGEZUKNOTEN", &NIImporter_VISUM::parse_NodesToTrafficLights);
163 : // two types of signalgruppe
164 8 : addParser("LSASIGNALGRUPPE", &NIImporter_VISUM::parse_SignalGroups);
165 8 : addParser("SIGNALGRUPPE", &NIImporter_VISUM::parse_SignalGroups);
166 : // three types of ABBZULSASIGNALGRUPPE
167 8 : addParser("ABBZULSASIGNALGRUPPE", &NIImporter_VISUM::parse_TurnsToSignalGroups);
168 8 : addParser("SIGNALGRUPPEZUABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
169 8 : addParser("SIGNALGRUPPEZUFSABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
170 :
171 8 : addParser(KEYS.getString(VISUM_FACEITEM), &NIImporter_VISUM::parse_AreaSubPartElement);
172 :
173 : // two types of LSAPHASE
174 8 : addParser("LSAPHASE", &NIImporter_VISUM::parse_Phases);
175 8 : addParser("PHASE", &NIImporter_VISUM::parse_Phases);
176 :
177 8 : addParser("LSASIGNALGRUPPEZULSAPHASE", &NIImporter_VISUM::parse_SignalGroupsToPhases);
178 8 : addParser("FAHRSTREIFENABBIEGER", &NIImporter_VISUM::parse_LanesConnections);
179 :
180 8 : addParser(KEYS.getString(VISUM_STOPPOINT), &NIImporter_VISUM::parse_stopPoints);
181 8 : }
182 :
183 :
184 8 : NIImporter_VISUM::~NIImporter_VISUM() {
185 25 : for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
186 17 : delete j->second;
187 : }
188 24 : }
189 :
190 :
191 : void
192 232 : NIImporter_VISUM::addParser(const std::string& name, ParsingFunction function) {
193 : TypeParser p;
194 : p.name = name;
195 232 : p.function = function;
196 232 : p.position = -1;
197 232 : mySingleDataParsers.push_back(p);
198 232 : }
199 :
200 :
201 : void
202 8 : NIImporter_VISUM::load() {
203 : // open the file
204 8 : if (!myLineReader.setFile(myFileName)) {
205 0 : throw ProcessError(TLF("Can not open visum-file '%'.", myFileName));
206 : }
207 : // scan the file for data positions
208 15987 : while (myLineReader.hasMore()) {
209 15979 : std::string line = myLineReader.readLine();
210 15979 : if (line.length() > 0 && line[0] == '$') {
211 : ParserVector::iterator i;
212 28710 : for (i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
213 55506 : std::string dataName = "$" + (*i).name + ":";
214 27753 : if (line.substr(0, dataName.length()) == dataName) {
215 159 : (*i).position = myLineReader.getPosition();
216 159 : (*i).pattern = line.substr(dataName.length());
217 477 : WRITE_MESSAGE("Found: " + dataName + " at line " + toString<int>(myLineReader.getLineNumber()));
218 : }
219 : }
220 : }
221 : }
222 : // go through the parsers and process all entries
223 240 : for (ParserVector::iterator i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
224 232 : if ((*i).position < 0) {
225 : // do not process using parsers for which no information was found
226 73 : continue;
227 : }
228 : // ok, the according information is stored in the file
229 318 : PROGRESS_BEGIN_MESSAGE("Parsing " + (*i).name);
230 : // reset the line reader and let it point to the begin of the according data field
231 159 : myLineReader.reinit();
232 159 : myLineReader.setPos((*i).position);
233 : // prepare the line parser
234 318 : myLineParser.reinit((*i).pattern);
235 : // read
236 : bool singleDataEndFound = false;
237 3919 : while (myLineReader.hasMore() && !singleDataEndFound) {
238 3760 : std::string line = myLineReader.readLine();
239 3760 : if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
240 : singleDataEndFound = true;
241 : } else {
242 3601 : myLineParser.parseLine(line);
243 : try {
244 3601 : myCurrentID = "<unknown>";
245 3601 : (this->*(*i).function)();
246 0 : } catch (OutOfBoundsException&) {
247 0 : WRITE_ERRORF(TL("Too short value line in % occurred."), (*i).name);
248 0 : } catch (NumberFormatException&) {
249 0 : WRITE_ERRORF(TL("A value in % should be numeric but is not (id='%')."), (*i).name, myCurrentID);
250 0 : } catch (UnknownElement& e) {
251 0 : WRITE_ERRORF(TL("One of the needed values ('%') is missing in %."), std::string(e.what()), (*i).name);
252 0 : }
253 : }
254 : }
255 : // close single reader processing
256 159 : PROGRESS_DONE_MESSAGE();
257 : }
258 8 : myNetBuilder.getEdgeCont().reduceGeometries(POSITION_EPS);
259 :
260 : // build traffic lights
261 25 : for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
262 17 : j->second->build(myNetBuilder.getEdgeCont(), myNetBuilder.getTLLogicCont());
263 : }
264 : // build district shapes
265 38 : for (std::map<NBDistrict*, PositionVector>::const_iterator k = myDistrictShapes.begin(); k != myDistrictShapes.end(); ++k) {
266 30 : (*k).first->addShape((*k).second);
267 : }
268 8 : }
269 :
270 :
271 :
272 :
273 :
274 : void
275 44 : NIImporter_VISUM::parse_VSysTypes() {
276 132 : std::string name = myLineParser.know("VSysCode") ? myLineParser.get("VSysCode").c_str() : myLineParser.get(KEYS.getString(VISUM_CODE)).c_str();
277 132 : std::string type = myLineParser.know("VSysMode") ? myLineParser.get("VSysMode").c_str() : myLineParser.get(KEYS.getString(VISUM_TYP)).c_str();
278 44 : myVSysTypes[name] = type;
279 44 : }
280 :
281 :
282 : void
283 800 : NIImporter_VISUM::parse_Types() {
284 : // get the id
285 800 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
286 : // get the maximum speed
287 800 : double speed = getWeightedFloat2("v0-IV", KEYS.getString(VISUM_V0), "km/h");
288 800 : if (speed == 0) {
289 : // unlimited speed
290 2 : speed = 3600;
291 798 : } else if (speed < 0) {
292 0 : WRITE_ERROR("Type '" + myCurrentID + "' has speed " + toString(speed));
293 : }
294 : // get the permissions
295 800 : SVCPermissions permissions = getPermissions(KEYS.getString(VISUM_TYPES), true);
296 : // get the priority
297 800 : const int priority = 1000 - StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_RANK)));
298 : // try to retrieve the number of lanes
299 800 : const int numLanes = myCapacity2Lanes.get(getNamedFloat("Kap-IV", KEYS.getString(VISUM_CAPACITY)));
300 : // insert the type
301 800 : myNetBuilder.getTypeCont().insertEdgeType(myCurrentID, numLanes, speed / (double) 3.6, priority, permissions, LaneSpreadFunction::RIGHT,
302 : NBEdge::UNSPECIFIED_WIDTH, false, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_WIDTH, 0, 0, 0);
303 800 : myNetBuilder.getTypeCont().markEdgeTypeAsSet(myCurrentID, SUMO_ATTR_NUMLANES);
304 800 : myNetBuilder.getTypeCont().markEdgeTypeAsSet(myCurrentID, SUMO_ATTR_SPEED);
305 800 : myNetBuilder.getTypeCont().markEdgeTypeAsSet(myCurrentID, SUMO_ATTR_PRIORITY);
306 800 : myNetBuilder.getTypeCont().markEdgeTypeAsSet(myCurrentID, SUMO_ATTR_ONEWAY);
307 800 : myNetBuilder.getTypeCont().markEdgeTypeAsSet(myCurrentID, SUMO_ATTR_ALLOW);
308 800 : myNetBuilder.getTypeCont().markEdgeTypeAsSet(myCurrentID, SUMO_ATTR_SPREADTYPE);
309 800 : }
310 :
311 :
312 : void
313 232 : NIImporter_VISUM::parse_Nodes() {
314 : // get the id
315 232 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
316 : // get the position
317 232 : double x = getNamedFloat(KEYS.getString(VISUM_XCOORD));
318 232 : double y = getNamedFloat(KEYS.getString(VISUM_YCOORD));
319 : Position pos(x, y);
320 232 : if (!NBNetBuilder::transformCoordinate(pos)) {
321 0 : WRITE_ERRORF(TL("Unable to project coordinates for node %."), myCurrentID);
322 0 : return;
323 : }
324 : // add to the list
325 232 : if (!myNetBuilder.getNodeCont().insert(myCurrentID, pos)) {
326 0 : WRITE_ERRORF(TL("Duplicate node occurred ('%')."), myCurrentID);
327 : }
328 : }
329 :
330 :
331 : void
332 50 : NIImporter_VISUM::parse_Districts() {
333 : // get the id
334 50 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
335 : // get the information whether the source and the destination
336 : // connections are weighted
337 : //bool sourcesWeighted = getWeightedBool("Proz_Q");
338 : //bool destWeighted = getWeightedBool("Proz_Z");
339 : // get the node information
340 50 : double x = getNamedFloat(KEYS.getString(VISUM_XCOORD));
341 50 : double y = getNamedFloat(KEYS.getString(VISUM_YCOORD));
342 : Position pos(x, y);
343 50 : if (!NBNetBuilder::transformCoordinate(pos, false)) {
344 0 : WRITE_ERRORF(TL("Unable to project coordinates for district %."), myCurrentID);
345 0 : return;
346 : }
347 : // build the district
348 50 : NBDistrict* district = new NBDistrict(myCurrentID, pos);
349 50 : if (!myNetBuilder.getDistrictCont().insert(district)) {
350 0 : WRITE_ERRORF(TL("Duplicate district occurred ('%')."), myCurrentID);
351 0 : delete district;
352 0 : return;
353 : }
354 50 : if (myLineParser.know(KEYS.getString(VISUM_SURFACEID))) {
355 : long long int flaecheID;
356 : try {
357 50 : flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
358 0 : } catch (EmptyData&) {
359 0 : flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_NO)));
360 0 : }
361 50 : myShapeDistrictMap[flaecheID] = district;
362 : }
363 : }
364 :
365 :
366 : void
367 25 : NIImporter_VISUM::parse_Point() {
368 25 : long long int id = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_ID)));
369 25 : double x = StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_XCOORD)));
370 50 : double y = StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_YCOORD)));
371 : Position pos(x, y);
372 25 : if (!NBNetBuilder::transformCoordinate(pos, false)) {
373 0 : WRITE_ERRORF(TL("Unable to project coordinates for point %."), toString(id));
374 0 : return;
375 : }
376 25 : myPoints[id] = pos;
377 : }
378 :
379 :
380 : void
381 462 : NIImporter_VISUM::parse_Edges() {
382 924 : if (myLineParser.know(KEYS.getString(VISUM_TYPES)) && myLineParser.get(KEYS.getString(VISUM_TYPES)) == "") {
383 : // no vehicle allowed; don't add
384 462 : return;
385 : }
386 : // get the id
387 462 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
388 : // get the from- & to-node and validate them
389 462 : NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
390 462 : NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
391 462 : if (!checkNodes(from, to)) {
392 : return;
393 : }
394 : // get the type
395 462 : std::string type = myLineParser.know(KEYS.getString(VISUM_TYP)) ? myLineParser.get(KEYS.getString(VISUM_TYP)) : myLineParser.get(KEYS.getString(VISUM_TYPE));
396 : // get the speed
397 462 : double speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
398 924 : if (!OptionsCont::getOptions().getBool("visum.use-type-speed")) {
399 : try {
400 462 : std::string speedS = myLineParser.know("v0-IV") ? myLineParser.get("v0-IV") : myLineParser.get(KEYS.getString(VISUM_V0));
401 462 : if (speedS.find("km/h") != std::string::npos) {
402 104 : speedS = speedS.substr(0, speedS.find("km/h"));
403 : }
404 462 : speed = StringUtils::toDouble(speedS) / 3.6;
405 0 : } catch (OutOfBoundsException&) {}
406 : }
407 462 : if (speed <= 0) {
408 0 : speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
409 : }
410 :
411 : // get the information whether the edge is a one-way
412 462 : bool oneway = myLineParser.know("Einbahn")
413 462 : ? StringUtils::toBool(myLineParser.get("Einbahn"))
414 : : true;
415 : // get the number of lanes
416 462 : int nolanes = myNetBuilder.getTypeCont().getEdgeTypeNumLanes(type);
417 924 : if (!OptionsCont::getOptions().getBool("visum.recompute-lane-number")) {
418 924 : if (!OptionsCont::getOptions().getBool("visum.use-type-laneno")) {
419 924 : if (myLineParser.know("Fahrstreifen")) {
420 0 : nolanes = StringUtils::toInt(myLineParser.get("Fahrstreifen"));
421 462 : } else if (myLineParser.know(KEYS.getString(VISUM_NUMLANES))) {
422 924 : nolanes = StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_NUMLANES)));
423 : }
424 : }
425 : } else {
426 0 : if (myLineParser.know(KEYS.getString(VISUM_CAPACITY))) {
427 0 : nolanes = myCapacity2Lanes.get(StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_CAPACITY))));
428 0 : } else if (myLineParser.know("KAP-IV")) {
429 0 : nolanes = myCapacity2Lanes.get(StringUtils::toDouble(myLineParser.get("KAP-IV")));
430 : }
431 : }
432 : // check whether the id is already used
433 : // (should be the opposite direction)
434 : bool oneway_checked = oneway;
435 462 : NBEdge* previous = myNetBuilder.getEdgeCont().retrieve(myCurrentID);
436 462 : if (previous != nullptr) {
437 225 : myCurrentID = '-' + myCurrentID;
438 225 : previous->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
439 : oneway_checked = false;
440 : }
441 462 : if (find(myTouchedEdges.begin(), myTouchedEdges.end(), myCurrentID) != myTouchedEdges.end()) {
442 : oneway_checked = false;
443 : }
444 462 : std::string tmpid = '-' + myCurrentID;
445 462 : if (find(myTouchedEdges.begin(), myTouchedEdges.end(), tmpid) != myTouchedEdges.end()) {
446 0 : previous = myNetBuilder.getEdgeCont().retrieve(tmpid);
447 0 : if (previous != nullptr) {
448 0 : previous->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
449 : }
450 : oneway_checked = false;
451 : }
452 462 : std::string name = StringUtils::latin1_to_utf8(myLineParser.get(KEYS.getString(VISUM_NAME)));
453 : // add the edge
454 462 : const SVCPermissions permissions = getPermissions(KEYS.getString(VISUM_TYPES), false, myNetBuilder.getTypeCont().getEdgeTypePermissions(type));
455 462 : int prio = myUseVisumPrio ? myNetBuilder.getTypeCont().getEdgeTypePriority(type) : -1;
456 462 : if (nolanes != 0 && speed != 0) {
457 450 : LaneSpreadFunction lsf = oneway_checked ? LaneSpreadFunction::CENTER : LaneSpreadFunction::RIGHT;
458 : NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, prio,
459 900 : NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, lsf, name);
460 450 : e->setPermissions(permissions);
461 450 : if (!myNetBuilder.getEdgeCont().insert(e)) {
462 0 : delete e;
463 0 : WRITE_ERRORF(TL("Duplicate edge occurred ('%')."), myCurrentID);
464 : }
465 : }
466 462 : myTouchedEdges.push_back(myCurrentID);
467 : // nothing more to do, when the edge is a one-way street
468 462 : if (oneway) {
469 : return;
470 : }
471 : // add the opposite edge
472 0 : myCurrentID = '-' + myCurrentID;
473 0 : if (nolanes != 0 && speed != 0) {
474 0 : LaneSpreadFunction lsf = oneway_checked ? LaneSpreadFunction::CENTER : LaneSpreadFunction::RIGHT;
475 : NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, prio,
476 0 : NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, lsf, name);
477 0 : e->setPermissions(permissions);
478 0 : if (!myNetBuilder.getEdgeCont().insert(e)) {
479 0 : delete e;
480 0 : WRITE_ERRORF(TL("Duplicate edge occurred ('%')."), myCurrentID);
481 : }
482 : }
483 0 : myTouchedEdges.push_back(myCurrentID);
484 : }
485 :
486 :
487 : void
488 30 : NIImporter_VISUM::parse_Kante() {
489 30 : long long int id = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_ID)));
490 30 : long long int from = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FROMPOINTID)));
491 30 : long long int to = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_TOPOINTID)));
492 30 : myEdges[id] = std::make_pair(from, to);
493 30 : }
494 :
495 :
496 : void
497 30 : NIImporter_VISUM::parse_PartOfArea() {
498 30 : long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
499 30 : long long int flaechePartID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FACEID)));
500 30 : if (mySubPartsAreas.find(flaechePartID) == mySubPartsAreas.end()) {
501 30 : mySubPartsAreas[flaechePartID] = std::vector<long long int>();
502 : }
503 30 : mySubPartsAreas[flaechePartID].push_back(flaecheID);
504 30 : }
505 :
506 :
507 : void
508 0 : NIImporter_VISUM::parse_Connectors() {
509 : // get the source district
510 0 : std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_SOURCE_DISTRICT)));
511 : // get the destination node
512 0 : NBNode* dest = getNamedNode(KEYS.getString(VISUM_FROMNODENO));
513 0 : if (dest == nullptr) {
514 : return;
515 : }
516 : // get the weight of the connection
517 : double proz = 1;
518 0 : if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
519 0 : proz = getNamedFloat("Proz", "Proz(IV)") / 100;
520 : }
521 : // get the information whether this is a sink or a source
522 0 : std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
523 0 : if (dir.length() == 0) {
524 0 : dir = KEYS.getString(VISUM_ORIGIN) + KEYS.getString(VISUM_DESTINATION);
525 : }
526 : // build the source when needed
527 0 : if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
528 0 : for (NBEdge* edge : dest->getOutgoingEdges()) {
529 0 : myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
530 : }
531 : }
532 : // build the sink when needed
533 0 : if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
534 0 : for (NBEdge* edge : dest->getIncomingEdges()) {
535 0 : myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
536 : }
537 : }
538 : }
539 :
540 :
541 :
542 : void
543 0 : NIImporter_VISUM::parse_Connectors_legacy() {
544 : // get the source district
545 0 : std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_SOURCE_DISTRICT)));
546 : // get the destination node
547 0 : NBNode* dest = getNamedNode(KEYS.getString(VISUM_FROMNODENO));
548 0 : if (dest == nullptr) {
549 : return;
550 : }
551 : // get the weight of the connection
552 : double proz = 1;
553 0 : if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
554 0 : proz = getNamedFloat("Proz", "Proz(IV)") / 100;
555 : }
556 : // get the duration to wait (unused)
557 : // double retard = -1;
558 : // if (myLineParser.know("t0-IV")) {
559 : // retard = getNamedFloat("t0-IV", -1);
560 : // }
561 : // get the type;
562 : // use a standard type with a large speed when a type is not given
563 :
564 0 : std::string type = myLineParser.know(KEYS.getString(VISUM_TYP))
565 0 : ? NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_TYP)))
566 0 : : "";
567 : // add the connectors as an edge
568 0 : std::string id = bez + "-" + dest->getID();
569 : // get the information whether this is a sink or a source
570 0 : std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
571 0 : if (dir.length() == 0) {
572 0 : dir = KEYS.getString(VISUM_ORIGIN) + KEYS.getString(VISUM_DESTINATION);
573 : }
574 : // build the source when needed
575 0 : if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
576 : const EdgeVector& edges = dest->getOutgoingEdges();
577 : bool hasContinuation = false;
578 0 : for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
579 0 : if (!(*i)->isMacroscopicConnector()) {
580 : hasContinuation = true;
581 : }
582 : }
583 0 : if (!hasContinuation) {
584 : // obviously, there is no continuation on the net
585 0 : WRITE_WARNINGF(TL("Incoming connector '%' will not be build - would be not connected to network."), id);
586 : } else {
587 0 : NBNode* src = buildDistrictNode(bez, dest, true);
588 0 : if (src == nullptr) {
589 0 : WRITE_ERRORF(TL("The district '%' could not be built."), bez);
590 0 : return;
591 : }
592 : NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
593 0 : OptionsCont::getOptions().getFloat("visum.connector-speeds"), NBEdge::UNSPECIFIED_FRICTION,
594 0 : OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
595 : -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
596 0 : LaneSpreadFunction::RIGHT, "");
597 : edge->setAsMacroscopicConnector();
598 0 : if (!myNetBuilder.getEdgeCont().insert(edge)) {
599 0 : WRITE_ERRORF(TL("A duplicate edge id occurred (ID='%')."), id);
600 0 : return;
601 : }
602 0 : edge = myNetBuilder.getEdgeCont().retrieve(id);
603 0 : if (edge != nullptr) {
604 0 : myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
605 : }
606 : }
607 : }
608 : // build the sink when needed
609 0 : if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
610 : const EdgeVector& edges = dest->getIncomingEdges();
611 : bool hasPredeccessor = false;
612 0 : for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
613 0 : if (!(*i)->isMacroscopicConnector()) {
614 : hasPredeccessor = true;
615 : }
616 : }
617 0 : if (!hasPredeccessor) {
618 : // obviously, the network is not connected to this node
619 0 : WRITE_WARNINGF(TL("Outgoing connector '%' will not be build - would be not connected to network."), id);
620 : } else {
621 0 : NBNode* src = buildDistrictNode(bez, dest, false);
622 0 : if (src == nullptr) {
623 0 : WRITE_ERRORF(TL("The district '%' could not be built."), bez);
624 0 : return;
625 : }
626 0 : id = "-" + id;
627 : NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
628 0 : OptionsCont::getOptions().getFloat("visum.connector-speeds"), NBEdge::UNSPECIFIED_FRICTION,
629 0 : OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
630 : -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
631 0 : LaneSpreadFunction::RIGHT, "");
632 : edge->setAsMacroscopicConnector();
633 0 : if (!myNetBuilder.getEdgeCont().insert(edge)) {
634 0 : WRITE_ERRORF(TL("A duplicate edge id occurred (ID='%')."), id);
635 0 : return;
636 : }
637 0 : edge = myNetBuilder.getEdgeCont().retrieve(id);
638 0 : if (edge != nullptr) {
639 0 : myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
640 : }
641 : }
642 : }
643 : }
644 :
645 :
646 : void
647 804 : NIImporter_VISUM::parse_Turns() {
648 1608 : if (myLineParser.know(KEYS.getString(VISUM_TYPES)) && myLineParser.get(KEYS.getString(VISUM_TYPES)) == "") {
649 : // no vehicle allowed; don't add
650 96 : return;
651 : }
652 : // retrieve the nodes
653 756 : NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
654 756 : NBNode* via = getNamedNode("UeberKnot", KEYS.getString(VISUM_VIANODENO));
655 756 : NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
656 756 : if (from == nullptr || via == nullptr || to == nullptr) {
657 : return;
658 : }
659 : // all nodes are known
660 1512 : std::string type = myLineParser.know("VSysCode")
661 756 : ? myLineParser.get("VSysCode")
662 756 : : myLineParser.get(KEYS.getString(VISUM_TYPES));
663 756 : if (myVSysTypes.find(type) != myVSysTypes.end() && myVSysTypes.find(type)->second == "IV") {
664 : // try to set the turning definition
665 416 : NBEdge* src = from->getConnectionTo(via);
666 416 : NBEdge* dest = via->getConnectionTo(to);
667 : // check both
668 416 : if (src == nullptr) {
669 48 : if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
670 0 : WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), from->getID(), via->getID());
671 : }
672 24 : return;
673 : }
674 392 : if (dest == nullptr) {
675 48 : if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
676 0 : WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), via->getID(), to->getID());
677 : }
678 24 : return;
679 : }
680 : // both edges found
681 : // set them into the edge
682 368 : src->addEdge2EdgeConnection(dest);
683 : }
684 : }
685 :
686 :
687 : void
688 351 : NIImporter_VISUM::parse_EdgePolys() {
689 : // get the from- & to-node and validate them
690 351 : NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
691 351 : NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
692 351 : if (!checkNodes(from, to)) {
693 0 : return;
694 : }
695 : bool failed = false;
696 : int index;
697 : double x, y;
698 : try {
699 351 : index = StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_INDEX)));
700 351 : x = getNamedFloat(KEYS.getString(VISUM_XCOORD));
701 351 : y = getNamedFloat(KEYS.getString(VISUM_YCOORD));
702 0 : } catch (NumberFormatException&) {
703 0 : WRITE_ERRORF(TL("Error in geometry description from node '%' to node '%'."), from->getID(), to->getID());
704 : return;
705 0 : }
706 : Position pos(x, y);
707 351 : if (!NBNetBuilder::transformCoordinate(pos)) {
708 0 : WRITE_ERRORF(TL("Unable to project coordinates for node '%'."), from->getID());
709 0 : return;
710 : }
711 351 : NBEdge* e = from->getConnectionTo(to);
712 351 : if (e != nullptr) {
713 351 : e->addGeometryPoint(index, pos);
714 : } else {
715 : failed = true;
716 : }
717 351 : e = to->getConnectionTo(from);
718 351 : if (e != nullptr) {
719 351 : e->addGeometryPoint(-index, pos);
720 : failed = false;
721 : }
722 : // check whether the operation has failed
723 0 : if (failed) {
724 0 : if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
725 0 : WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), from->getID(), to->getID());
726 : }
727 : }
728 : }
729 :
730 :
731 : void
732 228 : NIImporter_VISUM::parse_Lanes() {
733 : // The base number of lanes for the edge was already defined in STRECKE
734 : // this refines lane specific attribute (width) and optionally introduces splits for additional lanes
735 : // It is permitted for KNOTNR to be 0
736 : //
737 : // get the edge
738 228 : NBEdge* baseEdge = getNamedEdge(KEYS.getString(VISUM_LINKNO));
739 228 : if (baseEdge == nullptr) {
740 220 : return;
741 : }
742 : NBEdge* edge = baseEdge;
743 : // get the node
744 228 : NBNode* node = getNamedNodeSecure("KNOTNR");
745 228 : if (node == nullptr) {
746 : node = edge->getToNode();
747 : } else {
748 228 : edge = getNamedEdgeContinuating(KEYS.getString(VISUM_LINKNO), node);
749 : }
750 : // check
751 228 : if (edge == nullptr) {
752 : return;
753 : }
754 : // get the lane
755 228 : std::string laneS = myLineParser.know("FSNR")
756 489 : ? NBHelpers::normalIDRepresentation(myLineParser.get("FSNR"))
757 618 : : NBHelpers::normalIDRepresentation(myLineParser.get("NR"));
758 : int lane = -1;
759 : try {
760 228 : lane = StringUtils::toInt(laneS);
761 0 : } catch (NumberFormatException&) {
762 0 : WRITE_ERRORF(TL("A lane number for edge '%' is not numeric (%)."), edge->getID(), laneS);
763 : return;
764 0 : }
765 228 : lane -= 1;
766 228 : if (lane < 0) {
767 0 : WRITE_ERRORF(TL("A lane number for edge '%' is not positive (%)."), edge->getID(), laneS);
768 0 : return;
769 : }
770 : // get the direction
771 456 : std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
772 : int prevLaneNo = baseEdge->getNumLanes();
773 228 : if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
774 : // get the last part of the turnaround direction
775 134 : NBEdge* cand = getReversedContinuating(edge, node);
776 134 : if (cand) {
777 : edge = cand;
778 : }
779 : }
780 : // get the length
781 228 : std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
782 228 : double length = -1;
783 : try {
784 228 : length = StringUtils::toDouble(lengthS);
785 0 : } catch (NumberFormatException&) {
786 0 : WRITE_ERRORF(TL("A lane length for edge '%' is not numeric (%)."), edge->getID(), lengthS);
787 : return;
788 0 : }
789 228 : if (length < 0) {
790 0 : WRITE_ERRORF(TL("A lane length for edge '%' is not positive (%)."), edge->getID(), lengthS);
791 0 : return;
792 : }
793 : //
794 228 : if (dirS == "1") {
795 136 : lane -= prevLaneNo;
796 : }
797 : //
798 228 : if (length == 0) {
799 228 : if ((int) edge->getNumLanes() > lane) {
800 : // ok, we know this already...
801 : return;
802 : }
803 : // increment by one
804 8 : edge->incLaneNo(1);
805 : } else {
806 : // check whether this edge already has been created
807 0 : if (isSplitEdge(edge, node)) {
808 0 : if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
809 0 : if ((int) edge->getNumLanes() > lane) {
810 : // ok, we know this already...
811 0 : return;
812 : }
813 : // increment by one
814 0 : edge->incLaneNo(1);
815 : return;
816 : }
817 : }
818 : // nope, we have to split the edge...
819 : // maybe it is not the proper edge to split - VISUM seems not to sort the splits...
820 : bool mustRecheck = true;
821 : double seenLength = 0;
822 0 : while (mustRecheck) {
823 0 : if (isSplitEdge(edge, node)) {
824 : // ok, we have a previously created edge here
825 0 : std::string sub = edge->getID();
826 0 : sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
827 0 : sub = sub.substr(1, sub.find('_', 1) - 1);
828 0 : double dist = StringUtils::toDouble(sub);
829 0 : if (dist < length) {
830 0 : seenLength += edge->getLength();
831 0 : if (dirS == "1") {
832 : // incoming -> move back
833 0 : edge = edge->getFromNode()->getIncomingEdges()[0];
834 : } else {
835 : // outgoing -> move forward
836 0 : edge = edge->getToNode()->getOutgoingEdges()[0];
837 : }
838 : } else {
839 : mustRecheck = false;
840 : }
841 : } else {
842 : // we have the center edge - do not continue...
843 : mustRecheck = false;
844 : }
845 : }
846 : // compute position
847 : Position p;
848 0 : double useLength = length - seenLength;
849 0 : useLength = edge->getLength() - useLength;
850 0 : if (useLength < 0 || useLength > edge->getLength()) {
851 0 : WRITE_WARNINGF(TL("Could not find split position for edge '%'."), edge->getID());
852 0 : return;
853 : }
854 0 : std::string edgeID = edge->getID();
855 0 : p = edge->getGeometry().positionAtOffset(useLength);
856 0 : if (isSplitEdge(edge, node)) {
857 0 : edgeID = edgeID.substr(0, edgeID.find('_'));
858 : }
859 0 : NBNode* rn = new NBNode(edgeID + "_" + toString((int) length) + "_" + node->getID(), p);
860 0 : if (!myNetBuilder.getNodeCont().insert(rn)) {
861 0 : throw ProcessError(TL("Ups - could not insert node!"));
862 : }
863 0 : std::string nid = edgeID + "_" + toString((int) length) + "_" + node->getID();
864 0 : myNetBuilder.getEdgeCont().splitAt(myNetBuilder.getDistrictCont(), edge, useLength, rn,
865 0 : edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
866 : // old edge is deleted and a new edge with the same name created
867 0 : edge = myNetBuilder.getEdgeCont().retrieve(edgeID);
868 0 : NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
869 0 : nedge = nedge->getToNode()->getOutgoingEdges()[0];
870 0 : while (isSplitEdge(edge, node)) {
871 : assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
872 0 : nedge->incLaneNo(1);
873 0 : nedge = nedge->getToNode()->getOutgoingEdges()[0];
874 : }
875 : }
876 : }
877 :
878 :
879 : void
880 17 : NIImporter_VISUM::parse_TrafficLights() {
881 17 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
882 17 : const SUMOTime cycleTime = TIME2STEPS(getWeightedFloat2("Umlaufzeit", "UMLZEIT", "s"));
883 17 : const SUMOTime intermediateTime = TIME2STEPS(getWeightedFloat2("StdZwischenzeit", "STDZWZEIT", "s"));
884 17 : bool phaseBased = myLineParser.know("PhasenBasiert")
885 17 : ? StringUtils::toBool(myLineParser.get("PhasenBasiert"))
886 : : false;
887 85 : const SUMOTime offset = myLineParser.know("ZEITVERSATZ") ? TIME2STEPS(getWeightedFloat("ZEITVERSATZ", "s")) : 0;
888 : // add to the list
889 17 : myTLS[myCurrentID] = new NIVisumTL(myCurrentID, cycleTime, offset, intermediateTime, phaseBased);
890 17 : }
891 :
892 :
893 : void
894 17 : NIImporter_VISUM::parse_NodesToTrafficLights() {
895 17 : std::string node = myLineParser.get("KnotNr").c_str();
896 17 : if (node == "0") {
897 : // this is a dummy value which cannot be assigned to
898 : return;
899 : }
900 17 : std::string trafficLight = myLineParser.get("LsaNr").c_str();
901 : // add to the list
902 17 : NBNode* n = myNetBuilder.getNodeCont().retrieve(node);
903 : auto tlIt = myTLS.find(trafficLight);
904 17 : if (n != nullptr && tlIt != myTLS.end()) {
905 34 : tlIt->second->addNode(n);
906 : } else {
907 0 : WRITE_ERROR("Could not assign" + std::string(n == nullptr ? " missing" : "") + " node '" + node
908 : + "' to" + std::string(tlIt == myTLS.end() ? " missing" : "") + " traffic light '" + trafficLight + "'");
909 : }
910 : }
911 :
912 :
913 : void
914 72 : NIImporter_VISUM::parse_SignalGroups() {
915 72 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
916 72 : std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
917 72 : const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
918 72 : const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
919 192 : const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
920 : // add to the list
921 72 : if (myTLS.find(LSAid) == myTLS.end()) {
922 0 : WRITE_ERRORF(TL("Could not find TLS '%' for setting the signal group."), LSAid);
923 : return;
924 : }
925 72 : myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, startTime, endTime, yellowTime);
926 : }
927 :
928 :
929 : void
930 184 : NIImporter_VISUM::parse_TurnsToSignalGroups() {
931 : // get the id
932 368 : std::string SGid = getNamedString("SGNR", "SIGNALGRUPPENNR");
933 368 : if (!myLineParser.know("LsaNr")) {
934 : /// XXX could be retrieved from context
935 0 : WRITE_WARNING(TL("Ignoring SIGNALGRUPPEZUFSABBIEGER because LsaNr is not known"));
936 : return;
937 : }
938 184 : std::string LSAid = getNamedString("LsaNr");
939 : // nodes
940 184 : NBNode* from = myLineParser.know("VonKnot") ? getNamedNode("VonKnot") : nullptr;
941 184 : NBNode* via = myLineParser.know("KNOTNR")
942 368 : ? getNamedNode("KNOTNR")
943 232 : : getNamedNode("UeberKnot", "UeberKnotNr");
944 184 : NBNode* to = myLineParser.know("NachKnot") ? getNamedNode("NachKnot") : nullptr;
945 : // edges
946 : NBEdge* edg1 = nullptr;
947 : NBEdge* edg2 = nullptr;
948 184 : if (from == nullptr && to == nullptr) {
949 184 : edg1 = getNamedEdgeContinuating("VONSTRNR", via);
950 368 : edg2 = getNamedEdgeContinuating("NACHSTRNR", via);
951 : } else {
952 0 : edg1 = getEdge(from, via);
953 0 : edg2 = getEdge(via, to);
954 : }
955 : // add to the list
956 184 : NIVisumTL::SignalGroup& SG = myTLS.find(LSAid)->second->getSignalGroup(SGid);
957 184 : if (edg1 != nullptr && edg2 != nullptr) {
958 184 : if (!via->hasIncoming(edg1)) {
959 : std::string sid;
960 163 : if (edg1->getID()[0] == '-') {
961 0 : sid = edg1->getID().substr(1);
962 : } else {
963 326 : sid = "-" + edg1->getID();
964 : }
965 163 : if (sid.find('_') != std::string::npos) {
966 0 : sid = sid.substr(0, sid.find('_'));
967 : }
968 163 : edg1 = getNamedEdgeContinuating(myNetBuilder.getEdgeCont().retrieve(sid), via);
969 : }
970 184 : if (!via->hasOutgoing(edg2)) {
971 : std::string sid;
972 21 : if (edg2->getID()[0] == '-') {
973 0 : sid = edg2->getID().substr(1);
974 : } else {
975 42 : sid = "-" + edg2->getID();
976 : }
977 21 : if (sid.find('_') != std::string::npos) {
978 0 : sid = sid.substr(0, sid.find('_'));
979 : }
980 21 : edg2 = getNamedEdgeContinuating(myNetBuilder.getEdgeCont().retrieve(sid), via);
981 : }
982 368 : SG.connections().push_back(NBConnection(edg1, edg2));
983 : }
984 : }
985 :
986 :
987 : void
988 30 : NIImporter_VISUM::parse_AreaSubPartElement() {
989 30 : long long int id = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FACEID)));
990 30 : long long int edgeid = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_EDGEID)));
991 30 : if (myEdges.find(edgeid) == myEdges.end()) {
992 0 : WRITE_ERROR(TL("Unknown edge in TEILFLAECHENELEMENT"));
993 0 : return;
994 : }
995 30 : std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
996 : // get index (unused)
997 : // std::string indexS = NBHelpers::normalIDRepresentation(myLineParser.get("INDEX"));
998 : // int index = -1;
999 : // try {
1000 : // index = StringUtils::toInt(indexS) - 1;
1001 : // } catch (NumberFormatException&) {
1002 : // WRITE_ERRORF(TL("An index for a TEILFLAECHENELEMENT is not numeric (id='%')."), toString(id));
1003 : // return;
1004 : // }
1005 30 : PositionVector shape;
1006 30 : shape.push_back(myPoints[myEdges[edgeid].first]);
1007 30 : shape.push_back(myPoints[myEdges[edgeid].second]);
1008 30 : if (dir.length() > 0 && dir[0] == '1') {
1009 0 : shape = shape.reverse();
1010 : }
1011 30 : if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
1012 0 : WRITE_ERRORF(TL("Unknown are for area part '%'."), myCurrentID);
1013 : return;
1014 : }
1015 :
1016 : const std::vector<long long int>& areas = mySubPartsAreas.find(id)->second;
1017 60 : for (std::vector<long long int>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
1018 30 : NBDistrict* d = myShapeDistrictMap[*i];
1019 30 : if (d == nullptr) {
1020 0 : continue;
1021 : }
1022 30 : if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
1023 60 : myDistrictShapes[d] = PositionVector();
1024 : }
1025 30 : if (dir.length() > 0 && dir[0] == '1') {
1026 0 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1027 0 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1028 : } else {
1029 30 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1030 30 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1031 : }
1032 : }
1033 30 : }
1034 :
1035 :
1036 : void
1037 0 : NIImporter_VISUM::parse_Phases() {
1038 : // get the id
1039 0 : const std::string phaseid = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
1040 0 : const std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1041 0 : const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
1042 0 : const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
1043 0 : const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
1044 0 : myTLS.find(LSAid)->second->addPhase(phaseid, startTime, endTime, yellowTime);
1045 0 : }
1046 :
1047 :
1048 0 : void NIImporter_VISUM::parse_SignalGroupsToPhases() {
1049 : // get the id
1050 0 : std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("PsNr"));
1051 0 : std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1052 0 : std::string SGid = NBHelpers::normalIDRepresentation(myLineParser.get("SGNR"));
1053 : // insert
1054 0 : NIVisumTL* LSA = myTLS.find(LSAid)->second;
1055 0 : NIVisumTL::SignalGroup& SG = LSA->getSignalGroup(SGid);
1056 0 : NIVisumTL::Phase* PH = LSA->getPhases().find(Phaseid)->second;
1057 0 : SG.phases()[Phaseid] = PH;
1058 0 : }
1059 :
1060 :
1061 178 : void NIImporter_VISUM::parse_LanesConnections() {
1062 : NBNode* node = nullptr;
1063 : NBEdge* fromEdge = nullptr;
1064 : NBEdge* toEdge = nullptr;
1065 : // get the node and edges depending on network format
1066 356 : const std::string nodeID = getNamedString("KNOTNR", "KNOT");
1067 178 : if (nodeID == "0") {
1068 0 : fromEdge = getNamedEdge("VONSTRNR", "VONSTR");
1069 0 : toEdge = getNamedEdge("NACHSTRNR", "NACHSTR");
1070 0 : if (fromEdge == nullptr) {
1071 : return;
1072 : }
1073 : node = fromEdge->getToNode();
1074 0 : WRITE_WARNING(TL("Ignoring lane-to-lane connection (not yet implemented for this format version)"));
1075 0 : return;
1076 : } else {
1077 356 : node = getNamedNode("KNOTNR", "KNOT");
1078 178 : if (node == nullptr) {
1079 : return;
1080 : }
1081 356 : fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node);
1082 356 : toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node);
1083 : }
1084 178 : if (fromEdge == nullptr || toEdge == nullptr) {
1085 : return;
1086 : }
1087 :
1088 : int fromLaneOffset = 0;
1089 178 : if (!node->hasIncoming(fromEdge)) {
1090 : fromLaneOffset = fromEdge->getNumLanes();
1091 156 : fromEdge = getReversedContinuating(fromEdge, node);
1092 : } else {
1093 22 : fromEdge = getReversedContinuating(fromEdge, node);
1094 44 : NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_')));
1095 : fromLaneOffset = tmp->getNumLanes();
1096 : }
1097 :
1098 : int toLaneOffset = 0;
1099 178 : if (!node->hasOutgoing(toEdge)) {
1100 : toLaneOffset = toEdge->getNumLanes();
1101 22 : toEdge = getReversedContinuating(toEdge, node);
1102 : } else {
1103 312 : NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_')));
1104 : toLaneOffset = tmp->getNumLanes();
1105 : }
1106 : // get the from-lane
1107 178 : std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR"));
1108 : int fromLane = -1;
1109 : try {
1110 178 : fromLane = StringUtils::toInt(fromLaneS);
1111 0 : } catch (NumberFormatException&) {
1112 0 : WRITE_ERRORF(TL("A from-lane number for edge '%' is not numeric (%)."), fromEdge->getID(), fromLaneS);
1113 : return;
1114 0 : }
1115 178 : fromLane -= 1;
1116 178 : if (fromLane < 0) {
1117 0 : WRITE_ERRORF(TL("A from-lane number for edge '%' is not positive (%)."), fromEdge->getID(), fromLaneS);
1118 0 : return;
1119 : }
1120 : // get the from-lane
1121 178 : std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR"));
1122 : int toLane = -1;
1123 : try {
1124 178 : toLane = StringUtils::toInt(toLaneS);
1125 0 : } catch (NumberFormatException&) {
1126 0 : WRITE_ERRORF(TL("A to-lane number for edge '%' is not numeric (%)."), toEdge->getID(), toLaneS);
1127 : return;
1128 0 : }
1129 178 : toLane -= 1;
1130 178 : if (toLane < 0) {
1131 0 : WRITE_ERRORF(TL("A to-lane number for edge '%' is not positive (%)."), toEdge->getID(), toLaneS);
1132 0 : return;
1133 : }
1134 : // !!! the next is probably a hack
1135 178 : if (fromLane - fromLaneOffset < 0) {
1136 : //fromLaneOffset = 0;
1137 : } else {
1138 178 : fromLane = (int)fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1;
1139 : }
1140 178 : if (toLane - toLaneOffset < 0) {
1141 : //toLaneOffset = 0;
1142 : } else {
1143 0 : toLane = (int)toEdge->getNumLanes() - (toLane - toLaneOffset) - 1;
1144 : }
1145 : //
1146 178 : if ((int) fromEdge->getNumLanes() <= fromLane) {
1147 0 : WRITE_ERRORF(TL("A from-lane number for edge '%' is larger than the edge's lane number (%)."), fromEdge->getID(), fromLaneS);
1148 0 : return;
1149 : }
1150 178 : if ((int) toEdge->getNumLanes() <= toLane) {
1151 0 : WRITE_ERRORF(TL("A to-lane number for edge '%' is larger than the edge's lane number (%)."), toEdge->getID(), toLaneS);
1152 0 : return;
1153 : }
1154 : //
1155 356 : fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::Lane2LaneInfoType::VALIDATED);
1156 : }
1157 :
1158 :
1159 47 : void NIImporter_VISUM::parse_stopPoints() {
1160 47 : std::string id = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
1161 47 : std::string name = StringUtils::latin1_to_utf8(myLineParser.get(KEYS.getString(VISUM_NAME)));
1162 47 : SVCPermissions permissions = getPermissions(KEYS.getString(VISUM_TYPES), true);
1163 47 : NBNode* from = getNamedNodeSecure(KEYS.getString(VISUM_FROMNODE));
1164 47 : NBNode* to = getNamedNodeSecure(KEYS.getString(VISUM_FROMNODENO));
1165 47 : const std::string edgeID = myLineParser.get(KEYS.getString(VISUM_LINKNO));
1166 47 : if (edgeID == "") {
1167 141 : WRITE_WARNINGF(TL("Ignoring stopping place '%' without edge id"), id);
1168 0 : } else if (from == nullptr && to == nullptr) {
1169 0 : WRITE_WARNINGF(TL("Ignoring stopping place '%' without node information"), id);
1170 : } else {
1171 0 : NBEdge* edge = getNamedEdge(KEYS.getString(VISUM_LINKNO));
1172 0 : if (edge == nullptr) {
1173 0 : WRITE_WARNINGF(TL("Ignoring stopping place '%' with invalid edge reference '%'"), id, edgeID);
1174 0 : return;
1175 0 : } else if (from != nullptr) {
1176 0 : if (edge->getToNode() == from) {
1177 0 : NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1178 0 : if (edge2 == nullptr) {
1179 0 : WRITE_WARNINGF(TL("Could not find edge with from-node '%' and base id '%' for stopping place '%'"), from->getID(), edge->getID(), id);
1180 : } else {
1181 : edge = edge2;
1182 : }
1183 0 : } else if (edge->getFromNode() != from) {
1184 0 : WRITE_WARNINGF(TL("Unexpected from-node '%' for edge '%' of stopping place '%'"), from->getID(), edge->getID(), id);
1185 : }
1186 : } else {
1187 0 : if (edge->getFromNode() == to) {
1188 0 : NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1189 0 : if (edge2 == nullptr) {
1190 0 : WRITE_WARNINGF(TL("Could not find edge with to-node '%' and base id '%' for stopping place '%'"), to->getID(), edge->getID(), id);
1191 : } else {
1192 : edge = edge2;
1193 : }
1194 0 : } else if (edge->getToNode() != to) {
1195 0 : WRITE_WARNINGF(TL("Unexpected to-node '%' for edge '%' of stopping place '%'"), to->getID(), edge->getID(), id);
1196 : }
1197 : }
1198 0 : double relPos = StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_RELPOS)));
1199 : /// @note could also retrieve Xkoord, ykoord from $HALTESTELLE
1200 0 : Position pos = edge->getGeometry().positionAtOffset(edge->getLength() * relPos);
1201 :
1202 0 : const double length = OptionsCont::getOptions().getFloat("osm.stop-output.length");
1203 0 : std::shared_ptr<NBPTStop> ptStop = std::make_shared<NBPTStop>(id, pos, edge->getID(), edge->getID(), length, name, permissions);
1204 0 : myNetBuilder.getPTStopCont().insert(ptStop);
1205 : }
1206 : }
1207 :
1208 :
1209 : double
1210 1770 : NIImporter_VISUM::getWeightedFloat(const std::string& name, const std::string& suffix) {
1211 : try {
1212 1770 : std::string val = myLineParser.get(name);
1213 902 : if (val.find(suffix) != std::string::npos) {
1214 0 : val = val.substr(0, val.find(suffix));
1215 : }
1216 902 : return StringUtils::toDouble(val);
1217 868 : } catch (...) {}
1218 868 : return -1;
1219 : }
1220 :
1221 :
1222 : double
1223 868 : NIImporter_VISUM::getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix) {
1224 868 : double result = getWeightedFloat(name, suffix);
1225 868 : if (result != -1) {
1226 : return result;
1227 : } else {
1228 868 : return getWeightedFloat(name2, suffix);
1229 : }
1230 : }
1231 :
1232 : bool
1233 0 : NIImporter_VISUM::getWeightedBool(const std::string& name) {
1234 : try {
1235 0 : return StringUtils::toBool(myLineParser.get(name));
1236 0 : } catch (...) {}
1237 : try {
1238 0 : return StringUtils::toBool(myLineParser.get((name + "(IV)")));
1239 0 : } catch (...) {}
1240 0 : return false;
1241 : }
1242 :
1243 : SVCPermissions
1244 1309 : NIImporter_VISUM::getPermissions(const std::string& name, bool warn, SVCPermissions unknown) {
1245 : SVCPermissions result = 0;
1246 6477 : for (std::string v : StringTokenizer(myLineParser.get(name), ",").getVector()) {
1247 : // common values in english and german
1248 : // || v == "funiculaire-telecabine" ---> no matching
1249 3859 : v = StringUtils::to_lower_case(v);
1250 3859 : if (v == "bus" || v == "tcsp" || v == "acces tc" || v == "Accès tc" || v == "accès tc") {
1251 0 : result |= SVC_BUS;
1252 3859 : } else if (v == "walk" || v == "w" || v == "f" || v == "ped" || v == "map") {
1253 944 : result |= SVC_PEDESTRIAN;
1254 2915 : } else if (v == "l" || v == "lkw" || v == "h" || v == "hgv" || v == "lw" || v == "truck" || v == "tru" || v == "pl") {
1255 327 : result |= SVC_TRUCK;
1256 2588 : } else if (v == "b" || v == "bike" || v == "velo") {
1257 201 : result |= SVC_BICYCLE;
1258 2387 : } else if (v == "train" || v == "rail") {
1259 0 : result |= SVC_RAIL;
1260 2387 : } else if (v == "tram") {
1261 0 : result |= SVC_TRAM;
1262 2387 : } else if (v == "p" || v == "pkw" || v == "car" || v == "c" || v == "vp" || v == "2rm") {
1263 1367 : result |= SVC_PASSENGER;
1264 : } else {
1265 1020 : if (warn) {
1266 1140 : WRITE_WARNINGF("Encountered unknown vehicle category '" + v + "' in type '%'", myLineParser.get(KEYS.getString(VISUM_NO)));
1267 : }
1268 1020 : result |= unknown;
1269 : }
1270 1309 : }
1271 1309 : return result;
1272 : }
1273 :
1274 : NBNode*
1275 4256 : NIImporter_VISUM::getNamedNode(const std::string& fieldName) {
1276 4256 : std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1277 4256 : NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1278 4256 : if (node == nullptr) {
1279 0 : WRITE_ERRORF(TL("The node '%' is not known."), nodeS);
1280 : }
1281 4256 : return node;
1282 : }
1283 :
1284 : NBNode*
1285 322 : NIImporter_VISUM::getNamedNodeSecure(const std::string& fieldName, NBNode* fallback) {
1286 322 : std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1287 322 : NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1288 322 : if (node == nullptr) {
1289 47 : return fallback;
1290 : }
1291 : return node;
1292 : }
1293 :
1294 :
1295 : NBNode*
1296 4096 : NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) {
1297 4096 : if (myLineParser.know(fieldName1)) {
1298 178 : return getNamedNode(fieldName1);
1299 : } else {
1300 3918 : return getNamedNode(fieldName2);
1301 : }
1302 : }
1303 :
1304 :
1305 : NBEdge*
1306 228 : NIImporter_VISUM::getNamedEdge(const std::string& fieldName) {
1307 228 : std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1308 228 : NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1309 228 : if (edge == nullptr) {
1310 0 : WRITE_ERRORF(TL("The edge '%' is not known."), edgeS);
1311 : }
1312 228 : return edge;
1313 : }
1314 :
1315 :
1316 : NBEdge*
1317 0 : NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) {
1318 0 : if (myLineParser.know(fieldName1)) {
1319 0 : return getNamedEdge(fieldName1);
1320 : } else {
1321 0 : return getNamedEdge(fieldName2);
1322 : }
1323 : }
1324 :
1325 :
1326 :
1327 : NBEdge*
1328 334 : NIImporter_VISUM::getReversedContinuating(NBEdge* edge, NBNode* node) {
1329 : std::string sid;
1330 334 : if (edge->getID()[0] == '-') {
1331 0 : sid = edge->getID().substr(1);
1332 : } else {
1333 668 : sid = "-" + edge->getID();
1334 : }
1335 334 : if (sid.find('_') != std::string::npos) {
1336 0 : sid = sid.substr(0, sid.find('_'));
1337 : }
1338 668 : return getNamedEdgeContinuating(myNetBuilder.getEdgeCont().retrieve(sid), node);
1339 : }
1340 :
1341 :
1342 : NBEdge*
1343 1470 : NIImporter_VISUM::getNamedEdgeContinuating(NBEdge* begin, NBNode* node) {
1344 1470 : if (begin == nullptr) {
1345 : return nullptr;
1346 : }
1347 : NBEdge* ret = begin;
1348 1470 : std::string edgeID = ret->getID();
1349 : // hangle forward
1350 2386 : while (ret != nullptr) {
1351 : // ok, this is the edge we are looking for
1352 1470 : if (ret->getToNode() == node) {
1353 554 : return ret;
1354 : }
1355 : const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1356 916 : if (nedges.size() != 1) {
1357 : // too many edges follow
1358 : ret = nullptr;
1359 721 : continue;
1360 : }
1361 195 : NBEdge* next = nedges[0];
1362 390 : if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1363 : // ok, another edge is next...
1364 : ret = nullptr;
1365 195 : continue;
1366 : }
1367 0 : if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1368 : ret = nullptr;
1369 0 : continue;
1370 : }
1371 : ret = next;
1372 : }
1373 :
1374 : ret = begin;
1375 : // hangle backward
1376 916 : while (ret != nullptr) {
1377 : // ok, this is the edge we are looking for
1378 916 : if (ret->getFromNode() == node) {
1379 916 : return ret;
1380 : }
1381 : const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1382 0 : if (nedges.size() != 1) {
1383 : // too many edges follow
1384 : ret = nullptr;
1385 : continue;
1386 : }
1387 0 : NBEdge* next = nedges[0];
1388 0 : if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1389 : // ok, another edge is next...
1390 : ret = nullptr;
1391 : continue;
1392 : }
1393 0 : if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1394 : ret = nullptr;
1395 : continue;
1396 : }
1397 : ret = next;
1398 : }
1399 : return nullptr;
1400 : }
1401 :
1402 :
1403 : NBEdge*
1404 952 : NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName, NBNode* node) {
1405 952 : std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1406 952 : NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1407 952 : if (edge == nullptr) {
1408 0 : WRITE_ERRORF(TL("The edge '%' is not known."), edgeS);
1409 : }
1410 1904 : return getNamedEdgeContinuating(edge, node);
1411 : }
1412 :
1413 :
1414 : NBEdge*
1415 356 : NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1416 : NBNode* node) {
1417 356 : if (myLineParser.know(fieldName1)) {
1418 356 : return getNamedEdgeContinuating(fieldName1, node);
1419 : } else {
1420 0 : return getNamedEdgeContinuating(fieldName2, node);
1421 : }
1422 : }
1423 :
1424 :
1425 : NBEdge*
1426 0 : NIImporter_VISUM::getEdge(NBNode* FromNode, NBNode* ToNode) {
1427 : EdgeVector::const_iterator i;
1428 0 : for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1429 0 : if (ToNode == (*i)->getToNode()) {
1430 : return (*i);
1431 : }
1432 : }
1433 : //!!!
1434 : return nullptr;
1435 : }
1436 :
1437 :
1438 : double
1439 2474 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName) {
1440 2474 : std::string value = myLineParser.get(fieldName);
1441 4948 : if (StringUtils::endsWith(myLineParser.get(fieldName), "km/h")) {
1442 0 : value = value.substr(0, value.length() - 4);
1443 : }
1444 4948 : return StringUtils::toDouble(value);
1445 : }
1446 :
1447 :
1448 : double
1449 0 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName, double defaultValue) {
1450 : try {
1451 0 : return StringUtils::toDouble(myLineParser.get(fieldName));
1452 0 : } catch (...) {
1453 : return defaultValue;
1454 0 : }
1455 : }
1456 :
1457 :
1458 : double
1459 1088 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) {
1460 1088 : if (myLineParser.know(fieldName1)) {
1461 0 : return getNamedFloat(fieldName1);
1462 : } else {
1463 1088 : return getNamedFloat(fieldName2);
1464 : }
1465 : }
1466 :
1467 :
1468 : double
1469 0 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1470 : double defaultValue) {
1471 0 : if (myLineParser.know(fieldName1)) {
1472 0 : return getNamedFloat(fieldName1, defaultValue);
1473 : } else {
1474 0 : return getNamedFloat(fieldName2, defaultValue);
1475 : }
1476 : }
1477 :
1478 :
1479 : std::string
1480 546 : NIImporter_VISUM::getNamedString(const std::string& fieldName) {
1481 1092 : return NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1482 : }
1483 :
1484 :
1485 : std::string
1486 362 : NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1487 : const std::string& fieldName2) {
1488 362 : if (myLineParser.know(fieldName1)) {
1489 178 : return getNamedString(fieldName1);
1490 : } else {
1491 184 : return getNamedString(fieldName2);
1492 : }
1493 : }
1494 :
1495 :
1496 :
1497 :
1498 :
1499 :
1500 : NBNode*
1501 0 : NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1502 : bool isSource) {
1503 : // get the district
1504 0 : NBDistrict* dist = myNetBuilder.getDistrictCont().retrieve(id);
1505 0 : if (dist == nullptr) {
1506 : return nullptr;
1507 : }
1508 : // build the id
1509 : std::string nid;
1510 0 : nid = id + "-" + dest->getID();
1511 0 : if (!isSource) {
1512 0 : nid = "-" + nid;
1513 : }
1514 : // insert the node
1515 0 : if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1516 0 : WRITE_ERRORF(TL("Could not build connector node '%'."), nid);
1517 : }
1518 : // return the node
1519 0 : return myNetBuilder.getNodeCont().retrieve(nid);
1520 : }
1521 :
1522 :
1523 : bool
1524 813 : NIImporter_VISUM::checkNodes(NBNode* from, NBNode* to) {
1525 813 : if (from == nullptr) {
1526 0 : WRITE_ERROR(TL(" The from-node was not found within the net"));
1527 : }
1528 813 : if (to == nullptr) {
1529 0 : WRITE_ERROR(TL(" The to-node was not found within the net"));
1530 : }
1531 813 : if (from == to) {
1532 0 : WRITE_ERROR(TL(" Both nodes are the same"));
1533 : }
1534 813 : return from != nullptr && to != nullptr && from != to;
1535 : }
1536 :
1537 : bool
1538 0 : NIImporter_VISUM::isSplitEdge(NBEdge* edge, NBNode* node) {
1539 0 : return (edge->getID().length() > node->getID().length() + 1
1540 0 : && (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()));
1541 : }
1542 :
1543 : void
1544 0 : NIImporter_VISUM::loadLanguage(const std::string& file) {
1545 0 : std::ifstream strm(file.c_str());
1546 0 : if (!strm.good()) {
1547 0 : throw ProcessError(TLF("Could not load VISUM language map from '%'.", file));
1548 : }
1549 0 : while (strm.good()) {
1550 : std::string keyDE;
1551 : std::string keyNew;
1552 0 : strm >> keyDE;
1553 0 : strm >> keyNew;
1554 : if (KEYS.hasString(keyDE)) {
1555 0 : VISUM_KEY key = KEYS.get(keyDE);
1556 0 : KEYS.remove(keyDE, key);
1557 0 : KEYS.insert(keyNew, key);
1558 0 : } else if (keyDE != "") {
1559 0 : WRITE_WARNINGF(TL("Unknown entry '%' in VISUM language map"), keyDE);
1560 : }
1561 : }
1562 :
1563 0 : }
1564 :
1565 :
1566 : /****************************************************************************/
|