Eclipse SUMO - Simulation of Urban MObility
NIImporter_VISUM.cpp
Go to the documentation of this file.
1/****************************************************************************/
2// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3// Copyright (C) 2001-2022 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/****************************************************************************/
21// A VISUM network importer
22/****************************************************************************/
23#include <config.h>
24
25#include <string>
32#include <netbuild/NBDistrict.h>
33
35#include "NILoader.h"
36#include "NIImporter_VISUM.h"
37
38
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
90
91// ===========================================================================
92// method definitions
93// ===========================================================================
94// ---------------------------------------------------------------------------
95// static methods (interface in this case)
96// ---------------------------------------------------------------------------
97void
99 // check whether the option is set (properly)
100 if (!oc.isSet("visum-file")) {
101 return;
102 }
103 // build the handler
104 NIImporter_VISUM loader(nb, oc.getString("visum-file"),
105 NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")),
106 oc.getBool("visum.use-type-priority"),
107 oc.getString("visum.language-file"));
108 loader.load();
109}
110
111
112
113// ---------------------------------------------------------------------------
114// loader methods
115// ---------------------------------------------------------------------------
117 const std::string& file,
118 NBCapacity2Lanes capacity2Lanes,
119 bool useVisumPrio,
120 const std::string& languageFile) :
121 myNetBuilder(nb), myFileName(file),
122 myCapacity2Lanes(capacity2Lanes), myUseVisumPrio(useVisumPrio) {
123 if (languageFile != "") {
124 loadLanguage(languageFile);
125 }
126
127 // the order of process is important!
128 // set1
134
135 // set2
136 // two types of "strecke"
139
140 // set3
141 if (OptionsCont::getOptions().getBool("visum.no-connectors")) {
143 } else {
145 }
146 // two types of "abbieger"
147 addParser("ABBIEGEBEZIEHUNG", &NIImporter_VISUM::parse_Turns);
149
153
154
155 // set4
156 // two types of lsa
159 // two types of knotenzulsa
163 // two types of signalgruppe
166 // three types of ABBZULSASIGNALGRUPPE
168 addParser("SIGNALGRUPPEZUABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
169 addParser("SIGNALGRUPPEZUFSABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
170
172
173 // two types of LSAPHASE
176
177 addParser("LSASIGNALGRUPPEZULSAPHASE", &NIImporter_VISUM::parse_SignalGroupsToPhases);
178 addParser("FAHRSTREIFENABBIEGER", &NIImporter_VISUM::parse_LanesConnections);
179
181}
182
183
185 for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
186 delete j->second;
187 }
188}
189
190
191void
192NIImporter_VISUM::addParser(const std::string& name, ParsingFunction function) {
193 TypeParser p;
194 p.name = name;
195 p.function = function;
196 p.position = -1;
197 mySingleDataParsers.push_back(p);
198}
199
200
201void
203 // open the file
205 throw ProcessError("Can not open visum-file '" + myFileName + "'.");
206 }
207 // scan the file for data positions
208 while (myLineReader.hasMore()) {
209 std::string line = myLineReader.readLine();
210 if (line.length() > 0 && line[0] == '$') {
211 ParserVector::iterator i;
212 for (i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
213 std::string dataName = "$" + (*i).name + ":";
214 if (line.substr(0, dataName.length()) == dataName) {
215 (*i).position = myLineReader.getPosition();
216 (*i).pattern = line.substr(dataName.length());
217 WRITE_MESSAGE("Found: " + dataName + " at line " + toString<int>(myLineReader.getLineNumber()));
218 }
219 }
220 }
221 }
222 // go through the parsers and process all entries
223 for (ParserVector::iterator i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
224 if ((*i).position < 0) {
225 // do not process using parsers for which no information was found
226 continue;
227 }
228 // ok, the according information is stored in the file
229 PROGRESS_BEGIN_MESSAGE("Parsing " + (*i).name);
230 // reset the line reader and let it point to the begin of the according data field
232 myLineReader.setPos((*i).position);
233 // prepare the line parser
234 myLineParser.reinit((*i).pattern);
235 // read
236 bool singleDataEndFound = false;
237 while (myLineReader.hasMore() && !singleDataEndFound) {
238 std::string line = myLineReader.readLine();
239 if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
240 singleDataEndFound = true;
241 } else {
243 try {
244 myCurrentID = "<unknown>";
245 (this->*(*i).function)();
246 } catch (OutOfBoundsException&) {
247 WRITE_ERROR("Too short value line in " + (*i).name + " occurred.");
248 } catch (NumberFormatException&) {
249 WRITE_ERROR("A value in " + (*i).name + " should be numeric but is not (id='" + myCurrentID + "').");
250 } catch (UnknownElement& e) {
251 WRITE_ERROR("One of the needed values ('" + std::string(e.what()) + "') is missing in " + (*i).name + ".");
252 }
253 }
254 }
255 // close single reader processing
257 }
259
260 // build traffic lights
261 for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
263 }
264 // build district shapes
265 for (std::map<NBDistrict*, PositionVector>::const_iterator k = myDistrictShapes.begin(); k != myDistrictShapes.end(); ++k) {
266 (*k).first->addShape((*k).second);
267 }
268}
269
270
271
272
273
274void
276 std::string name = myLineParser.know("VSysCode") ? myLineParser.get("VSysCode").c_str() : myLineParser.get(KEYS.getString(VISUM_CODE)).c_str();
277 std::string type = myLineParser.know("VSysMode") ? myLineParser.get("VSysMode").c_str() : myLineParser.get(KEYS.getString(VISUM_TYP)).c_str();
278 myVSysTypes[name] = type;
279}
280
281
282void
284 // get the id
286 // get the maximum speed
287 double speed = getWeightedFloat2("v0-IV", KEYS.getString(VISUM_V0), "km/h");
288 if (speed == 0) {
289 // unlimited speed
290 speed = 3600;
291 } else if (speed < 0) {
292 WRITE_ERROR("Type '" + myCurrentID + "' has speed " + toString(speed));
293 }
294 // get the permissions
296 // get the priority
297 const int priority = 1000 - StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_RANK)));
298 // try to retrieve the number of lanes
299 const int numLanes = myCapacity2Lanes.get(getNamedFloat("Kap-IV", KEYS.getString(VISUM_CAPACITY)));
300 // insert the type
301 myNetBuilder.getTypeCont().insertEdgeType(myCurrentID, numLanes, speed / (double) 3.6, priority, permissions, LaneSpreadFunction::RIGHT,
309}
310
311
312void
314 // get the id
316 // get the position
319 Position pos(x, y);
321 WRITE_ERROR("Unable to project coordinates for node " + myCurrentID + ".");
322 return;
323 }
324 // add to the list
326 WRITE_ERROR("Duplicate node occurred ('" + myCurrentID + "').");
327 }
328}
329
330
331void
333 // get the id
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
342 Position pos(x, y);
343 if (!NBNetBuilder::transformCoordinate(pos, false)) {
344 WRITE_ERROR("Unable to project coordinates for district " + myCurrentID + ".");
345 return;
346 }
347 // build the district
348 NBDistrict* district = new NBDistrict(myCurrentID, pos);
349 if (!myNetBuilder.getDistrictCont().insert(district)) {
350 WRITE_ERROR("Duplicate district occurred ('" + myCurrentID + "').");
351 delete district;
352 return;
353 }
356 myShapeDistrictMap[flaecheID] = district;
357 }
358}
359
360
361void
366 Position pos(x, y);
367 if (!NBNetBuilder::transformCoordinate(pos, false)) {
368 WRITE_ERROR("Unable to project coordinates for point " + toString(id) + ".");
369 return;
370 }
371 myPoints[id] = pos;
372}
373
374
375void
378 // no vehicle allowed; don't add
379 return;
380 }
381 // get the id
383 // get the from- & to-node and validate them
384 NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
385 NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
386 if (!checkNodes(from, to)) {
387 return;
388 }
389 // get the type
391 // get the speed
392 double speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
393 if (!OptionsCont::getOptions().getBool("visum.use-type-speed")) {
394 try {
395 std::string speedS = myLineParser.know("v0-IV") ? myLineParser.get("v0-IV") : myLineParser.get(KEYS.getString(VISUM_V0));
396 if (speedS.find("km/h") != std::string::npos) {
397 speedS = speedS.substr(0, speedS.find("km/h"));
398 }
399 speed = StringUtils::toDouble(speedS) / 3.6;
400 } catch (OutOfBoundsException&) {}
401 }
402 if (speed <= 0) {
404 }
405
406 // get the information whether the edge is a one-way
407 bool oneway = myLineParser.know("Einbahn")
409 : true;
410 // get the number of lanes
411 int nolanes = myNetBuilder.getTypeCont().getEdgeTypeNumLanes(type);
412 if (!OptionsCont::getOptions().getBool("visum.recompute-lane-number")) {
413 if (!OptionsCont::getOptions().getBool("visum.use-type-laneno")) {
414 if (myLineParser.know("Fahrstreifen")) {
415 nolanes = StringUtils::toInt(myLineParser.get("Fahrstreifen"));
418 }
419 }
420 } else {
423 } else if (myLineParser.know("KAP-IV")) {
425 }
426 }
427 // check whether the id is already used
428 // (should be the opposite direction)
429 bool oneway_checked = oneway;
431 if (previous != nullptr) {
432 myCurrentID = '-' + myCurrentID;
434 oneway_checked = false;
435 }
436 if (find(myTouchedEdges.begin(), myTouchedEdges.end(), myCurrentID) != myTouchedEdges.end()) {
437 oneway_checked = false;
438 }
439 std::string tmpid = '-' + myCurrentID;
440 if (find(myTouchedEdges.begin(), myTouchedEdges.end(), tmpid) != myTouchedEdges.end()) {
441 previous = myNetBuilder.getEdgeCont().retrieve(tmpid);
442 if (previous != nullptr) {
444 }
445 oneway_checked = false;
446 }
448 // add the edge
451 if (nolanes != 0 && speed != 0) {
453 NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, prio,
455 e->setPermissions(permissions);
456 if (!myNetBuilder.getEdgeCont().insert(e)) {
457 delete e;
458 WRITE_ERROR("Duplicate edge occurred ('" + myCurrentID + "').");
459 }
460 }
461 myTouchedEdges.push_back(myCurrentID);
462 // nothing more to do, when the edge is a one-way street
463 if (oneway) {
464 return;
465 }
466 // add the opposite edge
467 myCurrentID = '-' + myCurrentID;
468 if (nolanes != 0 && speed != 0) {
470 NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, NBEdge::UNSPECIFIED_FRICTION, nolanes, prio,
472 e->setPermissions(permissions);
473 if (!myNetBuilder.getEdgeCont().insert(e)) {
474 delete e;
475 WRITE_ERROR("Duplicate edge occurred ('" + myCurrentID + "').");
476 }
477 }
478 myTouchedEdges.push_back(myCurrentID);
479}
480
481
482void
487 myEdges[id] = std::make_pair(from, to);
488}
489
490
491void
494 long long int flaechePartID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FACEID)));
495 if (mySubPartsAreas.find(flaechePartID) == mySubPartsAreas.end()) {
496 mySubPartsAreas[flaechePartID] = std::vector<long long int>();
497 }
498 mySubPartsAreas[flaechePartID].push_back(flaecheID);
499}
500
501
502void
504 // get the source district
506 // get the destination node
508 if (dest == nullptr) {
509 return;
510 }
511 // get the weight of the connection
512 double proz = 1;
513 if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
514 proz = getNamedFloat("Proz", "Proz(IV)") / 100;
515 }
516 // get the information whether this is a sink or a source
517 std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
518 if (dir.length() == 0) {
520 }
521 // build the source when needed
522 if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
523 for (NBEdge* edge : dest->getOutgoingEdges()) {
524 myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
525 }
526 }
527 // build the sink when needed
528 if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
529 for (NBEdge* edge : dest->getIncomingEdges()) {
530 myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
531 }
532 }
533}
534
535
536
537void
539 // get the source district
541 // get the destination node
543 if (dest == nullptr) {
544 return;
545 }
546 // get the weight of the connection
547 double proz = 1;
548 if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
549 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 std::string type = myLineParser.know(KEYS.getString(VISUM_TYP))
561 : "";
562 // add the connectors as an edge
563 std::string id = bez + "-" + dest->getID();
564 // get the information whether this is a sink or a source
565 std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
566 if (dir.length() == 0) {
568 }
569 // build the source when needed
570 if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
571 const EdgeVector& edges = dest->getOutgoingEdges();
572 bool hasContinuation = false;
573 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
574 if (!(*i)->isMacroscopicConnector()) {
575 hasContinuation = true;
576 }
577 }
578 if (!hasContinuation) {
579 // obviously, there is no continuation on the net
580 WRITE_WARNING("Incoming connector '" + id + "' will not be build - would be not connected to network.");
581 } else {
582 NBNode* src = buildDistrictNode(bez, dest, true);
583 if (src == nullptr) {
584 WRITE_ERROR("The district '" + bez + "' could not be built.");
585 return;
586 }
587 NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
588 OptionsCont::getOptions().getFloat("visum.connector-speeds"), NBEdge::UNSPECIFIED_FRICTION,
589 OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
593 if (!myNetBuilder.getEdgeCont().insert(edge)) {
594 WRITE_ERROR("A duplicate edge id occurred (ID='" + id + "').");
595 return;
596 }
597 edge = myNetBuilder.getEdgeCont().retrieve(id);
598 if (edge != nullptr) {
599 myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
600 }
601 }
602 }
603 // build the sink when needed
604 if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
605 const EdgeVector& edges = dest->getIncomingEdges();
606 bool hasPredeccessor = false;
607 for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
608 if (!(*i)->isMacroscopicConnector()) {
609 hasPredeccessor = true;
610 }
611 }
612 if (!hasPredeccessor) {
613 // obviously, the network is not connected to this node
614 WRITE_WARNING("Outgoing connector '" + id + "' will not be build - would be not connected to network.");
615 } else {
616 NBNode* src = buildDistrictNode(bez, dest, false);
617 if (src == nullptr) {
618 WRITE_ERROR("The district '" + bez + "' could not be built.");
619 return;
620 }
621 id = "-" + id;
622 NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
623 OptionsCont::getOptions().getFloat("visum.connector-speeds"), NBEdge::UNSPECIFIED_FRICTION,
624 OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
628 if (!myNetBuilder.getEdgeCont().insert(edge)) {
629 WRITE_ERROR("A duplicate edge id occurred (ID='" + id + "').");
630 return;
631 }
632 edge = myNetBuilder.getEdgeCont().retrieve(id);
633 if (edge != nullptr) {
634 myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
635 }
636 }
637 }
638}
639
640
641void
644 // no vehicle allowed; don't add
645 return;
646 }
647 // retrieve the nodes
648 NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
649 NBNode* via = getNamedNode("UeberKnot", KEYS.getString(VISUM_VIANODENO));
650 NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
651 if (from == nullptr || via == nullptr || to == nullptr) {
652 return;
653 }
654 // all nodes are known
655 std::string type = myLineParser.know("VSysCode")
656 ? myLineParser.get("VSysCode")
658 if (myVSysTypes.find(type) != myVSysTypes.end() && myVSysTypes.find(type)->second == "IV") {
659 // try to set the turning definition
660 NBEdge* src = from->getConnectionTo(via);
661 NBEdge* dest = via->getConnectionTo(to);
662 // check both
663 if (src == nullptr) {
664 if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
665 WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + via->getID() + "'.");
666 }
667 return;
668 }
669 if (dest == nullptr) {
670 if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
671 WRITE_WARNING("There is no edge from node '" + via->getID() + "' to node '" + to->getID() + "'.");
672 }
673 return;
674 }
675 // both edges found
676 // set them into the edge
677 src->addEdge2EdgeConnection(dest);
678 }
679}
680
681
682void
684 // get the from- & to-node and validate them
685 NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
686 NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
687 if (!checkNodes(from, to)) {
688 return;
689 }
690 bool failed = false;
691 int index;
692 double x, y;
693 try {
697 } catch (NumberFormatException&) {
698 WRITE_ERROR("Error in geometry description from node '" + from->getID() + "' to node '" + to->getID() + "'.");
699 return;
700 }
701 Position pos(x, y);
703 WRITE_ERROR("Unable to project coordinates for node '" + from->getID() + "'.");
704 return;
705 }
706 NBEdge* e = from->getConnectionTo(to);
707 if (e != nullptr) {
708 e->addGeometryPoint(index, pos);
709 } else {
710 failed = true;
711 }
712 e = to->getConnectionTo(from);
713 if (e != nullptr) {
714 e->addGeometryPoint(-index, pos);
715 failed = false;
716 }
717 // check whether the operation has failed
718 if (failed) {
719 if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
720 WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + to->getID() + "'.");
721 }
722 }
723}
724
725
726void
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
734 if (baseEdge == nullptr) {
735 return;
736 }
737 NBEdge* edge = baseEdge;
738 // get the node
739 NBNode* node = getNamedNodeSecure("KNOTNR");
740 if (node == nullptr) {
741 node = edge->getToNode();
742 } else {
744 }
745 // check
746 if (edge == nullptr) {
747 return;
748 }
749 // get the lane
750 std::string laneS = myLineParser.know("FSNR")
753 int lane = -1;
754 try {
755 lane = StringUtils::toInt(laneS);
756 } catch (NumberFormatException&) {
757 WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not numeric (" + laneS + ").");
758 return;
759 }
760 lane -= 1;
761 if (lane < 0) {
762 WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not positive (" + laneS + ").");
763 return;
764 }
765 // get the direction
766 std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
767 int prevLaneNo = baseEdge->getNumLanes();
768 if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
769 // get the last part of the turnaround direction
770 NBEdge* cand = getReversedContinuating(edge, node);
771 if (cand) {
772 edge = cand;
773 }
774 }
775 // get the length
776 std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
777 double length = -1;
778 try {
779 length = StringUtils::toDouble(lengthS);
780 } catch (NumberFormatException&) {
781 WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not numeric (" + lengthS + ").");
782 return;
783 }
784 if (length < 0) {
785 WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not positive (" + lengthS + ").");
786 return;
787 }
788 //
789 if (dirS == "1") {
790 lane -= prevLaneNo;
791 }
792 //
793 if (length == 0) {
794 if ((int) edge->getNumLanes() > lane) {
795 // ok, we know this already...
796 return;
797 }
798 // increment by one
799 edge->incLaneNo(1);
800 } else {
801 // check whether this edge already has been created
802 if (isSplitEdge(edge, node)) {
803 if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
804 if ((int) edge->getNumLanes() > lane) {
805 // ok, we know this already...
806 return;
807 }
808 // increment by one
809 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 while (mustRecheck) {
818 if (isSplitEdge(edge, node)) {
819 // ok, we have a previously created edge here
820 std::string sub = edge->getID();
821 sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
822 sub = sub.substr(1, sub.find('_', 1) - 1);
823 double dist = StringUtils::toDouble(sub);
824 if (dist < length) {
825 seenLength += edge->getLength();
826 if (dirS == "1") {
827 // incoming -> move back
828 edge = edge->getFromNode()->getIncomingEdges()[0];
829 } else {
830 // outgoing -> move forward
831 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 double useLength = length - seenLength;
844 useLength = edge->getLength() - useLength;
845 if (useLength < 0 || useLength > edge->getLength()) {
846 WRITE_WARNING("Could not find split position for edge '" + edge->getID() + "'.");
847 return;
848 }
849 std::string edgeID = edge->getID();
850 p = edge->getGeometry().positionAtOffset(useLength);
851 if (isSplitEdge(edge, node)) {
852 edgeID = edgeID.substr(0, edgeID.find('_'));
853 }
854 NBNode* rn = new NBNode(edgeID + "_" + toString((int) length) + "_" + node->getID(), p);
855 if (!myNetBuilder.getNodeCont().insert(rn)) {
856 throw ProcessError("Ups - could not insert node!");
857 }
858 std::string nid = edgeID + "_" + toString((int) length) + "_" + node->getID();
860 edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
861 // old edge is deleted and a new edge with the same name created
862 edge = myNetBuilder.getEdgeCont().retrieve(edgeID);
863 NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
864 nedge = nedge->getToNode()->getOutgoingEdges()[0];
865 while (isSplitEdge(edge, node)) {
866 assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
867 nedge->incLaneNo(1);
868 nedge = nedge->getToNode()->getOutgoingEdges()[0];
869 }
870 }
871}
872
873
874void
877 const SUMOTime cycleTime = TIME2STEPS(getWeightedFloat2("Umlaufzeit", "UMLZEIT", "s"));
878 const SUMOTime intermediateTime = TIME2STEPS(getWeightedFloat2("StdZwischenzeit", "STDZWZEIT", "s"));
879 bool phaseBased = myLineParser.know("PhasenBasiert")
880 ? StringUtils::toBool(myLineParser.get("PhasenBasiert"))
881 : false;
882 const SUMOTime offset = myLineParser.know("ZEITVERSATZ") ? TIME2STEPS(getWeightedFloat("ZEITVERSATZ", "s")) : 0;
883 // add to the list
884 myTLS[myCurrentID] = new NIVisumTL(myCurrentID, cycleTime, offset, intermediateTime, phaseBased);
885}
886
887
888void
890 std::string node = myLineParser.get("KnotNr").c_str();
891 if (node == "0") {
892 // this is a dummy value which cannot be assigned to
893 return;
894 }
895 std::string trafficLight = myLineParser.get("LsaNr").c_str();
896 // add to the list
898 auto tlIt = myTLS.find(trafficLight);
899 if (n != nullptr && tlIt != myTLS.end()) {
900 tlIt->second->addNode(n);
901 } else {
902 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
908void
911 std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
912 const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
913 const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
914 const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
915 // add to the list
916 if (myTLS.find(LSAid) == myTLS.end()) {
917 WRITE_ERROR("Could not find TLS '" + LSAid + "' for setting the signal group.");
918 return;
919 }
920 myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, startTime, endTime, yellowTime);
921}
922
923
924void
926 // get the id
927 std::string SGid = getNamedString("SGNR", "SIGNALGRUPPENNR");
928 if (!myLineParser.know("LsaNr")) {
930 WRITE_WARNING(TL("Ignoring SIGNALGRUPPEZUFSABBIEGER because LsaNr is not known"));
931 return;
932 }
933 std::string LSAid = getNamedString("LsaNr");
934 // nodes
935 NBNode* from = myLineParser.know("VonKnot") ? getNamedNode("VonKnot") : nullptr;
936 NBNode* via = myLineParser.know("KNOTNR")
937 ? getNamedNode("KNOTNR")
938 : getNamedNode("UeberKnot", "UeberKnotNr");
939 NBNode* to = myLineParser.know("NachKnot") ? getNamedNode("NachKnot") : nullptr;
940 // edges
941 NBEdge* edg1 = nullptr;
942 NBEdge* edg2 = nullptr;
943 if (from == nullptr && to == nullptr) {
944 edg1 = getNamedEdgeContinuating("VONSTRNR", via);
945 edg2 = getNamedEdgeContinuating("NACHSTRNR", via);
946 } else {
947 edg1 = getEdge(from, via);
948 edg2 = getEdge(via, to);
949 }
950 // add to the list
951 NIVisumTL::SignalGroup& SG = myTLS.find(LSAid)->second->getSignalGroup(SGid);
952 if (edg1 != nullptr && edg2 != nullptr) {
953 if (!via->hasIncoming(edg1)) {
954 std::string sid;
955 if (edg1->getID()[0] == '-') {
956 sid = edg1->getID().substr(1);
957 } else {
958 sid = "-" + edg1->getID();
959 }
960 if (sid.find('_') != std::string::npos) {
961 sid = sid.substr(0, sid.find('_'));
962 }
964 }
965 if (!via->hasOutgoing(edg2)) {
966 std::string sid;
967 if (edg2->getID()[0] == '-') {
968 sid = edg2->getID().substr(1);
969 } else {
970 sid = "-" + edg2->getID();
971 }
972 if (sid.find('_') != std::string::npos) {
973 sid = sid.substr(0, sid.find('_'));
974 }
976 }
977 SG.connections().push_back(NBConnection(edg1, edg2));
978 }
979}
980
981
982void
986 if (myEdges.find(edgeid) == myEdges.end()) {
987 WRITE_ERROR(TL("Unknown edge in TEILFLAECHENELEMENT"));
988 return;
989 }
990 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_ERROR("An index for a TEILFLAECHENELEMENT is not numeric (id='" + toString(id) + "').");
998// return;
999// }
1000 PositionVector shape;
1001 shape.push_back(myPoints[myEdges[edgeid].first]);
1002 shape.push_back(myPoints[myEdges[edgeid].second]);
1003 if (dir.length() > 0 && dir[0] == '1') {
1004 shape = shape.reverse();
1005 }
1006 if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
1007 WRITE_ERROR("Unkown are for area part '" + myCurrentID + "'.");
1008 return;
1009 }
1010
1011 const std::vector<long long int>& areas = mySubPartsAreas.find(id)->second;
1012 for (std::vector<long long int>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
1014 if (d == nullptr) {
1015 continue;
1016 }
1017 if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
1019 }
1020 if (dir.length() > 0 && dir[0] == '1') {
1021 myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1022 myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1023 } else {
1024 myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1025 myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1026 }
1027 }
1028}
1029
1030
1031void
1033 // get the id
1035 const std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1036 const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
1037 const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
1038 const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
1039 myTLS.find(LSAid)->second->addPhase(phaseid, startTime, endTime, yellowTime);
1040}
1041
1042
1044 // get the id
1045 std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("PsNr"));
1046 std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1047 std::string SGid = NBHelpers::normalIDRepresentation(myLineParser.get("SGNR"));
1048 // insert
1049 NIVisumTL* LSA = myTLS.find(LSAid)->second;
1050 NIVisumTL::SignalGroup& SG = LSA->getSignalGroup(SGid);
1051 NIVisumTL::Phase* PH = LSA->getPhases().find(Phaseid)->second;
1052 SG.phases()[Phaseid] = PH;
1053}
1054
1055
1057 NBNode* node = nullptr;
1058 NBEdge* fromEdge = nullptr;
1059 NBEdge* toEdge = nullptr;
1060 // get the node and edges depending on network format
1061 const std::string nodeID = getNamedString("KNOTNR", "KNOT");
1062 if (nodeID == "0") {
1063 fromEdge = getNamedEdge("VONSTRNR", "VONSTR");
1064 toEdge = getNamedEdge("NACHSTRNR", "NACHSTR");
1065 if (fromEdge == nullptr) {
1066 return;
1067 }
1068 node = fromEdge->getToNode();
1069 WRITE_WARNING(TL("Ignoring lane-to-lane connection (not yet implemented for this format version)"));
1070 return;
1071 } else {
1072 node = getNamedNode("KNOTNR", "KNOT");
1073 if (node == nullptr) {
1074 return;
1075 }
1076 fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node);
1077 toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node);
1078 }
1079 if (fromEdge == nullptr || toEdge == nullptr) {
1080 return;
1081 }
1082
1083 int fromLaneOffset = 0;
1084 if (!node->hasIncoming(fromEdge)) {
1085 fromLaneOffset = fromEdge->getNumLanes();
1086 fromEdge = getReversedContinuating(fromEdge, node);
1087 } else {
1088 fromEdge = getReversedContinuating(fromEdge, node);
1089 NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_')));
1090 fromLaneOffset = tmp->getNumLanes();
1091 }
1092
1093 int toLaneOffset = 0;
1094 if (!node->hasOutgoing(toEdge)) {
1095 toLaneOffset = toEdge->getNumLanes();
1096 toEdge = getReversedContinuating(toEdge, node);
1097 } else {
1098 NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_')));
1099 toLaneOffset = tmp->getNumLanes();
1100 }
1101 // get the from-lane
1102 std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR"));
1103 int fromLane = -1;
1104 try {
1105 fromLane = StringUtils::toInt(fromLaneS);
1106 } catch (NumberFormatException&) {
1107 WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not numeric (" + fromLaneS + ").");
1108 return;
1109 }
1110 fromLane -= 1;
1111 if (fromLane < 0) {
1112 WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not positive (" + fromLaneS + ").");
1113 return;
1114 }
1115 // get the from-lane
1116 std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR"));
1117 int toLane = -1;
1118 try {
1119 toLane = StringUtils::toInt(toLaneS);
1120 } catch (NumberFormatException&) {
1121 WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not numeric (" + toLaneS + ").");
1122 return;
1123 }
1124 toLane -= 1;
1125 if (toLane < 0) {
1126 WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not positive (" + toLaneS + ").");
1127 return;
1128 }
1129 // !!! the next is probably a hack
1130 if (fromLane - fromLaneOffset < 0) {
1131 //fromLaneOffset = 0;
1132 } else {
1133 fromLane = (int)fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1;
1134 }
1135 if (toLane - toLaneOffset < 0) {
1136 //toLaneOffset = 0;
1137 } else {
1138 toLane = (int)toEdge->getNumLanes() - (toLane - toLaneOffset) - 1;
1139 }
1140 //
1141 if ((int) fromEdge->getNumLanes() <= fromLane) {
1142 WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is larger than the edge's lane number (" + fromLaneS + ").");
1143 return;
1144 }
1145 if ((int) toEdge->getNumLanes() <= toLane) {
1146 WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is larger than the edge's lane number (" + toLaneS + ").");
1147 return;
1148 }
1149 //
1150 fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::Lane2LaneInfoType::VALIDATED);
1151}
1152
1153
1160 const std::string edgeID = myLineParser.get(KEYS.getString(VISUM_LINKNO));
1161 if (edgeID == "") {
1162 WRITE_WARNINGF(TL("Ignoring stopping place '%' without edge id"), id);
1163 } else if (from == nullptr && to == nullptr) {
1164 WRITE_WARNINGF(TL("Ignoring stopping place '%' without node informatio"), id);
1165 } else {
1167 if (from != nullptr) {
1168 if (edge->getToNode() == from) {
1169 NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1170 if (edge2 == nullptr) {
1171 WRITE_WARNINGF(TL("Could not find edge with from-node '%' and base id '%' for stopping place '%'"), from->getID(), edge->getID(), id);
1172 } else {
1173 edge = edge2;
1174 }
1175 } else if (edge->getFromNode() != from) {
1176 WRITE_WARNINGF(TL("Unexpected from-node '%' for edge '%' of stopping place '%'"), from->getID(), edge->getID(), id);
1177 }
1178 } else {
1179 if (edge->getFromNode() == to) {
1180 NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1181 if (edge2 == nullptr) {
1182 WRITE_WARNINGF(TL("Could not find edge with to-node '%' and base id '%' for stopping place '%'"), to->getID(), edge->getID(), id);
1183 } else {
1184 edge = edge2;
1185 }
1186 } else if (edge->getToNode() != to) {
1187 WRITE_WARNINGF(TL("Unexpected to-node '%' for edge '%' of stopping place '%'"), to->getID(), edge->getID(), id);
1188 }
1189 }
1192 Position pos = edge->getGeometry().positionAtOffset(edge->getLength() * relPos);
1193
1194 const double length = OptionsCont::getOptions().getFloat("osm.stop-output.length");
1195 NBPTStop* ptStop = new NBPTStop(id, pos, edge->getID(), edge->getID(), length, name, permissions);
1197 }
1198}
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212double
1213NIImporter_VISUM::getWeightedFloat(const std::string& name, const std::string& suffix) {
1214 try {
1215 std::string val = myLineParser.get(name);
1216 if (val.find(suffix) != std::string::npos) {
1217 val = val.substr(0, val.find(suffix));
1218 }
1219 return StringUtils::toDouble(val);
1220 } catch (...) {}
1221 return -1;
1222}
1223
1224
1225double
1226NIImporter_VISUM::getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix) {
1227 double result = getWeightedFloat(name, suffix);
1228 if (result != -1) {
1229 return result;
1230 } else {
1231 return getWeightedFloat(name2, suffix);
1232 }
1233}
1234
1235bool
1236NIImporter_VISUM::getWeightedBool(const std::string& name) {
1237 try {
1238 return StringUtils::toBool(myLineParser.get(name));
1239 } catch (...) {}
1240 try {
1241 return StringUtils::toBool(myLineParser.get((name + "(IV)")));
1242 } catch (...) {}
1243 return false;
1244}
1245
1247NIImporter_VISUM::getPermissions(const std::string& name, bool warn, SVCPermissions unknown) {
1248 SVCPermissions result = 0;
1249 for (std::string v : StringTokenizer(myLineParser.get(name), ",").getVector()) {
1250 // common values in english and german
1251 // || v == "funiculaire-telecabine" ---> no matching
1253 if (v == "bus" || v == "tcsp" || v == "acces tc" || v == "Accès tc" || v == "accès tc") {
1254 result |= SVC_BUS;
1255 } else if (v == "walk" || v == "w" || v == "f" || v == "ped" || v == "map") {
1256 result |= SVC_PEDESTRIAN;
1257 } else if (v == "l" || v == "lkw" || v == "h" || v == "hgv" || v == "lw" || v == "truck" || v == "tru" || v == "pl") {
1258 result |= SVC_TRUCK;
1259 } else if (v == "b" || v == "bike" || v == "velo") {
1260 result |= SVC_BICYCLE;
1261 } else if (v == "train" || v == "rail") {
1262 result |= SVC_RAIL;
1263 } else if (v == "tram") {
1264 result |= SVC_TRAM;
1265 } else if (v == "p" || v == "pkw" || v == "car" || v == "c" || v == "vp" || v == "2rm") {
1266 result |= SVC_PASSENGER;
1267 } else {
1268 if (warn) {
1269 WRITE_WARNINGF("Encountered unknown vehicle category '" + v + "' in type '%'", myLineParser.get(KEYS.getString(VISUM_NO)));
1270 }
1271 result |= unknown;
1272 }
1273 }
1274 return result;
1275}
1276
1277NBNode*
1278NIImporter_VISUM::getNamedNode(const std::string& fieldName) {
1279 std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1280 NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1281 if (node == nullptr) {
1282 WRITE_ERROR("The node '" + nodeS + "' is not known.");
1283 }
1284 return node;
1285}
1286
1287NBNode*
1288NIImporter_VISUM::getNamedNodeSecure(const std::string& fieldName, NBNode* fallback) {
1289 std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1290 NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1291 if (node == nullptr) {
1292 return fallback;
1293 }
1294 return node;
1295}
1296
1297
1298NBNode*
1299NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) {
1300 if (myLineParser.know(fieldName1)) {
1301 return getNamedNode(fieldName1);
1302 } else {
1303 return getNamedNode(fieldName2);
1304 }
1305}
1306
1307
1308NBEdge*
1309NIImporter_VISUM::getNamedEdge(const std::string& fieldName) {
1310 std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1311 NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1312 if (edge == nullptr) {
1313 WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1314 }
1315 return edge;
1316}
1317
1318
1319NBEdge*
1320NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) {
1321 if (myLineParser.know(fieldName1)) {
1322 return getNamedEdge(fieldName1);
1323 } else {
1324 return getNamedEdge(fieldName2);
1325 }
1326}
1327
1328
1329
1330NBEdge*
1332 std::string sid;
1333 if (edge->getID()[0] == '-') {
1334 sid = edge->getID().substr(1);
1335 } else {
1336 sid = "-" + edge->getID();
1337 }
1338 if (sid.find('_') != std::string::npos) {
1339 sid = sid.substr(0, sid.find('_'));
1340 }
1342}
1343
1344
1345NBEdge*
1347 if (begin == nullptr) {
1348 return nullptr;
1349 }
1350 NBEdge* ret = begin;
1351 std::string edgeID = ret->getID();
1352 // hangle forward
1353 while (ret != nullptr) {
1354 // ok, this is the edge we are looking for
1355 if (ret->getToNode() == node) {
1356 return ret;
1357 }
1358 const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1359 if (nedges.size() != 1) {
1360 // too many edges follow
1361 ret = nullptr;
1362 continue;
1363 }
1364 NBEdge* next = nedges[0];
1365 if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1366 // ok, another edge is next...
1367 ret = nullptr;
1368 continue;
1369 }
1370 if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1371 ret = nullptr;
1372 continue;
1373 }
1374 ret = next;
1375 }
1376
1377 ret = begin;
1378 // hangle backward
1379 while (ret != nullptr) {
1380 // ok, this is the edge we are looking for
1381 if (ret->getFromNode() == node) {
1382 return ret;
1383 }
1384 const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1385 if (nedges.size() != 1) {
1386 // too many edges follow
1387 ret = nullptr;
1388 continue;
1389 }
1390 NBEdge* next = nedges[0];
1391 if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1392 // ok, another edge is next...
1393 ret = nullptr;
1394 continue;
1395 }
1396 if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1397 ret = nullptr;
1398 continue;
1399 }
1400 ret = next;
1401 }
1402 return nullptr;
1403}
1404
1405
1406NBEdge*
1407NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName, NBNode* node) {
1408 std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1409 NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1410 if (edge == nullptr) {
1411 WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1412 }
1413 return getNamedEdgeContinuating(edge, node);
1414}
1415
1416
1417NBEdge*
1418NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1419 NBNode* node) {
1420 if (myLineParser.know(fieldName1)) {
1421 return getNamedEdgeContinuating(fieldName1, node);
1422 } else {
1423 return getNamedEdgeContinuating(fieldName2, node);
1424 }
1425}
1426
1427
1428NBEdge*
1430 EdgeVector::const_iterator i;
1431 for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1432 if (ToNode == (*i)->getToNode()) {
1433 return (*i);
1434 }
1435 }
1437 return nullptr;
1438}
1439
1440
1441double
1442NIImporter_VISUM::getNamedFloat(const std::string& fieldName) {
1443 std::string value = myLineParser.get(fieldName);
1444 if (StringUtils::endsWith(myLineParser.get(fieldName), "km/h")) {
1445 value = value.substr(0, value.length() - 4);
1446 }
1447 return StringUtils::toDouble(value);
1448}
1449
1450
1451double
1452NIImporter_VISUM::getNamedFloat(const std::string& fieldName, double defaultValue) {
1453 try {
1454 return StringUtils::toDouble(myLineParser.get(fieldName));
1455 } catch (...) {
1456 return defaultValue;
1457 }
1458}
1459
1460
1461double
1462NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) {
1463 if (myLineParser.know(fieldName1)) {
1464 return getNamedFloat(fieldName1);
1465 } else {
1466 return getNamedFloat(fieldName2);
1467 }
1468}
1469
1470
1471double
1472NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1473 double defaultValue) {
1474 if (myLineParser.know(fieldName1)) {
1475 return getNamedFloat(fieldName1, defaultValue);
1476 } else {
1477 return getNamedFloat(fieldName2, defaultValue);
1478 }
1479}
1480
1481
1482std::string
1483NIImporter_VISUM::getNamedString(const std::string& fieldName) {
1485}
1486
1487
1488std::string
1489NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1490 const std::string& fieldName2) {
1491 if (myLineParser.know(fieldName1)) {
1492 return getNamedString(fieldName1);
1493 } else {
1494 return getNamedString(fieldName2);
1495 }
1496}
1497
1498
1499
1500
1501
1502
1503NBNode*
1504NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1505 bool isSource) {
1506 // get the district
1508 if (dist == nullptr) {
1509 return nullptr;
1510 }
1511 // build the id
1512 std::string nid;
1513 nid = id + "-" + dest->getID();
1514 if (!isSource) {
1515 nid = "-" + nid;
1516 }
1517 // insert the node
1518 if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1519 WRITE_ERROR("Could not build connector node '" + nid + "'.");
1520 }
1521 // return the node
1522 return myNetBuilder.getNodeCont().retrieve(nid);
1523}
1524
1525
1526bool
1528 if (from == nullptr) {
1529 WRITE_ERROR(TL(" The from-node was not found within the net"));
1530 }
1531 if (to == nullptr) {
1532 WRITE_ERROR(TL(" The to-node was not found within the net"));
1533 }
1534 if (from == to) {
1535 WRITE_ERROR(TL(" Both nodes are the same"));
1536 }
1537 return from != nullptr && to != nullptr && from != to;
1538}
1539
1540bool
1542 return (edge->getID().length() > node->getID().length() + 1
1543 && (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()));
1544}
1545
1546void
1547NIImporter_VISUM::loadLanguage(const std::string& file) {
1548 std::ifstream strm(file.c_str());
1549 if (!strm.good()) {
1550 throw ProcessError("Could not load VISUM language map from '" + file + "'.");
1551 }
1552 while (strm.good()) {
1553 std::string keyDE;
1554 std::string keyNew;
1555 strm >> keyDE;
1556 strm >> keyNew;
1557 if (KEYS.hasString(keyDE)) {
1558 VISUM_KEY key = KEYS.get(keyDE);
1559 KEYS.remove(keyDE, key);
1560 KEYS.insert(keyNew, key);
1561 } else if (keyDE != "") {
1562 WRITE_WARNING("Unknown entry '" + keyDE + "' in VISUM language map");
1563 }
1564 }
1565
1566}
1567
1568
1569/****************************************************************************/
long long int SUMOTime
Definition: GUI.h:36
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:266
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:267
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:274
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:265
#define TL(string)
Definition: MsgHandler.h:282
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:270
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:269
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:42
#define TIME2STEPS(x)
Definition: SUMOTime.h:56
@ SVC_TRUCK
vehicle is a large transport vehicle
@ SVC_RAIL
vehicle is a not electrified rail
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
@ SVC_BICYCLE
vehicle is a bicycle
@ SVC_TRAM
vehicle is a light rail
@ SVC_BUS
vehicle is a bus
@ SVC_PEDESTRIAN
pedestrian
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
@ SUMO_ATTR_ALLOW
@ SUMO_ATTR_SPEED
@ SUMO_ATTR_ONEWAY
@ SUMO_ATTR_PRIORITY
@ SUMO_ATTR_NUMLANES
@ SUMO_ATTR_SPREADTYPE
The information about how to spread the lanes from the given position.
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
void setPos(unsigned long pos)
Sets the current position within the file to the given value.
Definition: LineReader.cpp:220
unsigned long getPosition()
Returns the current position within the file.
Definition: LineReader.cpp:187
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
Definition: LineReader.cpp:67
bool setFile(const std::string &file)
Reinitialises the reader for reading from the given file.
Definition: LineReader.cpp:179
int getLineNumber()
Definition: LineReader.h:143
void reinit()
Reinitialises the reading (of the previous file)
Definition: LineReader.cpp:193
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
Definition: LineReader.cpp:51
A helper class which computes the lane number from given capacity.
int get(double capacity) const
Returns the number of lanes computed from the given capacity.
NBDistrict * retrieve(const std::string &id) const
Returns the districts with the given id.
bool addSink(const std::string &dist, NBEdge *const destination, double weight)
Adds a sink to the named district.
bool insert(NBDistrict *const district)
Adds a district to the dictionary.
bool addSource(const std::string &dist, NBEdge *const source, double weight)
Adds a source to the named district.
A class representing a single district.
Definition: NBDistrict.h:62
const Position & getPosition() const
Returns the position of this district's center.
Definition: NBDistrict.h:120
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:274
void reduceGeometries(const double minDist)
Definition: NBEdgeCont.cpp:776
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:177
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:588
The representation of a single edge during network building.
Definition: NBEdge.h:92
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:980
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false)
Adds a connection to another edge.
Definition: NBEdge.cpp:1058
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:599
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:4100
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:552
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:366
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:3834
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:787
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, const bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:1092
const std::string & getID() const
Definition: NBEdge.h:1526
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:968
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:526
@ VALIDATED
The connection was computed and validated.
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:545
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:357
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:360
void setAsMacroscopicConnector()
Definition: NBEdge.h:1131
static std::string normalIDRepresentation(const std::string &id)
converts the numerical id to its "normal" string representation
Definition: NBHelpers.cpp:69
Instance responsible for building networks.
Definition: NBNetBuilder.h:107
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
Definition: NBNetBuilder.h:164
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:144
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:139
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:159
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:149
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:154
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:91
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:120
Represents a single node (junction) during network building.
Definition: NBNode.h:66
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
Definition: NBNode.cpp:1746
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:258
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:263
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
Definition: NBNode.cpp:1752
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:2465
bool insert(NBPTStop *ptStop, bool floating=false)
Inserts a node into the map.
The representation of a single pt stop.
Definition: NBPTStop.h:46
bool markEdgeTypeAsSet(const std::string &id, const SumoXMLAttr attr)
Marks an attribute of a edgeType as set.
Definition: NBTypeCont.cpp:320
void insertEdgeType(const std::string &id, int numLanes, double maxSpeed, int prio, SVCPermissions permissions, LaneSpreadFunction spreadType, double width, bool oneWayIsDefault, double sidewalkWidth, double bikeLaneWidth, double widthResolution, double maxWidth, double minWidth)
Adds a edgeType into the list.
Definition: NBTypeCont.cpp:204
double getEdgeTypeSpeed(const std::string &edgeType) const
Returns the maximal velocity for the given edgeType [m/s].
Definition: NBTypeCont.cpp:500
int getEdgeTypePriority(const std::string &edgeType) const
Returns the priority for the given edgeType.
Definition: NBTypeCont.cpp:511
int getEdgeTypeNumLanes(const std::string &edgeType) const
Returns the number of lanes for the given edgeType.
Definition: NBTypeCont.cpp:494
SVCPermissions getEdgeTypePermissions(const std::string &edgeType) const
Returns allowed vehicle classes for the given edgeType.
Definition: NBTypeCont.cpp:549
A VISUM network importer.
void load()
Parses the VISUM-network file storing the parsed structures within myNetBuilder.
void parse_Phases()
Parses LSAPHASE/PHASE.
NBCapacity2Lanes myCapacity2Lanes
The converter to compute the lane number of edges from their capacity.
static StringBijection< VISUM_KEY > KEYS
link directions
NBNetBuilder & myNetBuilder
The network builder to fill with loaded values.
void parse_Edges()
Parses STRECKE/STRECKEN.
double getWeightedFloat2(const std::string &name, const std::string &name2, const std::string &suffix)
as above but with two alternative names
~NIImporter_VISUM()
destructor
std::vector< std::string > myTouchedEdges
Already read edges.
NBEdge * getNamedEdge(const std::string &fieldName)
Tries to get the edge which name is stored in the given field.
double getWeightedFloat(const std::string &name, const std::string &suffix)
tries to get a double which is possibly assigned to a certain modality
void parse_VSysTypes()
Parses VSYS.
SVCPermissions getPermissions(const std::string &name, bool warn=false, SVCPermissions unknown=SVCAll)
parse permissions
void parse_NodesToTrafficLights()
Parses KNOTENZULSA/SIGNALANLAGEZUKNOTEN.
void parse_PartOfArea()
Parses FLAECHENELEMENT.
void parse_TrafficLights()
Parses LSA/SIGNALANLAGE.
NBNode * getNamedNodeSecure(const std::string &fieldName, NBNode *fallback=0)
void parse_Point()
Parses PUNKT.
void parse_Districts()
Parses BEZIRK.
VSysTypeNames myVSysTypes
The used vsystypes.
std::string myCurrentID
The name of the currently parsed item used for error reporting.
bool getWeightedBool(const std::string &name)
tries to get a bool which is possibly assigned to a certain modality
void parse_stopPoints()
Parses HALTEPUNKT (public transport stop locations)
std::map< NBDistrict *, PositionVector > myDistrictShapes
A temporary storage for district shapes as they are filled incrementally.
std::string myFileName
The name of the parsed file, for error reporting.
std::map< long long int, Position > myPoints
A map of point ids to positions.
void addParser(const std::string &name, ParsingFunction function)
Adds a parser into the sorted list of parsers to use.
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads network definition from the assigned option and stores it in the given network builder.
NIImporter_VISUM(NBNetBuilder &nb, const std::string &file, NBCapacity2Lanes capacity2Lanes, bool useVisumPrio, const std::string &languageFile)
constructor
static StringBijection< VISUM_KEY >::Entry KEYS_DE[]
Strings for the keywords.
std::map< long long int, std::pair< long long int, long long int > > myEdges
A map of edge (not road, but "edge" in this case) ids to from/to-points.
void parse_EdgePolys()
Parses STRECKENPOLY.
LineReader myLineReader
The line reader to use to read from the file.
bool myUseVisumPrio
Information whether VISUM priority information shall be used.
void loadLanguage(const std::string &file)
bool checkNodes(NBNode *from, NBNode *to)
Returns whether both nodes are a valid combination of from/to-nodes.
NBEdge * getReversedContinuating(NBEdge *edge, NBNode *node)
Returns the opposite direction of the given edge.
ParserVector mySingleDataParsers
List of known parsers.
void parse_SignalGroupsToPhases()
Parses LSASIGNALGRUPPEZULSAPHASE.
NBNode * getNamedNode(const std::string &fieldName)
Tries to get the node which name is stored in the given field.
void parse_Kante()
Parses FLAECHENELEMENT.
void parse_SignalGroups()
Parses LSASIGNALGRUPPE/SIGNALGRUPPE.
NBNode * buildDistrictNode(const std::string &id, NBNode *dest, bool isSource)
Builds a node for the given district and returns it.
void parse_Lanes()
Parses FAHRSTREIFEN.
NBEdge * getEdge(NBNode *FromNode, NBNode *ToNode)
Returns the edge that connects both nodes.
NamedColumnsParser myLineParser
the parser to parse the information from the data lines
double getNamedFloat(const std::string &fieldName)
Returns the value from the named column as a float.
std::map< long long int, NBDistrict * > myShapeDistrictMap
A map from district shape definition name to the district.
void parse_Turns()
Parses ABBIEGEBEZIEHUNG/ABBIEGER.
void parse_Nodes()
Parses KNOTEN.
void parse_TurnsToSignalGroups()
Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER.
NBEdge * getNamedEdgeContinuating(const std::string &fieldName, NBNode *node)
Tries to get the edge which name is stored in the given field continuating the search for a subedge t...
std::string getNamedString(const std::string &fieldName)
Returns the value from the named column as a normalised string.
void parse_LanesConnections()
Parses FAHRSTREIFENABBIEGER.
static bool isSplitEdge(NBEdge *edge, NBNode *node)
whether the edge id ends with _nodeID
void parse_Types()
Parses STRECKENTYP.
void parse_Connectors()
Parses ANBINDUNG.
void parse_AreaSubPartElement()
Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER.
std::map< long long int, std::vector< long long int > > mySubPartsAreas
A map from area parts to area ids.
NIVisumTL_Map myTLS
List of visum traffic lights.
A phase.
Definition: NIVisumTL.h:88
A signal group can be defined either by a time period or by phases.
Definition: NIVisumTL.h:103
std::map< std::string, Phase * > & phases()
Returns the phases map.
Definition: NIVisumTL.h:118
NBConnectionVector & connections()
Returns the connections vector.
Definition: NIVisumTL.h:113
Intermediate class for storing visum traffic lights during their import.
Definition: NIVisumTL.h:41
std::map< std::string, Phase * > & getPhases()
Returns the map of named phases.
Definition: NIVisumTL.h:159
SignalGroup & getSignalGroup(const std::string &name)
Returns the named signal group.
Definition: NIVisumTL.cpp:66
void reinit(const std::string &def, const std::string &defDelim=";", const std::string &lineDelim=";", bool chomp=false, bool ignoreCase=true)
Reinitialises the parser.
bool know(const std::string &name) const
Returns the information whether the named column is known.
void parseLine(const std::string &line)
Parses the contents of the line.
std::string get(const std::string &name, bool prune=false) const
Returns the named information.
const std::string & getID() const
Returns the id.
Definition: Named.h:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:59
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
A list of positions.
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
PositionVector reverse() const
reverse position vector
const std::string & getString(const T key) const
void remove(const std::string str, const T key)
bool hasString(const std::string &str) const
T get(const std::string &str) const
void insert(const std::string str, const T key, bool checkDuplicates=true)
std::vector< std::string > getVector()
return vector of strings
static long long int toLong(const std::string &sData)
converts a string into the long value described by it by calling the char-type converter,...
static std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
Definition: StringUtils.cpp:76
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static std::string latin1_to_utf8(std::string str)
Transfers from Latin 1 (ISO-8859-1) to UTF-8.
Definition: StringUtils.cpp:86
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
static bool toBool(const std::string &sData)
converts a string into the bool value described by it by calling the char-type converter
A complete call description for parsing a single db.
ParsingFunction function
Pointer to the function used for parsing.
std::string name
The name of the db.
long position
Position of the according db within the file.