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-2020 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>
28 #include <utils/common/ToString.h>
32 #include <netbuild/NBDistrict.h>
33 
34 #include <netbuild/NBNetBuilder.h>
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  { "NR", VISUM_NO } // must be the last one
78 };
79 
80 
81 
83 
84 // ===========================================================================
85 // method definitions
86 // ===========================================================================
87 // ---------------------------------------------------------------------------
88 // static methods (interface in this case)
89 // ---------------------------------------------------------------------------
90 void
92  // check whether the option is set (properly)
93  if (!oc.isSet("visum-file")) {
94  return;
95  }
96  // build the handler
97  NIImporter_VISUM loader(nb, oc.getString("visum-file"),
98  NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")),
99  oc.getBool("visum.use-type-priority"),
100  oc.getString("visum.language-file"));
101  loader.load();
102 }
103 
104 
105 
106 // ---------------------------------------------------------------------------
107 // loader methods
108 // ---------------------------------------------------------------------------
110  const std::string& file,
111  NBCapacity2Lanes capacity2Lanes,
112  bool useVisumPrio,
113  const std::string& languageFile) :
114  myNetBuilder(nb), myFileName(file),
115  myCapacity2Lanes(capacity2Lanes), myUseVisumPrio(useVisumPrio) {
116  if (languageFile != "") {
117  loadLanguage(languageFile);
118  }
119 
120  // the order of process is important!
121  // set1
127 
128  // set2
129  // two types of "strecke"
132 
133  // set3
134  if (OptionsCont::getOptions().getBool("visum.no-connectors")) {
136  } else {
138  }
139  // two types of "abbieger"
140  addParser("ABBIEGEBEZIEHUNG", &NIImporter_VISUM::parse_Turns);
142 
144  addParser("FAHRSTREIFEN", &NIImporter_VISUM::parse_Lanes);
146 
147 
148  // set4
149  // two types of lsa
152  // two types of knotenzulsa
156  // two types of signalgruppe
157  addParser("LSASIGNALGRUPPE", &NIImporter_VISUM::parse_SignalGroups);
159  // three types of ABBZULSASIGNALGRUPPE
160  addParser("ABBZULSASIGNALGRUPPE", &NIImporter_VISUM::parse_TurnsToSignalGroups);
161  addParser("SIGNALGRUPPEZUABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
162  addParser("SIGNALGRUPPEZUFSABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
163 
165 
166  // two types of LSAPHASE
169 
170  addParser("LSASIGNALGRUPPEZULSAPHASE", &NIImporter_VISUM::parse_SignalGroupsToPhases);
171  addParser("FAHRSTREIFENABBIEGER", &NIImporter_VISUM::parse_LanesConnections);
172 }
173 
174 
176  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
177  delete j->second;
178  }
179 }
180 
181 
182 void
183 NIImporter_VISUM::addParser(const std::string& name, ParsingFunction function) {
184  TypeParser p;
185  p.name = name;
186  p.function = function;
187  p.position = -1;
188  mySingleDataParsers.push_back(p);
189 }
190 
191 
192 void
194  // open the file
196  throw ProcessError("Can not open visum-file '" + myFileName + "'.");
197  }
198  // scan the file for data positions
199  while (myLineReader.hasMore()) {
200  std::string line = myLineReader.readLine();
201  if (line.length() > 0 && line[0] == '$') {
202  ParserVector::iterator i;
203  for (i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
204  std::string dataName = "$" + (*i).name + ":";
205  if (line.substr(0, dataName.length()) == dataName) {
206  (*i).position = myLineReader.getPosition();
207  (*i).pattern = line.substr(dataName.length());
208  WRITE_MESSAGE("Found: " + dataName + " at line " + toString<int>(myLineReader.getLineNumber()));
209  }
210  }
211  }
212  }
213  // go through the parsers and process all entries
214  for (ParserVector::iterator i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
215  if ((*i).position < 0) {
216  // do not process using parsers for which no information was found
217  continue;
218  }
219  // ok, the according information is stored in the file
220  PROGRESS_BEGIN_MESSAGE("Parsing " + (*i).name);
221  // reset the line reader and let it point to the begin of the according data field
223  myLineReader.setPos((*i).position);
224  // prepare the line parser
225  myLineParser.reinit((*i).pattern);
226  // read
227  bool singleDataEndFound = false;
228  while (myLineReader.hasMore() && !singleDataEndFound) {
229  std::string line = myLineReader.readLine();
230  if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
231  singleDataEndFound = true;
232  } else {
233  myLineParser.parseLine(line);
234  try {
235  myCurrentID = "<unknown>";
236  (this->*(*i).function)();
237  } catch (OutOfBoundsException&) {
238  WRITE_ERROR("Too short value line in " + (*i).name + " occurred.");
239  } catch (NumberFormatException&) {
240  WRITE_ERROR("A value in " + (*i).name + " should be numeric but is not (id='" + myCurrentID + "').");
241  } catch (UnknownElement& e) {
242  WRITE_ERROR("One of the needed values ('" + std::string(e.what()) + "') is missing in " + (*i).name + ".");
243  }
244  }
245  }
246  // close single reader processing
248  }
249  myNetBuilder.getEdgeCont().reduceGeometries(POSITION_EPS);
250 
251  // build traffic lights
252  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
253  j->second->build(myNetBuilder.getEdgeCont(), myNetBuilder.getTLLogicCont());
254  }
255  // build district shapes
256  for (std::map<NBDistrict*, PositionVector>::const_iterator k = myDistrictShapes.begin(); k != myDistrictShapes.end(); ++k) {
257  (*k).first->addShape((*k).second);
258  }
259 }
260 
261 
262 
263 
264 
265 void
267  std::string name = myLineParser.know("VSysCode") ? myLineParser.get("VSysCode").c_str() : myLineParser.get(KEYS.getString(VISUM_CODE)).c_str();
268  std::string type = myLineParser.know("VSysMode") ? myLineParser.get("VSysMode").c_str() : myLineParser.get(KEYS.getString(VISUM_TYP)).c_str();
269  myVSysTypes[name] = type;
270 }
271 
272 
273 void
275  // get the id
277  // get the maximum speed
278  double speed = getWeightedFloat2("v0-IV", KEYS.getString(VISUM_V0), "km/h");
279  if (speed == 0) {
280  // unlimited speed
281  speed = 3600;
282  } else if (speed < 0) {
283  WRITE_ERROR("Type '" + myCurrentID + "' has speed " + toString(speed));
284  }
285  // get the permissions
287  // get the priority
288  const int priority = 1000 - StringUtils::toInt(myLineParser.get(KEYS.getString(VISUM_RANK)));
289  // try to retrieve the number of lanes
290  const int numLanes = myCapacity2Lanes.get(getNamedFloat("Kap-IV", KEYS.getString(VISUM_CAPACITY)));
291  // insert the type
292  myNetBuilder.getTypeCont().insertEdgeType(myCurrentID, numLanes, speed / (double) 3.6, priority, permissions, NBEdge::UNSPECIFIED_WIDTH, false, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_WIDTH, 0, 0, 0);
298 }
299 
300 
301 void
303  // get the id
305  // get the position
308  Position pos(x, y);
310  WRITE_ERROR("Unable to project coordinates for node " + myCurrentID + ".");
311  return;
312  }
313  // add to the list
315  WRITE_ERROR("Duplicate node occurred ('" + myCurrentID + "').");
316  }
317 }
318 
319 
320 void
322  // get the id
324  // get the information whether the source and the destination
325  // connections are weighted
326  //bool sourcesWeighted = getWeightedBool("Proz_Q");
327  //bool destWeighted = getWeightedBool("Proz_Z");
328  // get the node information
331  Position pos(x, y);
332  if (!NBNetBuilder::transformCoordinate(pos, false)) {
333  WRITE_ERROR("Unable to project coordinates for district " + myCurrentID + ".");
334  return;
335  }
336  // build the district
337  NBDistrict* district = new NBDistrict(myCurrentID, pos);
338  if (!myNetBuilder.getDistrictCont().insert(district)) {
339  WRITE_ERROR("Duplicate district occurred ('" + myCurrentID + "').");
340  delete district;
341  return;
342  }
344  long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
345  myShapeDistrictMap[flaecheID] = district;
346  }
347 }
348 
349 
350 void
355  Position pos(x, y);
356  if (!NBNetBuilder::transformCoordinate(pos, false)) {
357  WRITE_ERROR("Unable to project coordinates for point " + toString(id) + ".");
358  return;
359  }
360  myPoints[id] = pos;
361 }
362 
363 
364 void
367  // no vehicle allowed; don't add
368  return;
369  }
370  // get the id
372  // get the from- & to-node and validate them
373  NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
374  NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
375  if (!checkNodes(from, to)) {
376  return;
377  }
378  // get the type
380  // get the speed
381  double speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
382  if (!OptionsCont::getOptions().getBool("visum.use-type-speed")) {
383  try {
384  std::string speedS = myLineParser.know("v0-IV") ? myLineParser.get("v0-IV") : myLineParser.get(KEYS.getString(VISUM_V0));
385  if (speedS.find("km/h") != std::string::npos) {
386  speedS = speedS.substr(0, speedS.find("km/h"));
387  }
388  speed = StringUtils::toDouble(speedS) / 3.6;
389  } catch (OutOfBoundsException&) {}
390  }
391  if (speed <= 0) {
392  speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
393  }
394 
395  // get the information whether the edge is a one-way
396  bool oneway = myLineParser.know("Einbahn")
397  ? StringUtils::toBool(myLineParser.get("Einbahn"))
398  : true;
399  // get the number of lanes
400  int nolanes = myNetBuilder.getTypeCont().getEdgeTypeNumLanes(type);
401  if (!OptionsCont::getOptions().getBool("visum.recompute-lane-number")) {
402  if (!OptionsCont::getOptions().getBool("visum.use-type-laneno")) {
403  if (myLineParser.know("Fahrstreifen")) {
404  nolanes = StringUtils::toInt(myLineParser.get("Fahrstreifen"));
407  }
408  }
409  } else {
412  } else if (myLineParser.know("KAP-IV")) {
414  }
415  }
416  // check whether the id is already used
417  // (should be the opposite direction)
418  bool oneway_checked = oneway;
420  if (previous != nullptr) {
421  myCurrentID = '-' + myCurrentID;
423  oneway_checked = false;
424  }
425  if (find(myTouchedEdges.begin(), myTouchedEdges.end(), myCurrentID) != myTouchedEdges.end()) {
426  oneway_checked = false;
427  }
428  std::string tmpid = '-' + myCurrentID;
429  if (find(myTouchedEdges.begin(), myTouchedEdges.end(), tmpid) != myTouchedEdges.end()) {
430  previous = myNetBuilder.getEdgeCont().retrieve(tmpid);
431  if (previous != nullptr) {
433  }
434  oneway_checked = false;
435  }
436  // add the edge
439  if (nolanes != 0 && speed != 0) {
441  // @todo parse name from visum files
442  NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, nolanes, prio,
444  e->setPermissions(permissions);
445  if (!myNetBuilder.getEdgeCont().insert(e)) {
446  delete e;
447  WRITE_ERROR("Duplicate edge occurred ('" + myCurrentID + "').");
448  }
449  }
450  myTouchedEdges.push_back(myCurrentID);
451  // nothing more to do, when the edge is a one-way street
452  if (oneway) {
453  return;
454  }
455  // add the opposite edge
456  myCurrentID = '-' + myCurrentID;
457  if (nolanes != 0 && speed != 0) {
459  // @todo parse name from visum files
460  NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, nolanes, prio,
462  e->setPermissions(permissions);
463  if (!myNetBuilder.getEdgeCont().insert(e)) {
464  delete e;
465  WRITE_ERROR("Duplicate edge occurred ('" + myCurrentID + "').");
466  }
467  }
468  myTouchedEdges.push_back(myCurrentID);
469 }
470 
471 
472 void
477  myEdges[id] = std::make_pair(from, to);
478 }
479 
480 
481 void
483  long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
484  long long int flaechePartID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_FACEID)));
485  if (mySubPartsAreas.find(flaechePartID) == mySubPartsAreas.end()) {
486  mySubPartsAreas[flaechePartID] = std::vector<long long int>();
487  }
488  mySubPartsAreas[flaechePartID].push_back(flaecheID);
489 }
490 
491 
492 void
494  // get the source district
496  // get the destination node
498  if (dest == nullptr) {
499  return;
500  }
501  // get the weight of the connection
502  double proz = 1;
503  if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
504  proz = getNamedFloat("Proz", "Proz(IV)") / 100;
505  }
506  // get the information whether this is a sink or a source
507  std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
508  if (dir.length() == 0) {
510  }
511  // build the source when needed
512  if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
513  for (NBEdge* edge : dest->getOutgoingEdges()) {
514  myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
515  }
516  }
517  // build the sink when needed
518  if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
519  for (NBEdge* edge : dest->getIncomingEdges()) {
520  myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
521  }
522  }
523 }
524 
525 
526 
527 void
529  // get the source district
531  // get the destination node
533  if (dest == nullptr) {
534  return;
535  }
536  // get the weight of the connection
537  double proz = 1;
538  if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
539  proz = getNamedFloat("Proz", "Proz(IV)") / 100;
540  }
541  // get the duration to wait (unused)
542 // double retard = -1;
543 // if (myLineParser.know("t0-IV")) {
544 // retard = getNamedFloat("t0-IV", -1);
545 // }
546  // get the type;
547  // use a standard type with a large speed when a type is not given
548 
549  std::string type = myLineParser.know(KEYS.getString(VISUM_TYP))
551  : "";
552  // add the connectors as an edge
553  std::string id = bez + "-" + dest->getID();
554  // get the information whether this is a sink or a source
555  std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
556  if (dir.length() == 0) {
558  }
559  // build the source when needed
560  if (dir.find(KEYS.getString(VISUM_ORIGIN)) != std::string::npos) {
561  const EdgeVector& edges = dest->getOutgoingEdges();
562  bool hasContinuation = false;
563  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
564  if (!(*i)->isMacroscopicConnector()) {
565  hasContinuation = true;
566  }
567  }
568  if (!hasContinuation) {
569  // obviously, there is no continuation on the net
570  WRITE_WARNING("Incoming connector '" + id + "' will not be build - would be not connected to network.");
571  } else {
572  NBNode* src = buildDistrictNode(bez, dest, true);
573  if (src == nullptr) {
574  WRITE_ERROR("The district '" + bez + "' could not be built.");
575  return;
576  }
577  NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
578  OptionsCont::getOptions().getFloat("visum.connector-speeds"),
579  OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
583  if (!myNetBuilder.getEdgeCont().insert(edge)) {
584  WRITE_ERROR("A duplicate edge id occurred (ID='" + id + "').");
585  return;
586  }
587  edge = myNetBuilder.getEdgeCont().retrieve(id);
588  if (edge != nullptr) {
589  myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
590  }
591  }
592  }
593  // build the sink when needed
594  if (dir.find(KEYS.getString(VISUM_DESTINATION)) != std::string::npos) {
595  const EdgeVector& edges = dest->getIncomingEdges();
596  bool hasPredeccessor = false;
597  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
598  if (!(*i)->isMacroscopicConnector()) {
599  hasPredeccessor = true;
600  }
601  }
602  if (!hasPredeccessor) {
603  // obviously, the network is not connected to this node
604  WRITE_WARNING("Outgoing connector '" + id + "' will not be build - would be not connected to network.");
605  } else {
606  NBNode* src = buildDistrictNode(bez, dest, false);
607  if (src == nullptr) {
608  WRITE_ERROR("The district '" + bez + "' could not be built.");
609  return;
610  }
611  id = "-" + id;
612  NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
613  OptionsCont::getOptions().getFloat("visum.connector-speeds"),
614  OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
618  if (!myNetBuilder.getEdgeCont().insert(edge)) {
619  WRITE_ERROR("A duplicate edge id occurred (ID='" + id + "').");
620  return;
621  }
622  edge = myNetBuilder.getEdgeCont().retrieve(id);
623  if (edge != nullptr) {
624  myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
625  }
626  }
627  }
628 }
629 
630 
631 void
634  // no vehicle allowed; don't add
635  return;
636  }
637  // retrieve the nodes
638  NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
639  NBNode* via = getNamedNode("UeberKnot", KEYS.getString(VISUM_VIANODENO));
640  NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
641  if (from == nullptr || via == nullptr || to == nullptr) {
642  return;
643  }
644  // all nodes are known
645  std::string type = myLineParser.know("VSysCode")
646  ? myLineParser.get("VSysCode")
648  if (myVSysTypes.find(type) != myVSysTypes.end() && myVSysTypes.find(type)->second == "IV") {
649  // try to set the turning definition
650  NBEdge* src = from->getConnectionTo(via);
651  NBEdge* dest = via->getConnectionTo(to);
652  // check both
653  if (src == nullptr) {
654  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
655  WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + via->getID() + "'.");
656  }
657  return;
658  }
659  if (dest == nullptr) {
660  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
661  WRITE_WARNING("There is no edge from node '" + via->getID() + "' to node '" + to->getID() + "'.");
662  }
663  return;
664  }
665  // both edges found
666  // set them into the edge
667  src->addEdge2EdgeConnection(dest);
668  }
669 }
670 
671 
672 void
674  // get the from- & to-node and validate them
675  NBNode* from = getNamedNode("VonKnot", KEYS.getString(VISUM_FROMNODE));
676  NBNode* to = getNamedNode("NachKnot", KEYS.getString(VISUM_TONODE));
677  if (!checkNodes(from, to)) {
678  return;
679  }
680  bool failed = false;
681  int index;
682  double x, y;
683  try {
687  } catch (NumberFormatException&) {
688  WRITE_ERROR("Error in geometry description from node '" + from->getID() + "' to node '" + to->getID() + "'.");
689  return;
690  }
691  Position pos(x, y);
693  WRITE_ERROR("Unable to project coordinates for node '" + from->getID() + "'.");
694  return;
695  }
696  NBEdge* e = from->getConnectionTo(to);
697  if (e != nullptr) {
698  e->addGeometryPoint(index, pos);
699  } else {
700  failed = true;
701  }
702  e = to->getConnectionTo(from);
703  if (e != nullptr) {
704  e->addGeometryPoint(-index, pos);
705  failed = false;
706  }
707  // check whether the operation has failed
708  if (failed) {
709  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
710  WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + to->getID() + "'.");
711  }
712  }
713 }
714 
715 
716 void
718  // The base number of lanes for the edge was already defined in STRECKE
719  // this refines lane specific attribute (width) and optionally introduces splits for additional lanes
720  // It is permitted for KNOTNR to be 0
721  //
722  // get the edge
723  NBEdge* baseEdge = getNamedEdge("STRNR");
724  if (baseEdge == nullptr) {
725  return;
726  }
727  NBEdge* edge = baseEdge;
728  // get the node
729  NBNode* node = getNamedNodeSecure("KNOTNR");
730  if (node == nullptr) {
731  node = edge->getToNode();
732  } else {
733  edge = getNamedEdgeContinuating("STRNR", node);
734  }
735  // check
736  if (edge == nullptr) {
737  return;
738  }
739  // get the lane
740  std::string laneS = myLineParser.know("FSNR")
743  int lane = -1;
744  try {
745  lane = StringUtils::toInt(laneS);
746  } catch (NumberFormatException&) {
747  WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not numeric (" + laneS + ").");
748  return;
749  }
750  lane -= 1;
751  if (lane < 0) {
752  WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not positive (" + laneS + ").");
753  return;
754  }
755  // get the direction
756  std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
757  int prevLaneNo = baseEdge->getNumLanes();
758  if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
759  // get the last part of the turnaround direction
760  NBEdge* cand = getReversedContinuating(edge, node);
761  if (cand) {
762  edge = cand;
763  }
764  }
765  // get the length
766  std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
767  double length = -1;
768  try {
769  length = StringUtils::toDouble(lengthS);
770  } catch (NumberFormatException&) {
771  WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not numeric (" + lengthS + ").");
772  return;
773  }
774  if (length < 0) {
775  WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not positive (" + lengthS + ").");
776  return;
777  }
778  //
779  if (dirS == "1") {
780  lane -= prevLaneNo;
781  }
782  //
783  if (length == 0) {
784  if ((int) edge->getNumLanes() > lane) {
785  // ok, we know this already...
786  return;
787  }
788  // increment by one
789  edge->incLaneNo(1);
790  } else {
791  // check whether this edge already has been created
792  if (isSplitEdge(edge, node)) {
793  if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
794  if ((int) edge->getNumLanes() > lane) {
795  // ok, we know this already...
796  return;
797  }
798  // increment by one
799  edge->incLaneNo(1);
800  return;
801  }
802  }
803  // nope, we have to split the edge...
804  // maybe it is not the proper edge to split - VISUM seems not to sort the splits...
805  bool mustRecheck = true;
806  double seenLength = 0;
807  while (mustRecheck) {
808  if (isSplitEdge(edge, node)) {
809  // ok, we have a previously created edge here
810  std::string sub = edge->getID();
811  sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
812  sub = sub.substr(1, sub.find('_', 1) - 1);
813  double dist = StringUtils::toDouble(sub);
814  if (dist < length) {
815  seenLength += edge->getLength();
816  if (dirS == "1") {
817  // incoming -> move back
818  edge = edge->getFromNode()->getIncomingEdges()[0];
819  } else {
820  // outgoing -> move forward
821  edge = edge->getToNode()->getOutgoingEdges()[0];
822  }
823  } else {
824  mustRecheck = false;
825  }
826  } else {
827  // we have the center edge - do not continue...
828  mustRecheck = false;
829  }
830  }
831  // compute position
832  Position p;
833  double useLength = length - seenLength;
834  useLength = edge->getLength() - useLength;
835  if (useLength < 0 || useLength > edge->getLength()) {
836  WRITE_WARNING("Could not find split position for edge '" + edge->getID() + "'.");
837  return;
838  }
839  std::string edgeID = edge->getID();
840  p = edge->getGeometry().positionAtOffset(useLength);
841  if (isSplitEdge(edge, node)) {
842  edgeID = edgeID.substr(0, edgeID.find('_'));
843  }
844  NBNode* rn = new NBNode(edgeID + "_" + toString((int) length) + "_" + node->getID(), p);
845  if (!myNetBuilder.getNodeCont().insert(rn)) {
846  throw ProcessError("Ups - could not insert node!");
847  }
848  std::string nid = edgeID + "_" + toString((int) length) + "_" + node->getID();
850  edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
851  // old edge is deleted and a new edge with the same name created
852  edge = myNetBuilder.getEdgeCont().retrieve(edgeID);
853  NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
854  nedge = nedge->getToNode()->getOutgoingEdges()[0];
855  while (isSplitEdge(edge, node)) {
856  assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
857  nedge->incLaneNo(1);
858  nedge = nedge->getToNode()->getOutgoingEdges()[0];
859  }
860  }
861 }
862 
863 
864 void
867  const SUMOTime cycleTime = TIME2STEPS(getWeightedFloat2("Umlaufzeit", "UMLZEIT", "s"));
868  const SUMOTime intermediateTime = TIME2STEPS(getWeightedFloat2("StdZwischenzeit", "STDZWZEIT", "s"));
869  bool phaseBased = myLineParser.know("PhasenBasiert")
870  ? StringUtils::toBool(myLineParser.get("PhasenBasiert"))
871  : false;
872  const SUMOTime offset = myLineParser.know("ZEITVERSATZ") ? TIME2STEPS(getWeightedFloat("ZEITVERSATZ", "s")) : 0;
873  // add to the list
874  myTLS[myCurrentID] = new NIVisumTL(myCurrentID, cycleTime, offset, intermediateTime, phaseBased);
875 }
876 
877 
878 void
880  std::string node = myLineParser.get("KnotNr").c_str();
881  if (node == "0") {
882  // this is a dummy value which cannot be assigned to
883  return;
884  }
885  std::string trafficLight = myLineParser.get("LsaNr").c_str();
886  // add to the list
888  auto tlIt = myTLS.find(trafficLight);
889  if (n != nullptr && tlIt != myTLS.end()) {
890  tlIt->second->addNode(n);
891  } else {
892  WRITE_ERROR("Could not assign" + std::string(n == nullptr ? " missing" : "") + " node '" + node
893  + "' to" + std::string(tlIt == myTLS.end() ? " missing" : "") + " traffic light '" + trafficLight + "'");
894  }
895 }
896 
897 
898 void
901  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
902  const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
903  const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
904  const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
905  // add to the list
906  if (myTLS.find(LSAid) == myTLS.end()) {
907  WRITE_ERROR("Could not find TLS '" + LSAid + "' for setting the signal group.");
908  return;
909  }
910  myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, startTime, endTime, yellowTime);
911 }
912 
913 
914 void
916  // get the id
917  std::string SGid = getNamedString("SGNR", "SIGNALGRUPPENNR");
918  if (!myLineParser.know("LsaNr")) {
920  WRITE_WARNING("Ignoring SIGNALGRUPPEZUFSABBIEGER because LsaNr is not known");
921  return;
922  }
923  std::string LSAid = getNamedString("LsaNr");
924  // nodes
925  NBNode* from = myLineParser.know("VonKnot") ? getNamedNode("VonKnot") : nullptr;
926  NBNode* via = myLineParser.know("KNOTNR")
927  ? getNamedNode("KNOTNR")
928  : getNamedNode("UeberKnot", "UeberKnotNr");
929  NBNode* to = myLineParser.know("NachKnot") ? getNamedNode("NachKnot") : nullptr;
930  // edges
931  NBEdge* edg1 = nullptr;
932  NBEdge* edg2 = nullptr;
933  if (from == nullptr && to == nullptr) {
934  edg1 = getNamedEdgeContinuating("VONSTRNR", via);
935  edg2 = getNamedEdgeContinuating("NACHSTRNR", via);
936  } else {
937  edg1 = getEdge(from, via);
938  edg2 = getEdge(via, to);
939  }
940  // add to the list
941  NIVisumTL::SignalGroup& SG = myTLS.find(LSAid)->second->getSignalGroup(SGid);
942  if (edg1 != nullptr && edg2 != nullptr) {
943  if (!via->hasIncoming(edg1)) {
944  std::string sid;
945  if (edg1->getID()[0] == '-') {
946  sid = edg1->getID().substr(1);
947  } else {
948  sid = "-" + edg1->getID();
949  }
950  if (sid.find('_') != std::string::npos) {
951  sid = sid.substr(0, sid.find('_'));
952  }
954  }
955  if (!via->hasOutgoing(edg2)) {
956  std::string sid;
957  if (edg2->getID()[0] == '-') {
958  sid = edg2->getID().substr(1);
959  } else {
960  sid = "-" + edg2->getID();
961  }
962  if (sid.find('_') != std::string::npos) {
963  sid = sid.substr(0, sid.find('_'));
964  }
966  }
967  SG.connections().push_back(NBConnection(edg1, edg2));
968  }
969 }
970 
971 
972 void
976  if (myEdges.find(edgeid) == myEdges.end()) {
977  WRITE_ERROR("Unknown edge in TEILFLAECHENELEMENT");
978  return;
979  }
980  std::string dir = myLineParser.get(KEYS.getString(VISUM_DIRECTION));
981 // get index (unused)
982 // std::string indexS = NBHelpers::normalIDRepresentation(myLineParser.get("INDEX"));
983 // int index = -1;
984 // try {
985 // index = StringUtils::toInt(indexS) - 1;
986 // } catch (NumberFormatException&) {
987 // WRITE_ERROR("An index for a TEILFLAECHENELEMENT is not numeric (id='" + toString(id) + "').");
988 // return;
989 // }
990  PositionVector shape;
991  shape.push_back(myPoints[myEdges[edgeid].first]);
992  shape.push_back(myPoints[myEdges[edgeid].second]);
993  if (dir.length() > 0 && dir[0] == '1') {
994  shape = shape.reverse();
995  }
996  if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
997  WRITE_ERROR("Unkown are for area part '" + myCurrentID + "'.");
998  return;
999  }
1000 
1001  const std::vector<long long int>& areas = mySubPartsAreas.find(id)->second;
1002  for (std::vector<long long int>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
1003  NBDistrict* d = myShapeDistrictMap[*i];
1004  if (d == nullptr) {
1005  continue;
1006  }
1007  if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
1009  }
1010  if (dir.length() > 0 && dir[0] == '1') {
1011  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1012  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1013  } else {
1014  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
1015  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
1016  }
1017  }
1018 }
1019 
1020 
1021 void
1023  // get the id
1025  const std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1026  const SUMOTime startTime = TIME2STEPS(getNamedFloat("GzStart", "GRUENANF"));
1027  const SUMOTime endTime = TIME2STEPS(getNamedFloat("GzEnd", "GRUENENDE"));
1028  const SUMOTime yellowTime = myLineParser.know("GELB") ? TIME2STEPS(getNamedFloat("GELB")) : -1;
1029  myTLS.find(LSAid)->second->addPhase(phaseid, startTime, endTime, yellowTime);
1030 }
1031 
1032 
1034  // get the id
1035  std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("PsNr"));
1036  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
1037  std::string SGid = NBHelpers::normalIDRepresentation(myLineParser.get("SGNR"));
1038  // insert
1039  NIVisumTL* LSA = myTLS.find(LSAid)->second;
1040  NIVisumTL::SignalGroup& SG = LSA->getSignalGroup(SGid);
1041  NIVisumTL::Phase* PH = LSA->getPhases().find(Phaseid)->second;
1042  SG.phases()[Phaseid] = PH;
1043 }
1044 
1045 
1047  NBNode* node = nullptr;
1048  NBEdge* fromEdge = nullptr;
1049  NBEdge* toEdge = nullptr;
1050  // get the node and edges depending on network format
1051  const std::string nodeID = getNamedString("KNOTNR", "KNOT");
1052  if (nodeID == "0") {
1053  fromEdge = getNamedEdge("VONSTRNR", "VONSTR");
1054  toEdge = getNamedEdge("NACHSTRNR", "NACHSTR");
1055  if (fromEdge == nullptr) {
1056  return;
1057  }
1058  node = fromEdge->getToNode();
1059  WRITE_WARNING("Ignoring lane-to-lane connection (not yet implemented for this format version)");
1060  return;
1061  } else {
1062  node = getNamedNode("KNOTNR", "KNOT");
1063  if (node == nullptr) {
1064  return;
1065  }
1066  fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node);
1067  toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node);
1068  }
1069  if (fromEdge == nullptr || toEdge == nullptr) {
1070  return;
1071  }
1072 
1073  int fromLaneOffset = 0;
1074  if (!node->hasIncoming(fromEdge)) {
1075  fromLaneOffset = fromEdge->getNumLanes();
1076  fromEdge = getReversedContinuating(fromEdge, node);
1077  } else {
1078  fromEdge = getReversedContinuating(fromEdge, node);
1079  NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_')));
1080  fromLaneOffset = tmp->getNumLanes();
1081  }
1082 
1083  int toLaneOffset = 0;
1084  if (!node->hasOutgoing(toEdge)) {
1085  toLaneOffset = toEdge->getNumLanes();
1086  toEdge = getReversedContinuating(toEdge, node);
1087  } else {
1088  NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_')));
1089  toLaneOffset = tmp->getNumLanes();
1090  }
1091  // get the from-lane
1092  std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR"));
1093  int fromLane = -1;
1094  try {
1095  fromLane = StringUtils::toInt(fromLaneS);
1096  } catch (NumberFormatException&) {
1097  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not numeric (" + fromLaneS + ").");
1098  return;
1099  }
1100  fromLane -= 1;
1101  if (fromLane < 0) {
1102  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not positive (" + fromLaneS + ").");
1103  return;
1104  }
1105  // get the from-lane
1106  std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR"));
1107  int toLane = -1;
1108  try {
1109  toLane = StringUtils::toInt(toLaneS);
1110  } catch (NumberFormatException&) {
1111  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not numeric (" + toLaneS + ").");
1112  return;
1113  }
1114  toLane -= 1;
1115  if (toLane < 0) {
1116  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not positive (" + toLaneS + ").");
1117  return;
1118  }
1119  // !!! the next is probably a hack
1120  if (fromLane - fromLaneOffset < 0) {
1121  //fromLaneOffset = 0;
1122  } else {
1123  fromLane = (int)fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1;
1124  }
1125  if (toLane - toLaneOffset < 0) {
1126  //toLaneOffset = 0;
1127  } else {
1128  toLane = (int)toEdge->getNumLanes() - (toLane - toLaneOffset) - 1;
1129  }
1130  //
1131  if ((int) fromEdge->getNumLanes() <= fromLane) {
1132  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is larger than the edge's lane number (" + fromLaneS + ").");
1133  return;
1134  }
1135  if ((int) toEdge->getNumLanes() <= toLane) {
1136  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is larger than the edge's lane number (" + toLaneS + ").");
1137  return;
1138  }
1139  //
1140  fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::Lane2LaneInfoType::VALIDATED);
1141 }
1142 
1143 
1144 
1145 
1146 
1147 
1148 
1149 
1150 
1151 
1152 
1153 
1154 
1155 double
1156 NIImporter_VISUM::getWeightedFloat(const std::string& name, const std::string& suffix) {
1157  try {
1158  std::string val = myLineParser.get(name);
1159  if (val.find(suffix) != std::string::npos) {
1160  val = val.substr(0, val.find(suffix));
1161  }
1162  return StringUtils::toDouble(val);
1163  } catch (...) {}
1164  return -1;
1165 }
1166 
1167 
1168 double
1169 NIImporter_VISUM::getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix) {
1170  double result = getWeightedFloat(name, suffix);
1171  if (result != -1) {
1172  return result;
1173  } else {
1174  return getWeightedFloat(name2, suffix);
1175  }
1176 }
1177 
1178 bool
1179 NIImporter_VISUM::getWeightedBool(const std::string& name) {
1180  try {
1181  return StringUtils::toBool(myLineParser.get(name));
1182  } catch (...) {}
1183  try {
1184  return StringUtils::toBool(myLineParser.get((name + "(IV)")));
1185  } catch (...) {}
1186  return false;
1187 }
1188 
1190 NIImporter_VISUM::getPermissions(const std::string& name, bool warn, SVCPermissions unknown) {
1191  SVCPermissions result = 0;
1192  for (std::string v : StringTokenizer(myLineParser.get(name), ",").getVector()) {
1193  // common values in english and german
1194  // || v == "funiculaire-telecabine" ---> no matching
1195  std::transform(v.begin(), v.end(), v.begin(), tolower);
1196  if (v == "bus" || v == "tcsp" || v == "acces tc" || v == "Accès tc" || v == "accès tc") {
1197  result |= SVC_BUS;
1198  } else if (v == "walk" || v == "w" || v == "f" || v == "ped" || v == "map") {
1199  result |= SVC_PEDESTRIAN;
1200  } else if (v == "l" || v == "lkw" || v == "h" || v == "hgv" || v == "lw" || v == "truck" || v == "tru" || v == "pl") {
1201  result |= SVC_TRUCK;
1202  } else if (v == "b" || v == "bike" || v == "velo") {
1203  result |= SVC_BICYCLE;
1204  } else if (v == "train" || v == "rail") {
1205  result |= SVC_RAIL;
1206  } else if (v == "tram") {
1207  result |= SVC_TRAM;
1208  } else if (v == "p" || v == "pkw" || v == "car" || v == "c" || v == "vp" || v == "2rm") {
1209  result |= SVC_PASSENGER;
1210  } else {
1211  if (warn) {
1212  WRITE_WARNING("Encountered unknown vehicle category '" + v + "' in type '" + myLineParser.get(KEYS.getString(VISUM_NO)) + "'");
1213  }
1214  result |= unknown;
1215  }
1216  }
1217  return result;
1218 }
1219 
1220 NBNode*
1221 NIImporter_VISUM::getNamedNode(const std::string& fieldName) {
1222  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1223  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1224  if (node == nullptr) {
1225  WRITE_ERROR("The node '" + nodeS + "' is not known.");
1226  }
1227  return node;
1228 }
1229 
1230 NBNode*
1231 NIImporter_VISUM::getNamedNodeSecure(const std::string& fieldName, NBNode* fallback) {
1232  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1233  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1234  if (node == nullptr) {
1235  return fallback;
1236  }
1237  return node;
1238 }
1239 
1240 
1241 NBNode*
1242 NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) {
1243  if (myLineParser.know(fieldName1)) {
1244  return getNamedNode(fieldName1);
1245  } else {
1246  return getNamedNode(fieldName2);
1247  }
1248 }
1249 
1250 
1251 NBEdge*
1252 NIImporter_VISUM::getNamedEdge(const std::string& fieldName) {
1253  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1254  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1255  if (edge == nullptr) {
1256  WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1257  }
1258  return edge;
1259 }
1260 
1261 
1262 NBEdge*
1263 NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) {
1264  if (myLineParser.know(fieldName1)) {
1265  return getNamedEdge(fieldName1);
1266  } else {
1267  return getNamedEdge(fieldName2);
1268  }
1269 }
1270 
1271 
1272 
1273 NBEdge*
1275  std::string sid;
1276  if (edge->getID()[0] == '-') {
1277  sid = edge->getID().substr(1);
1278  } else {
1279  sid = "-" + edge->getID();
1280  }
1281  if (sid.find('_') != std::string::npos) {
1282  sid = sid.substr(0, sid.find('_'));
1283  }
1285 }
1286 
1287 
1288 NBEdge*
1290  if (begin == nullptr) {
1291  return nullptr;
1292  }
1293  NBEdge* ret = begin;
1294  std::string edgeID = ret->getID();
1295  // hangle forward
1296  while (ret != nullptr) {
1297  // ok, this is the edge we are looking for
1298  if (ret->getToNode() == node) {
1299  return ret;
1300  }
1301  const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1302  if (nedges.size() != 1) {
1303  // too many edges follow
1304  ret = nullptr;
1305  continue;
1306  }
1307  NBEdge* next = nedges[0];
1308  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1309  // ok, another edge is next...
1310  ret = nullptr;
1311  continue;
1312  }
1313  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1314  ret = nullptr;
1315  continue;
1316  }
1317  ret = next;
1318  }
1319 
1320  ret = begin;
1321  // hangle backward
1322  while (ret != nullptr) {
1323  // ok, this is the edge we are looking for
1324  if (ret->getFromNode() == node) {
1325  return ret;
1326  }
1327  const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1328  if (nedges.size() != 1) {
1329  // too many edges follow
1330  ret = nullptr;
1331  continue;
1332  }
1333  NBEdge* next = nedges[0];
1334  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1335  // ok, another edge is next...
1336  ret = nullptr;
1337  continue;
1338  }
1339  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1340  ret = nullptr;
1341  continue;
1342  }
1343  ret = next;
1344  }
1345  return nullptr;
1346 }
1347 
1348 
1349 NBEdge*
1350 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName, NBNode* node) {
1351  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1352  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1353  if (edge == nullptr) {
1354  WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1355  }
1356  return getNamedEdgeContinuating(edge, node);
1357 }
1358 
1359 
1360 NBEdge*
1361 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1362  NBNode* node) {
1363  if (myLineParser.know(fieldName1)) {
1364  return getNamedEdgeContinuating(fieldName1, node);
1365  } else {
1366  return getNamedEdgeContinuating(fieldName2, node);
1367  }
1368 }
1369 
1370 
1371 NBEdge*
1373  EdgeVector::const_iterator i;
1374  for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1375  if (ToNode == (*i)->getToNode()) {
1376  return (*i);
1377  }
1378  }
1380  return nullptr;
1381 }
1382 
1383 
1384 double
1385 NIImporter_VISUM::getNamedFloat(const std::string& fieldName) {
1386  std::string value = myLineParser.get(fieldName);
1387  if (StringUtils::endsWith(myLineParser.get(fieldName), "km/h")) {
1388  value = value.substr(0, value.length() - 4);
1389  }
1390  return StringUtils::toDouble(value);
1391 }
1392 
1393 
1394 double
1395 NIImporter_VISUM::getNamedFloat(const std::string& fieldName, double defaultValue) {
1396  try {
1397  return StringUtils::toDouble(myLineParser.get(fieldName));
1398  } catch (...) {
1399  return defaultValue;
1400  }
1401 }
1402 
1403 
1404 double
1405 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) {
1406  if (myLineParser.know(fieldName1)) {
1407  return getNamedFloat(fieldName1);
1408  } else {
1409  return getNamedFloat(fieldName2);
1410  }
1411 }
1412 
1413 
1414 double
1415 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1416  double defaultValue) {
1417  if (myLineParser.know(fieldName1)) {
1418  return getNamedFloat(fieldName1, defaultValue);
1419  } else {
1420  return getNamedFloat(fieldName2, defaultValue);
1421  }
1422 }
1423 
1424 
1425 std::string
1426 NIImporter_VISUM::getNamedString(const std::string& fieldName) {
1428 }
1429 
1430 
1431 std::string
1432 NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1433  const std::string& fieldName2) {
1434  if (myLineParser.know(fieldName1)) {
1435  return getNamedString(fieldName1);
1436  } else {
1437  return getNamedString(fieldName2);
1438  }
1439 }
1440 
1441 
1442 
1443 
1444 
1445 
1446 NBNode*
1447 NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1448  bool isSource) {
1449  // get the district
1451  if (dist == nullptr) {
1452  return nullptr;
1453  }
1454  // build the id
1455  std::string nid;
1456  nid = id + "-" + dest->getID();
1457  if (!isSource) {
1458  nid = "-" + nid;
1459  }
1460  // insert the node
1461  if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1462  WRITE_ERROR("Could not build connector node '" + nid + "'.");
1463  }
1464  // return the node
1465  return myNetBuilder.getNodeCont().retrieve(nid);
1466 }
1467 
1468 
1469 bool
1471  if (from == nullptr) {
1472  WRITE_ERROR(" The from-node was not found within the net");
1473  }
1474  if (to == nullptr) {
1475  WRITE_ERROR(" The to-node was not found within the net");
1476  }
1477  if (from == to) {
1478  WRITE_ERROR(" Both nodes are the same");
1479  }
1480  return from != nullptr && to != nullptr && from != to;
1481 }
1482 
1483 bool
1485  return (edge->getID().length() > node->getID().length() + 1
1486  && (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()));
1487 }
1488 
1489 void
1490 NIImporter_VISUM::loadLanguage(const std::string& file) {
1491  std::ifstream strm(file.c_str());
1492  if (!strm.good()) {
1493  throw ProcessError("Could not load VISUM language map from '" + file + "'.");
1494  }
1495  while (strm.good()) {
1496  std::string keyDE;
1497  std::string keyNew;
1498  strm >> keyDE;
1499  strm >> keyNew;
1500  if (KEYS.hasString(keyDE)) {
1501  VISUM_KEY key = KEYS.get(keyDE);
1502  KEYS.remove(keyDE, key);
1503  KEYS.insert(keyNew, key);
1504  } else if (keyDE != "") {
1505  WRITE_WARNING("Unknown entry '" + keyDE + "' in VISUM language map");
1506  }
1507  }
1508 
1509 }
1510 
1511 
1512 /****************************************************************************/
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:278
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:280
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:279
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
#define TIME2STEPS(x)
Definition: SUMOTime.h:55
long long int SUMOTime
Definition: SUMOTime.h:31
@ 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
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
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:275
void reduceGeometries(const double minDist)
Definition: NBEdgeCont.cpp:773
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:178
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:586
The representation of a single edge during network building.
Definition: NBEdge.h:91
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:913
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false)
Adds a connection to another edge.
Definition: NBEdge.cpp:985
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:563
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:3627
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:3402
const std::string & getID() const
Definition: NBEdge.h:1423
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:516
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:907
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:490
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:716
@ VALIDATED
The connection was computed and validated.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:324
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:327
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 length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:1019
void setAsMacroscopicConnector()
Definition: NBEdge.h:1052
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:509
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
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:168
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:158
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:148
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:153
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:163
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:90
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:119
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:1651
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:259
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:254
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
Definition: NBNode.cpp:1657
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:2303
bool markEdgeTypeAsSet(const std::string &id, const SumoXMLAttr attr)
Marks an attribute of a edgeType as set.
Definition: NBTypeCont.cpp:287
double getEdgeTypeSpeed(const std::string &edgeType) const
Returns the maximal velocity for the given edgeType [m/s].
Definition: NBTypeCont.cpp:451
int getEdgeTypePriority(const std::string &edgeType) const
Returns the priority for the given edgeType.
Definition: NBTypeCont.cpp:457
int getEdgeTypeNumLanes(const std::string &edgeType) const
Returns the number of lanes for the given edgeType.
Definition: NBTypeCont.cpp:445
SVCPermissions getEdgeTypePermissions(const std::string &edgeType) const
Returns allowed vehicle classes for the given edgeType.
Definition: NBTypeCont.cpp:495
void insertEdgeType(const std::string &id, int numLanes, double maxSpeed, int prio, SVCPermissions permissions, double width, bool oneWayIsDefault, double sidewalkWidth, double bikeLaneWidth, double widthResolution, double maxWidth, double minWidth)
Adds a edgeType into the list.
Definition: NBTypeCont.cpp:173
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
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:73
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:58
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
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
void remove(const std::string str, const T key)
bool hasString(const std::string &str) const
const std::string & getString(const T key) 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 double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
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.