Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file NIImporter_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 1884 : NIImporter_VISUM::loadNetwork(const OptionsCont& oc, NBNetBuilder& nb) {
99 : // check whether the option is set (properly)
100 3768 : if (!oc.isSet("visum-file")) {
101 1876 : 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 : 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 50 : long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
356 50 : myShapeDistrictMap[flaecheID] = district;
357 : }
358 : }
359 :
360 :
361 : void
362 25 : NIImporter_VISUM::parse_Point() {
363 25 : long long int id = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_ID)));
364 25 : double x = StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_XCOORD)));
365 50 : double y = StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_YCOORD)));
366 : Position pos(x, y);
367 25 : if (!NBNetBuilder::transformCoordinate(pos, false)) {
368 0 : WRITE_ERRORF(TL("Unable to project coordinates for point %."), toString(id));
369 : return;
370 : }
371 25 : myPoints[id] = pos;
372 : }
373 :
374 :
375 : void
376 462 : NIImporter_VISUM::parse_Edges() {
377 924 : if (myLineParser.know(KEYS.getString(VISUM_TYPES)) && myLineParser.get(KEYS.getString(VISUM_TYPES)) == "") {
378 : // no vehicle allowed; don't add
379 462 : return;
380 : }
381 : // get the id
382 462 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
383 : // get the from- & to-node and validate them
384 462 : NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
385 462 : NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
386 462 : if (!checkNodes(from, to)) {
387 : return;
388 : }
389 : // get the type
390 462 : std::string type = myLineParser.know(KEYS.getString(VISUM_TYP)) ? myLineParser.get(KEYS.getString(VISUM_TYP)) : myLineParser.get(KEYS.getString(VISUM_TYPE));
391 : // get the speed
392 462 : double speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
393 924 : if (!OptionsCont::getOptions().getBool("visum.use-type-speed")) {
394 : try {
395 462 : std::string speedS = myLineParser.know("v0-IV") ? myLineParser.get("v0-IV") : myLineParser.get(KEYS.getString(VISUM_V0));
396 462 : if (speedS.find("km/h") != std::string::npos) {
397 104 : speedS = speedS.substr(0, speedS.find("km/h"));
398 : }
399 462 : speed = StringUtils::toDouble(speedS) / 3.6;
400 0 : } catch (OutOfBoundsException&) {}
401 : }
402 462 : if (speed <= 0) {
403 0 : speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
404 : }
405 :
406 : // get the information whether the edge is a one-way
407 462 : bool oneway = myLineParser.know("Einbahn")
408 462 : ? StringUtils::toBool(myLineParser.get("Einbahn"))
409 : : true;
410 : // get the number of lanes
411 462 : int nolanes = myNetBuilder.getTypeCont().getEdgeTypeNumLanes(type);
412 924 : if (!OptionsCont::getOptions().getBool("visum.recompute-lane-number")) {
413 924 : if (!OptionsCont::getOptions().getBool("visum.use-type-laneno")) {
414 924 : if (myLineParser.know("Fahrstreifen")) {
415 0 : nolanes = StringUtils::toInt(myLineParser.get("Fahrstreifen"));
416 462 : } else if (myLineParser.know(KEYS.getString(VISUM_NUMLANES))) {
417 924 : nolanes = StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_NUMLANES)));
418 : }
419 : }
420 : } else {
421 0 : if (myLineParser.know(KEYS.getString(VISUM_CAPACITY))) {
422 0 : nolanes = myCapacity2Lanes.get(StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_CAPACITY))));
423 0 : } else if (myLineParser.know("KAP-IV")) {
424 0 : nolanes = myCapacity2Lanes.get(StringUtils::toDouble(myLineParser.get("KAP-IV")));
425 : }
426 : }
427 : // check whether the id is already used
428 : // (should be the opposite direction)
429 : bool oneway_checked = oneway;
430 462 : NBEdge* previous = myNetBuilder.getEdgeCont().retrieve(myCurrentID);
431 462 : if (previous != nullptr) {
432 225 : myCurrentID = '-' + myCurrentID;
433 225 : previous->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
434 : oneway_checked = false;
435 : }
436 462 : if (find(myTouchedEdges.begin(), myTouchedEdges.end(), myCurrentID) != myTouchedEdges.end()) {
437 : oneway_checked = false;
438 : }
439 462 : std::string tmpid = '-' + myCurrentID;
440 462 : if (find(myTouchedEdges.begin(), myTouchedEdges.end(), tmpid) != myTouchedEdges.end()) {
441 0 : previous = myNetBuilder.getEdgeCont().retrieve(tmpid);
442 0 : if (previous != nullptr) {
443 0 : previous->setLaneSpreadFunction(LaneSpreadFunction::RIGHT);
444 : }
445 : oneway_checked = false;
446 : }
447 462 : std::string name = StringUtils::latin1_to_utf8(myLineParser.get(KEYS.getString(VISUM_NAME)));
448 : // add the edge
449 462 : const SVCPermissions permissions = getPermissions(KEYS.getString(VISUM_TYPES), false, myNetBuilder.getTypeCont().getEdgeTypePermissions(type));
450 462 : int prio = myUseVisumPrio ? myNetBuilder.getTypeCont().getEdgeTypePriority(type) : -1;
451 462 : if (nolanes != 0 && speed != 0) {
452 450 : LaneSpreadFunction lsf = oneway_checked ? LaneSpreadFunction::CENTER : LaneSpreadFunction::RIGHT;
453 : NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, prio,
454 900 : NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, lsf, name);
455 450 : e->setPermissions(permissions);
456 450 : if (!myNetBuilder.getEdgeCont().insert(e)) {
457 0 : delete e;
458 0 : WRITE_ERRORF(TL("Duplicate edge occurred ('%')."), myCurrentID);
459 : }
460 : }
461 462 : myTouchedEdges.push_back(myCurrentID);
462 : // nothing more to do, when the edge is a one-way street
463 462 : if (oneway) {
464 : return;
465 : }
466 : // add the opposite edge
467 0 : myCurrentID = '-' + myCurrentID;
468 0 : if (nolanes != 0 && speed != 0) {
469 0 : LaneSpreadFunction lsf = oneway_checked ? LaneSpreadFunction::CENTER : LaneSpreadFunction::RIGHT;
470 : NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, prio,
471 0 : NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET, lsf, name);
472 0 : e->setPermissions(permissions);
473 0 : if (!myNetBuilder.getEdgeCont().insert(e)) {
474 0 : delete e;
475 0 : WRITE_ERRORF(TL("Duplicate edge occurred ('%')."), myCurrentID);
476 : }
477 : }
478 0 : myTouchedEdges.push_back(myCurrentID);
479 : }
480 :
481 :
482 : void
483 30 : NIImporter_VISUM::parse_Kante() {
484 30 : long long int id = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_ID)));
485 30 : long long int from = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FROMPOINTID)));
486 30 : long long int to = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_TOPOINTID)));
487 30 : myEdges[id] = std::make_pair(from, to);
488 30 : }
489 :
490 :
491 : void
492 30 : NIImporter_VISUM::parse_PartOfArea() {
493 30 : long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
494 30 : long long int flaechePartID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FACEID)));
495 30 : if (mySubPartsAreas.find(flaechePartID) == mySubPartsAreas.end()) {
496 30 : mySubPartsAreas[flaechePartID] = std::vector<long long int>();
497 : }
498 30 : mySubPartsAreas[flaechePartID].push_back(flaecheID);
499 30 : }
500 :
501 :
502 : void
503 0 : NIImporter_VISUM::parse_Connectors() {
504 : // get the source district
505 0 : std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_SOURCE_DISTRICT)));
506 : // get the destination node
507 0 : NBNode* dest = getNamedNode(KEYS.getString(VISUM_FROMNODENO));
508 0 : if (dest == nullptr) {
509 : return;
510 : }
511 : // get the weight of the connection
512 : double proz = 1;
513 0 : if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
514 0 : proz = getNamedFloat("Proz", "Proz(IV)") / 100;
515 : }
516 : // get the information whether this is a sink or a source
517 0 : std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
518 0 : if (dir.length() == 0) {
519 0 : dir = KEYS.getString(VISUM_ORIGIN) + KEYS.getString(VISUM_DESTINATION);
520 : }
521 : // build the source when needed
522 0 : if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
523 0 : for (NBEdge* edge : dest->getOutgoingEdges()) {
524 0 : myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
525 : }
526 : }
527 : // build the sink when needed
528 0 : if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
529 0 : for (NBEdge* edge : dest->getIncomingEdges()) {
530 0 : myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
531 : }
532 : }
533 : }
534 :
535 :
536 :
537 : void
538 0 : NIImporter_VISUM::parse_Connectors_legacy() {
539 : // get the source district
540 0 : std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_SOURCE_DISTRICT)));
541 : // get the destination node
542 0 : NBNode* dest = getNamedNode(KEYS.getString(VISUM_FROMNODENO));
543 0 : if (dest == nullptr) {
544 : return;
545 : }
546 : // get the weight of the connection
547 : double proz = 1;
548 0 : if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
549 0 : proz = getNamedFloat("Proz", "Proz(IV)") / 100;
550 : }
551 : // get the duration to wait (unused)
552 : // double retard = -1;
553 : // if (myLineParser.know("t0-IV")) {
554 : // retard = getNamedFloat("t0-IV", -1);
555 : // }
556 : // get the type;
557 : // use a standard type with a large speed when a type is not given
558 :
559 0 : std::string type = myLineParser.know(KEYS.getString(VISUM_TYP))
560 0 : ? NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_TYP)))
561 0 : : "";
562 : // add the connectors as an edge
563 0 : std::string id = bez + "-" + dest->getID();
564 : // get the information whether this is a sink or a source
565 0 : std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
566 0 : if (dir.length() == 0) {
567 0 : dir = KEYS.getString(VISUM_ORIGIN) + KEYS.getString(VISUM_DESTINATION);
568 : }
569 : // build the source when needed
570 0 : if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
571 : const EdgeVector& edges = dest->getOutgoingEdges();
572 : bool hasContinuation = false;
573 0 : for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
574 0 : if (!(*i)->isMacroscopicConnector()) {
575 : hasContinuation = true;
576 : }
577 : }
578 0 : if (!hasContinuation) {
579 : // obviously, there is no continuation on the net
580 0 : WRITE_WARNINGF(TL("Incoming connector '%' will not be build - would be not connected to network."), id);
581 : } else {
582 0 : NBNode* src = buildDistrictNode(bez, dest, true);
583 0 : if (src == nullptr) {
584 0 : WRITE_ERRORF(TL("The district '%' could not be built."), bez);
585 0 : return;
586 : }
587 : NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
588 0 : OptionsCont::getOptions().getFloat("visum.connector-speeds"), NBEdge::UNSPECIFIED_FRICTION,
589 0 : OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
590 : -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
591 0 : LaneSpreadFunction::RIGHT, "");
592 : edge->setAsMacroscopicConnector();
593 0 : if (!myNetBuilder.getEdgeCont().insert(edge)) {
594 0 : WRITE_ERRORF(TL("A duplicate edge id occurred (ID='%')."), id);
595 0 : return;
596 : }
597 0 : edge = myNetBuilder.getEdgeCont().retrieve(id);
598 0 : if (edge != nullptr) {
599 0 : myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
600 : }
601 : }
602 : }
603 : // build the sink when needed
604 0 : if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
605 : const EdgeVector& edges = dest->getIncomingEdges();
606 : bool hasPredeccessor = false;
607 0 : for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
608 0 : if (!(*i)->isMacroscopicConnector()) {
609 : hasPredeccessor = true;
610 : }
611 : }
612 0 : if (!hasPredeccessor) {
613 : // obviously, the network is not connected to this node
614 0 : WRITE_WARNINGF(TL("Outgoing connector '%' will not be build - would be not connected to network."), id);
615 : } else {
616 0 : NBNode* src = buildDistrictNode(bez, dest, false);
617 0 : if (src == nullptr) {
618 0 : WRITE_ERRORF(TL("The district '%' could not be built."), bez);
619 0 : return;
620 : }
621 0 : id = "-" + id;
622 : NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
623 0 : OptionsCont::getOptions().getFloat("visum.connector-speeds"), NBEdge::UNSPECIFIED_FRICTION,
624 0 : OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
625 : -1, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_OFFSET,
626 0 : LaneSpreadFunction::RIGHT, "");
627 : edge->setAsMacroscopicConnector();
628 0 : if (!myNetBuilder.getEdgeCont().insert(edge)) {
629 0 : WRITE_ERRORF(TL("A duplicate edge id occurred (ID='%')."), id);
630 0 : return;
631 : }
632 0 : edge = myNetBuilder.getEdgeCont().retrieve(id);
633 0 : if (edge != nullptr) {
634 0 : myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
635 : }
636 : }
637 : }
638 : }
639 :
640 :
641 : void
642 804 : NIImporter_VISUM::parse_Turns() {
643 1608 : if (myLineParser.know(KEYS.getString(VISUM_TYPES)) && myLineParser.get(KEYS.getString(VISUM_TYPES)) == "") {
644 : // no vehicle allowed; don't add
645 96 : return;
646 : }
647 : // retrieve the nodes
648 756 : NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
649 756 : NBNode* via = getNamedNode("UeberKnot", KEYS.getString(VISUM_VIANODENO));
650 756 : NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
651 756 : if (from == nullptr || via == nullptr || to == nullptr) {
652 : return;
653 : }
654 : // all nodes are known
655 1512 : std::string type = myLineParser.know("VSysCode")
656 756 : ? myLineParser.get("VSysCode")
657 756 : : myLineParser.get(KEYS.getString(VISUM_TYPES));
658 756 : if (myVSysTypes.find(type) != myVSysTypes.end() && myVSysTypes.find(type)->second == "IV") {
659 : // try to set the turning definition
660 416 : NBEdge* src = from->getConnectionTo(via);
661 416 : NBEdge* dest = via->getConnectionTo(to);
662 : // check both
663 416 : if (src == nullptr) {
664 48 : if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
665 0 : WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), from->getID(), via->getID());
666 : }
667 24 : return;
668 : }
669 392 : if (dest == nullptr) {
670 48 : if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
671 0 : WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), via->getID(), to->getID());
672 : }
673 24 : return;
674 : }
675 : // both edges found
676 : // set them into the edge
677 368 : src->addEdge2EdgeConnection(dest);
678 : }
679 : }
680 :
681 :
682 : void
683 351 : NIImporter_VISUM::parse_EdgePolys() {
684 : // get the from- & to-node and validate them
685 351 : NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
686 351 : NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
687 351 : if (!checkNodes(from, to)) {
688 0 : return;
689 : }
690 : bool failed = false;
691 : int index;
692 : double x, y;
693 : try {
694 351 : index = StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_INDEX)));
695 351 : x = getNamedFloat(KEYS.getString(VISUM_XCOORD));
696 351 : y = getNamedFloat(KEYS.getString(VISUM_YCOORD));
697 0 : } catch (NumberFormatException&) {
698 0 : WRITE_ERRORF(TL("Error in geometry description from node '%' to node '%'."), from->getID(), to->getID());
699 : return;
700 0 : }
701 : Position pos(x, y);
702 351 : if (!NBNetBuilder::transformCoordinate(pos)) {
703 0 : WRITE_ERRORF(TL("Unable to project coordinates for node '%'."), from->getID());
704 : return;
705 : }
706 351 : NBEdge* e = from->getConnectionTo(to);
707 351 : if (e != nullptr) {
708 351 : e->addGeometryPoint(index, pos);
709 : } else {
710 : failed = true;
711 : }
712 351 : e = to->getConnectionTo(from);
713 351 : if (e != nullptr) {
714 351 : e->addGeometryPoint(-index, pos);
715 : failed = false;
716 : }
717 : // check whether the operation has failed
718 0 : if (failed) {
719 0 : if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
720 0 : WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), from->getID(), to->getID());
721 : }
722 : }
723 : }
724 :
725 :
726 : void
727 228 : NIImporter_VISUM::parse_Lanes() {
728 : // The base number of lanes for the edge was already defined in STRECKE
729 : // this refines lane specific attribute (width) and optionally introduces splits for additional lanes
730 : // It is permitted for KNOTNR to be 0
731 : //
732 : // get the edge
733 228 : NBEdge* baseEdge = getNamedEdge(KEYS.getString(VISUM_LINKNO));
734 228 : if (baseEdge == nullptr) {
735 220 : return;
736 : }
737 : NBEdge* edge = baseEdge;
738 : // get the node
739 228 : NBNode* node = getNamedNodeSecure("KNOTNR");
740 228 : if (node == nullptr) {
741 : node = edge->getToNode();
742 : } else {
743 228 : edge = getNamedEdgeContinuating(KEYS.getString(VISUM_LINKNO), node);
744 : }
745 : // check
746 228 : if (edge == nullptr) {
747 : return;
748 : }
749 : // get the lane
750 228 : std::string laneS = myLineParser.know("FSNR")
751 489 : ? NBHelpers::normalIDRepresentation(myLineParser.get("FSNR"))
752 618 : : NBHelpers::normalIDRepresentation(myLineParser.get("NR"));
753 : int lane = -1;
754 : try {
755 228 : lane = StringUtils::toInt(laneS);
756 0 : } catch (NumberFormatException&) {
757 0 : WRITE_ERRORF(TL("A lane number for edge '%' is not numeric (%)."), edge->getID(), laneS);
758 : return;
759 0 : }
760 228 : lane -= 1;
761 228 : if (lane < 0) {
762 0 : WRITE_ERRORF(TL("A lane number for edge '%' is not positive (%)."), edge->getID(), laneS);
763 0 : return;
764 : }
765 : // get the direction
766 456 : std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
767 : int prevLaneNo = baseEdge->getNumLanes();
768 228 : if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
769 : // get the last part of the turnaround direction
770 134 : NBEdge* cand = getReversedContinuating(edge, node);
771 134 : if (cand) {
772 : edge = cand;
773 : }
774 : }
775 : // get the length
776 228 : std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
777 228 : double length = -1;
778 : try {
779 228 : length = StringUtils::toDouble(lengthS);
780 0 : } catch (NumberFormatException&) {
781 0 : WRITE_ERRORF(TL("A lane length for edge '%' is not numeric (%)."), edge->getID(), lengthS);
782 : return;
783 0 : }
784 228 : if (length < 0) {
785 0 : WRITE_ERRORF(TL("A lane length for edge '%' is not positive (%)."), edge->getID(), lengthS);
786 0 : return;
787 : }
788 : //
789 228 : if (dirS == "1") {
790 136 : lane -= prevLaneNo;
791 : }
792 : //
793 228 : if (length == 0) {
794 228 : if ((int) edge->getNumLanes() > lane) {
795 : // ok, we know this already...
796 : return;
797 : }
798 : // increment by one
799 8 : edge->incLaneNo(1);
800 : } else {
801 : // check whether this edge already has been created
802 0 : if (isSplitEdge(edge, node)) {
803 0 : if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
804 0 : if ((int) edge->getNumLanes() > lane) {
805 : // ok, we know this already...
806 0 : return;
807 : }
808 : // increment by one
809 0 : edge->incLaneNo(1);
810 : return;
811 : }
812 : }
813 : // nope, we have to split the edge...
814 : // maybe it is not the proper edge to split - VISUM seems not to sort the splits...
815 : bool mustRecheck = true;
816 : double seenLength = 0;
817 0 : while (mustRecheck) {
818 0 : if (isSplitEdge(edge, node)) {
819 : // ok, we have a previously created edge here
820 0 : std::string sub = edge->getID();
821 0 : sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
822 0 : sub = sub.substr(1, sub.find('_', 1) - 1);
823 0 : double dist = StringUtils::toDouble(sub);
824 0 : if (dist < length) {
825 0 : seenLength += edge->getLength();
826 0 : if (dirS == "1") {
827 : // incoming -> move back
828 0 : edge = edge->getFromNode()->getIncomingEdges()[0];
829 : } else {
830 : // outgoing -> move forward
831 0 : edge = edge->getToNode()->getOutgoingEdges()[0];
832 : }
833 : } else {
834 : mustRecheck = false;
835 : }
836 : } else {
837 : // we have the center edge - do not continue...
838 : mustRecheck = false;
839 : }
840 : }
841 : // compute position
842 : Position p;
843 0 : double useLength = length - seenLength;
844 0 : useLength = edge->getLength() - useLength;
845 0 : if (useLength < 0 || useLength > edge->getLength()) {
846 0 : WRITE_WARNINGF(TL("Could not find split position for edge '%'."), edge->getID());
847 : return;
848 : }
849 0 : std::string edgeID = edge->getID();
850 0 : p = edge->getGeometry().positionAtOffset(useLength);
851 0 : if (isSplitEdge(edge, node)) {
852 0 : edgeID = edgeID.substr(0, edgeID.find('_'));
853 : }
854 0 : NBNode* rn = new NBNode(edgeID + "_" + toString((int) length) + "_" + node->getID(), p);
855 0 : if (!myNetBuilder.getNodeCont().insert(rn)) {
856 0 : throw ProcessError(TL("Ups - could not insert node!"));
857 : }
858 0 : std::string nid = edgeID + "_" + toString((int) length) + "_" + node->getID();
859 0 : myNetBuilder.getEdgeCont().splitAt(myNetBuilder.getDistrictCont(), edge, useLength, rn,
860 0 : edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
861 : // old edge is deleted and a new edge with the same name created
862 0 : edge = myNetBuilder.getEdgeCont().retrieve(edgeID);
863 0 : NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
864 0 : nedge = nedge->getToNode()->getOutgoingEdges()[0];
865 0 : while (isSplitEdge(edge, node)) {
866 : assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
867 0 : nedge->incLaneNo(1);
868 0 : nedge = nedge->getToNode()->getOutgoingEdges()[0];
869 : }
870 : }
871 : }
872 :
873 :
874 : void
875 17 : NIImporter_VISUM::parse_TrafficLights() {
876 17 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
877 17 : const SUMOTime cycleTime = TIME2STEPS(getWeightedFloat2("Umlaufzeit", "UMLZEIT", "s"));
878 17 : const SUMOTime intermediateTime = TIME2STEPS(getWeightedFloat2("StdZwischenzeit", "STDZWZEIT", "s"));
879 17 : bool phaseBased = myLineParser.know("PhasenBasiert")
880 17 : ? StringUtils::toBool(myLineParser.get("PhasenBasiert"))
881 : : false;
882 85 : const SUMOTime offset = myLineParser.know("ZEITVERSATZ") ? TIME2STEPS(getWeightedFloat("ZEITVERSATZ", "s")) : 0;
883 : // add to the list
884 17 : myTLS[myCurrentID] = new NIVisumTL(myCurrentID, cycleTime, offset, intermediateTime, phaseBased);
885 17 : }
886 :
887 :
888 : void
889 17 : NIImporter_VISUM::parse_NodesToTrafficLights() {
890 17 : std::string node = myLineParser.get("KnotNr").c_str();
891 17 : if (node == "0") {
892 : // this is a dummy value which cannot be assigned to
893 : return;
894 : }
895 17 : std::string trafficLight = myLineParser.get("LsaNr").c_str();
896 : // add to the list
897 17 : NBNode* n = myNetBuilder.getNodeCont().retrieve(node);
898 : auto tlIt = myTLS.find(trafficLight);
899 17 : if (n != nullptr && tlIt != myTLS.end()) {
900 34 : tlIt->second->addNode(n);
901 : } else {
902 0 : WRITE_ERROR("Could not assign" + std::string(n == nullptr ? " missing" : "") + " node '" + node
903 : + "' to" + std::string(tlIt == myTLS.end() ? " missing" : "") + " traffic light '" + trafficLight + "'");
904 : }
905 : }
906 :
907 :
908 : void
909 72 : NIImporter_VISUM::parse_SignalGroups() {
910 72 : myCurrentID = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
911 72 : std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
912 72 : const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
913 72 : const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
914 192 : const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
915 : // add to the list
916 72 : if (myTLS.find(LSAid) == myTLS.end()) {
917 0 : WRITE_ERRORF(TL("Could not find TLS '%' for setting the signal group."), LSAid);
918 : return;
919 : }
920 72 : myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, startTime, endTime, yellowTime);
921 : }
922 :
923 :
924 : void
925 184 : NIImporter_VISUM::parse_TurnsToSignalGroups() {
926 : // get the id
927 368 : std::string SGid = getNamedString("SGNR", "SIGNALGRUPPENNR");
928 368 : if (!myLineParser.know("LsaNr")) {
929 : /// XXX could be retrieved from context
930 0 : WRITE_WARNING(TL("Ignoring SIGNALGRUPPEZUFSABBIEGER because LsaNr is not known"));
931 : return;
932 : }
933 184 : std::string LSAid = getNamedString("LsaNr");
934 : // nodes
935 184 : NBNode* from = myLineParser.know("VonKnot") ? getNamedNode("VonKnot") : nullptr;
936 184 : NBNode* via = myLineParser.know("KNOTNR")
937 368 : ? getNamedNode("KNOTNR")
938 232 : : getNamedNode("UeberKnot", "UeberKnotNr");
939 184 : NBNode* to = myLineParser.know("NachKnot") ? getNamedNode("NachKnot") : nullptr;
940 : // edges
941 : NBEdge* edg1 = nullptr;
942 : NBEdge* edg2 = nullptr;
943 184 : if (from == nullptr && to == nullptr) {
944 184 : edg1 = getNamedEdgeContinuating("VONSTRNR", via);
945 368 : edg2 = getNamedEdgeContinuating("NACHSTRNR", via);
946 : } else {
947 0 : edg1 = getEdge(from, via);
948 0 : edg2 = getEdge(via, to);
949 : }
950 : // add to the list
951 184 : NIVisumTL::SignalGroup& SG = myTLS.find(LSAid)->second->getSignalGroup(SGid);
952 184 : if (edg1 != nullptr && edg2 != nullptr) {
953 184 : if (!via->hasIncoming(edg1)) {
954 : std::string sid;
955 163 : if (edg1->getID()[0] == '-') {
956 0 : sid = edg1->getID().substr(1);
957 : } else {
958 326 : sid = "-" + edg1->getID();
959 : }
960 163 : if (sid.find('_') != std::string::npos) {
961 0 : sid = sid.substr(0, sid.find('_'));
962 : }
963 163 : edg1 = getNamedEdgeContinuating(myNetBuilder.getEdgeCont().retrieve(sid), via);
964 : }
965 184 : if (!via->hasOutgoing(edg2)) {
966 : std::string sid;
967 21 : if (edg2->getID()[0] == '-') {
968 0 : sid = edg2->getID().substr(1);
969 : } else {
970 42 : sid = "-" + edg2->getID();
971 : }
972 21 : if (sid.find('_') != std::string::npos) {
973 0 : sid = sid.substr(0, sid.find('_'));
974 : }
975 21 : edg2 = getNamedEdgeContinuating(myNetBuilder.getEdgeCont().retrieve(sid), via);
976 : }
977 368 : SG.connections().push_back(NBConnection(edg1, edg2));
978 : }
979 : }
980 :
981 :
982 : void
983 30 : NIImporter_VISUM::parse_AreaSubPartElement() {
984 30 : long long int id = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FACEID)));
985 30 : long long int edgeid = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_EDGEID)));
986 30 : if (myEdges.find(edgeid) == myEdges.end()) {
987 0 : WRITE_ERROR(TL("Unknown edge in TEILFLAECHENELEMENT"));
988 0 : return;
989 : }
990 30 : std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
991 : // get index (unused)
992 : // std::string indexS = NBHelpers::normalIDRepresentation(myLineParser.get("INDEX"));
993 : // int index = -1;
994 : // try {
995 : // index = StringUtils::toInt(indexS) - 1;
996 : // } catch (NumberFormatException&) {
997 : // WRITE_ERRORF(TL("An index for a TEILFLAECHENELEMENT is not numeric (id='%')."), toString(id));
998 : // return;
999 : // }
1000 30 : PositionVector shape;
1001 30 : shape.push_back(myPoints[myEdges[edgeid].first]);
1002 30 : shape.push_back(myPoints[myEdges[edgeid].second]);
1003 30 : if (dir.length() > 0 && dir[0] == '1') {
1004 0 : shape = shape.reverse();
1005 : }
1006 30 : if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
1007 0 : WRITE_ERRORF(TL("Unknown are for area part '%'."), myCurrentID);
1008 : return;
1009 : }
1010 :
1011 : const std::vector<long long int>& areas = mySubPartsAreas.find(id)->second;
1012 60 : for (std::vector<long long int>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
1013 30 : NBDistrict* d = myShapeDistrictMap[*i];
1014 30 : if (d == nullptr) {
1015 0 : continue;
1016 : }
1017 30 : if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
1018 60 : myDistrictShapes[d] = PositionVector();
1019 : }
1020 30 : if (dir.length() > 0 && dir[0] == '1') {
1021 0 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1022 0 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1023 : } else {
1024 30 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1025 30 : myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1026 : }
1027 : }
1028 30 : }
1029 :
1030 :
1031 : void
1032 0 : NIImporter_VISUM::parse_Phases() {
1033 : // get the id
1034 0 : const std::string phaseid = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
1035 0 : const std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1036 0 : const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
1037 0 : const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
1038 0 : const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
1039 0 : myTLS.find(LSAid)->second->addPhase(phaseid, startTime, endTime, yellowTime);
1040 0 : }
1041 :
1042 :
1043 0 : void NIImporter_VISUM::parse_SignalGroupsToPhases() {
1044 : // get the id
1045 0 : std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("PsNr"));
1046 0 : std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1047 0 : std::string SGid = NBHelpers::normalIDRepresentation(myLineParser.get("SGNR"));
1048 : // insert
1049 0 : NIVisumTL* LSA = myTLS.find(LSAid)->second;
1050 0 : NIVisumTL::SignalGroup& SG = LSA->getSignalGroup(SGid);
1051 0 : NIVisumTL::Phase* PH = LSA->getPhases().find(Phaseid)->second;
1052 0 : SG.phases()[Phaseid] = PH;
1053 0 : }
1054 :
1055 :
1056 178 : void NIImporter_VISUM::parse_LanesConnections() {
1057 : NBNode* node = nullptr;
1058 : NBEdge* fromEdge = nullptr;
1059 : NBEdge* toEdge = nullptr;
1060 : // get the node and edges depending on network format
1061 356 : const std::string nodeID = getNamedString("KNOTNR", "KNOT");
1062 178 : if (nodeID == "0") {
1063 0 : fromEdge = getNamedEdge("VONSTRNR", "VONSTR");
1064 0 : toEdge = getNamedEdge("NACHSTRNR", "NACHSTR");
1065 0 : if (fromEdge == nullptr) {
1066 : return;
1067 : }
1068 : node = fromEdge->getToNode();
1069 0 : WRITE_WARNING(TL("Ignoring lane-to-lane connection (not yet implemented for this format version)"));
1070 0 : return;
1071 : } else {
1072 356 : node = getNamedNode("KNOTNR", "KNOT");
1073 178 : if (node == nullptr) {
1074 : return;
1075 : }
1076 356 : fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node);
1077 356 : toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node);
1078 : }
1079 178 : if (fromEdge == nullptr || toEdge == nullptr) {
1080 : return;
1081 : }
1082 :
1083 : int fromLaneOffset = 0;
1084 178 : if (!node->hasIncoming(fromEdge)) {
1085 : fromLaneOffset = fromEdge->getNumLanes();
1086 156 : fromEdge = getReversedContinuating(fromEdge, node);
1087 : } else {
1088 22 : fromEdge = getReversedContinuating(fromEdge, node);
1089 44 : NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_')));
1090 : fromLaneOffset = tmp->getNumLanes();
1091 : }
1092 :
1093 : int toLaneOffset = 0;
1094 178 : if (!node->hasOutgoing(toEdge)) {
1095 : toLaneOffset = toEdge->getNumLanes();
1096 22 : toEdge = getReversedContinuating(toEdge, node);
1097 : } else {
1098 312 : NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_')));
1099 : toLaneOffset = tmp->getNumLanes();
1100 : }
1101 : // get the from-lane
1102 178 : std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR"));
1103 : int fromLane = -1;
1104 : try {
1105 178 : fromLane = StringUtils::toInt(fromLaneS);
1106 0 : } catch (NumberFormatException&) {
1107 0 : WRITE_ERRORF(TL("A from-lane number for edge '%' is not numeric (%)."), fromEdge->getID(), fromLaneS);
1108 : return;
1109 0 : }
1110 178 : fromLane -= 1;
1111 178 : if (fromLane < 0) {
1112 0 : WRITE_ERRORF(TL("A from-lane number for edge '%' is not positive (%)."), fromEdge->getID(), fromLaneS);
1113 0 : return;
1114 : }
1115 : // get the from-lane
1116 178 : std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR"));
1117 : int toLane = -1;
1118 : try {
1119 178 : toLane = StringUtils::toInt(toLaneS);
1120 0 : } catch (NumberFormatException&) {
1121 0 : WRITE_ERRORF(TL("A to-lane number for edge '%' is not numeric (%)."), toEdge->getID(), toLaneS);
1122 : return;
1123 0 : }
1124 178 : toLane -= 1;
1125 178 : if (toLane < 0) {
1126 0 : WRITE_ERRORF(TL("A to-lane number for edge '%' is not positive (%)."), toEdge->getID(), toLaneS);
1127 0 : return;
1128 : }
1129 : // !!! the next is probably a hack
1130 178 : if (fromLane - fromLaneOffset < 0) {
1131 : //fromLaneOffset = 0;
1132 : } else {
1133 178 : fromLane = (int)fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1;
1134 : }
1135 178 : if (toLane - toLaneOffset < 0) {
1136 : //toLaneOffset = 0;
1137 : } else {
1138 0 : toLane = (int)toEdge->getNumLanes() - (toLane - toLaneOffset) - 1;
1139 : }
1140 : //
1141 178 : if ((int) fromEdge->getNumLanes() <= fromLane) {
1142 0 : WRITE_ERRORF(TL("A from-lane number for edge '%' is larger than the edge's lane number (%)."), fromEdge->getID(), fromLaneS);
1143 0 : return;
1144 : }
1145 178 : if ((int) toEdge->getNumLanes() <= toLane) {
1146 0 : WRITE_ERRORF(TL("A to-lane number for edge '%' is larger than the edge's lane number (%)."), toEdge->getID(), toLaneS);
1147 0 : return;
1148 : }
1149 : //
1150 356 : fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::Lane2LaneInfoType::VALIDATED);
1151 : }
1152 :
1153 :
1154 47 : void NIImporter_VISUM::parse_stopPoints() {
1155 47 : std::string id = NBHelpers::normalIDRepresentation(myLineParser.get(KEYS.getString(VISUM_NO)));
1156 47 : std::string name = StringUtils::latin1_to_utf8(myLineParser.get(KEYS.getString(VISUM_NAME)));
1157 47 : SVCPermissions permissions = getPermissions(KEYS.getString(VISUM_TYPES), true);
1158 47 : NBNode* from = getNamedNodeSecure(KEYS.getString(VISUM_FROMNODE));
1159 47 : NBNode* to = getNamedNodeSecure(KEYS.getString(VISUM_FROMNODENO));
1160 47 : const std::string edgeID = myLineParser.get(KEYS.getString(VISUM_LINKNO));
1161 47 : if (edgeID == "") {
1162 141 : WRITE_WARNINGF(TL("Ignoring stopping place '%' without edge id"), id);
1163 0 : } else if (from == nullptr && to == nullptr) {
1164 0 : WRITE_WARNINGF(TL("Ignoring stopping place '%' without node information"), id);
1165 : } else {
1166 0 : NBEdge* edge = getNamedEdge(KEYS.getString(VISUM_LINKNO));
1167 0 : if (edge == nullptr) {
1168 0 : WRITE_WARNINGF(TL("Ignoring stopping place '%' with invalid edge reference '%'"), id, edgeID);
1169 0 : return;
1170 0 : } else if (from != nullptr) {
1171 0 : if (edge->getToNode() == from) {
1172 0 : NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1173 0 : if (edge2 == nullptr) {
1174 0 : WRITE_WARNINGF(TL("Could not find edge with from-node '%' and base id '%' for stopping place '%'"), from->getID(), edge->getID(), id);
1175 : } else {
1176 : edge = edge2;
1177 : }
1178 0 : } else if (edge->getFromNode() != from) {
1179 0 : WRITE_WARNINGF(TL("Unexpected from-node '%' for edge '%' of stopping place '%'"), from->getID(), edge->getID(), id);
1180 : }
1181 : } else {
1182 0 : if (edge->getFromNode() == to) {
1183 0 : NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1184 0 : if (edge2 == nullptr) {
1185 0 : WRITE_WARNINGF(TL("Could not find edge with to-node '%' and base id '%' for stopping place '%'"), to->getID(), edge->getID(), id);
1186 : } else {
1187 : edge = edge2;
1188 : }
1189 0 : } else if (edge->getToNode() != to) {
1190 0 : WRITE_WARNINGF(TL("Unexpected to-node '%' for edge '%' of stopping place '%'"), to->getID(), edge->getID(), id);
1191 : }
1192 : }
1193 0 : double relPos = StringUtils::toDouble(myLineParser.get(KEYS.getString(VISUM_RELPOS)));
1194 : /// @note could also retrieve Xkoord, ykoord from $HALTESTELLE
1195 0 : Position pos = edge->getGeometry().positionAtOffset(edge->getLength() * relPos);
1196 :
1197 0 : const double length = OptionsCont::getOptions().getFloat("osm.stop-output.length");
1198 0 : std::shared_ptr<NBPTStop> ptStop = std::make_shared<NBPTStop>(id, pos, edge->getID(), edge->getID(), length, name, permissions);
1199 0 : myNetBuilder.getPTStopCont().insert(ptStop);
1200 : }
1201 : }
1202 :
1203 :
1204 : double
1205 1770 : NIImporter_VISUM::getWeightedFloat(const std::string& name, const std::string& suffix) {
1206 : try {
1207 1770 : std::string val = myLineParser.get(name);
1208 902 : if (val.find(suffix) != std::string::npos) {
1209 0 : val = val.substr(0, val.find(suffix));
1210 : }
1211 902 : return StringUtils::toDouble(val);
1212 868 : } catch (...) {}
1213 868 : return -1;
1214 : }
1215 :
1216 :
1217 : double
1218 868 : NIImporter_VISUM::getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix) {
1219 868 : double result = getWeightedFloat(name, suffix);
1220 868 : if (result != -1) {
1221 : return result;
1222 : } else {
1223 868 : return getWeightedFloat(name2, suffix);
1224 : }
1225 : }
1226 :
1227 : bool
1228 0 : NIImporter_VISUM::getWeightedBool(const std::string& name) {
1229 : try {
1230 0 : return StringUtils::toBool(myLineParser.get(name));
1231 0 : } catch (...) {}
1232 : try {
1233 0 : return StringUtils::toBool(myLineParser.get((name + "(IV)")));
1234 0 : } catch (...) {}
1235 0 : return false;
1236 : }
1237 :
1238 : SVCPermissions
1239 1309 : NIImporter_VISUM::getPermissions(const std::string& name, bool warn, SVCPermissions unknown) {
1240 : SVCPermissions result = 0;
1241 6477 : for (std::string v : StringTokenizer(myLineParser.get(name), ",").getVector()) {
1242 : // common values in english and german
1243 : // || v == "funiculaire-telecabine" ---> no matching
1244 3859 : v = StringUtils::to_lower_case(v);
1245 3859 : if (v == "bus" || v == "tcsp" || v == "acces tc" || v == "Accès tc" || v == "accès tc") {
1246 0 : result |= SVC_BUS;
1247 3859 : } else if (v == "walk" || v == "w" || v == "f" || v == "ped" || v == "map") {
1248 944 : result |= SVC_PEDESTRIAN;
1249 2915 : } else if (v == "l" || v == "lkw" || v == "h" || v == "hgv" || v == "lw" || v == "truck" || v == "tru" || v == "pl") {
1250 327 : result |= SVC_TRUCK;
1251 2588 : } else if (v == "b" || v == "bike" || v == "velo") {
1252 201 : result |= SVC_BICYCLE;
1253 2387 : } else if (v == "train" || v == "rail") {
1254 0 : result |= SVC_RAIL;
1255 2387 : } else if (v == "tram") {
1256 0 : result |= SVC_TRAM;
1257 2387 : } else if (v == "p" || v == "pkw" || v == "car" || v == "c" || v == "vp" || v == "2rm") {
1258 1367 : result |= SVC_PASSENGER;
1259 : } else {
1260 1020 : if (warn) {
1261 1140 : WRITE_WARNINGF("Encountered unknown vehicle category '" + v + "' in type '%'", myLineParser.get(KEYS.getString(VISUM_NO)));
1262 : }
1263 1020 : result |= unknown;
1264 : }
1265 1309 : }
1266 1309 : return result;
1267 : }
1268 :
1269 : NBNode*
1270 4256 : NIImporter_VISUM::getNamedNode(const std::string& fieldName) {
1271 4256 : std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1272 4256 : NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1273 4256 : if (node == nullptr) {
1274 0 : WRITE_ERRORF(TL("The node '%' is not known."), nodeS);
1275 : }
1276 4256 : return node;
1277 : }
1278 :
1279 : NBNode*
1280 322 : NIImporter_VISUM::getNamedNodeSecure(const std::string& fieldName, NBNode* fallback) {
1281 322 : std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1282 322 : NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1283 322 : if (node == nullptr) {
1284 47 : return fallback;
1285 : }
1286 : return node;
1287 : }
1288 :
1289 :
1290 : NBNode*
1291 4096 : NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) {
1292 4096 : if (myLineParser.know(fieldName1)) {
1293 178 : return getNamedNode(fieldName1);
1294 : } else {
1295 3918 : return getNamedNode(fieldName2);
1296 : }
1297 : }
1298 :
1299 :
1300 : NBEdge*
1301 228 : NIImporter_VISUM::getNamedEdge(const std::string& fieldName) {
1302 228 : std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1303 228 : NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1304 228 : if (edge == nullptr) {
1305 0 : WRITE_ERRORF(TL("The edge '%' is not known."), edgeS);
1306 : }
1307 228 : return edge;
1308 : }
1309 :
1310 :
1311 : NBEdge*
1312 0 : NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) {
1313 0 : if (myLineParser.know(fieldName1)) {
1314 0 : return getNamedEdge(fieldName1);
1315 : } else {
1316 0 : return getNamedEdge(fieldName2);
1317 : }
1318 : }
1319 :
1320 :
1321 :
1322 : NBEdge*
1323 334 : NIImporter_VISUM::getReversedContinuating(NBEdge* edge, NBNode* node) {
1324 : std::string sid;
1325 334 : if (edge->getID()[0] == '-') {
1326 0 : sid = edge->getID().substr(1);
1327 : } else {
1328 668 : sid = "-" + edge->getID();
1329 : }
1330 334 : if (sid.find('_') != std::string::npos) {
1331 0 : sid = sid.substr(0, sid.find('_'));
1332 : }
1333 668 : return getNamedEdgeContinuating(myNetBuilder.getEdgeCont().retrieve(sid), node);
1334 : }
1335 :
1336 :
1337 : NBEdge*
1338 1470 : NIImporter_VISUM::getNamedEdgeContinuating(NBEdge* begin, NBNode* node) {
1339 1470 : if (begin == nullptr) {
1340 : return nullptr;
1341 : }
1342 : NBEdge* ret = begin;
1343 1470 : std::string edgeID = ret->getID();
1344 : // hangle forward
1345 2386 : while (ret != nullptr) {
1346 : // ok, this is the edge we are looking for
1347 1470 : if (ret->getToNode() == node) {
1348 554 : return ret;
1349 : }
1350 : const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1351 916 : if (nedges.size() != 1) {
1352 : // too many edges follow
1353 : ret = nullptr;
1354 721 : continue;
1355 : }
1356 195 : NBEdge* next = nedges[0];
1357 390 : if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1358 : // ok, another edge is next...
1359 : ret = nullptr;
1360 195 : continue;
1361 : }
1362 0 : if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1363 : ret = nullptr;
1364 0 : continue;
1365 : }
1366 : ret = next;
1367 : }
1368 :
1369 : ret = begin;
1370 : // hangle backward
1371 916 : while (ret != nullptr) {
1372 : // ok, this is the edge we are looking for
1373 916 : if (ret->getFromNode() == node) {
1374 916 : return ret;
1375 : }
1376 : const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1377 0 : if (nedges.size() != 1) {
1378 : // too many edges follow
1379 : ret = nullptr;
1380 : continue;
1381 : }
1382 0 : NBEdge* next = nedges[0];
1383 0 : if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1384 : // ok, another edge is next...
1385 : ret = nullptr;
1386 : continue;
1387 : }
1388 0 : if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1389 : ret = nullptr;
1390 : continue;
1391 : }
1392 : ret = next;
1393 : }
1394 : return nullptr;
1395 : }
1396 :
1397 :
1398 : NBEdge*
1399 952 : NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName, NBNode* node) {
1400 952 : std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1401 952 : NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1402 952 : if (edge == nullptr) {
1403 0 : WRITE_ERRORF(TL("The edge '%' is not known."), edgeS);
1404 : }
1405 1904 : return getNamedEdgeContinuating(edge, node);
1406 : }
1407 :
1408 :
1409 : NBEdge*
1410 356 : NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1411 : NBNode* node) {
1412 356 : if (myLineParser.know(fieldName1)) {
1413 356 : return getNamedEdgeContinuating(fieldName1, node);
1414 : } else {
1415 0 : return getNamedEdgeContinuating(fieldName2, node);
1416 : }
1417 : }
1418 :
1419 :
1420 : NBEdge*
1421 0 : NIImporter_VISUM::getEdge(NBNode* FromNode, NBNode* ToNode) {
1422 : EdgeVector::const_iterator i;
1423 0 : for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1424 0 : if (ToNode == (*i)->getToNode()) {
1425 : return (*i);
1426 : }
1427 : }
1428 : //!!!
1429 : return nullptr;
1430 : }
1431 :
1432 :
1433 : double
1434 2474 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName) {
1435 2474 : std::string value = myLineParser.get(fieldName);
1436 4948 : if (StringUtils::endsWith(myLineParser.get(fieldName), "km/h")) {
1437 0 : value = value.substr(0, value.length() - 4);
1438 : }
1439 4948 : return StringUtils::toDouble(value);
1440 : }
1441 :
1442 :
1443 : double
1444 0 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName, double defaultValue) {
1445 : try {
1446 0 : return StringUtils::toDouble(myLineParser.get(fieldName));
1447 0 : } catch (...) {
1448 : return defaultValue;
1449 0 : }
1450 : }
1451 :
1452 :
1453 : double
1454 1088 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) {
1455 1088 : if (myLineParser.know(fieldName1)) {
1456 0 : return getNamedFloat(fieldName1);
1457 : } else {
1458 1088 : return getNamedFloat(fieldName2);
1459 : }
1460 : }
1461 :
1462 :
1463 : double
1464 0 : NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1465 : double defaultValue) {
1466 0 : if (myLineParser.know(fieldName1)) {
1467 0 : return getNamedFloat(fieldName1, defaultValue);
1468 : } else {
1469 0 : return getNamedFloat(fieldName2, defaultValue);
1470 : }
1471 : }
1472 :
1473 :
1474 : std::string
1475 546 : NIImporter_VISUM::getNamedString(const std::string& fieldName) {
1476 1092 : return NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1477 : }
1478 :
1479 :
1480 : std::string
1481 362 : NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1482 : const std::string& fieldName2) {
1483 362 : if (myLineParser.know(fieldName1)) {
1484 178 : return getNamedString(fieldName1);
1485 : } else {
1486 184 : return getNamedString(fieldName2);
1487 : }
1488 : }
1489 :
1490 :
1491 :
1492 :
1493 :
1494 :
1495 : NBNode*
1496 0 : NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1497 : bool isSource) {
1498 : // get the district
1499 0 : NBDistrict* dist = myNetBuilder.getDistrictCont().retrieve(id);
1500 0 : if (dist == nullptr) {
1501 : return nullptr;
1502 : }
1503 : // build the id
1504 : std::string nid;
1505 0 : nid = id + "-" + dest->getID();
1506 0 : if (!isSource) {
1507 0 : nid = "-" + nid;
1508 : }
1509 : // insert the node
1510 0 : if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1511 0 : WRITE_ERRORF(TL("Could not build connector node '%'."), nid);
1512 : }
1513 : // return the node
1514 0 : return myNetBuilder.getNodeCont().retrieve(nid);
1515 : }
1516 :
1517 :
1518 : bool
1519 813 : NIImporter_VISUM::checkNodes(NBNode* from, NBNode* to) {
1520 813 : if (from == nullptr) {
1521 0 : WRITE_ERROR(TL(" The from-node was not found within the net"));
1522 : }
1523 813 : if (to == nullptr) {
1524 0 : WRITE_ERROR(TL(" The to-node was not found within the net"));
1525 : }
1526 813 : if (from == to) {
1527 0 : WRITE_ERROR(TL(" Both nodes are the same"));
1528 : }
1529 813 : return from != nullptr && to != nullptr && from != to;
1530 : }
1531 :
1532 : bool
1533 0 : NIImporter_VISUM::isSplitEdge(NBEdge* edge, NBNode* node) {
1534 0 : return (edge->getID().length() > node->getID().length() + 1
1535 0 : && (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()));
1536 : }
1537 :
1538 : void
1539 0 : NIImporter_VISUM::loadLanguage(const std::string& file) {
1540 0 : std::ifstream strm(file.c_str());
1541 0 : if (!strm.good()) {
1542 0 : throw ProcessError(TLF("Could not load VISUM language map from '%'.", file));
1543 : }
1544 0 : while (strm.good()) {
1545 : std::string keyDE;
1546 : std::string keyNew;
1547 0 : strm >> keyDE;
1548 0 : strm >> keyNew;
1549 : if (KEYS.hasString(keyDE)) {
1550 0 : VISUM_KEY key = KEYS.get(keyDE);
1551 0 : KEYS.remove(keyDE, key);
1552 0 : KEYS.insert(keyNew, key);
1553 0 : } else if (keyDE != "") {
1554 0 : WRITE_WARNINGF(TL("Unknown entry '%' in VISUM language map"), keyDE);
1555 : }
1556 : }
1557 :
1558 0 : }
1559 :
1560 :
1561 : /****************************************************************************/
|