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.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
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 #include <netbuild/NBNetBuilder.h>
34 #include <netbuild/NBPTStop.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  { "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 // ---------------------------------------------------------------------------
97 void
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 
151  addParser("FAHRSTREIFEN", &NIImporter_VISUM::parse_Lanes);
153 
154 
155  // set4
156  // two types of lsa
159  // two types of knotenzulsa
163  // two types of signalgruppe
164  addParser("LSASIGNALGRUPPE", &NIImporter_VISUM::parse_SignalGroups);
166  // three types of ABBZULSASIGNALGRUPPE
167  addParser("ABBZULSASIGNALGRUPPE", &NIImporter_VISUM::parse_TurnsToSignalGroups);
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 
191 void
192 NIImporter_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 
201 void
203  // open the file
205  throw ProcessError(TLF("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 {
242  myLineParser.parseLine(line);
243  try {
244  myCurrentID = "<unknown>";
245  (this->*(*i).function)();
246  } catch (OutOfBoundsException&) {
247  WRITE_ERRORF(TL("Too short value line in % occurred."), (*i).name);
248  } catch (NumberFormatException&) {
249  WRITE_ERRORF(TL("A value in % should be numeric but is not (id='%')."), (*i).name, myCurrentID);
250  } catch (UnknownElement& e) {
251  WRITE_ERRORF(TL("One of the needed values ('%') is missing in %."), std::string(e.what()), (*i).name);
252  }
253  }
254  }
255  // close single reader processing
257  }
258  myNetBuilder.getEdgeCont().reduceGeometries(POSITION_EPS);
259 
260  // build traffic lights
261  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
262  j->second->build(myNetBuilder.getEdgeCont(), myNetBuilder.getTLLogicCont());
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 
274 void
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 
282 void
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 
312 void
314  // get the id
316  // get the position
319  Position pos(x, y);
321  WRITE_ERRORF(TL("Unable to project coordinates for node %."), myCurrentID);
322  return;
323  }
324  // add to the list
326  WRITE_ERRORF(TL("Duplicate node occurred ('%')."), myCurrentID);
327  }
328 }
329 
330 
331 void
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_ERRORF(TL("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_ERRORF(TL("Duplicate district occurred ('%')."), myCurrentID);
351  delete district;
352  return;
353  }
355  long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
356  myShapeDistrictMap[flaecheID] = district;
357  }
358 }
359 
360 
361 void
366  Position pos(x, y);
367  if (!NBNetBuilder::transformCoordinate(pos, false)) {
368  WRITE_ERRORF(TL("Unable to project coordinates for point %."), toString(id));
369  return;
370  }
371  myPoints[id] = pos;
372 }
373 
374 
375 void
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) {
403  speed = myNetBuilder.getTypeCont().getEdgeTypeSpeed(type);
404  }
405 
406  // get the information whether the edge is a one-way
407  bool oneway = myLineParser.know("Einbahn")
408  ? StringUtils::toBool(myLineParser.get("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_ERRORF(TL("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_ERRORF(TL("Duplicate edge occurred ('%')."), myCurrentID);
476  }
477  }
478  myTouchedEdges.push_back(myCurrentID);
479 }
480 
481 
482 void
487  myEdges[id] = std::make_pair(from, to);
488 }
489 
490 
491 void
493  long long int flaecheID = StringUtils::toLong(myLineParser.get(KEYS.getString(VISUM_SURFACEID)));
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 
502 void
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 
537 void
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_WARNINGF(TL("Incoming connector '%' will not be build - would be not connected to network."), id);
581  } else {
582  NBNode* src = buildDistrictNode(bez, dest, true);
583  if (src == nullptr) {
584  WRITE_ERRORF(TL("The district '%' could not be built."), bez);
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_ERRORF(TL("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_WARNINGF(TL("Outgoing connector '%' will not be build - would be not connected to network."), id);
615  } else {
616  NBNode* src = buildDistrictNode(bez, dest, false);
617  if (src == nullptr) {
618  WRITE_ERRORF(TL("The district '%' could not be built."), bez);
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_ERRORF(TL("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 
641 void
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_WARNINGF(TL("There is no edge from node '%' to node '%'."), from->getID(), via->getID());
666  }
667  return;
668  }
669  if (dest == nullptr) {
670  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
671  WRITE_WARNINGF(TL("There is no edge from node '%' to node '%'."), via->getID(), to->getID());
672  }
673  return;
674  }
675  // both edges found
676  // set them into the edge
677  src->addEdge2EdgeConnection(dest);
678  }
679 }
680 
681 
682 void
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_ERRORF(TL("Error in geometry description from node '%' to node '%'."), from->getID(), to->getID());
699  return;
700  }
701  Position pos(x, y);
703  WRITE_ERRORF(TL("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_WARNINGF(TL("There is no edge from node '%' to node '%'."), from->getID(), to->getID());
721  }
722  }
723 }
724 
725 
726 void
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_ERRORF(TL("A lane number for edge '%' is not numeric (%)."), edge->getID(), laneS);
758  return;
759  }
760  lane -= 1;
761  if (lane < 0) {
762  WRITE_ERRORF(TL("A lane number for edge '%' is not positive (%)."), edge->getID(), 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_ERRORF(TL("A lane length for edge '%' is not numeric (%)."), edge->getID(), lengthS);
782  return;
783  }
784  if (length < 0) {
785  WRITE_ERRORF(TL("A lane length for edge '%' is not positive (%)."), edge->getID(), 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_WARNINGF(TL("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(TL("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 
874 void
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 
888 void
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 
908 void
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_ERRORF(TL("Could not find TLS '%' for setting the signal group."), LSAid);
918  return;
919  }
920  myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, startTime, endTime, yellowTime);
921 }
922 
923 
924 void
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 
982 void
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_ERRORF(TL("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_ERRORF(TL("Unknown are for area part '%'."), myCurrentID);
1008  return;
1009  }
1010 
1011  const std::vector<long long int>& areas = mySubPartsAreas.find(id)->second;
1012  for (std::vector<long long int>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
1013  NBDistrict* d = myShapeDistrictMap[*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 
1031 void
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_ERRORF(TL("A from-lane number for edge '%' is not numeric (%)."), fromEdge->getID(), fromLaneS);
1108  return;
1109  }
1110  fromLane -= 1;
1111  if (fromLane < 0) {
1112  WRITE_ERRORF(TL("A from-lane number for edge '%' is not positive (%)."), fromEdge->getID(), 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_ERRORF(TL("A to-lane number for edge '%' is not numeric (%)."), toEdge->getID(), toLaneS);
1122  return;
1123  }
1124  toLane -= 1;
1125  if (toLane < 0) {
1126  WRITE_ERRORF(TL("A to-lane number for edge '%' is not positive (%)."), toEdge->getID(), 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_ERRORF(TL("A from-lane number for edge '%' is larger than the edge's lane number (%)."), fromEdge->getID(), fromLaneS);
1143  return;
1144  }
1145  if ((int) toEdge->getNumLanes() <= toLane) {
1146  WRITE_ERRORF(TL("A to-lane number for edge '%' is larger than the edge's lane number (%)."), toEdge->getID(), toLaneS);
1147  return;
1148  }
1149  //
1150  fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::Lane2LaneInfoType::VALIDATED);
1151 }
1152 
1153 
1157  SVCPermissions permissions = getPermissions(KEYS.getString(VISUM_TYPES), true);
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 information"), id);
1165  } else {
1167  if (edge == nullptr) {
1168  WRITE_WARNINGF(TL("Ignoring stopping place '%' with invalid edge reference '%'"), id, edgeID);
1169  return;
1170  } else if (from != nullptr) {
1171  if (edge->getToNode() == from) {
1172  NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1173  if (edge2 == nullptr) {
1174  WRITE_WARNINGF(TL("Could not find edge with from-node '%' and base id '%' for stopping place '%'"), from->getID(), edge->getID(), id);
1175  } else {
1176  edge = edge2;
1177  }
1178  } else if (edge->getFromNode() != from) {
1179  WRITE_WARNINGF(TL("Unexpected from-node '%' for edge '%' of stopping place '%'"), from->getID(), edge->getID(), id);
1180  }
1181  } else {
1182  if (edge->getFromNode() == to) {
1183  NBEdge* edge2 = myNetBuilder.getEdgeCont().retrieve("-" + edge->getID());
1184  if (edge2 == nullptr) {
1185  WRITE_WARNINGF(TL("Could not find edge with to-node '%' and base id '%' for stopping place '%'"), to->getID(), edge->getID(), id);
1186  } else {
1187  edge = edge2;
1188  }
1189  } else if (edge->getToNode() != to) {
1190  WRITE_WARNINGF(TL("Unexpected to-node '%' for edge '%' of stopping place '%'"), to->getID(), edge->getID(), id);
1191  }
1192  }
1195  Position pos = edge->getGeometry().positionAtOffset(edge->getLength() * relPos);
1196 
1197  const double length = OptionsCont::getOptions().getFloat("osm.stop-output.length");
1198  std::shared_ptr<NBPTStop> ptStop = std::make_shared<NBPTStop>(id, pos, edge->getID(), edge->getID(), length, name, permissions);
1199  myNetBuilder.getPTStopCont().insert(ptStop);
1200  }
1201 }
1202 
1203 
1204 double
1205 NIImporter_VISUM::getWeightedFloat(const std::string& name, const std::string& suffix) {
1206  try {
1207  std::string val = myLineParser.get(name);
1208  if (val.find(suffix) != std::string::npos) {
1209  val = val.substr(0, val.find(suffix));
1210  }
1211  return StringUtils::toDouble(val);
1212  } catch (...) {}
1213  return -1;
1214 }
1215 
1216 
1217 double
1218 NIImporter_VISUM::getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix) {
1219  double result = getWeightedFloat(name, suffix);
1220  if (result != -1) {
1221  return result;
1222  } else {
1223  return getWeightedFloat(name2, suffix);
1224  }
1225 }
1226 
1227 bool
1228 NIImporter_VISUM::getWeightedBool(const std::string& name) {
1229  try {
1230  return StringUtils::toBool(myLineParser.get(name));
1231  } catch (...) {}
1232  try {
1233  return StringUtils::toBool(myLineParser.get((name + "(IV)")));
1234  } catch (...) {}
1235  return false;
1236 }
1237 
1239 NIImporter_VISUM::getPermissions(const std::string& name, bool warn, SVCPermissions unknown) {
1240  SVCPermissions result = 0;
1241  for (std::string v : StringTokenizer(myLineParser.get(name), ",").getVector()) {
1242  // common values in english and german
1243  // || v == "funiculaire-telecabine" ---> no matching
1245  if (v == "bus" || v == "tcsp" || v == "acces tc" || v == "Accès tc" || v == "accès tc") {
1246  result |= SVC_BUS;
1247  } else if (v == "walk" || v == "w" || v == "f" || v == "ped" || v == "map") {
1248  result |= SVC_PEDESTRIAN;
1249  } else if (v == "l" || v == "lkw" || v == "h" || v == "hgv" || v == "lw" || v == "truck" || v == "tru" || v == "pl") {
1250  result |= SVC_TRUCK;
1251  } else if (v == "b" || v == "bike" || v == "velo") {
1252  result |= SVC_BICYCLE;
1253  } else if (v == "train" || v == "rail") {
1254  result |= SVC_RAIL;
1255  } else if (v == "tram") {
1256  result |= SVC_TRAM;
1257  } else if (v == "p" || v == "pkw" || v == "car" || v == "c" || v == "vp" || v == "2rm") {
1258  result |= SVC_PASSENGER;
1259  } else {
1260  if (warn) {
1261  WRITE_WARNINGF("Encountered unknown vehicle category '" + v + "' in type '%'", myLineParser.get(KEYS.getString(VISUM_NO)));
1262  }
1263  result |= unknown;
1264  }
1265  }
1266  return result;
1267 }
1268 
1269 NBNode*
1270 NIImporter_VISUM::getNamedNode(const std::string& fieldName) {
1271  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1272  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1273  if (node == nullptr) {
1274  WRITE_ERRORF(TL("The node '%' is not known."), nodeS);
1275  }
1276  return node;
1277 }
1278 
1279 NBNode*
1280 NIImporter_VISUM::getNamedNodeSecure(const std::string& fieldName, NBNode* fallback) {
1281  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1282  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1283  if (node == nullptr) {
1284  return fallback;
1285  }
1286  return node;
1287 }
1288 
1289 
1290 NBNode*
1291 NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) {
1292  if (myLineParser.know(fieldName1)) {
1293  return getNamedNode(fieldName1);
1294  } else {
1295  return getNamedNode(fieldName2);
1296  }
1297 }
1298 
1299 
1300 NBEdge*
1301 NIImporter_VISUM::getNamedEdge(const std::string& fieldName) {
1302  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1303  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1304  if (edge == nullptr) {
1305  WRITE_ERRORF(TL("The edge '%' is not known."), edgeS);
1306  }
1307  return edge;
1308 }
1309 
1310 
1311 NBEdge*
1312 NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) {
1313  if (myLineParser.know(fieldName1)) {
1314  return getNamedEdge(fieldName1);
1315  } else {
1316  return getNamedEdge(fieldName2);
1317  }
1318 }
1319 
1320 
1321 
1322 NBEdge*
1324  std::string sid;
1325  if (edge->getID()[0] == '-') {
1326  sid = edge->getID().substr(1);
1327  } else {
1328  sid = "-" + edge->getID();
1329  }
1330  if (sid.find('_') != std::string::npos) {
1331  sid = sid.substr(0, sid.find('_'));
1332  }
1334 }
1335 
1336 
1337 NBEdge*
1339  if (begin == nullptr) {
1340  return nullptr;
1341  }
1342  NBEdge* ret = begin;
1343  std::string edgeID = ret->getID();
1344  // hangle forward
1345  while (ret != nullptr) {
1346  // ok, this is the edge we are looking for
1347  if (ret->getToNode() == node) {
1348  return ret;
1349  }
1350  const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1351  if (nedges.size() != 1) {
1352  // too many edges follow
1353  ret = nullptr;
1354  continue;
1355  }
1356  NBEdge* next = nedges[0];
1357  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1358  // ok, another edge is next...
1359  ret = nullptr;
1360  continue;
1361  }
1362  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1363  ret = nullptr;
1364  continue;
1365  }
1366  ret = next;
1367  }
1368 
1369  ret = begin;
1370  // hangle backward
1371  while (ret != nullptr) {
1372  // ok, this is the edge we are looking for
1373  if (ret->getFromNode() == node) {
1374  return ret;
1375  }
1376  const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1377  if (nedges.size() != 1) {
1378  // too many edges follow
1379  ret = nullptr;
1380  continue;
1381  }
1382  NBEdge* next = nedges[0];
1383  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1384  // ok, another edge is next...
1385  ret = nullptr;
1386  continue;
1387  }
1388  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1389  ret = nullptr;
1390  continue;
1391  }
1392  ret = next;
1393  }
1394  return nullptr;
1395 }
1396 
1397 
1398 NBEdge*
1399 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName, NBNode* node) {
1400  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1401  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1402  if (edge == nullptr) {
1403  WRITE_ERRORF(TL("The edge '%' is not known."), edgeS);
1404  }
1405  return getNamedEdgeContinuating(edge, node);
1406 }
1407 
1408 
1409 NBEdge*
1410 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1411  NBNode* node) {
1412  if (myLineParser.know(fieldName1)) {
1413  return getNamedEdgeContinuating(fieldName1, node);
1414  } else {
1415  return getNamedEdgeContinuating(fieldName2, node);
1416  }
1417 }
1418 
1419 
1420 NBEdge*
1422  EdgeVector::const_iterator i;
1423  for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1424  if (ToNode == (*i)->getToNode()) {
1425  return (*i);
1426  }
1427  }
1429  return nullptr;
1430 }
1431 
1432 
1433 double
1434 NIImporter_VISUM::getNamedFloat(const std::string& fieldName) {
1435  std::string value = myLineParser.get(fieldName);
1436  if (StringUtils::endsWith(myLineParser.get(fieldName), "km/h")) {
1437  value = value.substr(0, value.length() - 4);
1438  }
1439  return StringUtils::toDouble(value);
1440 }
1441 
1442 
1443 double
1444 NIImporter_VISUM::getNamedFloat(const std::string& fieldName, double defaultValue) {
1445  try {
1446  return StringUtils::toDouble(myLineParser.get(fieldName));
1447  } catch (...) {
1448  return defaultValue;
1449  }
1450 }
1451 
1452 
1453 double
1454 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) {
1455  if (myLineParser.know(fieldName1)) {
1456  return getNamedFloat(fieldName1);
1457  } else {
1458  return getNamedFloat(fieldName2);
1459  }
1460 }
1461 
1462 
1463 double
1464 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1465  double defaultValue) {
1466  if (myLineParser.know(fieldName1)) {
1467  return getNamedFloat(fieldName1, defaultValue);
1468  } else {
1469  return getNamedFloat(fieldName2, defaultValue);
1470  }
1471 }
1472 
1473 
1474 std::string
1475 NIImporter_VISUM::getNamedString(const std::string& fieldName) {
1477 }
1478 
1479 
1480 std::string
1481 NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1482  const std::string& fieldName2) {
1483  if (myLineParser.know(fieldName1)) {
1484  return getNamedString(fieldName1);
1485  } else {
1486  return getNamedString(fieldName2);
1487  }
1488 }
1489 
1490 
1491 
1492 
1493 
1494 
1495 NBNode*
1496 NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1497  bool isSource) {
1498  // get the district
1500  if (dist == nullptr) {
1501  return nullptr;
1502  }
1503  // build the id
1504  std::string nid;
1505  nid = id + "-" + dest->getID();
1506  if (!isSource) {
1507  nid = "-" + nid;
1508  }
1509  // insert the node
1510  if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1511  WRITE_ERRORF(TL("Could not build connector node '%'."), nid);
1512  }
1513  // return the node
1514  return myNetBuilder.getNodeCont().retrieve(nid);
1515 }
1516 
1517 
1518 bool
1520  if (from == nullptr) {
1521  WRITE_ERROR(TL(" The from-node was not found within the net"));
1522  }
1523  if (to == nullptr) {
1524  WRITE_ERROR(TL(" The to-node was not found within the net"));
1525  }
1526  if (from == to) {
1527  WRITE_ERROR(TL(" Both nodes are the same"));
1528  }
1529  return from != nullptr && to != nullptr && from != to;
1530 }
1531 
1532 bool
1534  return (edge->getID().length() > node->getID().length() + 1
1535  && (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()));
1536 }
1537 
1538 void
1539 NIImporter_VISUM::loadLanguage(const std::string& file) {
1540  std::ifstream strm(file.c_str());
1541  if (!strm.good()) {
1542  throw ProcessError(TLF("Could not load VISUM language map from '%'.", file));
1543  }
1544  while (strm.good()) {
1545  std::string keyDE;
1546  std::string keyNew;
1547  strm >> keyDE;
1548  strm >> keyNew;
1549  if (KEYS.hasString(keyDE)) {
1550  VISUM_KEY key = KEYS.get(keyDE);
1551  KEYS.remove(keyDE, key);
1552  KEYS.insert(keyNew, key);
1553  } else if (keyDE != "") {
1554  WRITE_WARNINGF(TL("Unknown entry '%' in VISUM language map"), keyDE);
1555  }
1556  }
1557 
1558 }
1559 
1560 
1561 /****************************************************************************/
long long int SUMOTime
Definition: GUI.h:35
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:304
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:300
#define TLF(string,...)
Definition: MsgHandler.h:317
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:299
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
#define TIME2STEPS(x)
Definition: SUMOTime.h:57
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ 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
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:223
unsigned long getPosition()
Returns the current position within the file.
Definition: LineReader.cpp:188
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
Definition: LineReader.cpp:68
bool setFile(const std::string &file)
Reinitialises the reader for reading from the given file.
Definition: LineReader.cpp:180
int getLineNumber()
Definition: LineReader.h:143
void reinit()
Reinitialises the reading (of the previous file)
Definition: LineReader.cpp:194
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
Definition: LineReader.cpp:52
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:281
void reduceGeometries(const double minDist)
Definition: NBEdgeCont.cpp:813
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:182
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:604
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:985
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:589
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:4269
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:351
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:4002
bool addEdge2EdgeConnection(NBEdge *dest, bool overrideRemoval=false, SVCPermissions permission=SVC_UNSPECIFIED)
Adds a connection to another edge.
Definition: NBEdge.cpp:1063
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:1098
const std::string & getID() const
Definition: NBEdge.h:1522
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:542
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:973
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:516
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:779
@ VALIDATED
The connection was computed and validated.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:342
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:345
void setAsMacroscopicConnector()
Definition: NBEdge.h:1123
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:535
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:159
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:149
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:139
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
Definition: NBNetBuilder.h:164
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:144
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:154
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:87
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:116
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:1847
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:273
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:268
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
Definition: NBNode.cpp:1853
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:2623
bool insert(std::shared_ptr< NBPTStop > ptStop, bool floating=false)
Inserts a node into the map.
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:503
int getEdgeTypePriority(const std::string &edgeType) const
Returns the priority for the given edgeType.
Definition: NBTypeCont.cpp:514
int getEdgeTypeNumLanes(const std::string &edgeType) const
Returns the number of lanes for the given edgeType.
Definition: NBTypeCont.cpp:497
SVCPermissions getEdgeTypePermissions(const std::string &edgeType) const
Returns allowed vehicle classes for the given edgeType.
Definition: NBTypeCont.cpp:552
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:60
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
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 std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
Definition: StringUtils.cpp:77
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:87
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.