Eclipse SUMO - Simulation of Urban MObility
NIImporter_DlrNavteq.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 // Importer for networks stored in Elmar's format
21 /****************************************************************************/
22 #include <config.h>
23 
24 #include <string>
25 #include <sstream>
26 #include <limits>
32 #include <utils/common/ToString.h>
37 #include <netbuild/NBNetBuilder.h>
38 #include <netbuild/NBNode.h>
39 #include <netbuild/NBNodeCont.h>
40 #include <netbuild/NBEdge.h>
41 #include <netbuild/NBEdgeCont.h>
42 #include <netbuild/NBTypeCont.h>
43 #include <netbuild/NBOwnTLDef.h>
45 #include "NILoader.h"
46 #include "NIImporter_DlrNavteq.h"
47 
48 
49 // ---------------------------------------------------------------------------
50 // static members
51 // ---------------------------------------------------------------------------
52 const std::string NIImporter_DlrNavteq::GEO_SCALE("1e-5");
53 const int NIImporter_DlrNavteq::EdgesHandler::MISSING_COLUMN = std::numeric_limits<int>::max();
54 const std::string NIImporter_DlrNavteq::UNDEFINED("-1");
56 
57 // ===========================================================================
58 // method definitions
59 // ===========================================================================
60 // ---------------------------------------------------------------------------
61 // static methods
62 // ---------------------------------------------------------------------------
63 void
65  // check whether the option is set (properly)
66  if (!oc.isSet("dlr-navteq-prefix")) {
67  return;
68  }
69  time_t csTime;
70  time(&csTime);
71  keepLength = oc.getBool("dlr-navteq.keep-length");
72  // parse file(s)
73  LineReader lr;
74  // load nodes
75  std::map<std::string, PositionVector> myGeoms;
76  PROGRESS_BEGIN_MESSAGE("Loading nodes");
77  std::string file = oc.getString("dlr-navteq-prefix") + "_nodes_unsplitted.txt";
78  NodesHandler handler1(nb.getNodeCont(), file, myGeoms);
79  if (!lr.setFile(file)) {
80  throw ProcessError("The file '" + file + "' could not be opened.");
81  }
82  lr.readAll(handler1);
84 
85  // load street names if given and wished
86  std::map<std::string, std::string> streetNames; // nameID : name
87  if (oc.getBool("output.street-names")) {
88  file = oc.getString("dlr-navteq-prefix") + "_names.txt";
89  if (lr.setFile(file)) {
90  PROGRESS_BEGIN_MESSAGE("Loading street names");
91  NamesHandler handler4(file, streetNames);
92  lr.readAll(handler4);
94  } else {
95  WRITE_WARNING("Output will not contain street names because the file '" + file + "' was not found");
96  }
97  }
98 
99  // load edges
100  PROGRESS_BEGIN_MESSAGE("Loading edges");
101  file = oc.getString("dlr-navteq-prefix") + "_links_unsplitted.txt";
102  // parse the file
103  EdgesHandler handler2(nb.getNodeCont(), nb.getEdgeCont(), nb.getTypeCont(), file, myGeoms, streetNames);
104  if (!lr.setFile(file)) {
105  throw ProcessError("The file '" + file + "' could not be opened.");
106  }
107  lr.readAll(handler2);
110 
111  // load traffic lights if given
112  file = oc.getString("dlr-navteq-prefix") + "_traffic_signals.txt";
113  if (lr.setFile(file)) {
114  PROGRESS_BEGIN_MESSAGE("Loading traffic lights");
115  TrafficlightsHandler handler3(nb.getNodeCont(), nb.getTLLogicCont(), nb.getEdgeCont(), file);
116  lr.readAll(handler3);
118  }
119 
120  // load prohibited manoeuvres if given
121  file = oc.getString("dlr-navteq-prefix") + "_prohibited_manoeuvres.txt";
122  if (lr.setFile(file)) {
123  PROGRESS_BEGIN_MESSAGE("Loading prohibited manoeuvres");
124  ProhibitionHandler handler6(nb.getEdgeCont(), file, csTime);
125  lr.readAll(handler6);
127  }
128 
129  // load connected lanes if given
130  file = oc.getString("dlr-navteq-prefix") + "_connected_lanes.txt";
131  if (lr.setFile(file)) {
132  PROGRESS_BEGIN_MESSAGE("Loading connected lanes");
133  ConnectedLanesHandler handler7(nb.getEdgeCont());
134  lr.readAll(handler7);
136  }
137 
138  // load time restrictions if given
139  file = oc.getString("dlr-navteq-prefix") + "_links_timerestrictions.txt";
140  if (lr.setFile(file)) {
141  PROGRESS_BEGIN_MESSAGE("Loading time restrictions");
142  if (!oc.isDefault("construction-date")) {
143  csTime = readDate(oc.getString("construction-date"));
144  }
145  TimeRestrictionsHandler handler5(nb.getEdgeCont(), nb.getDistrictCont(), csTime);
146  lr.readAll(handler5);
147  handler5.printSummary();
149  }
150 
151 }
152 
153 double
154 NIImporter_DlrNavteq::readVersion(const std::string& line, const std::string& file) {
155  assert(line[0] == '#');
156  const std::string marker = "extraction version: v";
157  const std::string lowerCase = StringUtils::to_lower_case(line);
158  if (lowerCase.find(marker) == std::string::npos) {
159  return -1;
160  }
161  const int vStart = (int)(lowerCase.find(marker) + marker.size());
162  const int vEnd = (int)line.find(" ", vStart);
163  try {
164  const double version = StringUtils::toDouble(line.substr(vStart, vEnd - vStart));
165  if (version < 0) {
166  throw ProcessError("Invalid version number '" + toString(version) + "' in file '" + file + "'.");
167  }
168  return version;
169  } catch (NumberFormatException&) {
170  throw ProcessError("Non-numerical value '" + line.substr(vStart, vEnd - vStart) + "' for version string in file '" + file + "'.");
171  }
172 }
173 
174 
175 // ---------------------------------------------------------------------------
176 // definitions of NIImporter_DlrNavteq::NodesHandler-methods
177 // ---------------------------------------------------------------------------
179  const std::string& file,
180  std::map<std::string, PositionVector>& geoms)
181  : myNodeCont(nc), myGeoms(geoms) {
182  UNUSED_PARAMETER(file);
183 }
184 
185 
187 
188 
189 bool
190 NIImporter_DlrNavteq::NodesHandler::report(const std::string& result) {
191  if (result[0] == '#') {
192  return true;
193  }
194  std::string id;
195  double x, y;
196  int no_geoms, intermediate;
197  // parse
198  std::istringstream stream(result);
199  // id
200  stream >> id;
201  if (stream.fail()) {
202  throw ProcessError("Something is wrong with the following data line\n" + result);
203  }
204  // intermediate?
205  stream >> intermediate;
206  if (stream.fail()) {
207  if (myNodeCont.size() == 0) { // be generous with extra data at beginning of file
208  return true;
209  }
210  throw ProcessError("Non-numerical value for intermediate status in node " + id + ".");
211  }
212  // number of geometrical information
213  stream >> no_geoms;
214  if (stream.fail()) {
215  throw ProcessError("Non-numerical value for number of geometries in node " + id + ".");
216  }
217  // geometrical information
218  PositionVector geoms;
219  for (int i = 0; i < no_geoms; i++) {
220  stream >> x;
221  if (stream.fail()) {
222  throw ProcessError("Non-numerical value for x-position in node " + id + ".");
223  }
224  stream >> y;
225  if (stream.fail()) {
226  throw ProcessError("Non-numerical value for y-position in node " + id + ".");
227  }
228  Position pos(x, y);
229  if (!NBNetBuilder::transformCoordinate(pos, true)) {
230  throw ProcessError("Unable to project coordinates for node " + id + ".");
231  }
232  geoms.push_back(pos);
233  }
234 
235  if (intermediate == 0) {
236  NBNode* n = new NBNode(id, geoms[0]);
237  if (!myNodeCont.insert(n)) {
238  delete n;
239  throw ProcessError("Could not add node '" + id + "'.");
240  }
241  } else {
242  myGeoms[id] = geoms;
243  }
244  return true;
245 }
246 
247 
248 // ---------------------------------------------------------------------------
249 // definitions of NIImporter_DlrNavteq::EdgesHandler-methods
250 // ---------------------------------------------------------------------------
252  NBTypeCont& tc, const std::string& file,
253  std::map<std::string, PositionVector>& geoms,
254  std::map<std::string, std::string>& streetNames):
255  myNodeCont(nc),
256  myEdgeCont(ec),
257  myTypeCont(tc),
258  myGeoms(geoms),
259  myStreetNames(streetNames),
260  myVersion(0),
261  myFile(file) {
262 }
263 
264 
266 
267 
268 bool
269 NIImporter_DlrNavteq::EdgesHandler::report(const std::string& result) {
270  // parse version number from first comment line and initialize column definitions
271  if (result[0] == '#') {
272  if (!myColumns.empty()) {
273  return true;
274  }
275  const double version = readVersion(result, myFile);
276  if (version > 0) {
277  myVersion = version;
278  // init columns
279  const int NUM_COLUMNS = 25; // @note arrays must match this size!
280  const int MC = MISSING_COLUMN;
281  if (myVersion < 3) {
282  const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, MC, 12, 13, 14, 15, 16, 17, 18, 19, 20, MC, MC, -21};
283  myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
284  } else if (myVersion < 6) {
285  const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, MC, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, -23};
286  myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
287  } else {
288  const int columns[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
289  myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
290  }
291  }
292  return true;
293  }
294  if (myColumns.empty()) {
295  throw ProcessError("Missing version string in file '" + myFile + "'.");
296  }
297  // interpret link attributes
299  const std::string id = getColumn(st, LINK_ID);
300  // form of way (for priority and permissions)
301  int form_of_way;
302  try {
303  form_of_way = StringUtils::toInt(getColumn(st, FORM_OF_WAY));
304  } catch (NumberFormatException&) {
305  throw ProcessError("Non-numerical value for form_of_way of link '" + id + "'.");
306  }
307  // brunnel type (bridge/tunnel/ferry (for permissions)
308  int brunnel_type;
309  try {
310  brunnel_type = StringUtils::toInt(getColumn(st, BRUNNEL_TYPE));
311  } catch (NumberFormatException&) {
312  throw ProcessError("Non-numerical value for brunnel_type of link '" + id + "'.");
313  }
314  // priority based on street_type / frc
315  int priority;
316  try {
317  priority = -StringUtils::toInt(getColumn(st, FUNCTIONAL_ROAD_CLASS));
318  // lower priority using form_of_way
319  if (form_of_way == 11) {
320  priority -= 1; // frontage road, very often with lowered curb
321  } else if (form_of_way > 11) {
322  priority -= 2; // parking/service access assume lowered curb
323  }
324  } catch (NumberFormatException&) {
325  throw ProcessError("Non-numerical value for street_type of link '" + id + "').");
326  }
327  // street name
328  std::string streetName = getStreetNameFromIDs(
329  getColumn(st, NAME_ID1_REGIONAL),
330  getColumn(st, NAME_ID2_LOCAL));
331  // try to get the nodes
332  const std::string fromID = getColumn(st, NODE_ID_FROM);
333  const std::string toID = getColumn(st, NODE_ID_TO);
334  NBNode* from = myNodeCont.retrieve(fromID);
335  NBNode* to = myNodeCont.retrieve(toID);
336  if (from == nullptr) {
337  throw ProcessError("The from-node '" + fromID + "' of link '" + id + "' could not be found");
338  }
339  if (to == nullptr) {
340  throw ProcessError("The to-node '" + toID + "' of link '" + id + "' could not be found");
341  }
342  // speed
343  double speed;
344  try {
345  speed = StringUtils::toInt(getColumn(st, SPEED_RESTRICTION, "-1")) / 3.6;
346  } catch (NumberFormatException&) {
347  throw ProcessError("Non-numerical value for the SPEED_RESTRICTION of link '" + id + "'.");
348  }
349  if (speed < 0) {
350  // speed category as fallback
351  speed = NINavTeqHelper::getSpeed(id, getColumn(st, SPEED_CATEGORY));
352  }
353  // number of lanes
354  int numLanes;
355  try {
356  // EXTENDED_NUMBER_OF_LANES is prefered but may not be defined
357  numLanes = StringUtils::toInt(getColumn(st, EXTENDED_NUMBER_OF_LANES, "-1"));
358  if (numLanes == -1) {
359  numLanes = NINavTeqHelper::getLaneNumber(id, getColumn(st, NUMBER_OF_LANES), speed);
360  }
361  } catch (NumberFormatException&) {
362  throw ProcessError("Non-numerical value for the number of lanes of link '" + id + "'.");
363  }
364 
365  const std::string navTeqTypeId = getColumn(st, VEHICLE_TYPE) + "_" + getColumn(st, FORM_OF_WAY);
366  // build the edge
367  NBEdge* e = nullptr;
368  const std::string interID = getColumn(st, BETWEEN_NODE_ID);
369  if (interID == "-1") {
370  e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, numLanes, priority,
372  } else {
373  PositionVector geoms = myGeoms[interID];
374  if (getColumn(st, CONNECTION, "0") == "1") {
375  geoms = geoms.reverse();
376  }
377  geoms.insert(geoms.begin(), from->getPosition());
378  geoms.push_back(to->getPosition());
379  const std::string origID = OptionsCont::getOptions().getBool("output.original-names") ? id : "";
380  e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, numLanes, priority,
382  }
383 
384  //Import length or edges from input file
385  if (keepLength) {
386  const double length = StringUtils::toDouble(getColumn(st, LENGTH));
387  e->setLoadedLength(length);
388  }
389 
390  // NavTeq imports can be done with a typemap (if supplied), if not, the old defaults are used
391  if (myTypeCont.knows(navTeqTypeId)) {
392  e->setPermissions(myTypeCont.getEdgeTypePermissions(navTeqTypeId));
393  } else {
394  // add vehicle type information to the edge
395  const SVCPermissions allPermissions = myTypeCont.getEdgeTypePermissions("");
396  const SVCPermissions defaultPermissions = OptionsCont::getOptions().getBool("dlr-navteq.tolerant-permissions") ? allPermissions : 0;
397  if (myVersion < 6.0) {
398  NINavTeqHelper::addVehicleClasses(*e, getColumn(st, VEHICLE_TYPE), allPermissions, defaultPermissions);
399  } else {
400  NINavTeqHelper::addVehicleClassesV6(*e, getColumn(st, VEHICLE_TYPE), allPermissions, defaultPermissions);
401  }
402  // permission modifications based on form_of_way
403  if (form_of_way == 14) { // pedestrian area (fussgaengerzone)
404  // unfortunately, the veh_type string is misleading in this case
406  }
407  // permission modifications based on brunnel_type
408  if (brunnel_type == 10) { // ferry
409  e->setPermissions(SVC_SHIP, -1);
410  }
411  }
412 
413  // insert the edge to the network
414  if (!myEdgeCont.insert(e)) {
415  delete e;
416  throw ProcessError("Could not add edge '" + id + "'.");
417  }
418  return true;
419 }
420 
421 
422 std::string
423 NIImporter_DlrNavteq::EdgesHandler::getColumn(const StringTokenizer& st, ColumnName name, const std::string fallback) {
424  assert(!myColumns.empty());
425  if (myColumns[name] == MISSING_COLUMN) {
426  if (fallback == "") {
427  throw ProcessError("Missing column " + toString(name) + ".");
428  } else {
429  return fallback;
430  }
431  } else if (myColumns[name] >= 0) {
432  return st.get((int)(myColumns[name]));
433  } else {
434  // negative column number implies an optional column
435  if ((int) st.size() <= -myColumns[name]) {
436  // the column is not present
437  if (fallback == "") {
438  throw ProcessError("Missing optional column " + toString(name) + " without default value.");
439  } else {
440  return fallback;
441  }
442  } else {
443  return st.get((int)(-myColumns[name]));
444  }
445  }
446 }
447 
448 
449 std::string
451  const std::string& regionalID, const std::string& localID) const {
452  std::string result = "";
453  bool hadRegional = false;
454  if (myStreetNames.count(regionalID) > 0) {
455  hadRegional = true;
456  result += myStreetNames[regionalID];
457  }
458  if (myStreetNames.count(localID) > 0) {
459  if (hadRegional) {
460  result += " / ";
461  }
462  result += myStreetNames[localID];
463  }
464  return result;
465 }
466 
467 // ---------------------------------------------------------------------------
468 // definitions of NIImporter_DlrNavteq::TrafficlightsHandler-methods
469 // ---------------------------------------------------------------------------
472  NBEdgeCont& ne,
473  const std::string& file) :
474  myNodeCont(nc),
475  myTLLogicCont(tlc),
476  myEdgeCont(ne) {
477  UNUSED_PARAMETER(file);
478 }
479 
480 
482 
483 
484 bool
486 // #ID POICOL-TYPE DESCRIPTION LONGITUDE LATITUDE NAVTEQ_LINK_ID NODEID
487 
488  if (result[0] == '#') {
489  return true;
490  }
492  const std::string edgeID = st.get(5);
493  NBEdge* edge = myEdgeCont.retrieve(edgeID);
494  if (edge == nullptr) {
495  WRITE_WARNINGF("The traffic light edge '%' could not be found.", edgeID);
496  } else {
497  NBNode* node = edge->getToNode();
498  if (node->getType() != SumoXMLNodeType::TRAFFIC_LIGHT) {
500  // @note. There may be additional information somewhere in the GDF files about traffic light type ...
502  // @note actually we could use the navteq node ID here
503  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(node->getID(), node, 0, type);
504  if (!myTLLogicCont.insert(tlDef)) {
505  // actually, nothing should fail here
506  delete tlDef;
507  throw ProcessError("Could not allocate tls for '" + node->getID() + "'.");
508  }
509  }
510  }
511  return true;
512 }
513 
514 
515 // ---------------------------------------------------------------------------
516 // definitions of NIImporter_DlrNavteq::NamesHandler-methods
517 // ---------------------------------------------------------------------------
519  const std::string& file, std::map<std::string, std::string>& streetNames) :
520  myStreetNames(streetNames) {
521  UNUSED_PARAMETER(file);
522 }
523 
524 
526 
527 
528 bool
529 NIImporter_DlrNavteq::NamesHandler::report(const std::string& result) {
530 // # NAME_ID Name
531  if (result[0] == '#') {
532  return true;
533  }
535  if (st.size() == 1) {
536  return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
537  }
538  assert(st.size() >= 2);
539  const std::string id = st.next();
540  if (st.size() > 2) {
541  const std::string permanent_id_info = st.next();
542  }
543  myStreetNames[id] = st.next();
544  return true;
545 }
546 
547 
548 // ---------------------------------------------------------------------------
549 // definitions of NIImporter_DlrNavteq::TimeRestrictionsHandler-methods
550 // ---------------------------------------------------------------------------
552  myEdgeCont(ec),
553  myDistrictCont(dc),
554  myConstructionTime(constructionTime),
555  myCS_min(std::numeric_limits<time_t>::max()),
556  myCS_max(std::numeric_limits<time_t>::min()),
557  myConstructionEntries(0),
558  myNotStarted(0),
559  myUnderConstruction(0),
560  myFinished(0),
561  myRemovedEdges(0) {
562 }
563 
564 
566 
567 
568 bool
570 // # NAME_ID Name
571  if (result[0] == '#') {
572  return true;
573  }
575  const std::string id = st.next();
576  const std::string type = st.next();
577  const std::string directionOfFlow = st.next(); // can be ignored since unidirectional edge ids are referenced in the file
578  const std::string throughTraffic = st.next();
579  const std::string vehicleType = st.next();
580  const std::string validityPeriod = st.next();
581  const std::string warning = "Unrecognized TIME_REC '" + validityPeriod + "'";
582  if (type == "CS") {
583  myConstructionEntries++;
584  if (validityPeriod.size() > 1024) {
585  WRITE_WARNING(warning);
586  }
587  // construction
588  char start[1024];
589  char duration[1024];
590 
591  int matched;
592 
593  matched = sscanf(validityPeriod.c_str(), "[(%[^)]){%[^}]}]", start, duration);
594  if (matched == 2) {
595  time_t tStart = readTimeRec(start, "");
596  time_t tEnd = readTimeRec(start, duration);
597  myCS_min = MIN2(myCS_min, tStart);
598  myCS_max = MAX2(myCS_max, tEnd);
599  //std::cout << " start=" << start << " tStart=" << tStart<< " translation=" << asctime(localtime(&tStart)) << "";
600  //std::cout << " duration=" << duration << " tEnd=" << tEnd << " translation=" << asctime(localtime(&tEnd)) << "\n";
601  if (myConstructionTime < tEnd) {
602  NBEdge* edge = myEdgeCont.retrieve(id);
603  if (edge != nullptr) {
604  myRemovedEdges++;
605  myEdgeCont.extract(myDistrictCont, edge, true);
606  }
607  if (myConstructionTime < tStart) {
608  myNotStarted++;
609  } else {
610  myUnderConstruction++;
611  }
612  } else {
613  myFinished++;
614  }
615  } else {
616  WRITE_WARNING(warning);
617  };
618  }
619  return true;
620 }
621 
622 
623 void
625  if (myConstructionEntries > 0) {
626  char buff[1024];
627  std::ostringstream msg;
628  strftime(buff, 1024, "%Y-%m-%d", localtime(&myCS_min));
629  msg << "Parsed " << myConstructionEntries << " construction entries between " << buff;
630  strftime(buff, 1024, "%Y-%m-%d", localtime(&myCS_max));
631  msg << " and " << buff << ".\n";
632  strftime(buff, 1024, "%Y-%m-%d", localtime(&myConstructionTime));
633  msg << "Removed " << myRemovedEdges << " edges not yet constructed at " << buff << ".\n";
634  msg << " not yet started: " << myNotStarted << "\n";
635  msg << " under construction: " << myUnderConstruction << "\n";
636  msg << " finished: " << myFinished << "\n";
637  WRITE_MESSAGE(msg.str());
638  }
639 }
640 
641 
642 int
643 NIImporter_DlrNavteq::readPrefixedInt(const std::string& s, const std::string& prefix, int fallBack) {
644  int result = fallBack;
645  size_t pos = s.find(prefix);
646  if (pos != std::string::npos) {
647  sscanf(s.substr(pos).c_str(), (prefix + "%i").c_str(), &result);
648  }
649  return result;
650 }
651 
652 time_t
653 NIImporter_DlrNavteq::readTimeRec(const std::string& start, const std::string& duration) {
654  // http://www.cplusplus.com/reference/ctime/mktime/
655  struct tm timeinfo;
656  timeinfo.tm_hour = 0;
657  timeinfo.tm_min = 0;
658  timeinfo.tm_sec = 0;
659  timeinfo.tm_year = 0;
660  timeinfo.tm_mon = 0;
661  timeinfo.tm_mday = 1;
662  timeinfo.tm_wday = 0;
663  timeinfo.tm_yday = 0;
664  timeinfo.tm_isdst = 0;
665 
666  timeinfo.tm_year = readPrefixedInt(start, "y") + readPrefixedInt(duration, "y") - 1900;
667  timeinfo.tm_mon = readPrefixedInt(start, "M") + readPrefixedInt(duration, "M") - 1;
668  timeinfo.tm_mday = 7 * (readPrefixedInt(start, "w") + readPrefixedInt(duration, "w"));
669  timeinfo.tm_mday += readPrefixedInt(start, "d") + readPrefixedInt(duration, "d");
670 
671  time_t result = mktime(&timeinfo);
672  return result;
673 }
674 
675 
676 time_t
677 NIImporter_DlrNavteq::readDate(const std::string& yyyymmdd) {
678  struct tm timeinfo;
679  timeinfo.tm_hour = 0;
680  timeinfo.tm_min = 0;
681  timeinfo.tm_sec = 0;
682  timeinfo.tm_wday = 0;
683  timeinfo.tm_yday = 0;
684  timeinfo.tm_isdst = 0;
685 
686  if (yyyymmdd.size() == 10
687  && yyyymmdd[4] == '-'
688  && yyyymmdd[7] == '-') {
689  try {
690  timeinfo.tm_year = StringUtils::toInt(yyyymmdd.substr(0, 4)) - 1900;
691  timeinfo.tm_mon = StringUtils::toInt(yyyymmdd.substr(5, 2)) - 1;
692  timeinfo.tm_mday = StringUtils::toInt(yyyymmdd.substr(8, 2));
693  return mktime(&timeinfo);
694  } catch (...) {
695  }
696  }
697  WRITE_ERROR("Could not parse YYYY-MM-DD date '" + yyyymmdd + "'");
698  time_t now;
699  time(&now);
700  return now;
701 }
702 
703 // ---------------------------------------------------------------------------
704 // definitions of NIImporter_DlrNavteq::ProhibitionHandler-methods
705 // ---------------------------------------------------------------------------
707  NBEdgeCont& ec, const std::string& file, time_t constructionTime) :
708  myEdgeCont(ec),
709  myFile(file),
710  myVersion(0),
711  myConstructionTime(constructionTime) {
712 }
713 
714 
716 
717 
718 bool
720 // # NAME_ID Name
721  if (result[0] == '#') {
722  if (myVersion == 0) {
723  const double version = readVersion(result, myFile);
724  if (version > 0) {
725  myVersion = version;
726  }
727  }
728  return true;
729  }
731  if (st.size() == 1) {
732  return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
733  }
734  if (myVersion >= 6) {
735  assert(st.size() >= 7);
736  const std::string id = st.next();
737  const std::string permanent = st.next();
738  const std::string validityPeriod = st.next();
739  const std::string throughTraffic = st.next();
740  const std::string vehicleType = st.next();
741  if (validityPeriod != UNDEFINED) {
742  WRITE_WARNINGF("Ignoring temporary prohibited manoeuvre (%).", validityPeriod);
743  return true;
744  }
745  }
746  const std::string startEdge = st.next();
747  const std::string endEdge = st.get(st.size() - 1);
748 
749  NBEdge* from = myEdgeCont.retrieve(startEdge);
750  if (from == nullptr) {
751  WRITE_WARNINGF("Ignoring prohibition from unknown start edge '%'.", startEdge);
752  return true;
753  }
754  NBEdge* to = myEdgeCont.retrieve(endEdge);
755  if (to == nullptr) {
756  WRITE_WARNINGF("Ignoring prohibition from unknown end edge '%'.", endEdge);
757  return true;
758  }
759  from->removeFromConnections(to, -1, -1, true);
760  return true;
761 }
762 
763 
764 // ---------------------------------------------------------------------------
765 // definitions of NIImporter_DlrNavteq::ConnectedLanesHandler-methods
766 // ---------------------------------------------------------------------------
768  NBEdgeCont& ec) :
769  myEdgeCont(ec) {
770 }
771 
772 
774 
775 
776 bool
778  if (result[0] == '#') {
779  return true;
780  }
782  if (st.size() == 1) {
783  return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
784  }
785  assert(st.size() >= 7);
786  const std::string nodeID = st.next();
787  const std::string vehicleType = st.next();
788  const std::string fromLaneS = st.next();
789  const std::string toLaneS = st.next();
790  const std::string throughTraffic = st.next();
791  const std::string startEdge = st.next();
792  const std::string endEdge = st.get(st.size() - 1);
793 
794  NBEdge* from = myEdgeCont.retrieve(startEdge);
795  if (from == nullptr) {
796  WRITE_WARNINGF("Ignoring prohibition from unknown start edge '%'.", startEdge);
797  return true;
798  }
799  NBEdge* to = myEdgeCont.retrieve(endEdge);
800  if (to == nullptr) {
801  WRITE_WARNINGF("Ignoring prohibition from unknown end edge '%'.", endEdge);
802  return true;
803  }
804  int fromLane = StringUtils::toInt(fromLaneS) - 1; // one based
805  if (fromLane < 0 || fromLane >= from->getNumLanes()) {
806  WRITE_WARNINGF("Ignoring invalid lane index '%' in connection from edge '%' with % lanes.", fromLaneS, startEdge, from->getNumLanes());
807  return true;
808  }
809  int toLane = StringUtils::toInt(toLaneS) - 1; // one based
810  if (toLane < 0 || toLane >= to->getNumLanes()) {
811  WRITE_WARNINGF("Ignoring invalid lane index '%' in connection to edge '%' with % lanes", toLaneS, endEdge, to->getNumLanes());
812  return true;
813  }
814  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::Lane2LaneInfoType::USER, true)) {
815  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
816  WRITE_WARNINGF("Could not set loaded connection from '%' to '%'.", from->getLaneID(fromLane), to->getLaneID(toLane));
817  }
818  // set as to be re-applied after network processing
819  // if this connection runs across a node cluster it may not be possible to set this
820  const bool warnOnly = st.size() > 7;
821  myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, false, KEEPCLEAR_UNSPECIFIED,
824  }
825  // ensure that connections for other lanes are guessed if not specified
827  from->getLaneStruct(fromLane).connectionsDone = true;
828  return true;
829 }
830 
831 
832 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:277
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:278
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:280
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:279
@ KEEPCLEAR_UNSPECIFIED
Definition: NBCont.h:60
@ SVC_SHIP
is an arbitrary ship
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
TrafficLightType
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:29
T MIN2(T a, T b)
Definition: StdDefs.h:73
T MAX2(T a, T b)
Definition: StdDefs.h:79
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
Retrieves a file linewise and reports the lines to a handler.
Definition: LineReader.h:48
bool setFile(const std::string &file)
Reinitialises the reader for reading from the given file.
Definition: LineReader.cpp:179
void readAll(LineHandler &lh)
Reads the whole file linewise, reporting every line to the given LineHandler.
Definition: LineReader.cpp:57
A container for districts.
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:59
void recheckLaneSpread()
Rechecks whether the lane spread is proper.
The representation of a single edge during network building.
Definition: NBEdge.h:91
void setPermissions(SVCPermissions permissions, int lane=-1)
set allowed/disallowed classes for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:3627
void disallowVehicleClass(int lane, SUMOVehicleClass vclass)
set disallowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:3465
const std::string & getID() const
Definition: NBEdge.h:1423
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:516
@ INIT
The edge has been loaded, nothing is computed yet.
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:339
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:490
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:333
void removeFromConnections(NBEdge *toEdge, int fromLane=-1, int toLane=-1, bool tryLater=false, const bool adaptToLaneRemoval=false, const bool keepPossibleTurns=false)
Removes the specified connection(s)
Definition: NBEdge.cpp:1318
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:336
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:3345
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:330
@ USER
The connection was given by the user.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:324
void declareConnectionsAsLoaded(EdgeBuildingStep step=EdgeBuildingStep::LANES2LANES_USER)
declares connections as fully loaded. This is needed to avoid recomputing connections if an edge has ...
Definition: NBEdge.h:1340
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:327
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:1019
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1326
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:3670
Instance responsible for building networks.
Definition: NBNetBuilder.h:107
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:168
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:158
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:148
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:153
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:163
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:58
Represents a single node (junction) during network building.
Definition: NBNode.h:66
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:306
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:271
const Position & getPosition() const
Definition: NBNode.h:246
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:44
The base class for traffic light logic definitions.
A container for traffic light definitions and built programs.
A storage for available edgeTypes of edges.
Definition: NBTypeCont.h:52
Imports prohibitions regarding connectivity.
bool report(const std::string &result)
Parsing method.
Importer of edges stored in unsplit elmar format.
std::string getStreetNameFromIDs(const std::string &regionalID, const std::string &localID) const
build the street name for the given ids
std::string getColumn(const StringTokenizer &st, ColumnName name, const std::string fallback="")
EdgesHandler(NBNodeCont &nc, NBEdgeCont &ec, NBTypeCont &tc, const std::string &file, std::map< std::string, PositionVector > &geoms, std::map< std::string, std::string > &streetNames)
Constructor.
bool report(const std::string &result)
Parsing method.
Importer of street names in DLRNavteq's (aka elmar) format.
bool report(const std::string &result)
Parsing method.
NamesHandler(const std::string &file, std::map< std::string, std::string > &streetNames)
Constructor.
Importer of nodes stored in unsplit elmar format.
NodesHandler(NBNodeCont &nc, const std::string &file, std::map< std::string, PositionVector > &geoms)
Constructor.
bool report(const std::string &result)
Parsing method.
Imports prohibitions regarding connectivity.
bool report(const std::string &result)
Parsing method.
ProhibitionHandler(NBEdgeCont &ne, const std::string &file, time_t constructionTime)
Constructor.
Importer of street names in DLRNavteq's (aka elmar) format.
TimeRestrictionsHandler(NBEdgeCont &ec, NBDistrictCont &dc, time_t constructionTime)
Constructor.
bool report(const std::string &result)
Parsing method.
Importer of traffic lights stored in DLRNavteq's (aka elmar) format.
TrafficlightsHandler(NBNodeCont &nc, NBTrafficLightLogicCont &tlc, NBEdgeCont &ne, const std::string &file)
Constructor.
bool report(const std::string &result)
Parsing method.
static double readVersion(const std::string &line, const std::string &file)
static time_t readTimeRec(const std::string &start, const std::string &duration)
static int readPrefixedInt(const std::string &s, const std::string &prefix, int fallBack=0)
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given dlr-navteq (aka Elmar-fomat) folder.
static const std::string GEO_SCALE
scaling factor for geo coordinates (DLRNavteq format uses this to increase floating point precisions)
static const std::string UNDEFINED
magic value for undefined stuff
static time_t readDate(const std::string &yyyymmdd)
static bool keepLength
decides whether the edge length of the input format should be used
static void addVehicleClasses(NBEdge &e, const std::string &classS, const SVCPermissions allPermissions, const SVCPermissions defaultPermissions)
Adds vehicle classes parsing the given list of allowed vehicles.
static void addVehicleClassesV6(NBEdge &e, const std::string &classS, const SVCPermissions allPermissions, const SVCPermissions defaultPermissions)
same as addVehicleClasses but for version 6+
static int getLaneNumber(const std::string &id, const std::string &laneNoS, double speed)
Returns the lane number evaluating the given Navteq-description.
static double getSpeed(const std::string &id, const std::string &speedClassS)
Returns the speed evaluating the given Navteq-description.
const std::string & getID() const
Returns the id.
Definition: Named.h:73
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
std::string getString(const std::string &name) const
Returns the string-value of the named option (only for Option_String)
bool isDefault(const std::string &name) const
Returns the information whether the named option has still the default value.
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
A list of positions.
static const PositionVector EMPTY
empty Vector
PositionVector reverse() const
reverse position vector
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
T get(const std::string &str) const
int size() const
returns the number of existing substrings
static const int WHITECHARS
identifier for splitting the given string at all whitespace characters
std::string get(int pos) const
returns the item at the given position
static const int TAB
the ascii index of the tab character
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static std::string to_lower_case(std::string str)
Transfers the content to lower case.
Definition: StringUtils.cpp:58
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
bool connectionsDone
Whether connection information for this lane is already completed.
Definition: NBEdge.h:176