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