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-2018 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
18 // A VISUM network importer
19 /****************************************************************************/
20 
21 
22 // ===========================================================================
23 // included modules
24 // ===========================================================================
25 #include <config.h>
26 
27 #include <string>
30 #include <utils/common/ToString.h>
34 #include <netbuild/NBDistrict.h>
35 
36 #include <netbuild/NBNetBuilder.h>
37 #include "NILoader.h"
38 #include "NIImporter_VISUM.h"
39 
40 
41 // ===========================================================================
42 // method definitions
43 // ===========================================================================
44 // ---------------------------------------------------------------------------
45 // static methods (interface in this case)
46 // ---------------------------------------------------------------------------
47 void
49  // check whether the option is set (properly)
50  if (!oc.isSet("visum-file")) {
51  return;
52  }
53  // build the handler
54  NIImporter_VISUM loader(nb, oc.getString("visum-file"),
55  NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")),
56  oc.getBool("visum.use-type-priority"));
57  loader.load();
58 }
59 
60 
61 
62 // ---------------------------------------------------------------------------
63 // loader methods
64 // ---------------------------------------------------------------------------
66  const std::string& file,
67  NBCapacity2Lanes capacity2Lanes,
68  bool useVisumPrio)
69  : myNetBuilder(nb), myFileName(file),
70  myCapacity2Lanes(capacity2Lanes), myUseVisumPrio(useVisumPrio) {
71  // the order of process is important!
72  // set1
78 
79  // set2
80  // two types of "strecke"
84 
85  // set3
87  // two types of "abbieger"
88  addParser("ABBIEGEBEZIEHUNG", &NIImporter_VISUM::parse_Turns);
90 
92  addParser("FAHRSTREIFEN", &NIImporter_VISUM::parse_Lanes);
93  addParser("FLAECHENELEMENT", &NIImporter_VISUM::parse_PartOfArea);
94 
95  // set4
96  // two types of lsa
99  // two types of knotenzulsa
103  // two types of signalgruppe
104  addParser("LSASIGNALGRUPPE", &NIImporter_VISUM::parse_SignalGroups);
106  // three types of ABBZULSASIGNALGRUPPE
107  addParser("ABBZULSASIGNALGRUPPE", &NIImporter_VISUM::parse_TurnsToSignalGroups);
108  addParser("SIGNALGRUPPEZUABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
109  addParser("SIGNALGRUPPEZUFSABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
110 
111  addParser("TEILFLAECHENELEMENT", &NIImporter_VISUM::parse_AreaSubPartElement);
112 
113  // two types of LSAPHASE
116 
117  addParser("LSASIGNALGRUPPEZULSAPHASE", &NIImporter_VISUM::parse_SignalGroupsToPhases);
118  addParser("FAHRSTREIFENABBIEGER", &NIImporter_VISUM::parse_LanesConnections);
119 }
120 
121 
123  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
124  delete j->second;
125  }
126 }
127 
128 
129 void
130 NIImporter_VISUM::addParser(const std::string& name, ParsingFunction function) {
131  TypeParser p;
132  p.name = name;
133  p.function = function;
134  p.position = -1;
135  mySingleDataParsers.push_back(p);
136 }
137 
138 
139 void
141  // open the file
143  throw ProcessError("Can not open visum-file '" + myFileName + "'.");
144  }
145  // scan the file for data positions
146  while (myLineReader.hasMore()) {
147  std::string line = myLineReader.readLine();
148  if (line.length() > 0 && line[0] == '$') {
149  ParserVector::iterator i;
150  for (i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
151  std::string dataName = "$" + (*i).name + ":";
152  if (line.substr(0, dataName.length()) == dataName) {
153  (*i).position = myLineReader.getPosition();
154  (*i).pattern = line.substr(dataName.length());
155  WRITE_MESSAGE("Found: " + dataName + " at " + toString<int>(myLineReader.getPosition()));
156  }
157  }
158  }
159  }
160  // go through the parsers and process all entries
161  for (ParserVector::iterator i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
162  if ((*i).position < 0) {
163  // do not process using parsers for which no information was found
164  continue;
165  }
166  // ok, the according information is stored in the file
167  PROGRESS_BEGIN_MESSAGE("Parsing " + (*i).name);
168  // reset the line reader and let it point to the begin of the according data field
170  myLineReader.setPos((*i).position);
171  // prepare the line parser
172  myLineParser.reinit((*i).pattern);
173  // read
174  bool singleDataEndFound = false;
175  while (myLineReader.hasMore() && !singleDataEndFound) {
176  std::string line = myLineReader.readLine();
177  if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
178  singleDataEndFound = true;
179  } else {
180  myLineParser.parseLine(line);
181  try {
182  myCurrentID = "<unknown>";
183  (this->*(*i).function)();
184  } catch (OutOfBoundsException&) {
185  WRITE_ERROR("Too short value line in " + (*i).name + " occurred.");
186  } catch (NumberFormatException&) {
187  WRITE_ERROR("A value in " + (*i).name + " should be numeric but is not (id='" + myCurrentID + "').");
188  } catch (UnknownElement& e) {
189  WRITE_ERROR("One of the needed values ('" + std::string(e.what()) + "') is missing in " + (*i).name + ".");
190  }
191  }
192  }
193  // close single reader processing
195  }
196  // build traffic lights
197  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
198  j->second->build(myNetBuilder.getEdgeCont(), myNetBuilder.getTLLogicCont());
199  }
200  // build district shapes
201  for (std::map<NBDistrict*, PositionVector>::const_iterator k = myDistrictShapes.begin(); k != myDistrictShapes.end(); ++k) {
202  (*k).first->addShape((*k).second);
203  }
204 }
205 
206 
207 
208 
209 
210 void
212  std::string name = myLineParser.know("VSysCode") ? myLineParser.get("VSysCode").c_str() : myLineParser.get("CODE").c_str();
213  std::string type = myLineParser.know("VSysMode") ? myLineParser.get("VSysMode").c_str() : myLineParser.get("Typ").c_str();
214  myVSysTypes[name] = type;
215 }
216 
217 
218 void
220  // get the id
222  // get the maximum speed
223  double speed = getWeightedFloat2("v0-IV", "V0IV", "km/h");
224  if (speed == 0) {
225  // unlimited speed
226  speed = 3600;
227  } else if (speed < 0) {
228  WRITE_ERROR("Type '" + myCurrentID + "' has speed " + toString(speed));
229  }
230  // get the permissions
231  SVCPermissions permissions = getPermissions("VSYSSET", true);
232  // get the priority
233  const int priority = 1000 - TplConvert::_2int(myLineParser.get("Rang").c_str());
234  // try to retrieve the number of lanes
235  const int numLanes = myCapacity2Lanes.get(getNamedFloat("Kap-IV", "KAPIV"));
236  // insert the type
237  myNetBuilder.getTypeCont().insert(myCurrentID, numLanes, speed / (double) 3.6, priority, permissions, NBEdge::UNSPECIFIED_WIDTH, false, NBEdge::UNSPECIFIED_WIDTH, NBEdge::UNSPECIFIED_WIDTH);
243 }
244 
245 
246 void
248  // get the id
250  // get the position
251  double x = getNamedFloat("XKoord");
252  double y = getNamedFloat("YKoord");
253  Position pos(x, y);
255  WRITE_ERROR("Unable to project coordinates for node " + myCurrentID + ".");
256  return;
257  }
258  // add to the list
260  WRITE_ERROR("Duplicate node occurred ('" + myCurrentID + "').");
261  }
262 }
263 
264 
265 void
267  // get the id
269  // get the information whether the source and the destination
270  // connections are weighted
271  //bool sourcesWeighted = getWeightedBool("Proz_Q");
272  //bool destWeighted = getWeightedBool("Proz_Z");
273  // get the node information
274  double x = getNamedFloat("XKoord");
275  double y = getNamedFloat("YKoord");
276  Position pos(x, y);
277  if (!NBNetBuilder::transformCoordinate(pos, false)) {
278  WRITE_ERROR("Unable to project coordinates for district " + myCurrentID + ".");
279  return;
280  }
281  // build the district
282  NBDistrict* district = new NBDistrict(myCurrentID, pos);
283  if (!myNetBuilder.getDistrictCont().insert(district)) {
284  WRITE_ERROR("Duplicate district occurred ('" + myCurrentID + "').");
285  delete district;
286  return;
287  }
288  if (myLineParser.know("FLAECHEID")) {
289  long long int flaecheID = TplConvert::_2long(myLineParser.get("FLAECHEID").c_str());
290  myShapeDistrictMap[flaecheID] = district;
291  }
292 }
293 
294 
295 void
297  long long int id = TplConvert::_2long(myLineParser.get("ID").c_str());
298  double x = TplConvert::_2double(myLineParser.get("XKOORD").c_str());
299  double y = TplConvert::_2double(myLineParser.get("YKOORD").c_str());
300  Position pos(x, y);
301  if (!NBNetBuilder::transformCoordinate(pos, false)) {
302  WRITE_ERROR("Unable to project coordinates for point " + toString(id) + ".");
303  return;
304  }
305  myPoints[id] = pos;
306 }
307 
308 
309 void
311  if (myLineParser.know("VSYSSET") && myLineParser.get("VSYSSET") == "") {
312  // no vehicle allowed; don't add
313  return;
314  }
315  // get the id
317  // get the from- & to-node and validate them
318  NBNode* from = getNamedNode("VonKnot", "VonKnotNr");
319  NBNode* to = getNamedNode("NachKnot", "NachKnotNr");
320  if (!checkNodes(from, to)) {
321  return;
322  }
323  // get the type
324  std::string type = myLineParser.know("Typ") ? myLineParser.get("Typ") : myLineParser.get("TypNr");
325  // get the speed
326  double speed = myNetBuilder.getTypeCont().getSpeed(type);
327  if (!OptionsCont::getOptions().getBool("visum.use-type-speed")) {
328  try {
329  std::string speedS = myLineParser.know("v0-IV") ? myLineParser.get("v0-IV") : myLineParser.get("V0IV");
330  if (speedS.find("km/h") != std::string::npos) {
331  speedS = speedS.substr(0, speedS.find("km/h"));
332  }
333  speed = TplConvert::_2doubleSec(speedS.c_str(), -1);
334  speed = speed / (double) 3.6;
335  } catch (OutOfBoundsException&) {}
336  }
337  if (speed <= 0) {
338  speed = myNetBuilder.getTypeCont().getSpeed(type);
339  }
340 
341  // get the information whether the edge is a one-way
342  bool oneway = myLineParser.know("Einbahn")
343  ? TplConvert::_2bool(myLineParser.get("Einbahn").c_str())
344  : true;
345  // get the number of lanes
346  int nolanes = myNetBuilder.getTypeCont().getNumLanes(type);
347  if (!OptionsCont::getOptions().getBool("visum.recompute-lane-number")) {
348  try {
349  if (!OptionsCont::getOptions().getBool("visum.use-type-laneno")) {
350  nolanes = myLineParser.know("Fahrstreifen")
351  ? TplConvert::_2intSec(myLineParser.get("Fahrstreifen").c_str(), 0)
352  : TplConvert::_2intSec(myLineParser.get("ANZFAHRSTREIFEN").c_str(), 0);
353  }
354  } catch (UnknownElement&) {
355  }
356  } else {
357  double cap = myLineParser.know("KAPIV")
358  ? TplConvert::_2doubleSec(myLineParser.get("KAPIV").c_str(), -1)
359  : TplConvert::_2doubleSec(myLineParser.get("KAP-IV").c_str(), -1);
360  nolanes = myCapacity2Lanes.get(cap);
361  }
362  // check whether the id is already used
363  // (should be the opposite direction)
364  bool oneway_checked = oneway;
366  if (previous != 0) {
367  myCurrentID = '-' + myCurrentID;
369  oneway_checked = false;
370  }
371  if (find(myTouchedEdges.begin(), myTouchedEdges.end(), myCurrentID) != myTouchedEdges.end()) {
372  oneway_checked = false;
373  }
374  std::string tmpid = '-' + myCurrentID;
375  if (find(myTouchedEdges.begin(), myTouchedEdges.end(), tmpid) != myTouchedEdges.end()) {
376  previous = myNetBuilder.getEdgeCont().retrieve(tmpid);
377  if (previous != 0) {
379  }
380  oneway_checked = false;
381  }
382  // add the edge
383  const SVCPermissions permissions = getPermissions("VSYSSET", false, myNetBuilder.getTypeCont().getPermissions(type));
384  int prio = myUseVisumPrio ? myNetBuilder.getTypeCont().getPriority(type) : -1;
385  if (nolanes != 0 && speed != 0) {
386  LaneSpreadFunction lsf = oneway_checked ? LANESPREAD_CENTER : LANESPREAD_RIGHT;
387  // @todo parse name from visum files
388  NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, nolanes, prio,
390  e->setPermissions(permissions);
391  if (!myNetBuilder.getEdgeCont().insert(e)) {
392  delete e;
393  WRITE_ERROR("Duplicate edge occurred ('" + myCurrentID + "').");
394  }
395  }
396  myTouchedEdges.push_back(myCurrentID);
397  // nothing more to do, when the edge is a one-way street
398  if (oneway) {
399  return;
400  }
401  // add the opposite edge
402  myCurrentID = '-' + myCurrentID;
403  if (nolanes != 0 && speed != 0) {
404  LaneSpreadFunction lsf = oneway_checked ? LANESPREAD_CENTER : LANESPREAD_RIGHT;
405  // @todo parse name from visum files
406  NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, nolanes, prio,
408  e->setPermissions(permissions);
409  if (!myNetBuilder.getEdgeCont().insert(e)) {
410  delete e;
411  WRITE_ERROR("Duplicate edge occurred ('" + myCurrentID + "').");
412  }
413  }
414  myTouchedEdges.push_back(myCurrentID);
415 }
416 
417 
418 void
420  long long int id = TplConvert::_2long(myLineParser.get("ID").c_str());
421  long long int from = TplConvert::_2long(myLineParser.get("VONPUNKTID").c_str());
422  long long int to = TplConvert::_2long(myLineParser.get("NACHPUNKTID").c_str());
423  myEdges[id] = std::make_pair(from, to);
424 }
425 
426 
427 void
429  long long int flaecheID = TplConvert::_2long(myLineParser.get("FLAECHEID").c_str());
430  long long int flaechePartID = TplConvert::_2long(myLineParser.get("TFLAECHEID").c_str());
431  if (mySubPartsAreas.find(flaechePartID) == mySubPartsAreas.end()) {
432  mySubPartsAreas[flaechePartID] = std::vector<long long int>();
433  }
434  mySubPartsAreas[flaechePartID].push_back(flaecheID);
435 }
436 
437 
438 void
440  if (OptionsCont::getOptions().getBool("visum.no-connectors")) {
441  // do nothing, if connectors shall not be imported
442  return;
443  }
444  // get the source district
445  std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get("BezNr"));
446  // get the destination node
447  NBNode* dest = getNamedNode("KnotNr");
448  if (dest == 0) {
449  return;
450  }
451  // get the weight of the connection
452  double proz = 1;
453  if (myLineParser.know("Proz") || myLineParser.know("Proz(IV)")) {
454  proz = getNamedFloat("Proz", "Proz(IV)") / 100;
455  }
456  // get the duration to wait (unused)
457 // double retard = -1;
458 // if (myLineParser.know("t0-IV")) {
459 // retard = getNamedFloat("t0-IV", -1);
460 // }
461  // get the type;
462  // use a standard type with a large speed when a type is not given
463  std::string type = myLineParser.know("Typ")
465  : "";
466  // add the connectors as an edge
467  std::string id = bez + "-" + dest->getID();
468  // get the information whether this is a sink or a source
469  std::string dir = myLineParser.get("Richtung");
470  if (dir.length() == 0) {
471  dir = "QZ";
472  }
473  // build the source when needed
474  if (dir.find('Q') != std::string::npos) {
475  const EdgeVector& edges = dest->getOutgoingEdges();
476  bool hasContinuation = false;
477  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
478  if (!(*i)->isMacroscopicConnector()) {
479  hasContinuation = true;
480  }
481  }
482  if (!hasContinuation) {
483  // obviously, there is no continuation on the net
484  WRITE_WARNING("Incoming connector '" + id + "' will not be build - would be not connected to network.");
485  } else {
486  NBNode* src = buildDistrictNode(bez, dest, true);
487  if (src == 0) {
488  WRITE_ERROR("The district '" + bez + "' could not be built.");
489  return;
490  }
491  NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
492  OptionsCont::getOptions().getFloat("visum.connector-speeds"),
493  OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
495  "", LANESPREAD_RIGHT);
497  if (!myNetBuilder.getEdgeCont().insert(edge)) {
498  WRITE_ERROR("A duplicate edge id occurred (ID='" + id + "').");
499  return;
500  }
501  edge = myNetBuilder.getEdgeCont().retrieve(id);
502  if (edge != 0) {
503  myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
504  }
505  }
506  }
507  // build the sink when needed
508  if (dir.find('Z') != std::string::npos) {
509  const EdgeVector& edges = dest->getIncomingEdges();
510  bool hasPredeccessor = false;
511  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
512  if (!(*i)->isMacroscopicConnector()) {
513  hasPredeccessor = true;
514  }
515  }
516  if (!hasPredeccessor) {
517  // obviously, the network is not connected to this node
518  WRITE_WARNING("Outgoing connector '" + id + "' will not be build - would be not connected to network.");
519  } else {
520  NBNode* src = buildDistrictNode(bez, dest, false);
521  if (src == 0) {
522  WRITE_ERROR("The district '" + bez + "' could not be built.");
523  return;
524  }
525  id = "-" + id;
526  NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
527  OptionsCont::getOptions().getFloat("visum.connector-speeds"),
528  OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
530  "", LANESPREAD_RIGHT);
532  if (!myNetBuilder.getEdgeCont().insert(edge)) {
533  WRITE_ERROR("A duplicate edge id occurred (ID='" + id + "').");
534  return;
535  }
536  edge = myNetBuilder.getEdgeCont().retrieve(id);
537  if (edge != 0) {
538  myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
539  }
540  }
541  }
542 }
543 
544 
545 void
547  if (myLineParser.know("VSYSSET") && myLineParser.get("VSYSSET") == "") {
548  // no vehicle allowed; don't add
549  return;
550  }
551  // retrieve the nodes
552  NBNode* from = getNamedNode("VonKnot", "VonKnotNr");
553  NBNode* via = getNamedNode("UeberKnot", "UeberKnotNr");
554  NBNode* to = getNamedNode("NachKnot", "NachKnotNr");
555  if (from == 0 || via == 0 || to == 0) {
556  return;
557  }
558  // all nodes are known
559  std::string type = myLineParser.know("VSysCode")
560  ? myLineParser.get("VSysCode")
561  : myLineParser.get("VSYSSET");
562  if (myVSysTypes.find(type) != myVSysTypes.end() && myVSysTypes.find(type)->second == "IV") {
563  // try to set the turning definition
564  NBEdge* src = from->getConnectionTo(via);
565  NBEdge* dest = via->getConnectionTo(to);
566  // check both
567  if (src == 0) {
568  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
569  WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + via->getID() + "'.");
570  }
571  return;
572  }
573  if (dest == 0) {
574  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
575  WRITE_WARNING("There is no edge from node '" + via->getID() + "' to node '" + to->getID() + "'.");
576  }
577  return;
578  }
579  // both edges found
580  // set them into the edge
581  src->addEdge2EdgeConnection(dest);
582  }
583 }
584 
585 
586 void
588  // get the from- & to-node and validate them
589  NBNode* from = getNamedNode("VonKnot", "VonKnotNr");
590  NBNode* to = getNamedNode("NachKnot", "NachKnotNr");
591  if (!checkNodes(from, to)) {
592  return;
593  }
594  bool failed = false;
595  int index;
596  double x, y;
597  try {
598  index = TplConvert::_2int(myLineParser.get("INDEX").c_str());
599  x = getNamedFloat("XKoord");
600  y = getNamedFloat("YKoord");
601  } catch (NumberFormatException&) {
602  WRITE_ERROR("Error in geometry description from node '" + from->getID() + "' to node '" + to->getID() + "'.");
603  return;
604  }
605  Position pos(x, y);
607  WRITE_ERROR("Unable to project coordinates for node '" + from->getID() + "'.");
608  return;
609  }
610  NBEdge* e = from->getConnectionTo(to);
611  if (e != 0) {
612  e->addGeometryPoint(index, pos);
613  } else {
614  failed = true;
615  }
616  e = to->getConnectionTo(from);
617  if (e != 0) {
618  e->addGeometryPoint(-index, pos);
619  failed = false;
620  }
621  // check whether the operation has failed
622  if (failed) {
623  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
624  WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + to->getID() + "'.");
625  }
626  }
627 }
628 
629 
630 void
632  // The base number of lanes for the edge was already defined in STRECKE
633  // this refines lane specific attribute (width) and optionally introduces splits for additional lanes
634  // It is permitted for KNOTNR to be 0
635  //
636  // get the edge
637  NBEdge* baseEdge = getNamedEdge("STRNR");
638  if (baseEdge == 0) {
639  return;
640  }
641  NBEdge* edge = baseEdge;
642  // get the node
643  NBNode* node = getNamedNodeSecure("KNOTNR");
644  if (node == 0) {
645  node = edge->getToNode();
646  } else {
647  edge = getNamedEdgeContinuating("STRNR", node);
648  }
649  // check
650  if (edge == 0) {
651  return;
652  }
653  // get the lane
654  std::string laneS = myLineParser.know("FSNR")
657  int lane = -1;
658  try {
659  lane = TplConvert::_2int(laneS.c_str());
660  } catch (NumberFormatException&) {
661  WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not numeric (" + laneS + ").");
662  return;
663  }
664  lane -= 1;
665  if (lane < 0) {
666  WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not positive (" + laneS + ").");
667  return;
668  }
669  // get the direction
670  std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
671  int prevLaneNo = baseEdge->getNumLanes();
672  if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
673  // get the last part of the turnaround direction
674  NBEdge* cand = getReversedContinuating(edge, node);
675  if (cand) {
676  edge = cand;
677  }
678  }
679  // get the length
680  std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
681  double length = -1;
682  try {
683  length = TplConvert::_2double(lengthS.c_str());
684  } catch (NumberFormatException&) {
685  WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not numeric (" + lengthS + ").");
686  return;
687  }
688  if (length < 0) {
689  WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not positive (" + lengthS + ").");
690  return;
691  }
692  //
693  if (dirS == "1") {
694  lane -= prevLaneNo;
695  }
696  //
697  if (length == 0) {
698  if ((int) edge->getNumLanes() > lane) {
699  // ok, we know this already...
700  return;
701  }
702  // increment by one
703  edge->incLaneNo(1);
704  } else {
705  // check whether this edge already has been created
706  if (isSplitEdge(edge, node)) {
707  if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
708  if ((int) edge->getNumLanes() > lane) {
709  // ok, we know this already...
710  return;
711  }
712  // increment by one
713  edge->incLaneNo(1);
714  return;
715  }
716  }
717  // nope, we have to split the edge...
718  // maybe it is not the proper edge to split - VISUM seems not to sort the splits...
719  bool mustRecheck = true;
720  double seenLength = 0;
721  while (mustRecheck) {
722  if (isSplitEdge(edge, node)) {
723  // ok, we have a previously created edge here
724  std::string sub = edge->getID();
725  sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
726  sub = sub.substr(1, sub.find('_', 1) - 1);
727  double dist = TplConvert::_2double(sub.c_str());
728  if (dist < length) {
729  seenLength += edge->getLength();
730  if (dirS == "1") {
731  // incoming -> move back
732  edge = edge->getFromNode()->getIncomingEdges()[0];
733  } else {
734  // outgoing -> move forward
735  edge = edge->getToNode()->getOutgoingEdges()[0];
736  }
737  } else {
738  mustRecheck = false;
739  }
740  } else {
741  // we have the center edge - do not continue...
742  mustRecheck = false;
743  }
744  }
745  // compute position
746  Position p;
747  double useLength = length - seenLength;
748  useLength = edge->getLength() - useLength;
749  if (useLength < 0 || useLength > edge->getLength()) {
750  WRITE_WARNING("Could not find split position for edge '" + edge->getID() + "'.");
751  return;
752  }
753  std::string edgeID = edge->getID();
754  p = edge->getGeometry().positionAtOffset(useLength);
755  if (isSplitEdge(edge, node)) {
756  edgeID = edgeID.substr(0, edgeID.find('_'));
757  }
758  NBNode* rn = new NBNode(edgeID + "_" + toString((int) length) + "_" + node->getID(), p);
759  if (!myNetBuilder.getNodeCont().insert(rn)) {
760  throw ProcessError("Ups - could not insert node!");
761  }
762  std::string nid = edgeID + "_" + toString((int) length) + "_" + node->getID();
764  edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
765  NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
766  nedge = nedge->getToNode()->getOutgoingEdges()[0];
767  while (isSplitEdge(edge, node)) {
768  assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
769  nedge->incLaneNo(1);
770  nedge = nedge->getToNode()->getOutgoingEdges()[0];
771  }
772  }
773 }
774 
775 
776 void
779  SUMOTime cycleTime = (SUMOTime) getWeightedFloat2("Umlaufzeit", "UMLZEIT", "s");
780  SUMOTime intermediateTime = (SUMOTime) getWeightedFloat2("StdZwischenzeit", "STDZWZEIT", "s");
781  bool phaseBased = myLineParser.know("PhasenBasiert")
782  ? TplConvert::_2bool(myLineParser.get("PhasenBasiert").c_str())
783  : false;
784  SUMOTime offset = myLineParser.know("ZEITVERSATZ") ? TIME2STEPS(getWeightedFloat("ZEITVERSATZ", "s")) : 0;
785  // add to the list
786  myTLS[myCurrentID] = new NIVisumTL(myCurrentID, cycleTime, offset, intermediateTime, phaseBased);
787 }
788 
789 
790 void
792  std::string node = myLineParser.get("KnotNr").c_str();
793  if (node == "0") {
794  // this is a dummy value which cannot be assigned to
795  return;
796  }
797  std::string trafficLight = myLineParser.get("LsaNr").c_str();
798  // add to the list
800  auto tlIt = myTLS.find(trafficLight);
801  if (n != 0 && tlIt != myTLS.end()) {
802  tlIt->second->addNode(n);
803  } else {
804  WRITE_ERROR("Could not assign" + std::string(n == 0 ? " missing" : "") + " node '" + node
805  + "' to" + std::string(tlIt == myTLS.end() ? " missing" : "") + " traffic light '" + trafficLight + "'");
806  }
807 }
808 
809 
810 void
813  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
814  double startTime = getNamedFloat("GzStart", "GRUENANF");
815  double endTime = getNamedFloat("GzEnd", "GRUENENDE");
816  double yellowTime = myLineParser.know("GELB") ? getNamedFloat("GELB") : -1;
817  // add to the list
818  if (myTLS.find(LSAid) == myTLS.end()) {
819  WRITE_ERROR("Could not find TLS '" + LSAid + "' for setting the signal group.");
820  return;
821  }
822  myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, (SUMOTime) startTime, (SUMOTime) endTime, (SUMOTime) yellowTime);
823 }
824 
825 
826 void
828  // get the id
829  std::string SGid = getNamedString("SGNR", "SIGNALGRUPPENNR");
830  if (!myLineParser.know("LsaNr")) {
832  WRITE_WARNING("Ignoring SIGNALGRUPPEZUFSABBIEGER because LsaNr is not known");
833  return;
834  }
835  std::string LSAid = getNamedString("LsaNr");
836  // nodes
837  NBNode* from = myLineParser.know("VonKnot") ? getNamedNode("VonKnot") : 0;
838  NBNode* via = myLineParser.know("KNOTNR")
839  ? getNamedNode("KNOTNR")
840  : getNamedNode("UeberKnot", "UeberKnotNr");
841  NBNode* to = myLineParser.know("NachKnot") ? getNamedNode("NachKnot") : 0;
842  // edges
843  NBEdge* edg1 = 0;
844  NBEdge* edg2 = 0;
845  if (from == 0 && to == 0) {
846  edg1 = getNamedEdgeContinuating("VONSTRNR", via);
847  edg2 = getNamedEdgeContinuating("NACHSTRNR", via);
848  } else {
849  edg1 = getEdge(from, via);
850  edg2 = getEdge(via, to);
851  }
852  // add to the list
853  NIVisumTL::SignalGroup& SG = myTLS.find(LSAid)->second->getSignalGroup(SGid);
854  if (edg1 != 0 && edg2 != 0) {
855  if (!via->hasIncoming(edg1)) {
856  std::string sid;
857  if (edg1->getID()[0] == '-') {
858  sid = edg1->getID().substr(1);
859  } else {
860  sid = "-" + edg1->getID();
861  }
862  if (sid.find('_') != std::string::npos) {
863  sid = sid.substr(0, sid.find('_'));
864  }
866  }
867  if (!via->hasOutgoing(edg2)) {
868  std::string sid;
869  if (edg2->getID()[0] == '-') {
870  sid = edg2->getID().substr(1);
871  } else {
872  sid = "-" + edg2->getID();
873  }
874  if (sid.find('_') != std::string::npos) {
875  sid = sid.substr(0, sid.find('_'));
876  }
878  }
879  SG.connections().push_back(NBConnection(edg1, edg2));
880  }
881 }
882 
883 
884 void
886  long long int id = TplConvert::_2long(myLineParser.get("TFLAECHEID").c_str());
887  long long int edgeid = TplConvert::_2long(myLineParser.get("KANTEID").c_str());
888  if (myEdges.find(edgeid) == myEdges.end()) {
889  WRITE_ERROR("Unknown edge in TEILFLAECHENELEMENT");
890  return;
891  }
892  std::string dir = myLineParser.get("RICHTUNG");
893 // get index (unused)
894 // std::string indexS = NBHelpers::normalIDRepresentation(myLineParser.get("INDEX"));
895 // int index = -1;
896 // try {
897 // index = TplConvert::_2int(indexS.c_str()) - 1;
898 // } catch (NumberFormatException&) {
899 // WRITE_ERROR("An index for a TEILFLAECHENELEMENT is not numeric (id='" + toString(id) + "').");
900 // return;
901 // }
902  PositionVector shape;
903  shape.push_back(myPoints[myEdges[edgeid].first]);
904  shape.push_back(myPoints[myEdges[edgeid].second]);
905  if (dir.length() > 0 && dir[0] == '1') {
906  shape = shape.reverse();
907  }
908  if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
909  WRITE_ERROR("Unkown are for area part '" + myCurrentID + "'.");
910  return;
911  }
912 
913  const std::vector<long long int>& areas = mySubPartsAreas.find(id)->second;
914  for (std::vector<long long int>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
916  if (d == 0) {
917  continue;
918  }
919  if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
921  }
922  if (dir.length() > 0 && dir[0] == '1') {
923  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
924  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
925  } else {
926  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
927  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
928  }
929  }
930 }
931 
932 
933 void
935  // get the id
936  std::string phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("Nr"));
937  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
938  double startTime = getNamedFloat("GzStart", "GRUENANF");
939  double endTime = getNamedFloat("GzEnd", "GRUENENDE");
940  double yellowTime = myLineParser.know("GELB") ? getNamedFloat("GELB") : -1;
941  myTLS.find(LSAid)->second->addPhase(phaseid, (SUMOTime) startTime, (SUMOTime) endTime, (SUMOTime) yellowTime);
942 }
943 
944 
946  // get the id
947  std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("PsNr"));
948  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
949  std::string SGid = NBHelpers::normalIDRepresentation(myLineParser.get("SGNR"));
950  // insert
951  NIVisumTL* LSA = myTLS.find(LSAid)->second;
952  NIVisumTL::SignalGroup& SG = LSA->getSignalGroup(SGid);
953  NIVisumTL::Phase* PH = LSA->getPhases().find(Phaseid)->second;
954  SG.phases()[Phaseid] = PH;
955 }
956 
957 
959  NBNode* node = 0;
960  NBEdge* fromEdge = 0;
961  NBEdge* toEdge = 0;
962  // get the node and edges depending on network format
963  const std::string nodeID = getNamedString("KNOTNR", "KNOT");
964  if (nodeID == "0") {
965  fromEdge = getNamedEdge("VONSTRNR", "VONSTR");
966  toEdge = getNamedEdge("NACHSTRNR", "NACHSTR");
967  if (fromEdge == 0) {
968  return;
969  }
970  node = fromEdge->getToNode();
971  WRITE_WARNING("Ignoring lane-to-lane connection (not yet implemented for this format version)");
972  return;
973  } else {
974  node = getNamedNode("KNOTNR", "KNOT");
975  if (node == 0) {
976  return;
977  }
978  fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node);
979  toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node);
980  }
981  if (fromEdge == 0 || toEdge == 0) {
982  return;
983  }
984 
985  int fromLaneOffset = 0;
986  if (!node->hasIncoming(fromEdge)) {
987  fromLaneOffset = fromEdge->getNumLanes();
988  fromEdge = getReversedContinuating(fromEdge, node);
989  } else {
990  fromEdge = getReversedContinuating(fromEdge, node);
991  NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_')));
992  fromLaneOffset = tmp->getNumLanes();
993  }
994 
995  int toLaneOffset = 0;
996  if (!node->hasOutgoing(toEdge)) {
997  toLaneOffset = toEdge->getNumLanes();
998  toEdge = getReversedContinuating(toEdge, node);
999  } else {
1000  NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_')));
1001  toLaneOffset = tmp->getNumLanes();
1002  }
1003  // get the from-lane
1004  std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR"));
1005  int fromLane = -1;
1006  try {
1007  fromLane = TplConvert::_2int(fromLaneS.c_str());
1008  } catch (NumberFormatException&) {
1009  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not numeric (" + fromLaneS + ").");
1010  return;
1011  }
1012  fromLane -= 1;
1013  if (fromLane < 0) {
1014  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not positive (" + fromLaneS + ").");
1015  return;
1016  }
1017  // get the from-lane
1018  std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR"));
1019  int toLane = -1;
1020  try {
1021  toLane = TplConvert::_2int(toLaneS.c_str());
1022  } catch (NumberFormatException&) {
1023  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not numeric (" + toLaneS + ").");
1024  return;
1025  }
1026  toLane -= 1;
1027  if (toLane < 0) {
1028  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not positive (" + toLaneS + ").");
1029  return;
1030  }
1031  // !!! the next is probably a hack
1032  if (fromLane - fromLaneOffset < 0) {
1033  //fromLaneOffset = 0;
1034  } else {
1035  fromLane = (int)fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1;
1036  }
1037  if (toLane - toLaneOffset < 0) {
1038  //toLaneOffset = 0;
1039  } else {
1040  toLane = (int)toEdge->getNumLanes() - (toLane - toLaneOffset) - 1;
1041  }
1042  //
1043  if ((int) fromEdge->getNumLanes() <= fromLane) {
1044  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is larger than the edge's lane number (" + fromLaneS + ").");
1045  return;
1046  }
1047  if ((int) toEdge->getNumLanes() <= toLane) {
1048  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is larger than the edge's lane number (" + toLaneS + ").");
1049  return;
1050  }
1051  //
1052  fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::L2L_VALIDATED);
1053 }
1054 
1055 
1056 
1057 
1058 
1059 
1060 
1061 
1062 
1063 
1064 
1065 
1066 
1067 double
1068 NIImporter_VISUM::getWeightedFloat(const std::string& name, const std::string& suffix) {
1069  try {
1070  std::string val = myLineParser.get(name);
1071  if (val.find(suffix) != std::string::npos) {
1072  val = val.substr(0, val.find(suffix));
1073  }
1074  return TplConvert::_2double(val.c_str());
1075  } catch (...) {}
1076  return -1;
1077 }
1078 
1079 
1080 double
1081 NIImporter_VISUM::getWeightedFloat2(const std::string& name, const std::string& name2, const std::string& suffix) {
1082  double result = getWeightedFloat(name, suffix);
1083  if (result != -1) {
1084  return result;
1085  } else {
1086  return getWeightedFloat(name2, suffix);
1087  }
1088 }
1089 
1090 bool
1091 NIImporter_VISUM::getWeightedBool(const std::string& name) {
1092  try {
1093  return TplConvert::_2bool(myLineParser.get(name).c_str());
1094  } catch (...) {}
1095  try {
1096  return TplConvert::_2bool(myLineParser.get((name + "(IV)")).c_str());
1097  } catch (...) {}
1098  return false;
1099 }
1100 
1102 NIImporter_VISUM::getPermissions(const std::string& name, bool warn, SVCPermissions unknown) {
1103  SVCPermissions result = 0;
1104  for (std::string v : StringTokenizer(myLineParser.get(name), ",").getVector()) {
1105  // common values in english and german
1106  std::transform(v.begin(), v.end(), v.begin(), tolower);
1107  if (v == "bus") {
1108  result |= SVC_BUS;
1109  } else if (v == "walk" || v == "w" || v == "f") {
1110  result |= SVC_PEDESTRIAN;
1111  } else if (v == "l" || v == "lkw" || v == "h" || v == "hgv" || v == "lw" || v == "truck" || v == "tru") {
1112  result |= SVC_TRUCK;
1113  } else if (v == "b" || v == "bike") {
1114  result |= SVC_BICYCLE;
1115  } else if (v == "train") {
1116  result |= SVC_RAIL;
1117  } else if (v == "tram") {
1118  result |= SVC_TRAM;
1119  } else if (v == "p" || v == "pkw" || v == "car" || v == "c") {
1120  result |= SVC_PASSENGER;
1121  } else {
1122  if (warn) {
1123  WRITE_WARNING("Encountered unknown vehicle category '" + v + "' in type '" + myLineParser.get("Nr") + "'");
1124  }
1125  result |= unknown;
1126  }
1127  }
1128  return result;
1129 }
1130 
1131 NBNode*
1132 NIImporter_VISUM::getNamedNode(const std::string& fieldName) {
1133  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1134  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1135  if (node == 0) {
1136  WRITE_ERROR("The node '" + nodeS + "' is not known.");
1137  }
1138  return node;
1139 }
1140 
1141 NBNode*
1142 NIImporter_VISUM::getNamedNodeSecure(const std::string& fieldName, NBNode* fallback) {
1143  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1144  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1145  if (node == 0) {
1146  return fallback;
1147  }
1148  return node;
1149 }
1150 
1151 
1152 NBNode*
1153 NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) {
1154  if (myLineParser.know(fieldName1)) {
1155  return getNamedNode(fieldName1);
1156  } else {
1157  return getNamedNode(fieldName2);
1158  }
1159 }
1160 
1161 
1162 NBEdge*
1163 NIImporter_VISUM::getNamedEdge(const std::string& fieldName) {
1164  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1165  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1166  if (edge == 0) {
1167  WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1168  }
1169  return edge;
1170 }
1171 
1172 
1173 NBEdge*
1174 NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) {
1175  if (myLineParser.know(fieldName1)) {
1176  return getNamedEdge(fieldName1);
1177  } else {
1178  return getNamedEdge(fieldName2);
1179  }
1180 }
1181 
1182 
1183 
1184 NBEdge*
1186  std::string sid;
1187  if (edge->getID()[0] == '-') {
1188  sid = edge->getID().substr(1);
1189  } else {
1190  sid = "-" + edge->getID();
1191  }
1192  if (sid.find('_') != std::string::npos) {
1193  sid = sid.substr(0, sid.find('_'));
1194  }
1196 }
1197 
1198 
1199 NBEdge*
1201  if (begin == 0) {
1202  return 0;
1203  }
1204  NBEdge* ret = begin;
1205  std::string edgeID = ret->getID();
1206  // hangle forward
1207  while (ret != 0) {
1208  // ok, this is the edge we are looking for
1209  if (ret->getToNode() == node) {
1210  return ret;
1211  }
1212  const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1213  if (nedges.size() != 1) {
1214  // too many edges follow
1215  ret = 0;
1216  continue;
1217  }
1218  NBEdge* next = nedges[0];
1219  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1220  // ok, another edge is next...
1221  ret = 0;
1222  continue;
1223  }
1224  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1225  ret = 0;
1226  continue;
1227  }
1228  ret = next;
1229  }
1230 
1231  ret = begin;
1232  // hangle backward
1233  while (ret != 0) {
1234  // ok, this is the edge we are looking for
1235  if (ret->getFromNode() == node) {
1236  return ret;
1237  }
1238  const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1239  if (nedges.size() != 1) {
1240  // too many edges follow
1241  ret = 0;
1242  continue;
1243  }
1244  NBEdge* next = nedges[0];
1245  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1246  // ok, another edge is next...
1247  ret = 0;
1248  continue;
1249  }
1250  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1251  ret = 0;
1252  continue;
1253  }
1254  ret = next;
1255  }
1256  return 0;
1257 }
1258 
1259 
1260 NBEdge*
1261 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName, NBNode* node) {
1262  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1263  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1264  if (edge == 0) {
1265  WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1266  }
1267  return getNamedEdgeContinuating(edge, node);
1268 }
1269 
1270 
1271 NBEdge*
1272 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1273  NBNode* node) {
1274  if (myLineParser.know(fieldName1)) {
1275  return getNamedEdgeContinuating(fieldName1, node);
1276  } else {
1277  return getNamedEdgeContinuating(fieldName2, node);
1278  }
1279 }
1280 
1281 
1282 NBEdge*
1284  EdgeVector::const_iterator i;
1285  for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1286  if (ToNode == (*i)->getToNode()) {
1287  return (*i);
1288  }
1289  }
1291  return 0;
1292 }
1293 
1294 
1295 double
1296 NIImporter_VISUM::getNamedFloat(const std::string& fieldName) {
1297  std::string value = myLineParser.get(fieldName);
1298  if (StringUtils::endsWith(myLineParser.get(fieldName), "km/h")) {
1299  value = value.substr(0, value.length() - 4);
1300  }
1301  return TplConvert::_2double(value.c_str());
1302 }
1303 
1304 
1305 double
1306 NIImporter_VISUM::getNamedFloat(const std::string& fieldName, double defaultValue) {
1307  try {
1308  return TplConvert::_2double(myLineParser.get(fieldName).c_str());
1309  } catch (...) {
1310  return defaultValue;
1311  }
1312 }
1313 
1314 
1315 double
1316 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) {
1317  if (myLineParser.know(fieldName1)) {
1318  return getNamedFloat(fieldName1);
1319  } else {
1320  return getNamedFloat(fieldName2);
1321  }
1322 }
1323 
1324 
1325 double
1326 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1327  double defaultValue) {
1328  if (myLineParser.know(fieldName1)) {
1329  return getNamedFloat(fieldName1, defaultValue);
1330  } else {
1331  return getNamedFloat(fieldName2, defaultValue);
1332  }
1333 }
1334 
1335 
1336 std::string
1337 NIImporter_VISUM::getNamedString(const std::string& fieldName) {
1339 }
1340 
1341 
1342 std::string
1343 NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1344  const std::string& fieldName2) {
1345  if (myLineParser.know(fieldName1)) {
1346  return getNamedString(fieldName1);
1347  } else {
1348  return getNamedString(fieldName2);
1349  }
1350 }
1351 
1352 
1353 
1354 
1355 
1356 
1357 NBNode*
1358 NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1359  bool isSource) {
1360  // get the district
1362  if (dist == 0) {
1363  return 0;
1364  }
1365  // build the id
1366  std::string nid;
1367  nid = id + "-" + dest->getID();
1368  if (!isSource) {
1369  nid = "-" + nid;
1370  }
1371  // insert the node
1372  if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1373  WRITE_ERROR("Could not build connector node '" + nid + "'.");
1374  }
1375  // return the node
1376  return myNetBuilder.getNodeCont().retrieve(nid);
1377 }
1378 
1379 
1380 bool
1382  if (from == 0) {
1383  WRITE_ERROR(" The from-node was not found within the net");
1384  }
1385  if (to == 0) {
1386  WRITE_ERROR(" The to-node was not found within the net");
1387  }
1388  if (from == to) {
1389  WRITE_ERROR(" Both nodes are the same");
1390  }
1391  return from != 0 && to != 0 && from != to;
1392 }
1393 
1394 bool
1396  return (edge->getID().length() > node->getID().length() + 1
1397  && (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()));
1398 }
1399 
1400 /****************************************************************************/
1401 
std::map< std::string, Phase * > & phases()
Returns the phases map.
Definition: NIVisumTL.h:117
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:108
void insert(const std::string &id, int numLanes, double maxSpeed, int prio, SVCPermissions permissions, double width, bool oneWayIsDefault, double sidewalkWidth, double bikeLaneWidth)
Adds a type into the list.
Definition: NBTypeCont.cpp:54
double getLength() const
Returns the computed length of the edge.
Definition: NBEdge.h:483
NBDistrict * retrieve(const std::string &id) const
Returns the districts with the given id.
long position
Position of the according db within the file.
unsigned long getPosition()
Returns the current position within the file.
Definition: LineReader.cpp:186
void parse_NodesToTrafficLights()
Parses KNOTENZULSA/SIGNALANLAGEZUKNOTEN.
double getSpeed(const std::string &type) const
Returns the maximal velocity for the given type [m/s].
Definition: NBTypeCont.cpp:174
A signal group can be defined either by a time period or by phases.
Definition: NIVisumTL.h:102
long long int SUMOTime
Definition: SUMOTime.h:36
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:160
void parse_Kante()
Parses FLAECHENELEMENT.
bool myUseVisumPrio
Information whether VISUM priority information shall be used.
void load()
Parses the VISUM-network file storing the parsed structures within myNetBuilder.
is a pedestrian
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
static double _2doubleSec(const E *const data, double def)
converts a 0-terminated char-type array into the double value described by it
Definition: TplConvert.h:365
std::map< NBDistrict *, PositionVector > myDistrictShapes
A temporary storage for district shapes as they are filled incrementally.
LineReader myLineReader
The line reader to use to read from the file.
std::vector< std::string > myTouchedEdges
Already read edges.
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...
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
bool readLine(LineHandler &lh)
Reads a single (the next) line from the file and reports it to the given LineHandler.
Definition: LineReader.cpp:69
static bool isSplitEdge(NBEdge *edge, NBNode *node)
whether the edge id ends with _nodeID
std::string myCurrentID
The name of the currently parsed item used for error reporting.
static bool _2bool(const E *const data)
converts a 0-terminated char-type array into the boolean value described by it
Definition: TplConvert.h:382
void parse_Turns()
Parses ABBIEGEBEZIEHUNG/ABBIEGER.
vehicle is a not electrified rail
VSysTypeNames myVSysTypes
The used vsystypes.
NBNode * getNamedNode(const std::string &fieldName)
Tries to get the node which name is stored in the given field.
void parse_TrafficLights()
Parses LSA/SIGNALANLAGE.
A helper class which computes the lane number from given capacity.
vehicle is a bicycle
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
The representation of a single edge during network building.
Definition: NBEdge.h:65
void parse_PartOfArea()
Parses FLAECHENELEMENT.
int getPriority(const std::string &type) const
Returns the priority for the given type.
Definition: NBTypeCont.cpp:180
vehicle is a light rail
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:256
void parse_SignalGroupsToPhases()
Parses LSASIGNALGRUPPEZULSAPHASE.
NIImporter_VISUM(NBNetBuilder &nb, const std::string &file, NBCapacity2Lanes capacity2Lanes, bool useVisumPrio)
constructor
bool setFile(const std::string &file)
Reinitialises the reader for reading from the given file.
Definition: LineReader.cpp:178
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:3251
void parse_EdgePolys()
Parses STRECKENPOLY.
static long long int _2long(const E *const data)
converts a char-type array into the long value described by it
Definition: TplConvert.h:204
bool markAsSet(const std::string &id, const SumoXMLAttr attr)
Marks an attribute of a type as set.
Definition: NBTypeCont.cpp:85
bool splitAt(NBDistrictCont &dc, NBEdge *edge, NBNode *node)
Splits the edge at the position nearest to the given node.
Definition: NBEdgeCont.cpp:556
PositionVector reverse() const
reverse position vector
void parse_Phases()
Parses LSAPHASE/PHASE.
int getNumLanes(const std::string &type) const
Returns the number of lanes for the given type.
Definition: NBTypeCont.cpp:168
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const std::string & getID() const
Returns the id.
Definition: Named.h:69
#define TIME2STEPS(x)
Definition: SUMOTime.h:60
std::string myFileName
The name of the parsed file, for error reporting.
void parse_AreaSubPartElement()
Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER.
std::string get(const std::string &name, bool prune=false) const
Returns the named information.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:253
NBEdge * getReversedContinuating(NBEdge *edge, NBNode *node)
Returns the opposite direction of the given edge.
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:242
void parse_SignalGroups()
Parses LSASIGNALGRUPPE/SIGNALGRUPPE.
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads network definition from the assigned option and stores it in the given network builder...
The connection was computed and validated.
Definition: NBEdge.h:109
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
A phase.
Definition: NIVisumTL.h:87
A VISUM network importer.
const EdgeVector & getOutgoingEdges() const
Returns this node&#39;s outgoing edges (The edges which start at this node)
Definition: NBNode.h:254
vehicle is a large transport vehicle
void parse_TurnsToSignalGroups()
Parses ABBZULSASIGNALGRUPPE/SIGNALGRUPPEZUABBIEGER.
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, bool keepClear=true, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED)
Adds a connection between the specified this edge&#39;s lane and an approached one.
Definition: NBEdge.cpp:966
A class representing a single district.
Definition: NBDistrict.h:65
NBEdge * getConnectionTo(NBNode *n) const
get connection to certain node
Definition: NBNode.cpp:1929
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
void reinit(const std::string &def, const std::string &defDelim=";", const std::string &lineDelim=";", bool chomp=false, bool ignoreCase=true)
Reinitialises the parser.
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:942
void incLaneNo(int by)
increment lane
Definition: NBEdge.cpp:3033
std::string getNamedString(const std::string &fieldName)
Returns the value from the named column as a normalised string.
static std::string normalIDRepresentation(const std::string &id)
converts the numerical id to its "normal" string representation
Definition: NBHelpers.cpp:71
bool addSource(const std::string &dist, NBEdge *const source, double weight)
Adds a source to the named district.
bool know(const std::string &name) const
Returns the information whether the named column is known.
double getNamedFloat(const std::string &fieldName)
Returns the value from the named column as a float.
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.
A complete call description for parsing a single db.
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:152
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:49
NIVisumTL_Map myTLS
List of visum traffic lights.
int get(double capacity) const
Returns the number of lanes computed from the given capacity.
void parse_Connectors()
Parses ANBINDUNG.
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:415
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:150
A list of positions.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
void setAsMacroscopicConnector()
Definition: NBEdge.h:950
double getWeightedFloat2(const std::string &name, const std::string &name2, const std::string &suffix)
as above but with two alternative names
std::map< long long int, std::vector< long long int > > mySubPartsAreas
A map from area parts to area ids.
bool addSink(const std::string &dist, NBEdge *const destination, double weight)
Adds a sink to the named district.
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:244
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_Districts()
Parses BEZIRK.
void addParser(const std::string &name, ParsingFunction function)
Adds a parser into the sorted list of parsers to use.
bool hasOutgoing(const NBEdge *const e) const
Returns whether the given edge starts at this node.
Definition: NBNode.cpp:1325
ParserVector mySingleDataParsers
List of known parsers.
std::map< long long int, Position > myPoints
A map of point ids to positions.
void parse_Point()
Parses PUNKT.
void(NIImporter_VISUM::* ParsingFunction)()
Definition of a function for parsing a single line from a certain db.
NBEdge * getEdge(NBNode *FromNode, NBNode *ToNode)
Returns the edge that connects both nodes.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
void parse_VSysTypes()
Parses VSYS.
vehicle is a passenger car (a "normal" car)
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
Definition: NBNode.cpp:1319
SVCPermissions getPermissions(const std::string &name, bool warn=false, SVCPermissions unknown=SVCAll)
parse permissions
void parse_Types()
Parses STRECKENTYP.
bool insert(NBDistrict *const district)
Adds a district to the dictionary.
void parse_Nodes()
Parses KNOTEN.
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:617
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:248
vehicle is a bus
void parse_Lanes()
Parses FAHRSTREIFEN.
static int _2int(const E *const data)
converts a char-type array into the integer value described by it
Definition: TplConvert.h:149
~NIImporter_VISUM()
destructor
const EdgeVector & getIncomingEdges() const
Returns this node&#39;s incoming edges (The edges which yield in this node)
Definition: NBNode.h:249
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:155
bool hasMore() const
Returns whether another line may be read (the file was not read completely)
Definition: LineReader.cpp:53
Instance responsible for building networks.
Definition: NBNetBuilder.h:109
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:34
NamedColumnsParser myLineParser
the parser to parse the information from the data lines
NBEdge * retrieve(const std::string &id, bool retrieveExtracted=false) const
Returns the edge that has the given id.
Definition: NBEdgeCont.cpp:245
std::map< long long int, NBDistrict * > myShapeDistrictMap
A map from district shape definition name to the district.
A storage for options typed value containers)
Definition: OptionsCont.h:92
static double _2double(const E *const data)
converts a char-type array into the double value described by it
Definition: TplConvert.h:305
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
NBNode * buildDistrictNode(const std::string &id, NBNode *dest, bool isSource)
Builds a node for the given district and returns it.
std::string name
The name of the db.
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:165
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge&#39;s lateral offset shal...
Intermediate class for storing visum traffic lights during their import.
Definition: NIVisumTL.h:44
NBConnectionVector & connections()
Returns the connections vector.
Definition: NIVisumTL.h:112
void reinit()
Reinitialises the reading (of the previous file)
Definition: LineReader.cpp:192
Represents a single node (junction) during network building.
Definition: NBNode.h:68
bool getWeightedBool(const std::string &name)
tries to get a bool which is possibly assigned to a certain modality
void setPos(unsigned long pos)
Sets the current position within the file to the given value.
Definition: LineReader.cpp:209
void parse_Edges()
Parses STRECKE/STRECKEN.
NBNetBuilder & myNetBuilder
The network builder to fill with loaded values.
void addGeometryPoint(int index, const Position &p)
Adds a further geometry point.
Definition: NBEdge.cpp:835
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:429
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:245
ParsingFunction function
Pointer to the function used for parsing.
const Position & getPosition() const
Returns the position of this district&#39;s center.
Definition: NBDistrict.h:123
static int _2intSec(const E *const data, int def)
converts a 0-terminated char-type array into the integer value described by it
Definition: TplConvert.h:189
bool checkNodes(NBNode *from, NBNode *to)
Returns whether both nodes are a valid combination of from/to-nodes.
void setLaneSpreadFunction(LaneSpreadFunction spread)
(Re)sets how the lanes lateral offset shall be computed
Definition: NBEdge.cpp:829
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:243
NBEdge * getNamedEdge(const std::string &fieldName)
Tries to get the edge which name is stored in the given field.
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:170
Position positionAtOffset(double pos, double lateralOffset=0) const
Returns the position at the given length.
void parseLine(const std::string &line)
Parses the contents of the line.
NBCapacity2Lanes myCapacity2Lanes
The converter to compute the lane number of edges from their capacity.
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:436
SVCPermissions getPermissions(const std::string &type) const
Returns allowed vehicle classes for the given type.
Definition: NBTypeCont.cpp:204
void parse_LanesConnections()
Parses FAHRSTREIFENABBIEGER.
NBNode * getNamedNodeSecure(const std::string &fieldName, NBNode *fallback=0)