SUMO - Simulation of Urban MObility
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NIImporter_VISUM.cpp
Go to the documentation of this file.
1 /****************************************************************************/
10 // A VISUM network importer
11 /****************************************************************************/
12 // SUMO, Simulation of Urban MObility; see http://sumo.sourceforge.net/
13 // Copyright (C) 2001-2012 DLR (http://www.dlr.de/) and contributors
14 /****************************************************************************/
15 //
16 // This file is part of SUMO.
17 // SUMO is free software: you can redistribute it and/or modify
18 // it under the terms of the GNU General Public License as published by
19 // the Free Software Foundation, either version 3 of the License, or
20 // (at your option) any later version.
21 //
22 /****************************************************************************/
23 
24 
25 // ===========================================================================
26 // included modules
27 // ===========================================================================
28 #ifdef _MSC_VER
29 #include <windows_config.h>
30 #else
31 #include <config.h>
32 #endif
33 
34 #include <string>
37 #include <utils/common/ToString.h>
40 #include <netbuild/NBDistrict.h>
42 
43 #include <netbuild/NBNetBuilder.h>
44 #include "NILoader.h"
45 #include "NIImporter_VISUM.h"
46 
47 #ifdef CHECK_MEMORY_LEAKS
48 #include <foreign/nvwa/debug_new.h>
49 #endif // CHECK_MEMORY_LEAKS
50 
51 
52 // ===========================================================================
53 // method definitions
54 // ===========================================================================
55 // ---------------------------------------------------------------------------
56 // static methods (interface in this case)
57 // ---------------------------------------------------------------------------
58 void
60  // check whether the option is set (properly)
61  if (!oc.isSet("visum-file")) {
62  return;
63  }
64  // build the handler
65  NIImporter_VISUM loader(nb, oc.getString("visum-file"),
66  NBCapacity2Lanes(oc.getFloat("lanes-from-capacity.norm")),
67  oc.getBool("visum.use-type-priority"));
68  loader.load();
69 }
70 
71 
72 
73 // ---------------------------------------------------------------------------
74 // loader methods
75 // ---------------------------------------------------------------------------
77  const std::string& file,
78  NBCapacity2Lanes capacity2Lanes,
79  bool useVisumPrio)
80  : myNetBuilder(nb), myFileName(file),
81  myCapacity2Lanes(capacity2Lanes), myUseVisumPrio(useVisumPrio) {
82  // the order of process is important!
83  // set1
89 
90  // set2
91  // two types of "strecke"
95 
96  // set3
98  // two types of "abbieger"
99  addParser("ABBIEGEBEZIEHUNG", &NIImporter_VISUM::parse_Turns);
101 
103  addParser("FAHRSTREIFEN", &NIImporter_VISUM::parse_Lanes);
104  addParser("FLAECHENELEMENT", &NIImporter_VISUM::parse_PartOfArea);
105 
106  // set4
107  // two types of lsa
110  // two types of knotenzulsa
114  // two types of signalgruppe
115  addParser("LSASIGNALGRUPPE", &NIImporter_VISUM::parse_SignalGroups);
117  // three types of ABBZULSASIGNALGRUPPE
118  addParser("ABBZULSASIGNALGRUPPE", &NIImporter_VISUM::parse_TurnsToSignalGroups);
119  addParser("SIGNALGRUPPEZUABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
120  addParser("SIGNALGRUPPEZUFSABBIEGER", &NIImporter_VISUM::parse_TurnsToSignalGroups);
121 
122  addParser("TEILFLAECHENELEMENT", &NIImporter_VISUM::parse_AreaSubPartElement);
123 
124  // two types of LSAPHASE
127 
128  addParser("LSASIGNALGRUPPEZULSAPHASE", &NIImporter_VISUM::parse_SignalGroupsToPhases);
129  addParser("FAHRSTREIFENABBIEGER", &NIImporter_VISUM::parse_LanesConnections);
130 }
131 
132 
134  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
135  delete j->second;
136  }
137 }
138 
139 
140 void
141 NIImporter_VISUM::addParser(const std::string& name, ParsingFunction function) {
142  TypeParser p;
143  p.name = name;
144  p.function = function;
145  p.position = -1;
146  mySingleDataParsers.push_back(p);
147 }
148 
149 
150 void
152  // open the file
154  throw ProcessError("Can not open visum-file '" + myFileName + "'.");
155  }
156  // scan the file for data positions
157  while (myLineReader.hasMore()) {
158  std::string line = myLineReader.readLine();
159  if (line.length() > 0 && line[0] == '$') {
160  ParserVector::iterator i;
161  for (i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
162  std::string dataName = "$" + (*i).name + ":";
163  if (line.substr(0, dataName.length()) == dataName) {
164  (*i).position = myLineReader.getPosition();
165  (*i).pattern = line.substr(dataName.length());
166  WRITE_MESSAGE("Found: " + dataName + " at " + toString<int>(myLineReader.getPosition()));
167  }
168  }
169  }
170  }
171  // go through the parsers and process all entries
172  for (ParserVector::iterator i = mySingleDataParsers.begin(); i != mySingleDataParsers.end(); i++) {
173  if ((*i).position < 0) {
174  // do not process using parsers for which no information was found
175  continue;
176  }
177  // ok, the according information is stored in the file
178  PROGRESS_BEGIN_MESSAGE("Parsing " + (*i).name);
179  // reset the line reader and let it point to the begin of the according data field
181  myLineReader.setPos((*i).position);
182  // prepare the line parser
183  myLineParser.reinit((*i).pattern);
184  // read
185  bool singleDataEndFound = false;
186  while (myLineReader.hasMore() && !singleDataEndFound) {
187  std::string line = myLineReader.readLine();
188  if (line.length() == 0 || line[0] == '*' || line[0] == '$') {
189  singleDataEndFound = true;
190  } else {
191  myLineParser.parseLine(line);
192  try {
193  myCurrentID = "<unknown>";
194  (this->*(*i).function)();
195  } catch (OutOfBoundsException&) {
196  WRITE_ERROR("Too short value line in " + (*i).name + " occured.");
197  } catch (NumberFormatException&) {
198  WRITE_ERROR("A value in " + (*i).name + " should be numeric but is not (id='" + myCurrentID + "').");
199  } catch (UnknownElement& e) {
200  WRITE_ERROR("One of the needed values ('" + std::string(e.what()) + "') is missing in " + (*i).name + ".");
201  }
202  }
203  }
204  // close single reader processing
206  }
207  // build traffic lights
208  for (NIVisumTL_Map::iterator j = myTLS.begin(); j != myTLS.end(); j++) {
209  j->second->build(myNetBuilder.getTLLogicCont());
210  }
211  // build district shapes
212  for (std::map<NBDistrict*, PositionVector>::const_iterator k = myDistrictShapes.begin(); k != myDistrictShapes.end(); ++k) {
213  (*k).first->addShape((*k).second);
214  }
215 }
216 
217 
218 
219 
220 
221 void
223  std::string name = myLineParser.know("VSysCode") ? myLineParser.get("VSysCode").c_str() : myLineParser.get("CODE").c_str();
224  std::string type = myLineParser.know("VSysMode") ? myLineParser.get("VSysMode").c_str() : myLineParser.get("Typ").c_str();
225  myVSysTypes[name] = type;
226 }
227 
228 
229 void
231  // get the id
233  // get the maximum speed
234  SUMOReal speed = getNamedFloat("v0-IV", "V0IV");
235  // get the priority
236  int priority = 1000 - TplConvert<char>::_2int(myLineParser.get("Rang").c_str());
237  // try to retrieve the number of lanes
238  SUMOReal cap = getNamedFloat("Kap-IV", "KAPIV");
239  int nolanes = myCapacity2Lanes.get(cap);
240  // insert the type
241  myNetBuilder.getTypeCont().insert(myCurrentID, nolanes, speed / (SUMOReal) 3.6, priority, -1);
242 }
243 
244 
245 void
247  // get the id
249  // get the position
250  SUMOReal x = getNamedFloat("XKoord");
251  SUMOReal y = getNamedFloat("YKoord");
252  Position pos(x, y);
253  if (!NILoader::transformCoordinates(pos)) {
254  WRITE_ERROR("Unable to project coordinates for node " + myCurrentID + ".");
255  return;
256  }
257  // add to the list
259  WRITE_ERROR("Duplicate node occured ('" + myCurrentID + "').");
260  }
261 }
262 
263 
264 void
266  // get the id
268  // get the information whether the source and the destination
269  // connections are weighted
270  //bool sourcesWeighted = getWeightedBool("Proz_Q");
271  //bool destWeighted = getWeightedBool("Proz_Z");
272  // get the node information
273  SUMOReal x = getNamedFloat("XKoord");
274  SUMOReal y = getNamedFloat("YKoord");
275  Position pos(x, y);
276  if (!NILoader::transformCoordinates(pos, false)) {
277  WRITE_ERROR("Unable to project coordinates for district " + myCurrentID + ".");
278  return;
279  }
280  // build the district
281  NBDistrict* district = new NBDistrict(myCurrentID, pos);
282  if (!myNetBuilder.getDistrictCont().insert(district)) {
283  WRITE_ERROR("Duplicate district occured ('" + myCurrentID + "').");
284  delete district;
285  return;
286  }
287  if (myLineParser.know("FLAECHEID")) {
288  long flaecheID = TplConvert<char>::_2long(myLineParser.get("FLAECHEID").c_str());
289  myShapeDistrictMap[flaecheID] = district;
290  }
291 }
292 
293 
294 void
296  long id = TplConvert<char>::_2long(myLineParser.get("ID").c_str());
297  SUMOReal x = TplConvert<char>::_2SUMOReal(myLineParser.get("XKOORD").c_str());
298  SUMOReal y = TplConvert<char>::_2SUMOReal(myLineParser.get("YKOORD").c_str());
299  Position pos(x, y);
300  if (!NILoader::transformCoordinates(pos, false)) {
301  WRITE_ERROR("Unable to project coordinates for point " + toString(id) + ".");
302  return;
303  }
304  myPoints[id] = pos;
305 }
306 
307 
308 void
310  if (myLineParser.know("VSYSSET") && myLineParser.get("VSYSSET") == "") {
311  // no vehicle allowed; don't add
312  return;
313  }
314  // get the id
316  // get the from- & to-node and validate them
317  NBNode* from = getNamedNode("VonKnot", "VonKnotNr");
318  NBNode* to = getNamedNode("NachKnot", "NachKnotNr");
319  if (!checkNodes(from, to)) {
320  return;
321  }
322  // get the type
323  std::string type = myLineParser.know("Typ") ? myLineParser.get("Typ") : myLineParser.get("TypNr");
324  // get the speed
325  SUMOReal speed = myNetBuilder.getTypeCont().getSpeed(type);
326  if (!OptionsCont::getOptions().getBool("visum.use-type-speed")) {
327  try {
328  speed = myLineParser.know("v0-IV")
329  ? TplConvertSec<char>::_2SUMORealSec(myLineParser.get("v0-IV").c_str(), -1)
330  : TplConvertSec<char>::_2SUMORealSec(myLineParser.get("V0IV").c_str(), -1);
331  speed = speed / (SUMOReal) 3.6;
332  } catch (OutOfBoundsException) {}
333  }
334  if (speed <= 0) {
335  speed = myNetBuilder.getTypeCont().getSpeed(type);
336  }
337 
338  // get the information whether the edge is a one-way
339  bool oneway = myLineParser.know("Einbahn")
340  ? TplConvert<char>::_2bool(myLineParser.get("Einbahn").c_str())
341  : true;
342  // get the number of lanes
343  int nolanes = myNetBuilder.getTypeCont().getNumLanes(type);
344  if (!OptionsCont::getOptions().getBool("visum.recompute-lane-number")) {
345  try {
346  if (!OptionsCont::getOptions().getBool("visum.use-type-laneno")) {
347  nolanes = myLineParser.know("Fahrstreifen")
348  ? TplConvertSec<char>::_2intSec(myLineParser.get("Fahrstreifen").c_str(), 0)
349  : TplConvertSec<char>::_2intSec(myLineParser.get("ANZFAHRSTREIFEN").c_str(), 0);
350  }
351  } catch (UnknownElement) {
352  }
353  } else {
354  SUMOReal cap = myLineParser.know("KAPIV")
355  ? TplConvertSec<char>::_2SUMORealSec(myLineParser.get("KAPIV").c_str(), -1)
356  : TplConvertSec<char>::_2SUMORealSec(myLineParser.get("KAP-IV").c_str(), -1);
357  nolanes = myCapacity2Lanes.get(cap);
358  }
359  // check whether the id is already used
360  // (should be the opposite direction)
361  bool oneway_checked = oneway;
363  if (previous != 0) {
364  myCurrentID = '-' + myCurrentID;
366  oneway_checked = false;
367  }
368  if (find(myTouchedEdges.begin(), myTouchedEdges.end(), myCurrentID) != myTouchedEdges.end()) {
369  oneway_checked = false;
370  }
371  std::string tmpid = '-' + myCurrentID;
372  if (find(myTouchedEdges.begin(), myTouchedEdges.end(), tmpid) != myTouchedEdges.end()) {
373  previous = myNetBuilder.getEdgeCont().retrieve(tmpid);
374  if (previous != 0) {
376  }
377  oneway_checked = false;
378  }
379  // add the edge
380  int prio = myUseVisumPrio ? myNetBuilder.getTypeCont().getPriority(type) : -1;
381  if (nolanes != 0 && speed != 0) {
382  LaneSpreadFunction lsf = oneway_checked ? LANESPREAD_CENTER : LANESPREAD_RIGHT;
383  // @todo parse name from visum files
384  NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, nolanes, prio,
386  if (!myNetBuilder.getEdgeCont().insert(e)) {
387  delete e;
388  WRITE_ERROR("Duplicate edge occured ('" + myCurrentID + "').");
389  }
390  }
391  myTouchedEdges.push_back(myCurrentID);
392  // nothing more to do, when the edge is a one-way street
393  if (oneway) {
394  return;
395  }
396  // add the opposite edge
397  myCurrentID = '-' + myCurrentID;
398  if (nolanes != 0 && speed != 0) {
399  LaneSpreadFunction lsf = oneway_checked ? LANESPREAD_CENTER : LANESPREAD_RIGHT;
400  // @todo parse name from visum files
401  NBEdge* e = new NBEdge(myCurrentID, from, to, type, speed, nolanes, prio,
403  if (!myNetBuilder.getEdgeCont().insert(e)) {
404  delete e;
405  WRITE_ERROR("Duplicate edge occured ('" + myCurrentID + "').");
406  }
407  }
408  myTouchedEdges.push_back(myCurrentID);
409 }
410 
411 
412 void
414  long id = TplConvert<char>::_2long(myLineParser.get("ID").c_str());
415  long from = TplConvert<char>::_2long(myLineParser.get("VONPUNKTID").c_str());
416  long to = TplConvert<char>::_2long(myLineParser.get("NACHPUNKTID").c_str());
417  myEdges[id] = std::make_pair(from, to);
418 }
419 
420 
421 void
423  long flaecheID = TplConvert<char>::_2long(myLineParser.get("FLAECHEID").c_str());
424  long flaechePartID = TplConvert<char>::_2long(myLineParser.get("TFLAECHEID").c_str());
425  if (mySubPartsAreas.find(flaechePartID) == mySubPartsAreas.end()) {
426  mySubPartsAreas[flaechePartID] = std::vector<long>();
427  }
428  mySubPartsAreas[flaechePartID].push_back(flaecheID);
429 }
430 
431 
432 void
434  if (OptionsCont::getOptions().getBool("visum.no-connectors")) {
435  // do nothing, if connectors shall not be imported
436  return;
437  }
438  // get the source district
439  std::string bez = NBHelpers::normalIDRepresentation(myLineParser.get("BezNr"));
440  // get the destination node
441  NBNode* dest = getNamedNode("KnotNr");
442  if (dest == 0) {
443  return;
444  }
445  // get the weight of the connection
446  SUMOReal proz = getWeightedFloat("Proz");
447  if (proz > 0) {
448  proz /= 100.;
449  } else {
450  proz = 1;
451  }
452  // get the duration to wait
453  SUMOReal retard = -1;
454  if (myLineParser.know("t0-IV")) {
455  retard = getNamedFloat("t0-IV", -1);
456  }
457  // get the type;
458  // use a standard type with a large speed when a type is not given
459  std::string type = myLineParser.know("Typ")
461  : "";
462  // add the connectors as an edge
463  std::string id = bez + "-" + dest->getID();
464  // get the information whether this is a sink or a source
465  std::string dir = myLineParser.get("Richtung");
466  if (dir.length() == 0) {
467  dir = "QZ";
468  }
469  // build the source when needed
470  if (dir.find('Q') != std::string::npos) {
471  const EdgeVector& edges = dest->getOutgoingEdges();
472  bool hasContinuation = false;
473  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
474  if (!(*i)->isMacroscopicConnector()) {
475  hasContinuation = true;
476  }
477  }
478  if (!hasContinuation) {
479  // obviously, there is no continuation on the net
480  WRITE_WARNING("Incoming connector '" + id + "' will not be build - would be not connected to network.");
481  } else {
482  NBNode* src = buildDistrictNode(bez, dest, true);
483  if (src == 0) {
484  WRITE_ERROR("The district '" + bez + "' could not be built.");
485  return;
486  }
487  NBEdge* edge = new NBEdge(id, src, dest, "VisumConnector",
488  OptionsCont::getOptions().getFloat("visum.connector-speeds"),
489  OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
491  "", LANESPREAD_RIGHT);
493  if (!myNetBuilder.getEdgeCont().insert(edge)) {
494  WRITE_ERROR("A duplicate edge id occured (ID='" + id + "').");
495  return;
496  }
497  edge = myNetBuilder.getEdgeCont().retrieve(id);
498  if (edge != 0) {
499  myNetBuilder.getDistrictCont().addSource(bez, edge, proz);
500  }
501  }
502  }
503  // build the sink when needed
504  if (dir.find('Z') != std::string::npos) {
505  const EdgeVector& edges = dest->getIncomingEdges();
506  bool hasPredeccessor = false;
507  for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); ++i) {
508  if (!(*i)->isMacroscopicConnector()) {
509  hasPredeccessor = true;
510  }
511  }
512  if (!hasPredeccessor) {
513  // obviously, the network is not connected to this node
514  WRITE_WARNING("Outgoing connector '" + id + "' will not be build - would be not connected to network.");
515  } else {
516  NBNode* src = buildDistrictNode(bez, dest, false);
517  if (src == 0) {
518  WRITE_ERROR("The district '" + bez + "' could not be built.");
519  return;
520  }
521  id = "-" + id;
522  NBEdge* edge = new NBEdge(id, dest, src, "VisumConnector",
523  OptionsCont::getOptions().getFloat("visum.connector-speeds"),
524  OptionsCont::getOptions().getInt("visum.connectors-lane-number"),
526  "", LANESPREAD_RIGHT);
528  if (!myNetBuilder.getEdgeCont().insert(edge)) {
529  WRITE_ERROR("A duplicate edge id occured (ID='" + id + "').");
530  return;
531  }
532  edge = myNetBuilder.getEdgeCont().retrieve(id);
533  if (edge != 0) {
534  myNetBuilder.getDistrictCont().addSink(bez, edge, proz);
535  }
536  }
537  }
538 }
539 
540 
541 void
543  if (myLineParser.know("VSYSSET") && myLineParser.get("VSYSSET") == "") {
544  // no vehicle allowed; don't add
545  return;
546  }
547  // retrieve the nodes
548  NBNode* from = getNamedNode("VonKnot", "VonKnotNr");
549  NBNode* via = getNamedNode("UeberKnot", "UeberKnotNr");
550  NBNode* to = getNamedNode("NachKnot", "NachKnotNr");
551  if (from == 0 || via == 0 || to == 0) {
552  return;
553  }
554  // all nodes are known
555  std::string type = myLineParser.know("VSysCode")
556  ? myLineParser.get("VSysCode")
557  : myLineParser.get("VSYSSET");
558  if (myVSysTypes.find(type) != myVSysTypes.end() && myVSysTypes.find(type)->second == "IV") {
559  // try to set the turning definition
560  NBEdge* src = from->getConnectionTo(via);
561  NBEdge* dest = via->getConnectionTo(to);
562  // check both
563  if (src == 0) {
564  // maybe it was removed due to something
565  if (OptionsCont::getOptions().isSet("keep-edges.min-speed")
566  ||
567  OptionsCont::getOptions().isSet("keep-edges.explicit")) {
568  WRITE_WARNING("Could not set connection from node '" + from->getID() + "' to node '" + via->getID() + "'.");
569  } else {
570  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
571  WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + via->getID() + "'.");
572  }
573  }
574  return;
575  }
576  if (dest == 0) {
577  if (OptionsCont::getOptions().isSet("keep-edges.min-speed")
578  ||
579  OptionsCont::getOptions().isSet("keep-edges.explicit")) {
580  WRITE_WARNING("Could not set connection from node '" + via->getID() + "' to node '" + to->getID() + "'.");
581  } else {
582  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
583  WRITE_WARNING("There is no edge from node '" + via->getID() + "' to node '" + to->getID() + "'.");
584  }
585  }
586  return;
587  }
588  // both edges found
589  // set them into the edge
590  src->addEdge2EdgeConnection(dest);
591  }
592 }
593 
594 
595 void
597  // get the from- & to-node and validate them
598  NBNode* from = getNamedNode("VonKnot", "VonKnotNr");
599  NBNode* to = getNamedNode("NachKnot", "NachKnotNr");
600  if (!checkNodes(from, to)) {
601  return;
602  }
603  bool failed = false;
604  int index;
605  SUMOReal x, y;
606  try {
607  index = TplConvert<char>::_2int(myLineParser.get("INDEX").c_str());
608  x = getNamedFloat("XKoord");
609  y = getNamedFloat("YKoord");
610  } catch (NumberFormatException&) {
611  WRITE_ERROR("Error in geometry description from node '" + from->getID() + "' to node '" + to->getID() + "'.");
612  return;
613  }
614  Position pos(x, y);
615  if (!NILoader::transformCoordinates(pos)) {
616  WRITE_ERROR("Unable to project coordinates for node '" + from->getID() + "'.");
617  return;
618  }
619  NBEdge* e = from->getConnectionTo(to);
620  if (e != 0) {
621  e->addGeometryPoint(index, pos);
622  } else {
623  failed = true;
624  }
625  e = to->getConnectionTo(from);
626  if (e != 0) {
627  e->addGeometryPoint(-index, pos);
628  failed = false;
629  }
630  // check whether the operation has failed
631  if (failed) {
632  // we should report this to the warning instance only if we have removed
633  // some nodes or edges...
634  if (OptionsCont::getOptions().isSet("keep-edges.min-speed") || OptionsCont::getOptions().isSet("keep-edges.explicit")) {
635  WRITE_WARNING("Could not set geometry between node '" + from->getID() + "' and node '" + to->getID() + "'.");
636  } else {
637  // ... in the other case we report this to the error instance
638  if (OptionsCont::getOptions().getBool("visum.verbose-warnings")) {
639  WRITE_WARNING("There is no edge from node '" + from->getID() + "' to node '" + to->getID() + "'.");
640  }
641  }
642  }
643 }
644 
645 
646 void
648  // get the node
649  NBNode* node = getNamedNode("KNOTNR");
650  // get the edge
651  NBEdge* baseEdge = getNamedEdge("STRNR");
652  NBEdge* edge = getNamedEdgeContinuating("STRNR", node);
653  // check
654  if (node == 0 || edge == 0) {
655  return;
656  }
657  // get the lane
658  std::string laneS = myLineParser.know("FSNR")
661  int lane = -1;
662  try {
663  lane = TplConvert<char>::_2int(laneS.c_str());
664  } catch (NumberFormatException&) {
665  WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not numeric (" + laneS + ").");
666  return;
667  }
668  lane -= 1;
669  if (lane < 0) {
670  WRITE_ERROR("A lane number for edge '" + edge->getID() + "' is not positive (" + laneS + ").");
671  return;
672  }
673  // get the direction
674  std::string dirS = NBHelpers::normalIDRepresentation(myLineParser.get("RICHTTYP"));
675  int prevLaneNo = baseEdge->getNumLanes();
676  if ((dirS == "1" && !(node->hasIncoming(edge))) || (dirS == "0" && !(node->hasOutgoing(edge)))) {
677  // get the last part of the turnaround direction
678  edge = getReversedContinuating(edge, node);
679  }
680  // get the length
681  std::string lengthS = NBHelpers::normalIDRepresentation(myLineParser.get("LAENGE"));
682  SUMOReal length = -1;
683  try {
684  length = TplConvert<char>::_2SUMOReal(lengthS.c_str());
685  } catch (NumberFormatException&) {
686  WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not numeric (" + lengthS + ").");
687  return;
688  }
689  if (length < 0) {
690  WRITE_ERROR("A lane length for edge '" + edge->getID() + "' is not positive (" + lengthS + ").");
691  return;
692  }
693  //
694  if (dirS == "1") {
695  lane -= prevLaneNo;
696  }
697  //
698  if (length == 0) {
699  if ((int) edge->getNumLanes() > lane) {
700  // ok, we know this already...
701  return;
702  }
703  // increment by one
704  edge->incLaneNo(1);
705  } else {
706  // check whether this edge already has been created
707  if (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) {
708  if (edge->getID().substr(edge->getID().find('_')) == "_" + toString(length) + "_" + node->getID()) {
709  if ((int) edge->getNumLanes() > lane) {
710  // ok, we know this already...
711  return;
712  }
713  // increment by one
714  edge->incLaneNo(1);
715  return;
716  }
717  }
718  // nope, we have to split the edge...
719  // maybe it is not the proper edge to split - VISUM seems not to sort the splits...
720  bool mustRecheck = true;
721  NBNode* nextNode = node;
722  SUMOReal seenLength = 0;
723  while (mustRecheck) {
724  if (edge->getID().substr(edge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) {
725  // ok, we have a previously created edge here
726  std::string sub = edge->getID();
727  sub = sub.substr(sub.rfind('_', sub.rfind('_') - 1));
728  sub = sub.substr(1, sub.find('_', 1) - 1);
729  SUMOReal dist = TplConvert<char>::_2SUMOReal(sub.c_str());
730  if (dist < length) {
731  seenLength += edge->getLength();
732  if (dirS == "1") {
733  // incoming -> move back
734  edge = edge->getFromNode()->getIncomingEdges()[0];
735  nextNode = edge->getToNode();
736  nextNode = edge->getFromNode();
737  } else {
738  // outgoing -> move forward
739  edge = edge->getToNode()->getOutgoingEdges()[0];
740  nextNode = edge->getFromNode();
741  nextNode = edge->getToNode();
742  }
743  } else {
744  mustRecheck = false;
745  }
746  } else {
747  // we have the center edge - do not continue...
748  mustRecheck = false;
749  }
750  }
751  // compute position
752  Position p;
753  SUMOReal useLength = length - seenLength;
754  useLength = edge->getLength() - useLength;
755  std::string edgeID = edge->getID();
756  p = edge->getGeometry().positionAtLengthPosition(useLength);
757  if (edgeID.substr(edgeID.length() - node->getID().length() - 1) == "_" + node->getID()) {
758  edgeID = edgeID.substr(0, edgeID.find('_'));
759  }
760  NBNode* rn = new NBNode(edgeID + "_" + toString((size_t) length) + "_" + node->getID(), p);
761  if (!myNetBuilder.getNodeCont().insert(rn)) {
762  throw ProcessError("Ups - could not insert node!");
763  }
764  std::string nid = edgeID + "_" + toString((size_t) length) + "_" + node->getID();
766  edge->getID(), nid, edge->getNumLanes() + 0, edge->getNumLanes() + 1);
767  NBEdge* nedge = myNetBuilder.getEdgeCont().retrieve(nid);
768  nedge = nedge->getToNode()->getOutgoingEdges()[0];
769  while (nedge->getID().substr(nedge->getID().length() - node->getID().length() - 1) == "_" + node->getID()) {
770  assert(nedge->getToNode()->getOutgoingEdges().size() > 0);
771  nedge->incLaneNo(1);
772  nedge = nedge->getToNode()->getOutgoingEdges()[0];
773  }
774  }
775 }
776 
777 
778 void
780  // get the id
782  // cycle time
783  SUMOReal CycleTime = getNamedFloat("Umlaufzeit", "UMLZEIT");
784  // IntermediateTime
785  SUMOReal IntermediateTime = getNamedFloat("StdZwischenzeit", "STDZWZEIT");
786  // PhaseBased
787  bool PhaseBased = myLineParser.know("PhasenBasiert")
788  ? TplConvert<char>::_2bool(myLineParser.get("PhasenBasiert").c_str())
789  : false;
790  // add to the list
791  myTLS[myCurrentID] = new NIVisumTL(myCurrentID, (SUMOTime) CycleTime, (SUMOTime) IntermediateTime, PhaseBased);
792 }
793 
794 
795 void
797  std::string node = myLineParser.get("KnotNr").c_str();
798  std::string trafficLight = myLineParser.get("LsaNr").c_str();
799  // add to the list
800  myTLS[trafficLight]->addNode(myNetBuilder.getNodeCont().retrieve(node));
801 }
802 
803 
804 void
806  // get the id
808  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
809  // StartTime
810  SUMOReal startTime = getNamedFloat("GzStart", "GRUENANF");
811  // EndTime
812  SUMOReal endTime = getNamedFloat("GzEnd", "GRUENENDE");
813  // add to the list
814  if (myTLS.find(LSAid) == myTLS.end()) {
815  WRITE_ERROR("Could not find TLS '" + LSAid + "' for setting the signal group.");
816  return;
817  }
818  myTLS.find(LSAid)->second->addSignalGroup(myCurrentID, (SUMOTime) startTime, (SUMOTime) endTime);
819 }
820 
821 
822 void
824  // get the id
825  std::string SGid = getNamedString("SGNR", "SIGNALGRUPPENNR");
826  std::string LSAid = getNamedString("LsaNr");
827  // nodes
828  NBNode* from = myLineParser.know("VonKnot") ? getNamedNode("VonKnot") : 0;
829  NBNode* via = myLineParser.know("KNOTNR")
830  ? getNamedNode("KNOTNR")
831  : getNamedNode("UeberKnot", "UeberKnotNr");
832  NBNode* to = myLineParser.know("NachKnot") ? getNamedNode("NachKnot") : 0;
833  // edges
834  NBEdge* edg1 = 0;
835  NBEdge* edg2 = 0;
836  if (from == 0 && to == 0) {
837  edg1 = getNamedEdgeContinuating("VONSTRNR", via);
838  edg2 = getNamedEdgeContinuating("NACHSTRNR", via);
839  } else {
840  edg1 = getEdge(from, via);
841  edg2 = getEdge(via, to);
842  }
843  // add to the list
844  NIVisumTL::SignalGroup& SG = myTLS.find(LSAid)->second->getSignalGroup(SGid);
845  if (edg1 != 0 && edg2 != 0) {
846  if (!via->hasIncoming(edg1)) {
847  std::string sid;
848  if (edg1->getID()[0] == '-') {
849  sid = edg1->getID().substr(1);
850  } else {
851  sid = "-" + edg1->getID();
852  }
853  if (sid.find('_') != std::string::npos) {
854  sid = sid.substr(0, sid.find('_'));
855  }
857  }
858  if (!via->hasOutgoing(edg2)) {
859  std::string sid;
860  if (edg2->getID()[0] == '-') {
861  sid = edg2->getID().substr(1);
862  } else {
863  sid = "-" + edg2->getID();
864  }
865  if (sid.find('_') != std::string::npos) {
866  sid = sid.substr(0, sid.find('_'));
867  }
869  }
870  SG.connections().push_back(NBConnection(edg1, edg2));
871  }
872 }
873 
874 
875 void
877  long id = TplConvert<char>::_2long(myLineParser.get("TFLAECHEID").c_str());
878  long edgeid = TplConvert<char>::_2long(myLineParser.get("KANTEID").c_str());
879  if (myEdges.find(edgeid) == myEdges.end()) {
880  WRITE_ERROR("Unknown edge in TEILFLAECHENELEMENT");
881  return;
882  }
883  std::string dir = myLineParser.get("RICHTUNG");
884  std::string indexS = NBHelpers::normalIDRepresentation(myLineParser.get("INDEX"));
885  int index = -1;
886  try {
887  index = TplConvert<char>::_2int(indexS.c_str()) - 1;
888  } catch (NumberFormatException&) {
889  WRITE_ERROR("An index for a TEILFLAECHENELEMENT is not numeric (id='" + toString(id) + "').");
890  return;
891  }
892  PositionVector shape;
893  shape.push_back(myPoints[myEdges[edgeid].first]);
894  shape.push_back(myPoints[myEdges[edgeid].second]);
895  if (dir.length() > 0 && dir[0] == '1') {
896  shape = shape.reverse();
897  }
898  if (mySubPartsAreas.find(id) == mySubPartsAreas.end()) {
899  WRITE_ERROR("Unkown are for area part '" + myCurrentID + "'.");
900  return;
901  }
902 
903  const std::vector<long> &areas = mySubPartsAreas.find(id)->second;
904  for (std::vector<long>::const_iterator i = areas.begin(); i != areas.end(); ++i) {
906  if (d == 0) {
907  continue;
908  }
909  if (myDistrictShapes.find(d) == myDistrictShapes.end()) {
911  }
912  if (dir.length() > 0 && dir[0] == '1') {
913  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
914  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
915  } else {
916  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].first]);
917  myDistrictShapes[d].push_back(myPoints[myEdges[edgeid].second]);
918  }
919  }
920 }
921 
922 
923 void
925  // get the id
926  std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("Nr"));
927  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
928  // StartTime
929  SUMOReal StartTime = getNamedFloat("GzStart", "GRUENANF");
930  // EndTime
931  SUMOReal EndTime = getNamedFloat("GzEnd", "GRUENENDE");
932  // add to the list
933  myTLS.find(LSAid)->second->addPhase(Phaseid, (SUMOTime) StartTime, (SUMOTime) EndTime);
934 }
935 
936 
938  // get the id
939  std::string Phaseid = NBHelpers::normalIDRepresentation(myLineParser.get("PsNr"));
940  std::string LSAid = NBHelpers::normalIDRepresentation(myLineParser.get("LsaNr"));
941  std::string SGid = NBHelpers::normalIDRepresentation(myLineParser.get("SGNR"));
942  // insert
943  NIVisumTL* LSA = myTLS.find(LSAid)->second;
944  NIVisumTL::SignalGroup& SG = LSA->getSignalGroup(SGid);
945  NIVisumTL::Phase* PH = LSA->getPhases().find(Phaseid)->second;
946  SG.phases()[Phaseid] = PH;
947 }
948 
949 
951  // get the node
952  NBNode* node = getNamedNode("KNOTNR", "KNOT");
953  if (node == 0) {
954  return;
955  }
956  // get the from-edge
957  NBEdge* fromEdge = getNamedEdgeContinuating("VONSTRNR", "VONSTR", node);
958  NBEdge* toEdge = getNamedEdgeContinuating("NACHSTRNR", "NACHSTR", node);
959  if (fromEdge == 0 || toEdge == 0) {
960  return;
961  }
962 
963  int fromLaneOffset = 0;
964  if (!node->hasIncoming(fromEdge)) {
965  fromLaneOffset = fromEdge->getNumLanes();
966  fromEdge = getReversedContinuating(fromEdge, node);
967  } else {
968  fromEdge = getReversedContinuating(fromEdge, node);
969  NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(fromEdge->getID().substr(0, fromEdge->getID().find('_')));
970  fromLaneOffset = tmp->getNumLanes();
971  }
972 
973  int toLaneOffset = 0;
974  if (!node->hasOutgoing(toEdge)) {
975  toLaneOffset = toEdge->getNumLanes();
976  toEdge = getReversedContinuating(toEdge, node);
977  } else {
978  NBEdge* tmp = myNetBuilder.getEdgeCont().retrieve(toEdge->getID().substr(0, toEdge->getID().find('_')));
979  toLaneOffset = tmp->getNumLanes();
980  }
981  // get the from-lane
982  std::string fromLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("VONFSNR"));
983  int fromLane = -1;
984  try {
985  fromLane = TplConvert<char>::_2int(fromLaneS.c_str());
986  } catch (NumberFormatException&) {
987  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not numeric (" + fromLaneS + ").");
988  return;
989  }
990  fromLane -= 1;
991  if (fromLane < 0) {
992  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is not positive (" + fromLaneS + ").");
993  return;
994  }
995  // get the from-lane
996  std::string toLaneS = NBHelpers::normalIDRepresentation(myLineParser.get("NACHFSNR"));
997  int toLane = -1;
998  try {
999  toLane = TplConvert<char>::_2int(toLaneS.c_str());
1000  } catch (NumberFormatException&) {
1001  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not numeric (" + toLaneS + ").");
1002  return;
1003  }
1004  toLane -= 1;
1005  if (toLane < 0) {
1006  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is not positive (" + toLaneS + ").");
1007  return;
1008  }
1009  // !!! the next is probably a hack
1010  if (fromLane - fromLaneOffset < 0) {
1011  fromLaneOffset = 0;
1012  } else {
1013  fromLane = fromEdge->getNumLanes() - (fromLane - fromLaneOffset) - 1;
1014  }
1015  if (toLane - toLaneOffset < 0) {
1016  toLaneOffset = 0;
1017  } else {
1018  toLane = toEdge->getNumLanes() - (toLane - toLaneOffset) - 1;
1019  }
1020  //
1021  if ((int) fromEdge->getNumLanes() <= fromLane) {
1022  WRITE_ERROR("A from-lane number for edge '" + fromEdge->getID() + "' is larger than the edge's lane number (" + fromLaneS + ").");
1023  return;
1024  }
1025  if ((int) toEdge->getNumLanes() <= toLane) {
1026  WRITE_ERROR("A to-lane number for edge '" + toEdge->getID() + "' is larger than the edge's lane number (" + toLaneS + ").");
1027  return;
1028  }
1029  //
1030  fromEdge->addLane2LaneConnection(fromLane, toEdge, toLane, NBEdge::L2L_VALIDATED);
1031 }
1032 
1033 
1034 
1035 
1036 
1037 
1038 
1039 
1040 
1041 
1042 
1043 
1044 
1045 SUMOReal
1046 NIImporter_VISUM::getWeightedFloat(const std::string& name) {
1047  try {
1048  return TplConvert<char>::_2SUMOReal(myLineParser.get(name).c_str());
1049  } catch (...) {}
1050  try {
1051  return TplConvert<char>::_2SUMOReal(myLineParser.get((name + "(IV)")).c_str());
1052  } catch (...) {}
1053  return -1;
1054 }
1055 
1056 
1057 bool
1058 NIImporter_VISUM::getWeightedBool(const std::string& name) {
1059  try {
1060  return TplConvert<char>::_2bool(myLineParser.get(name).c_str());
1061  } catch (...) {}
1062  try {
1063  return TplConvert<char>::_2bool(myLineParser.get((name + "(IV)")).c_str());
1064  } catch (...) {}
1065  return false;
1066 }
1067 
1068 
1069 NBNode*
1071  std::string nodeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1072  NBNode* node = myNetBuilder.getNodeCont().retrieve(nodeS);
1073  if (node == 0) {
1074  WRITE_ERROR("The node '" + nodeS + "' is not known.");
1075  }
1076  return node;
1077 }
1078 
1079 
1080 NBNode*
1081 NIImporter_VISUM::getNamedNode(const std::string& fieldName1, const std::string& fieldName2) throw(OutOfBoundsException, NumberFormatException, UnknownElement) {
1082  if (myLineParser.know(fieldName1)) {
1083  return getNamedNode(fieldName1);
1084  } else {
1085  return getNamedNode(fieldName2);
1086  }
1087 }
1088 
1089 
1090 NBEdge*
1092  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1093  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1094  if (edge == 0) {
1095  WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1096  }
1097  return edge;
1098 }
1099 
1100 
1101 NBEdge*
1102 NIImporter_VISUM::getNamedEdge(const std::string& fieldName1, const std::string& fieldName2) throw(OutOfBoundsException, NumberFormatException, UnknownElement) {
1103  if (myLineParser.know(fieldName1)) {
1104  return getNamedEdge(fieldName1);
1105  } else {
1106  return getNamedEdge(fieldName2);
1107  }
1108 }
1109 
1110 
1111 
1112 NBEdge*
1114  std::string sid;
1115  if (edge->getID()[0] == '-') {
1116  sid = edge->getID().substr(1);
1117  } else {
1118  sid = "-" + edge->getID();
1119  }
1120  if (sid.find('_') != std::string::npos) {
1121  sid = sid.substr(0, sid.find('_'));
1122  }
1124 }
1125 
1126 
1127 NBEdge*
1129  if (begin == 0) {
1130  return 0;
1131  }
1132  NBEdge* ret = begin;
1133  std::string edgeID = ret->getID();
1134  // hangle forward
1135  while (ret != 0) {
1136  // ok, this is the edge we are looking for
1137  if (ret->getToNode() == node) {
1138  return ret;
1139  }
1140  const EdgeVector& nedges = ret->getToNode()->getOutgoingEdges();
1141  if (nedges.size() != 1) {
1142  // too many edges follow
1143  ret = 0;
1144  continue;
1145  }
1146  NBEdge* next = nedges[0];
1147  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1148  // ok, another edge is next...
1149  ret = 0;
1150  continue;
1151  }
1152  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1153  ret = 0;
1154  continue;
1155  }
1156  ret = next;
1157  }
1158 
1159  ret = begin;
1160  // hangle backward
1161  while (ret != 0) {
1162  // ok, this is the edge we are looking for
1163  if (ret->getFromNode() == node) {
1164  return ret;
1165  }
1166  const EdgeVector& nedges = ret->getFromNode()->getIncomingEdges();
1167  if (nedges.size() != 1) {
1168  // too many edges follow
1169  ret = 0;
1170  continue;
1171  }
1172  NBEdge* next = nedges[0];
1173  if (ret->getID().substr(0, edgeID.length()) != next->getID().substr(0, edgeID.length())) {
1174  // ok, another edge is next...
1175  ret = 0;
1176  continue;
1177  }
1178  if (next->getID().substr(next->getID().length() - node->getID().length()) != node->getID()) {
1179  ret = 0;
1180  continue;
1181  }
1182  ret = next;
1183  }
1184  return 0;
1185 }
1186 
1187 
1188 NBEdge*
1190  std::string edgeS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1191  NBEdge* edge = myNetBuilder.getEdgeCont().retrieve(edgeS);
1192  if (edge == 0) {
1193  WRITE_ERROR("The edge '" + edgeS + "' is not known.");
1194  }
1195  return getNamedEdgeContinuating(edge, node);
1196 }
1197 
1198 
1199 NBEdge*
1200 NIImporter_VISUM::getNamedEdgeContinuating(const std::string& fieldName1, const std::string& fieldName2,
1202  if (myLineParser.know(fieldName1)) {
1203  return getNamedEdgeContinuating(fieldName1, node);
1204  } else {
1205  return getNamedEdgeContinuating(fieldName2, node);
1206  }
1207 }
1208 
1209 
1210 NBEdge*
1212  EdgeVector::const_iterator i;
1213  for (i = FromNode->getOutgoingEdges().begin(); i != FromNode->getOutgoingEdges().end(); i++) {
1214  if (ToNode == (*i)->getToNode()) {
1215  return(*i);
1216  }
1217  }
1219  return 0;
1220 }
1221 
1222 
1223 SUMOReal
1225  std::string valS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1226  return TplConvert<char>::_2SUMOReal(valS.c_str());
1227 }
1228 
1229 
1230 SUMOReal
1231 NIImporter_VISUM::getNamedFloat(const std::string& fieldName, SUMOReal defaultValue) {
1232  try {
1233  std::string valS = NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1234  return TplConvert<char>::_2SUMOReal(valS.c_str());
1235  } catch (...) {
1236  return defaultValue;
1237  }
1238 }
1239 
1240 
1241 SUMOReal
1242 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2) throw(OutOfBoundsException, NumberFormatException, UnknownElement) {
1243  if (myLineParser.know(fieldName1)) {
1244  return getNamedFloat(fieldName1);
1245  } else {
1246  return getNamedFloat(fieldName2);
1247  }
1248 }
1249 
1250 
1251 SUMOReal
1252 NIImporter_VISUM::getNamedFloat(const std::string& fieldName1, const std::string& fieldName2,
1253  SUMOReal defaultValue) {
1254  if (myLineParser.know(fieldName1)) {
1255  return getNamedFloat(fieldName1, defaultValue);
1256  } else {
1257  return getNamedFloat(fieldName2, defaultValue);
1258  }
1259 }
1260 
1261 
1262 std::string
1264  return NBHelpers::normalIDRepresentation(myLineParser.get(fieldName));
1265 }
1266 
1267 
1268 std::string
1269 NIImporter_VISUM::getNamedString(const std::string& fieldName1,
1270  const std::string& fieldName2) throw(OutOfBoundsException, NumberFormatException, UnknownElement) {
1271  if (myLineParser.know(fieldName1)) {
1272  return getNamedString(fieldName1);
1273  } else {
1274  return getNamedString(fieldName2);
1275  }
1276 }
1277 
1278 
1279 
1280 
1281 
1282 
1283 NBNode*
1284 NIImporter_VISUM::buildDistrictNode(const std::string& id, NBNode* dest,
1285  bool isSource) {
1286  // get the district
1288  if (dist == 0) {
1289  return 0;
1290  }
1291  // build the id
1292  std::string nid;
1293  nid = id + "-" + dest->getID();
1294  if (!isSource) {
1295  nid = "-" + nid;
1296  }
1297  // insert the node
1298  if (!myNetBuilder.getNodeCont().insert(nid, dist->getPosition())) {
1299  WRITE_ERROR("Could not build connector node '" + nid + "'.");
1300  }
1301  // return the node
1302  return myNetBuilder.getNodeCont().retrieve(nid);
1303 }
1304 
1305 
1306 bool
1308  if (from == 0) {
1309  WRITE_ERROR(" The from-node was not found within the net");
1310  }
1311  if (to == 0) {
1312  WRITE_ERROR(" The to-node was not found within the net");
1313  }
1314  if (from == to) {
1315  WRITE_ERROR(" Both nodes are the same");
1316  }
1317  return from != 0 && to != 0 && from != to;
1318 }
1319 
1320 
1321 /****************************************************************************/
1322