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.dev/sumo
3 // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
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(TL("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(TLF("The file '%' could not be opened.", file));
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(TL("Loading street names"));
91  NamesHandler handler4(file, streetNames);
92  lr.readAll(handler4);
94  } else {
95  WRITE_WARNINGF(TL("Output will not contain street names because the file '%' was not found"), file);
96  }
97  }
98 
99  // load edges
100  PROGRESS_BEGIN_MESSAGE(TL("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(TLF("The file '%' could not be opened.", file));
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(TL("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(TL("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(TL("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(TL("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(TLF("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(TLF("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(TLF("Non-numerical value for x-position in node %.", id));
223  }
224  stream >> y;
225  if (stream.fail()) {
226  throw ProcessError(TLF("Non-numerical value for y-position in node %.", id));
227  }
228  Position pos(x, y);
229  if (!NBNetBuilder::transformCoordinate(pos, true)) {
230  throw ProcessError(TLF("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  if (OptionsCont::getOptions().getBool("ignore-errors")) {
240  WRITE_WARNINGF(TL("Could not add node '%'."), id);
241  } else {
242  throw ProcessError(TLF("Could not add node '%'.", id));
243  }
244  }
245  } else {
246  myGeoms[id] = geoms;
247  }
248  return true;
249 }
250 
251 
252 // ---------------------------------------------------------------------------
253 // definitions of NIImporter_DlrNavteq::EdgesHandler-methods
254 // ---------------------------------------------------------------------------
256  NBTypeCont& tc, const std::string& file,
257  std::map<std::string, PositionVector>& geoms,
258  std::map<std::string, std::string>& streetNames):
259  myNodeCont(nc),
260  myEdgeCont(ec),
261  myTypeCont(tc),
262  myGeoms(geoms),
263  myStreetNames(streetNames),
264  myVersion(0),
265  myFile(file) {
266 }
267 
268 
270 
271 
272 bool
273 NIImporter_DlrNavteq::EdgesHandler::report(const std::string& result) {
274  // parse version number from first comment line and initialize column definitions
275  if (result[0] == '#') {
276  if (!myColumns.empty()) {
277  return true;
278  }
279  const double version = readVersion(result, myFile);
280  if (version > 0) {
281  myVersion = version;
282  // init columns
283  const int NUM_COLUMNS = 25; // @note arrays must match this size!
284  const int MC = MISSING_COLUMN;
285  if (myVersion < 3) {
286  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};
287  myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
288  } else if (myVersion < 6) {
289  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};
290  myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
291  } else {
292  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};
293  myColumns = std::vector<int>(columns, columns + NUM_COLUMNS);
294  }
295  }
296  return true;
297  }
298  if (myColumns.empty()) {
299  throw ProcessError(TLF("Missing version string in file '%'.", myFile));
300  }
301  // interpret link attributes
303  const std::string id = getColumn(st, LINK_ID);
304  // form of way (for priority and permissions)
305  int form_of_way;
306  try {
307  form_of_way = StringUtils::toInt(getColumn(st, FORM_OF_WAY));
308  } catch (NumberFormatException&) {
309  throw ProcessError(TLF("Non-numerical value for form_of_way of link '%'.", id));
310  }
311  // brunnel type (bridge/tunnel/ferry (for permissions)
312  int brunnel_type;
313  try {
314  brunnel_type = StringUtils::toInt(getColumn(st, BRUNNEL_TYPE));
315  } catch (NumberFormatException&) {
316  throw ProcessError(TLF("Non-numerical value for brunnel_type of link '%'.", id));
317  }
318  // priority based on street_type / frc
319  int priority;
320  try {
321  priority = -StringUtils::toInt(getColumn(st, FUNCTIONAL_ROAD_CLASS));
322  // lower priority using form_of_way
323  if (form_of_way == 11) {
324  priority -= 1; // frontage road, very often with lowered curb
325  } else if (form_of_way > 11) {
326  priority -= 2; // parking/service access assume lowered curb
327  }
328  } catch (NumberFormatException&) {
329  throw ProcessError(TLF("Non-numerical value for street_type of link '%'.", id));
330  }
331  // street name
332  std::string streetName = getStreetNameFromIDs(
333  getColumn(st, NAME_ID1_REGIONAL),
334  getColumn(st, NAME_ID2_LOCAL));
335  // try to get the nodes
336  const std::string fromID = getColumn(st, NODE_ID_FROM);
337  const std::string toID = getColumn(st, NODE_ID_TO);
338  NBNode* from = myNodeCont.retrieve(fromID);
339  NBNode* to = myNodeCont.retrieve(toID);
340  if (from == nullptr) {
341  throw ProcessError("The from-node '" + fromID + "' of link '" + id + "' could not be found");
342  }
343  if (to == nullptr) {
344  throw ProcessError("The to-node '" + toID + "' of link '" + id + "' could not be found");
345  }
346  // speed
347  double speed;
348  try {
349  speed = StringUtils::toInt(getColumn(st, SPEED_RESTRICTION, "-1")) / 3.6;
350  } catch (NumberFormatException&) {
351  throw ProcessError(TLF("Non-numerical value for the SPEED_RESTRICTION of link '%'.", id));
352  }
353  if (speed < 0) {
354  // speed category as fallback
355  speed = NINavTeqHelper::getSpeed(id, getColumn(st, SPEED_CATEGORY));
356  }
357  // number of lanes
358  int numLanes;
359  try {
360  // EXTENDED_NUMBER_OF_LANES is prefered but may not be defined
361  numLanes = StringUtils::toInt(getColumn(st, EXTENDED_NUMBER_OF_LANES, "-1"));
362  if (numLanes == -1) {
363  numLanes = NINavTeqHelper::getLaneNumber(id, getColumn(st, NUMBER_OF_LANES), speed);
364  }
365  } catch (NumberFormatException&) {
366  throw ProcessError(TLF("Non-numerical value for the number of lanes of link '%'.", id));
367  }
368 
369  const std::string navTeqTypeId = getColumn(st, VEHICLE_TYPE) + "_" + getColumn(st, FORM_OF_WAY);
370  // build the edge
371  NBEdge* e = nullptr;
372  const std::string interID = getColumn(st, BETWEEN_NODE_ID);
373  if (interID == "-1") {
374  e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, NBEdge::UNSPECIFIED_FRICTION, numLanes, priority,
376  } else {
377  PositionVector geoms = myGeoms[interID];
378  if (getColumn(st, CONNECTION, "0") == "1") {
379  geoms = geoms.reverse();
380  }
381  geoms.insert(geoms.begin(), from->getPosition());
382  geoms.push_back(to->getPosition());
383  const std::string origID = OptionsCont::getOptions().getBool("output.original-names") ? id : "";
384  e = new NBEdge(id, from, to, myTypeCont.knows(navTeqTypeId) ? navTeqTypeId : "", speed, NBEdge::UNSPECIFIED_FRICTION, numLanes, priority,
386  }
387 
388  //Import length or edges from input file
389  if (keepLength) {
390  const double length = StringUtils::toDouble(getColumn(st, LENGTH));
391  e->setLoadedLength(length);
392  }
393 
394  // NavTeq imports can be done with a typemap (if supplied), if not, the old defaults are used
395  if (myTypeCont.knows(navTeqTypeId)) {
396  e->setPermissions(myTypeCont.getEdgeTypePermissions(navTeqTypeId));
397  } else {
398  // add vehicle type information to the edge
399  const SVCPermissions allPermissions = myTypeCont.getEdgeTypePermissions("");
400  const SVCPermissions defaultPermissions = OptionsCont::getOptions().getBool("dlr-navteq.tolerant-permissions") ? allPermissions : 0;
401  if (myVersion < 6.0) {
402  NINavTeqHelper::addVehicleClasses(*e, getColumn(st, VEHICLE_TYPE), allPermissions, defaultPermissions);
403  } else {
404  NINavTeqHelper::addVehicleClassesV6(*e, getColumn(st, VEHICLE_TYPE), allPermissions, defaultPermissions);
405  }
406  // permission modifications based on form_of_way
407  if (form_of_way == 14) { // pedestrian area (fussgaengerzone)
408  // unfortunately, the veh_type string is misleading in this case
410  }
411  // permission modifications based on brunnel_type
412  if (brunnel_type == 10) { // ferry
413  e->setPermissions(SVC_SHIP, -1);
414  }
415  }
416 
417  // insert the edge to the network
418  if (!myEdgeCont.insert(e)) {
419  delete e;
420  throw ProcessError(TLF("Could not add edge '%'.", id));
421  }
422  return true;
423 }
424 
425 
426 std::string
427 NIImporter_DlrNavteq::EdgesHandler::getColumn(const StringTokenizer& st, ColumnName name, const std::string fallback) {
428  assert(!myColumns.empty());
429  if (myColumns[name] == MISSING_COLUMN) {
430  if (fallback == "") {
431  throw ProcessError(TLF("Missing column %.", toString(name)));
432  } else {
433  return fallback;
434  }
435  } else if (myColumns[name] >= 0) {
436  return st.get((int)(myColumns[name]));
437  } else {
438  // negative column number implies an optional column
439  if ((int) st.size() <= -myColumns[name]) {
440  // the column is not present
441  if (fallback == "") {
442  throw ProcessError(TLF("Missing optional column % without default value.", toString(name)));
443  } else {
444  return fallback;
445  }
446  } else {
447  return st.get((int)(-myColumns[name]));
448  }
449  }
450 }
451 
452 
453 std::string
455  const std::string& regionalID, const std::string& localID) const {
456  std::string result = "";
457  bool hadRegional = false;
458  if (myStreetNames.count(regionalID) > 0) {
459  hadRegional = true;
460  result += myStreetNames[regionalID];
461  }
462  if (myStreetNames.count(localID) > 0) {
463  if (hadRegional) {
464  result += " / ";
465  }
466  result += myStreetNames[localID];
467  }
468  return result;
469 }
470 
471 // ---------------------------------------------------------------------------
472 // definitions of NIImporter_DlrNavteq::TrafficlightsHandler-methods
473 // ---------------------------------------------------------------------------
476  NBEdgeCont& ne,
477  const std::string& file) :
478  myNodeCont(nc),
479  myTLLogicCont(tlc),
480  myEdgeCont(ne) {
481  UNUSED_PARAMETER(file);
482 }
483 
484 
486 
487 
488 bool
490 // #ID POICOL-TYPE DESCRIPTION LONGITUDE LATITUDE NAVTEQ_LINK_ID NODEID
491 
492  if (result[0] == '#') {
493  return true;
494  }
496  const std::string edgeID = st.get(5);
497  NBEdge* edge = myEdgeCont.retrieve(edgeID);
498  if (edge == nullptr) {
499  WRITE_WARNINGF(TL("The traffic light edge '%' could not be found."), edgeID);
500  } else {
501  NBNode* node = edge->getToNode();
502  if (node->getType() != SumoXMLNodeType::TRAFFIC_LIGHT) {
504  // @note. There may be additional information somewhere in the GDF files about traffic light type ...
506  // @note actually we could use the navteq node ID here
507  NBTrafficLightDefinition* tlDef = new NBOwnTLDef(node->getID(), node, 0, type);
508  if (!myTLLogicCont.insert(tlDef)) {
509  // actually, nothing should fail here
510  delete tlDef;
511  throw ProcessError(TLF("Could not allocate tls for '%'.", node->getID()));
512  }
513  }
514  }
515  return true;
516 }
517 
518 
519 // ---------------------------------------------------------------------------
520 // definitions of NIImporter_DlrNavteq::NamesHandler-methods
521 // ---------------------------------------------------------------------------
523  const std::string& file, std::map<std::string, std::string>& streetNames) :
524  myStreetNames(streetNames) {
525  UNUSED_PARAMETER(file);
526 }
527 
528 
530 
531 
532 bool
533 NIImporter_DlrNavteq::NamesHandler::report(const std::string& result) {
534 // # NAME_ID Name
535  if (result[0] == '#') {
536  return true;
537  }
539  if (st.size() == 1) {
540  return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
541  }
542  assert(st.size() >= 2);
543  const std::string id = st.next();
544  if (st.size() > 2) {
545  const std::string permanent_id_info = st.next();
546  }
547  myStreetNames[id] = st.next();
548  return true;
549 }
550 
551 
552 // ---------------------------------------------------------------------------
553 // definitions of NIImporter_DlrNavteq::TimeRestrictionsHandler-methods
554 // ---------------------------------------------------------------------------
556  myEdgeCont(ec),
557  myDistrictCont(dc),
558  myConstructionTime(constructionTime),
559  myCS_min(std::numeric_limits<time_t>::max()),
560  myCS_max(std::numeric_limits<time_t>::min()),
561  myConstructionEntries(0),
562  myNotStarted(0),
563  myUnderConstruction(0),
564  myFinished(0),
565  myRemovedEdges(0) {
566 }
567 
568 
570 
571 
572 bool
574 // # NAME_ID Name
575  if (result[0] == '#') {
576  return true;
577  }
579  const std::string id = st.next();
580  const std::string type = st.next();
581  const std::string directionOfFlow = st.next(); // can be ignored since unidirectional edge ids are referenced in the file
582  const std::string throughTraffic = st.next();
583  const std::string vehicleType = st.next();
584  const std::string validityPeriod = st.next();
585  const std::string warning = "Unrecognized TIME_REC '" + validityPeriod + "'";
586  if (type == "CS") {
587  myConstructionEntries++;
588  if (validityPeriod.size() > 1024) {
589  WRITE_WARNING(warning);
590  }
591  // construction
592  char start[1024];
593  char duration[1024];
594 
595  int matched;
596 
597  matched = sscanf(validityPeriod.c_str(), "[(%[^)]){%[^}]}]", start, duration);
598  if (matched == 2) {
599  time_t tStart = readTimeRec(start, "");
600  time_t tEnd = readTimeRec(start, duration);
601  myCS_min = MIN2(myCS_min, tStart);
602  myCS_max = MAX2(myCS_max, tEnd);
603  //std::cout << " start=" << start << " tStart=" << tStart<< " translation=" << asctime(localtime(&tStart)) << "";
604  //std::cout << " duration=" << duration << " tEnd=" << tEnd << " translation=" << asctime(localtime(&tEnd)) << "\n";
605  if (myConstructionTime < tEnd) {
606  NBEdge* edge = myEdgeCont.retrieve(id);
607  if (edge != nullptr) {
608  myRemovedEdges++;
609  myEdgeCont.extract(myDistrictCont, edge, true);
610  }
611  if (myConstructionTime < tStart) {
612  myNotStarted++;
613  } else {
614  myUnderConstruction++;
615  }
616  } else {
617  myFinished++;
618  }
619  } else {
620  WRITE_WARNING(warning);
621  };
622  }
623  return true;
624 }
625 
626 
627 void
629  if (myConstructionEntries > 0) {
630  char buff[1024];
631  std::ostringstream msg;
632  strftime(buff, 1024, "%Y-%m-%d", localtime(&myCS_min));
633  msg << "Parsed " << myConstructionEntries << " construction entries between " << buff;
634  strftime(buff, 1024, "%Y-%m-%d", localtime(&myCS_max));
635  msg << " and " << buff << ".\n";
636  strftime(buff, 1024, "%Y-%m-%d", localtime(&myConstructionTime));
637  msg << "Removed " << myRemovedEdges << " edges not yet constructed at " << buff << ".\n";
638  msg << " not yet started: " << myNotStarted << "\n";
639  msg << " under construction: " << myUnderConstruction << "\n";
640  msg << " finished: " << myFinished << "\n";
641  WRITE_MESSAGE(msg.str());
642  }
643 }
644 
645 
646 int
647 NIImporter_DlrNavteq::readPrefixedInt(const std::string& s, const std::string& prefix, int fallBack) {
648  int result = fallBack;
649  const size_t pos = s.find(prefix);
650  if (pos != std::string::npos) {
651  sscanf(s.substr(pos + prefix.size()).c_str(), "%i", &result);
652  }
653  return result;
654 }
655 
656 
657 time_t
658 NIImporter_DlrNavteq::readTimeRec(const std::string& start, const std::string& duration) {
659  // http://www.cplusplus.com/reference/ctime/mktime/
660  struct tm timeinfo;
661  timeinfo.tm_hour = 0;
662  timeinfo.tm_min = 0;
663  timeinfo.tm_sec = 0;
664  timeinfo.tm_year = 0;
665  timeinfo.tm_mon = 0;
666  timeinfo.tm_mday = 1;
667  timeinfo.tm_wday = 0;
668  timeinfo.tm_yday = 0;
669  timeinfo.tm_isdst = 0;
670 
671  timeinfo.tm_year = readPrefixedInt(start, "y") + readPrefixedInt(duration, "y") - 1900;
672  timeinfo.tm_mon = readPrefixedInt(start, "M") + readPrefixedInt(duration, "M") - 1;
673  timeinfo.tm_mday = 7 * (readPrefixedInt(start, "w") + readPrefixedInt(duration, "w"));
674  timeinfo.tm_mday += readPrefixedInt(start, "d") + readPrefixedInt(duration, "d");
675 
676  time_t result = mktime(&timeinfo);
677  return result;
678 }
679 
680 
681 time_t
682 NIImporter_DlrNavteq::readDate(const std::string& yyyymmdd) {
683  struct tm timeinfo;
684  timeinfo.tm_hour = 0;
685  timeinfo.tm_min = 0;
686  timeinfo.tm_sec = 0;
687  timeinfo.tm_wday = 0;
688  timeinfo.tm_yday = 0;
689  timeinfo.tm_isdst = 0;
690 
691  if (yyyymmdd.size() == 10
692  && yyyymmdd[4] == '-'
693  && yyyymmdd[7] == '-') {
694  try {
695  timeinfo.tm_year = StringUtils::toInt(yyyymmdd.substr(0, 4)) - 1900;
696  timeinfo.tm_mon = StringUtils::toInt(yyyymmdd.substr(5, 2)) - 1;
697  timeinfo.tm_mday = StringUtils::toInt(yyyymmdd.substr(8, 2));
698  return mktime(&timeinfo);
699  } catch (...) {
700  }
701  }
702  WRITE_ERRORF(TL("Could not parse YYYY-MM-DD date '%'"), yyyymmdd);
703  time_t now;
704  time(&now);
705  return now;
706 }
707 
708 // ---------------------------------------------------------------------------
709 // definitions of NIImporter_DlrNavteq::ProhibitionHandler-methods
710 // ---------------------------------------------------------------------------
712  NBEdgeCont& ec, const std::string& file, time_t constructionTime) :
713  myEdgeCont(ec),
714  myFile(file),
715  myVersion(0),
716  myConstructionTime(constructionTime) {
717 }
718 
719 
721 
722 
723 bool
725 // # NAME_ID Name
726  if (result[0] == '#') {
727  if (myVersion == 0) {
728  const double version = readVersion(result, myFile);
729  if (version > 0) {
730  myVersion = version;
731  }
732  }
733  return true;
734  }
736  if (st.size() == 1) {
737  return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
738  }
739  if (myVersion >= 6) {
740  assert(st.size() >= 7);
741  const std::string id = st.next();
742  const std::string permanent = st.next();
743  const std::string validityPeriod = st.next();
744  const std::string throughTraffic = st.next();
745  const std::string vehicleType = st.next();
746  if (validityPeriod != UNDEFINED) {
747  WRITE_WARNINGF(TL("Ignoring temporary prohibited manoeuvre (%)."), validityPeriod);
748  return true;
749  }
750  }
751  const std::string startEdge = st.next();
752  const std::string endEdge = st.get(st.size() - 1);
753 
754  NBEdge* from = myEdgeCont.retrieve(startEdge);
755  if (from == nullptr) {
756  WRITE_WARNINGF(TL("Ignoring prohibition from unknown start edge '%'."), startEdge);
757  return true;
758  }
759  NBEdge* to = myEdgeCont.retrieve(endEdge);
760  if (to == nullptr) {
761  WRITE_WARNINGF(TL("Ignoring prohibition from unknown end edge '%'."), endEdge);
762  return true;
763  }
764  from->removeFromConnections(to, -1, -1, true);
765  return true;
766 }
767 
768 
769 // ---------------------------------------------------------------------------
770 // definitions of NIImporter_DlrNavteq::ConnectedLanesHandler-methods
771 // ---------------------------------------------------------------------------
773  NBEdgeCont& ec) :
774  myEdgeCont(ec) {
775 }
776 
777 
779 
780 
781 bool
783  if (result[0] == '#') {
784  return true;
785  }
787  if (st.size() == 1) {
788  return true; // one line with the number of data containing lines in it (also starts with a comment # since ersion 6.5)
789  }
790  assert(st.size() >= 7);
791  const std::string nodeID = st.next();
792  const std::string vehicleType = st.next();
793  const std::string fromLaneS = st.next();
794  const std::string toLaneS = st.next();
795  const std::string throughTraffic = st.next();
796  const std::string startEdge = st.next();
797  const std::string endEdge = st.get(st.size() - 1);
798 
799  NBEdge* from = myEdgeCont.retrieve(startEdge);
800  if (from == nullptr) {
801  WRITE_WARNINGF(TL("Ignoring prohibition from unknown start edge '%'."), startEdge);
802  return true;
803  }
804  NBEdge* to = myEdgeCont.retrieve(endEdge);
805  if (to == nullptr) {
806  WRITE_WARNINGF(TL("Ignoring prohibition from unknown end edge '%'."), endEdge);
807  return true;
808  }
809  int fromLane = StringUtils::toInt(fromLaneS) - 1; // one based
810  if (fromLane < 0 || fromLane >= from->getNumLanes()) {
811  WRITE_WARNINGF(TL("Ignoring invalid lane index '%' in connection from edge '%' with % lanes."), fromLaneS, startEdge, from->getNumLanes());
812  return true;
813  }
814  int toLane = StringUtils::toInt(toLaneS) - 1; // one based
815  if (toLane < 0 || toLane >= to->getNumLanes()) {
816  WRITE_WARNINGF(TL("Ignoring invalid lane index '%' in connection to edge '%' with % lanes"), toLaneS, endEdge, to->getNumLanes());
817  return true;
818  }
819  if (!from->addLane2LaneConnection(fromLane, to, toLane, NBEdge::Lane2LaneInfoType::USER, true)) {
820  if (OptionsCont::getOptions().getBool("show-errors.connections-first-try")) {
821  WRITE_WARNINGF(TL("Could not set loaded connection from '%' to '%'."), from->getLaneID(fromLane), to->getLaneID(toLane));
822  }
823  // set as to be re-applied after network processing
824  // if this connection runs across a node cluster it may not be possible to set this
825  const bool warnOnly = st.size() > 7;
826  myEdgeCont.addPostProcessConnection(from->getID(), fromLane, to->getID(), toLane, false, KEEPCLEAR_UNSPECIFIED,
829  }
830  // ensure that connections for other lanes are guessed if not specified
832  from->getLaneStruct(fromLane).connectionsDone = true;
833  return true;
834 }
835 
836 
837 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:297
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:295
#define TL(string)
Definition: MsgHandler.h:315
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:300
#define TLF(string,...)
Definition: MsgHandler.h:317
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:299
@ KEEPCLEAR_UNSPECIFIED
Definition: NBCont.h:61
long long int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
@ SVC_SHIP
is an arbitrary ship
@ SVC_PASSENGER
vehicle is a passenger car (a "normal" car)
TrafficLightType
#define UNUSED_PARAMETER(x)
Definition: StdDefs.h:30
T MIN2(T a, T b)
Definition: StdDefs.h:76
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
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:180
void readAll(LineHandler &lh)
Reads the whole file linewise, reporting every line to the given LineHandler.
Definition: LineReader.cpp:58
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:92
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:4331
static const double UNSPECIFIED_FRICTION
unspecified lane friction
Definition: NBEdge.h:351
void disallowVehicleClass(int lane, SUMOVehicleClass vclass)
set disallowed class for the given lane or for all lanes if -1 is given
Definition: NBEdge.cpp:4127
bool addLane2LaneConnection(int fromLane, NBEdge *dest, int toLane, Lane2LaneInfoType type, bool mayUseSameDestination=false, bool mayDefinitelyPass=false, KeepClear keepClear=KEEPCLEAR_UNSPECIFIED, double contPos=UNSPECIFIED_CONTPOS, double visibility=UNSPECIFIED_VISIBILITY_DISTANCE, double speed=UNSPECIFIED_SPEED, double friction=UNSPECIFIED_FRICTION, double length=myDefaultConnectionLength, const PositionVector &customShape=PositionVector::EMPTY, const bool uncontrolled=UNSPECIFIED_CONNECTION_UNCONTROLLED, SVCPermissions permissions=SVC_UNSPECIFIED, const bool indirectLeft=false, const std::string &edgeType="", SVCPermissions changeLeft=SVC_UNSPECIFIED, SVCPermissions changeRight=SVC_UNSPECIFIED, bool postProcess=false)
Adds a connection between the specified this edge's lane and an approached one.
Definition: NBEdge.cpp:1126
const std::string & getID() const
Definition: NBEdge.h:1524
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:542
@ INIT
The edge has been loaded, nothing is computed yet.
static const double UNSPECIFIED_LOADED_LENGTH
no length override given
Definition: NBEdge.h:360
int getNumLanes() const
Returns the number of lanes.
Definition: NBEdge.h:516
static const double UNSPECIFIED_CONTPOS
unspecified internal junction position
Definition: NBEdge.h:354
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:1441
static const double UNSPECIFIED_VISIBILITY_DISTANCE
unspecified foe visibility for connections
Definition: NBEdge.h:357
std::string getLaneID(int lane) const
get lane ID
Definition: NBEdge.cpp:4006
static const double UNSPECIFIED_SPEED
unspecified lane speed
Definition: NBEdge.h:348
@ USER
The connection was given by the user.
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:342
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:1438
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:345
Lane & getLaneStruct(int lane)
Definition: NBEdge.h:1424
void setLoadedLength(double val)
set loaded length
Definition: NBEdge.cpp:4383
Instance responsible for building networks.
Definition: NBNetBuilder.h:107
NBDistrictCont & getDistrictCont()
Returns a reference the districts container.
Definition: NBNetBuilder.h:159
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:149
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:139
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=nullptr)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:144
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:154
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:57
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:338
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:285
const Position & getPosition() const
Definition: NBNode.h:260
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:74
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
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:60
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:37
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 std::string to_lower_case(const std::string &str)
Transfers the content to lower case.
Definition: StringUtils.cpp:79
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
Definition: json.hpp:4471
bool connectionsDone
Whether connection information for this lane is already completed.
Definition: NBEdge.h:186