Eclipse SUMO - Simulation of Urban MObility
NIImporter_OpenStreetMap.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-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
19 // Importer for networks stored in OpenStreetMap format
20 /****************************************************************************/
21 
22 
23 // ===========================================================================
24 // included modules
25 // ===========================================================================
26 #include <config.h>
27 #include <algorithm>
28 #include <set>
29 #include <functional>
30 #include <sstream>
31 #include <limits>
35 #include <utils/common/ToString.h>
39 #include <netbuild/NBEdge.h>
40 #include <netbuild/NBEdgeCont.h>
41 #include <netbuild/NBNode.h>
42 #include <netbuild/NBNodeCont.h>
43 #include <netbuild/NBNetBuilder.h>
44 #include <netbuild/NBOwnTLDef.h>
50 #include <utils/xml/XMLSubSys.h>
51 #include <netbuild/NBPTLine.h>
52 #include <netbuild/NBPTLineCont.h>
53 #include "NILoader.h"
55 
56 //#define DEBUG_LAYER_ELEVATION
57 
58 // ---------------------------------------------------------------------------
59 // static members
60 // ---------------------------------------------------------------------------
62 
63 const long long int NIImporter_OpenStreetMap::INVALID_ID = std::numeric_limits<long long int>::max();
64 
65 // ===========================================================================
66 // Private classes
67 // ===========================================================================
68 
72 public:
73  bool operator()(const Edge* e1, const Edge* e2) const {
74  if (e1->myHighWayType != e2->myHighWayType) {
75  return e1->myHighWayType > e2->myHighWayType;
76  }
77  if (e1->myNoLanes != e2->myNoLanes) {
78  return e1->myNoLanes > e2->myNoLanes;
79  }
80  if (e1->myNoLanesForward != e2->myNoLanesForward) {
81  return e1->myNoLanesForward > e2->myNoLanesForward;
82  }
83  if (e1->myMaxSpeed != e2->myMaxSpeed) {
84  return e1->myMaxSpeed > e2->myMaxSpeed;
85  }
86  if (e1->myIsOneWay != e2->myIsOneWay) {
87  return e1->myIsOneWay > e2->myIsOneWay;
88  }
89  return e1->myCurrentNodes > e2->myCurrentNodes;
90  }
91 };
92 
93 // ===========================================================================
94 // method definitions
95 // ===========================================================================
96 // ---------------------------------------------------------------------------
97 // static methods
98 // ---------------------------------------------------------------------------
99 const std::string NIImporter_OpenStreetMap::compoundTypeSeparator("|"); //clang-tidy says: "compundTypeSeparator with
100 // static storage duration my throw an exception that cannot be caught
101 
102 void
104  NIImporter_OpenStreetMap importer;
105  importer.load(oc, nb);
106 }
107 
109 
111  // delete nodes
112  for (auto myUniqueNode : myUniqueNodes) {
113  delete myUniqueNode;
114  }
115  // delete edges
116  for (auto& myEdge : myEdges) {
117  delete myEdge.second;
118  }
119  // delete platform shapes
120  for (auto& myPlatformShape : myPlatformShapes) {
121  delete myPlatformShape.second;
122  }
123 }
124 
125 void
127  // check whether the option is set (properly)
128  if (!oc.isSet("osm-files")) {
129  return;
130  }
131  /* Parse file(s)
132  * Each file is parsed twice: first for nodes, second for edges. */
133  std::vector<std::string> files = oc.getStringVector("osm-files");
134  // load nodes, first
135  NodesHandler nodesHandler(myOSMNodes, myUniqueNodes, oc);
136  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
137  // nodes
138  if (!FileHelpers::isReadable(*file)) {
139  WRITE_ERROR("Could not open osm-file '" + *file + "'.");
140  return;
141  }
142  nodesHandler.setFileName(*file);
143  PROGRESS_BEGIN_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
144  if (!XMLSubSys::runParser(nodesHandler, *file)) {
145  return;
146  }
148  }
149  // load edges, then
151  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
152  // edges
153  edgesHandler.setFileName(*file);
154  PROGRESS_BEGIN_MESSAGE("Parsing edges from osm-file '" + *file + "'");
155  XMLSubSys::runParser(edgesHandler, *file);
157  }
158 
159  /* Remove duplicate edges with the same shape and attributes */
160  if (!oc.getBool("osm.skip-duplicates-check")) {
161  PROGRESS_BEGIN_MESSAGE("Removing duplicate edges");
162  if (myEdges.size() > 1) {
163  std::set<const Edge*, CompareEdges> dupsFinder;
164  for (auto it = myEdges.begin(); it != myEdges.end();) {
165  if (dupsFinder.count(it->second) > 0) {
166  WRITE_MESSAGE("Found duplicate edges. Removing " + toString(it->first));
167  delete it->second;
168  myEdges.erase(it++);
169  } else {
170  dupsFinder.insert(it->second);
171  it++;
172  }
173  }
174  }
176  }
177 
178  /* Mark which nodes are used (by edges or traffic lights).
179  * This is necessary to detect which OpenStreetMap nodes are for
180  * geometry only */
181  std::map<long long int, int> nodeUsage;
182  // Mark which nodes are used by edges (begin and end)
183  for (std::map<long long int, Edge*>::const_iterator i = myEdges.begin(); i != myEdges.end(); ++i) {
184  Edge* e = (*i).second;
185  assert(e->myCurrentIsRoad);
186  for (std::vector<long long int>::const_iterator j = e->myCurrentNodes.begin();
187  j != e->myCurrentNodes.end();
188  ++j) {
189  if (nodeUsage.find(*j) == nodeUsage.end()) {
190  nodeUsage[*j] = 0;
191  }
192  nodeUsage[*j] = nodeUsage[*j] + 1;
193  }
194  }
195  // Mark which nodes are used by traffic lights
196  for (std::map<long long int, NIOSMNode*>::const_iterator nodesIt = myOSMNodes.begin();
197  nodesIt != myOSMNodes.end();
198  ++nodesIt) {
199  if (nodesIt->second->tlsControlled || nodesIt->second->railwaySignal /* || nodesIt->second->railwayCrossing*/) {
200  // If the key is not found in the map, the value is automatically
201  // initialized with 0.
202  nodeUsage[nodesIt->first] += 1;
203  }
204  }
205 
206  /* Instantiate edges
207  * Only those nodes in the middle of an edge which are used by more than
208  * one edge are instantiated. Other nodes are considered as geometry nodes. */
209  NBNodeCont& nc = nb.getNodeCont();
211  for (auto& myEdge : myEdges) {
212  Edge* e = myEdge.second;
213  assert(e->myCurrentIsRoad);
214  if (e->myCurrentNodes.size() < 2) {
215  WRITE_WARNING("Discarding way '" + toString(e->id) + "' because it has only " +
216  toString(e->myCurrentNodes.size()) + " node(s)");
217  continue;
218  }
220  // build nodes;
221  // - the from- and to-nodes must be built in any case
222  // - the in-between nodes are only built if more than one edge references them
223  NBNode* currentFrom = insertNodeChecking(*e->myCurrentNodes.begin(), nc, tlsc);
224  NBNode* last = insertNodeChecking(*(e->myCurrentNodes.end() - 1), nc, tlsc);
225  int running = 0;
226  std::vector<long long int> passed;
227  for (auto j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
228  passed.push_back(*j);
229  if (nodeUsage[*j] > 1 && j != e->myCurrentNodes.end() - 1 && j != e->myCurrentNodes.begin()) {
230  NBNode* currentTo = insertNodeChecking(*j, nc, tlsc);
231  running = insertEdge(e, running, currentFrom, currentTo, passed, nb);
232  currentFrom = currentTo;
233  passed.clear();
234  passed.push_back(*j);
235  }
236  }
237  if (running == 0) {
238  running = -1;
239  }
240  insertEdge(e, running, currentFrom, last, passed, nb);
241  }
242 
243  const double layerElevation = oc.getFloat("osm.layer-elevation");
244  if (layerElevation > 0) {
245  reconstructLayerElevation(layerElevation, nb);
246  }
247 
248  //revise pt stops; remove stops on deleted edges
249  if (OptionsCont::getOptions().isSet("ptstop-output")) {
251  }
252 
253  // load relations (after edges are built since we want to apply
254  // turn-restrictions directly to NBEdges)
256  &(nb.getPTLineCont()), oc);
257  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
258  // relations
259  relationHandler.setFileName(*file);
260  PROGRESS_BEGIN_MESSAGE("Parsing relations from osm-file '" + *file + "'");
261  XMLSubSys::runParser(relationHandler, *file);
263  }
264 }
265 
266 NBNode*
268  NBNode* node = nc.retrieve(toString(id));
269  if (node == nullptr) {
270  NIOSMNode* n = myOSMNodes.find(id)->second;
271  Position pos(n->lon, n->lat, n->ele);
272  if (!NBNetBuilder::transformCoordinate(pos, true)) {
273  WRITE_ERROR("Unable to project coordinates for junction '" + toString(id) + "'.");
274  return nullptr;
275  }
276  node = new NBNode(toString(id), pos);
277  if (!nc.insert(node)) {
278  WRITE_ERROR("Could not insert junction '" + toString(id) + "'.");
279  delete node;
280  return nullptr;
281  }
282  n->node = node;
283  if (n->railwayCrossing) {
284  node->reinit(pos, NODETYPE_RAIL_CROSSING);
285  } else if (n->railwaySignal) {
286  node->reinit(pos, NODETYPE_RAIL_SIGNAL);
287  } else if (n->tlsControlled) {
288  // ok, this node is a traffic light node where no other nodes
289  // participate
290  // @note: The OSM-community has not settled on a schema for differentiating between fixed and actuated lights
292  OptionsCont::getOptions().getString("tls.default-type"));
293  NBOwnTLDef* tlDef = new NBOwnTLDef(toString(id), node, 0, type);
294  if (!tlsc.insert(tlDef)) {
295  // actually, nothing should fail here
296  delete tlDef;
297  throw ProcessError("Could not allocate tls '" + toString(id) + "'.");
298  }
299  }
300  if (n->railwayBufferStop) {
301  node->setParameter("buffer_stop", "true");
302  }
303  }
304  return node;
305 }
306 
307 int
309  const std::vector<long long int>& passed, NBNetBuilder& nb) {
310  NBNodeCont& nc = nb.getNodeCont();
311  NBEdgeCont& ec = nb.getEdgeCont();
312  NBTypeCont& tc = nb.getTypeCont();
313  NBPTStopCont& sc = nb.getPTStopCont();
314 
316  // patch the id
317  std::string id = toString(e->id);
318  if (from == nullptr || to == nullptr) {
319  WRITE_ERROR("Discarding edge '" + id + "' because the nodes could not be built.");
320  return index;
321  }
322  if (index >= 0) {
323  id = id + "#" + toString(index);
324  } else {
325  index = 0;
326  }
327  if (from == to) {
328  assert(passed.size() >= 2);
329  if (passed.size() == 2) {
330  WRITE_WARNING("Discarding edge '" + id + "' which connects two identical nodes without geometry.");
331  return index;
332  }
333  // in the special case of a looped way split again using passed
334  int intermediateIndex = (int) passed.size() / 2;
335  NBNode* intermediate = insertNodeChecking(passed[intermediateIndex], nc, tlsc);
336  std::vector<long long int> part1(passed.begin(), passed.begin() + intermediateIndex + 1);
337  std::vector<long long int> part2(passed.begin() + intermediateIndex, passed.end());
338  index = insertEdge(e, index, from, intermediate, part1, nb);
339  return insertEdge(e, index, intermediate, to, part2, nb);
340  }
341  const int newIndex = index + 1;
342 
343  // convert the shape
344  PositionVector shape;
345  double distanceStart = myOSMNodes[passed.front()]->positionMeters;
346  double distanceEnd = myOSMNodes[passed.back()]->positionMeters;
347  const bool useDistance = distanceStart != std::numeric_limits<double>::max() && distanceEnd != std::numeric_limits<double>::max();
348  if (useDistance) {
349  // negative sign denotes counting in the other direction
350  if (distanceStart < distanceEnd) {
351  distanceStart *= -1;
352  } else {
353  distanceEnd *= -1;
354  }
355  } else {
356  distanceStart = 0;
357  distanceEnd = 0;
358  }
359  for (long long i : passed) {
360  NIOSMNode* n = myOSMNodes.find(i)->second;
361  if (n->ptStopPosition) {
362  NBPTStop* existingPtStop = sc.get(toString(n->id));
363  if (existingPtStop != nullptr) {
364  existingPtStop->registerAdditionalEdge(toString(e->id), id);
365  } else {
366  Position ptPos(n->lon, n->lat, n->ele);
367  if (!NBNetBuilder::transformCoordinate(ptPos)) {
368  WRITE_ERROR("Unable to project coordinates for node '" + toString(n->id) + "'.");
369  }
370  NBPTStop* ptStop = new NBPTStop(toString(n->id), ptPos, id, toString(e->id), n->ptStopLength, n->name,
371  n->permissions);
372 
373  sc.insert(ptStop);
374  }
375  }
376  Position pos(n->lon, n->lat, n->ele);
377  shape.push_back(pos);
378  }
380  WRITE_ERROR("Unable to project coordinates for edge '" + id + "'.");
381  }
382  std::string type = usableType(e->myHighWayType, id, tc);
383  if (type == "") {
384  return newIndex;
385  }
386 
387  // otherwise it is not an edge and will be ignored
388  bool ok = true;
389  int numLanesForward = tc.getNumLanes(type);
390  int numLanesBackward = tc.getNumLanes(type);
391  double speed = tc.getSpeed(type);
392  bool defaultsToOneWay = tc.getIsOneWay(type);
393  SVCPermissions permissions = tc.getPermissions(type);
394  if (e->myCurrentIsElectrified && (permissions & SVC_RAIL) != 0) {
395  permissions |= (SVC_RAIL_ELECTRIC | SVC_RAIL_FAST);
396  }
397  SVCPermissions forwardPermissions = permissions;
398  SVCPermissions backwardPermissions = permissions;
399  const std::string streetName = isRailway(forwardPermissions) && e->ref != "" ? e->ref : e->streetName;
400  double forwardWidth = tc.getWidth(type);
401  double backwardWidth = tc.getWidth(type);
402  const bool addSidewalk = (tc.getSidewalkWidth(type) != NBEdge::UNSPECIFIED_WIDTH);
403  const bool addBikeLane = (tc.getBikeLaneWidth(type) != NBEdge::UNSPECIFIED_WIDTH);
404  // check directions
405  bool addForward = true;
406  bool addBackward = true;
407  if ((e->myIsOneWay == "true" || e->myIsOneWay == "yes" || e->myIsOneWay == "1"
408  || (defaultsToOneWay && e->myIsOneWay != "no" && e->myIsOneWay != "false" && e->myIsOneWay != "0"))
409  && e->myRailDirection != WAY_BOTH) {
410  addBackward = false;
411  }
412  if (e->myIsOneWay == "-1" || e->myIsOneWay == "reverse" || e->myRailDirection == WAY_BACKWARD) {
413  // one-way in reversed direction of way
414  addForward = false;
415  addBackward = true;
416  }
417  if (!e->myIsOneWay.empty() && e->myIsOneWay != "false" && e->myIsOneWay != "no" && e->myIsOneWay != "true"
418  && e->myIsOneWay != "yes" && e->myIsOneWay != "-1" && e->myIsOneWay != "1" && e->myIsOneWay != "reverse") {
419  WRITE_WARNING("New value for oneway found: " + e->myIsOneWay);
420  }
421  // if we had been able to extract the number of lanes, override the highway type default
422  if (e->myNoLanes > 0) {
423  if (addForward && !addBackward) {
424  numLanesForward = e->myNoLanes;
425  } else if (!addForward && addBackward) {
426  numLanesBackward = e->myNoLanes;
427  } else {
428  if (e->myNoLanesForward > 0) {
429  numLanesForward = e->myNoLanesForward;
430  } else if (e->myNoLanesForward < 0) {
431  numLanesForward = e->myNoLanes + e->myNoLanesForward;
432  } else {
433  numLanesForward = (int) std::ceil(e->myNoLanes / 2.0);
434  }
435  numLanesBackward = e->myNoLanes - numLanesForward;
436  // sometimes ways are tagged according to their physical width of a single
437  // lane but they are intended for traffic in both directions
438  numLanesForward = MAX2(1, numLanesForward);
439  numLanesBackward = MAX2(1, numLanesBackward);
440  }
441  } else if (e->myNoLanes == 0) {
442  WRITE_WARNING("Skipping edge '" + id + "' because it has zero lanes.");
443  ok = false;
444  }
445  // if we had been able to extract the maximum speed, override the type's default
446  if (e->myMaxSpeed != MAXSPEED_UNGIVEN) {
447  speed = (double)(e->myMaxSpeed / 3.6);
448  }
449  if (speed <= 0) {
450  WRITE_WARNING("Skipping edge '" + id + "' because it has speed " + toString(speed));
451  ok = false;
452  }
453  // deal with cycleways that run in the opposite direction of a one-way street
454  WayType cyclewayType = e->myCyclewayType; // make a copy because we do some temporary modifications
455  if (addBikeLane) {
456  if (!addForward && (cyclewayType & WAY_FORWARD) != 0) {
457  addForward = true;
458  forwardPermissions = SVC_BICYCLE;
459  forwardWidth = tc.getBikeLaneWidth(type);
460  numLanesForward = 1;
461  // do not add an additional cycle lane
462  cyclewayType = (WayType)(cyclewayType & ~WAY_FORWARD); //clang tidy thinks "!WAY_FORWARD" is always false
463  }
464  if (!addBackward && (cyclewayType & WAY_BACKWARD) != 0) {
465  addBackward = true;
466  backwardPermissions = SVC_BICYCLE;
467  backwardWidth = tc.getBikeLaneWidth(type);
468  numLanesBackward = 1;
469  // do not add an additional cycle lane
470  cyclewayType = (WayType)(cyclewayType & ~WAY_BACKWARD); //clang tidy thinks "!WAY_BACKWARD" is always false
471  }
472  }
473  // deal with sidewalks that run in the opposite direction of a one-way street
474  WayType sidewalkType = e->mySidewalkType; // make a copy because we do some temporary modifications
475  if (addSidewalk) {
476  if (!addForward && (sidewalkType & WAY_FORWARD) != 0) {
477  addForward = true;
478  forwardPermissions = SVC_PEDESTRIAN;
479  forwardWidth = tc.getSidewalkWidth(type);
480  numLanesForward = 1;
481  // do not add an additional sidewalk
482  sidewalkType = (WayType)(sidewalkType & ~WAY_FORWARD); //clang tidy thinks "!WAY_FORWARD" is always false
483  }
484  if (!addBackward && (sidewalkType & WAY_BACKWARD) != 0) {
485  addBackward = true;
486  backwardPermissions = SVC_PEDESTRIAN;
487  backwardWidth = tc.getSidewalkWidth(type);
488  numLanesBackward = 1;
489  // do not add an additional cycle lane
490  sidewalkType = (WayType)(sidewalkType & ~WAY_BACKWARD); //clang tidy thinks "!WAY_BACKWARD" is always false
491  }
492  }
493  // deal with busways that run in the opposite direction of a one-way street
494  if (!addForward && (e->myBuswayType & WAY_FORWARD) != 0) {
495  addForward = true;
496  forwardPermissions = SVC_BUS;
497  numLanesForward = 1;
498  }
499  if (!addBackward && (e->myBuswayType & WAY_BACKWARD) != 0) {
500  addBackward = true;
501  backwardPermissions = SVC_BUS;
502  numLanesBackward = 1;
503  }
504 
505  const std::string origID = OptionsCont::getOptions().getBool("output.original-names") ? toString(e->id) : "";
506  if (ok) {
507  LaneSpreadFunction lsf = (addBackward || OptionsCont::getOptions().getBool("osm.oneway-spread-right")) &&
509 
510  id = StringUtils::escapeXML(id);
511  const std::string reverseID = "-" + id;
512 
513  if (addForward) {
514  assert(numLanesForward > 0);
515  NBEdge* nbe = new NBEdge(id, from, to, type, speed, numLanesForward, tc.getPriority(type),
516  forwardWidth, NBEdge::UNSPECIFIED_OFFSET, shape,
517  StringUtils::escapeXML(streetName), origID, lsf, true);
518  nbe->setPermissions(forwardPermissions);
519  if ((e->myBuswayType & WAY_FORWARD) != 0) {
520  nbe->setPermissions(SVC_BUS, 0);
521  }
522  if (addBikeLane && (cyclewayType == WAY_UNKNOWN || (cyclewayType & WAY_FORWARD) != 0)) {
523  nbe->addBikeLane(tc.getBikeLaneWidth(type));
524  } else if (nbe->getPermissions(0) == SVC_BUS) {
525  // bikes drive on buslanes if no separate cycle lane is available
527  }
528  if (addSidewalk && (sidewalkType == WAY_UNKNOWN || (sidewalkType & WAY_FORWARD) != 0)) {
529  nbe->addSidewalk(tc.getSidewalkWidth(type));
530  }
532  nbe->setDistance(distanceStart);
533  if (!ec.insert(nbe)) {
534  delete nbe;
535  throw ProcessError("Could not add edge '" + id + "'.");
536  }
537  }
538  if (addBackward) {
539  assert(numLanesBackward > 0);
540  NBEdge* nbe = new NBEdge(reverseID, to, from, type, speed, numLanesBackward, tc.getPriority(type),
541  backwardWidth, NBEdge::UNSPECIFIED_OFFSET, shape.reverse(),
542  StringUtils::escapeXML(streetName), origID, lsf, true);
543  nbe->setPermissions(backwardPermissions);
544  if ((e->myBuswayType & WAY_BACKWARD) != 0) {
545  nbe->setPermissions(SVC_BUS, 0);
546  }
547  if (addBikeLane && (cyclewayType == WAY_UNKNOWN || (cyclewayType & WAY_BACKWARD) != 0)) {
548  nbe->addBikeLane(tc.getBikeLaneWidth(type));
549  } else if (nbe->getPermissions(0) == SVC_BUS) {
550  // bikes drive on buslanes if no separate cycle lane is available
552  }
553  if (addSidewalk && (sidewalkType == WAY_UNKNOWN || (sidewalkType & WAY_BACKWARD) != 0)) {
554  nbe->addSidewalk(tc.getSidewalkWidth(type));
555  }
557  nbe->setDistance(distanceEnd);
558  if (!ec.insert(nbe)) {
559  delete nbe;
560  throw ProcessError("Could not add edge '-" + id + "'.");
561  }
562  }
563  if ((e->myParkingType & PARKING_BOTH) != 0 && OptionsCont::getOptions().isSet("parking-output")) {
564  if ((e->myParkingType & PARKING_RIGHT) != 0) {
565  if (addForward) {
566  nb.getParkingCont().push_back(NBParking(id, id));
567  } else {
569  if ((e->myParkingType & PARKING_LEFT) == 0 && !addBackward) {
571  nb.getParkingCont().push_back(NBParking(reverseID, reverseID));
572  }
573  }
574  }
575  if ((e->myParkingType & PARKING_LEFT) != 0) {
576  if (addBackward) {
577  nb.getParkingCont().push_back(NBParking(reverseID, reverseID));
578  } else {
580  if ((e->myParkingType & PARKING_RIGHT) == 0 && !addForward) {
582  nb.getParkingCont().push_back(NBParking(id, id));
583  }
584  }
585  }
586  }
587  }
588  return newIndex;
589 }
590 
591 // ---------------------------------------------------------------------------
592 // definitions of NIImporter_OpenStreetMap::NodesHandler-methods
593 // ---------------------------------------------------------------------------
594 NIImporter_OpenStreetMap::NodesHandler::NodesHandler(std::map<long long int, NIOSMNode*>& toFill,
595  std::set<NIOSMNode*, CompareNodes>& uniqueNodes,
596  const OptionsCont& oc)
597 
598  :
599  SUMOSAXHandler("osm - file"),
600  myToFill(toFill),
601  myLastNodeID(-1),
602  myIsInValidNodeTag(false),
603  myHierarchyLevel(0),
604  myUniqueNodes(uniqueNodes),
605  myImportElevation(oc.getBool("osm.elevation")),
606  myOptionsCont(oc) {
607 }
608 
610 
611 void
613  ++myHierarchyLevel;
614  if (element == SUMO_TAG_NODE) {
615  bool ok = true;
616  if (myHierarchyLevel != 2) {
617  WRITE_ERROR("Node element on wrong XML hierarchy level (id='" + toString(attrs.get<long
618  long
619  int>(SUMO_ATTR_ID,
620  nullptr, ok))
621  + "', level='" + toString(myHierarchyLevel) + "').");
622  return;
623  }
624  const long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
625  const std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
626  if (action == "delete" || !ok) {
627  return;
628  }
629  myLastNodeID = -1;
630  if (myToFill.find(id) == myToFill.end()) {
631  myLastNodeID = id;
632  // assume we are loading multiple files...
633  // ... so we won't report duplicate nodes
634  bool ok2 = true;
635  double tlat, tlon;
636  std::istringstream lon(attrs.get<std::string>(SUMO_ATTR_LON, toString(id).c_str(), ok2));
637  if (!ok2) {
638  return;
639  }
640  lon >> tlon;
641  if (lon.fail()) {
642  WRITE_ERROR("Node's '" + toString(id) + "' lon information is not numeric.");
643  return;
644  }
645  std::istringstream lat(attrs.get<std::string>(SUMO_ATTR_LAT, toString(id).c_str(), ok2));
646  if (!ok2) {
647  return;
648  }
649  lat >> tlat;
650  if (lat.fail()) {
651  WRITE_ERROR("Node's '" + toString(id) + "' lat information is not numeric.");
652  return;
653  }
654  auto* toAdd = new NIOSMNode(id, tlon, tlat);
655  myIsInValidNodeTag = true;
656 
657  auto similarNode = myUniqueNodes.find(toAdd);
658  if (similarNode == myUniqueNodes.end()) {
659  myUniqueNodes.insert(toAdd);
660  } else {
661  delete toAdd;
662  toAdd = *similarNode;
663  WRITE_MESSAGE("Found duplicate nodes. Substituting " + toString(id) + " with " + toString(toAdd->id));
664  }
665  myToFill[id] = toAdd;
666  }
667  }
668  if (element == SUMO_TAG_TAG && myIsInValidNodeTag) {
669  if (myHierarchyLevel != 3) {
670  WRITE_ERROR("Tag element on wrong XML hierarchy level.");
671  return;
672  }
673  bool ok = true;
674  std::string key = attrs.get<std::string>(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok, false);
675  // we check whether the key is relevant (and we really need to transcode the value) to avoid hitting #1636
676  if (key == "highway" || key == "ele" || key == "crossing" || key == "railway" || key == "public_transport"
677  || key == "name" || key == "train" || key == "bus" || key == "tram" || key == "light_rail" || key == "subway" || key == "station" || key == "noexit"
678  || StringUtils::startsWith(key, "railway:signal")
679  || StringUtils::startsWith(key, "railway:position")
680  ) {
681  std::string value = attrs.get<std::string>(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, false);
682  if (key == "highway" && value.find("traffic_signal") != std::string::npos) {
683  myToFill[myLastNodeID]->tlsControlled = true;
684  } else if (key == "crossing" && value.find("traffic_signals") != std::string::npos) {
685  myToFill[myLastNodeID]->tlsControlled = true;
686  } else if ((key == "noexit" && value == "yes")
687  || (key == "railway" && value == "buffer_stop")) {
688  myToFill[myLastNodeID]->railwayBufferStop = true;
689  } else if (key == "railway" && value.find("crossing") != std::string::npos) {
690  myToFill[myLastNodeID]->railwayCrossing = true;
691  } else if (StringUtils::startsWith(key, "railway:signal") && (
692  value == "block" || value == "entry" || value == "exit" || value == "intermediate")) {
693  myToFill[myLastNodeID]->railwaySignal = true;
694  } else if (StringUtils::startsWith(key, "railway:position") && value.size() > myToFill[myLastNodeID]->position.size()) {
695  // use the entry with the highest precision (more digits)
696  myToFill[myLastNodeID]->position = value;
697  } else if ((key == "public_transport" && value == "stop_position") ||
698  (key == "highway" && value == "bus_stop")) {
699  myToFill[myLastNodeID]->ptStopPosition = true;
700  if (myToFill[myLastNodeID]->ptStopLength == 0) {
701  // default length
702  myToFill[myLastNodeID]->ptStopLength = myOptionsCont.getFloat("osm.stop-output.length");
703  }
704  } else if (key == "name") {
705  myToFill[myLastNodeID]->name = value;
706  } else if (key == "train") {
707  myToFill[myLastNodeID]->permissions = SVC_RAIL;
708  myToFill[myLastNodeID]->ptStopLength = myOptionsCont.getFloat("osm.stop-output.length.train");
709  } else if (key == "subway" || key == "light_rail"
710  || (key == "station" && (value == "subway" || value == "light_rail"))) {
711  myToFill[myLastNodeID]->permissions = SVC_RAIL_URBAN;
712  myToFill[myLastNodeID]->ptStopLength = myOptionsCont.getFloat("osm.stop-output.length.train");
713  } else if (key == "bus") {
714  myToFill[myLastNodeID]->permissions = SVC_BUS;
715  myToFill[myLastNodeID]->ptStopLength = myOptionsCont.getFloat("osm.stop-output.length.bus");
716  } else if (key == "tram") {
717  myToFill[myLastNodeID]->permissions = SVC_TRAM;
718  myToFill[myLastNodeID]->ptStopLength = myOptionsCont.getFloat("osm.stop-output.length.tram");
719  } else if (myImportElevation && key == "ele") {
720  try {
721  myToFill[myLastNodeID]->ele = StringUtils::toDouble(value);
722  } catch (...) {
723  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in node '" +
724  toString(myLastNodeID) + "'.");
725  }
726  }
727  }
728  }
729 }
730 
731 void
733  if (element == SUMO_TAG_NODE && myHierarchyLevel == 2) {
734  myLastNodeID = -1;
735  myIsInValidNodeTag = false;
736  }
737  --myHierarchyLevel;
738 }
739 
740 // ---------------------------------------------------------------------------
741 // definitions of NIImporter_OpenStreetMap::EdgesHandler-methods
742 // ---------------------------------------------------------------------------
744  const std::map<long long int, NIOSMNode*>& osmNodes,
745  std::map<long long int, Edge*>& toFill, std::map<long long int, Edge*>& platformShapes):
746  SUMOSAXHandler("osm - file"),
747  myOSMNodes(osmNodes),
748  myEdgeMap(toFill),
749  myPlatformShapesMap(platformShapes) {
750  mySpeedMap["signals"] = MAXSPEED_UNGIVEN;
751  mySpeedMap["none"] = 142.; // Auswirkungen eines allgemeinen Tempolimits auf Autobahnen im Land Brandeburg (2007)
752  mySpeedMap["no"] = 142.;
753  mySpeedMap["walk"] = 5.;
754  mySpeedMap["DE:rural"] = 100.;
755  mySpeedMap["DE:urban"] = 50.;
756  mySpeedMap["DE:living_street"] = 10.;
757  myAllAttributes = OptionsCont::getOptions().getBool("osm.all-attributes");
758 
759 }
760 
762 
763 void
765  const SUMOSAXAttributes& attrs) {
766  myParentElements.push_back(element);
767  // parse "way" elements
768  if (element == SUMO_TAG_WAY) {
769  bool ok = true;
770  const long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
771  std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
772  if (action == "delete" || !ok) {
773  myCurrentEdge = nullptr;
774  return;
775  }
776  myCurrentEdge = new Edge(id);
777  }
778  // parse "nd" (node) elements
779  if (element == SUMO_TAG_ND && myCurrentEdge != nullptr) {
780  bool ok = true;
781  long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
782  if (ok) {
783  auto node = myOSMNodes.find(ref);
784  if (node == myOSMNodes.end()) {
785  WRITE_WARNING("The referenced geometry information (ref='" + toString(ref) + "') is not known");
786  return;
787  }
788 
789  ref = node->second->id; // node may have been substituted
790  if (myCurrentEdge->myCurrentNodes.empty() ||
791  myCurrentEdge->myCurrentNodes.back() != ref) { // avoid consecutive duplicates
792  myCurrentEdge->myCurrentNodes.push_back(ref);
793  }
794 
795  }
796  }
797  // parse values
798  if (element == SUMO_TAG_TAG && myParentElements.size() > 2
799  && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY) {
800  if (myCurrentEdge == nullptr) {
801  return;
802  }
803  bool ok = true;
804  std::string key = attrs.get<std::string>(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok, false);
805  if (key.size() > 8 && StringUtils::startsWith(key, "cycleway:")) {
806  // handle special cycleway keys
807  const std::string cyclewaySpec = key.substr(9);
808  key = "cycleway";
809  if (cyclewaySpec == "right") {
810  myCurrentEdge->myCyclewayType = (WayType)(myCurrentEdge->myCyclewayType | WAY_FORWARD);
811  } else if (cyclewaySpec == "left") {
812  myCurrentEdge->myCyclewayType = (WayType)(myCurrentEdge->myCyclewayType | WAY_BACKWARD);
813  } else if (cyclewaySpec == "both") {
814  myCurrentEdge->myCyclewayType = (WayType)(myCurrentEdge->myCyclewayType | WAY_BOTH);
815  } else {
816  key = "ignore";
817  }
818  if ((myCurrentEdge->myCyclewayType & WAY_BOTH) != 0) {
819  // now we have some info on directionality
820  myCurrentEdge->myCyclewayType = (WayType)(myCurrentEdge->myCyclewayType & ~WAY_UNKNOWN);
821  }
822  } else if (key.size() > 6 && StringUtils::startsWith(key, "busway:")) {
823  // handle special busway keys
824  const std::string buswaySpec = key.substr(7);
825  key = "busway";
826  if (buswaySpec == "right") {
827  myCurrentEdge->myBuswayType = (WayType)(myCurrentEdge->myBuswayType | WAY_FORWARD);
828  } else if (buswaySpec == "left") {
829  myCurrentEdge->myBuswayType = (WayType)(myCurrentEdge->myBuswayType | WAY_BACKWARD);
830  } else if (buswaySpec == "both") {
831  myCurrentEdge->myBuswayType = (WayType)(myCurrentEdge->myBuswayType | WAY_BOTH);
832  } else {
833  key = "ignore";
834  }
835  }
836  if (myAllAttributes && (key == "bridge" || key == "tunnel")) {
837  myCurrentEdge->setParameter(key, "true"); // could be differentiated further if necessary
838  }
839  // we check whether the key is relevant (and we really need to transcode the value) to avoid hitting #1636
840  if (!StringUtils::endsWith(key, "way") && !StringUtils::startsWith(key, "lanes")
841  && key != "maxspeed" && key != "junction" && key != "name" && key != "tracks" && key != "layer"
842  && key != "route"
843  && key != "sidewalk"
844  && key != "ref"
845  && key != "highspeed"
846  && !StringUtils::startsWith(key, "parking")
847  && key != "postal_code"
848  && key != "railway:preferred_direction"
849  && key != "railway:bidirectional"
850  && key != "railway:track_ref"
851  && key != "usage"
852  && key != "electrified"
853  && key != "public_transport") {
854  return;
855  }
856  std::string value = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok, false);
857 
858  if ((key == "highway" && value != "platform") || key == "railway" || key == "waterway" || key == "cycleway"
859  || key == "busway" || key == "route" || key == "sidewalk" || key == "highspeed"
860  || key == "usage") {
861  // build type id
862  std::string singleTypeID = key + "." + value;
863  myCurrentEdge->myCurrentIsRoad = true;
864  // special cycleway stuff
865  if (key == "cycleway") {
866  if (value == "no") {
867  return;
868  }
869  if (value == "opposite_track") {
870  myCurrentEdge->myCyclewayType = WAY_BACKWARD;
871  } else if (value == "opposite_lane") {
872  myCurrentEdge->myCyclewayType = WAY_BACKWARD;
873  }
874  }
875  // special sidewalk stuff
876  if (key == "sidewalk") {
877  if (value == "no" || value == "none") {
878  myCurrentEdge->mySidewalkType = WAY_NONE;
879  } else if (value == "both") {
880  myCurrentEdge->mySidewalkType = WAY_BOTH;
881  } else if (value == "right") {
882  myCurrentEdge->mySidewalkType = WAY_FORWARD;
883  } else if (value == "left") {
884  myCurrentEdge->mySidewalkType = WAY_BACKWARD;
885  }
886  // no need to extend the type id
887  return;
888  }
889  // special busway stuff
890  if (key == "busway") {
891  if (value == "no") {
892  return;
893  }
894  if (value == "opposite_track") {
895  myCurrentEdge->myBuswayType = WAY_BACKWARD;
896  } else if (value == "opposite_lane") {
897  myCurrentEdge->myBuswayType = WAY_BACKWARD;
898  }
899  // no need to extend the type id
900  return;
901  }
902  if (key == "highspeed") {
903  if (value == "no") {
904  return;
905  }
906  singleTypeID = "railway.highspeed";
907  }
908  // special case: never build compound type for highspeed rail
909  if (!myCurrentEdge->myHighWayType.empty() && singleTypeID != "railway.highspeed") {
910  if (myCurrentEdge->myHighWayType == "railway.highspeed") {
911  return;
912  }
913  // osm-ways may be used by more than one mode (eg railway.tram + highway.residential. this is relevant for multimodal traffic)
914  // we create a new type for this kind of situation which must then be resolved in insertEdge()
915  std::vector<std::string> types = StringTokenizer(myCurrentEdge->myHighWayType,
917  types.push_back(singleTypeID);
918  myCurrentEdge->myHighWayType = joinToStringSorting(types, compoundTypeSeparator);
919  } else {
920  myCurrentEdge->myHighWayType = singleTypeID;
921  }
922  } else if (key == "lanes") {
923  try {
924  myCurrentEdge->myNoLanes = StringUtils::toInt(value);
925  } catch (NumberFormatException&) {
926  // might be a list of values
927  StringTokenizer st(value, ";", true);
928  std::vector<std::string> list = st.getVector();
929  if (list.size() >= 2) {
930  int minLanes = std::numeric_limits<int>::max();
931  try {
932  for (auto& i : list) {
933  int numLanes = StringUtils::toInt(StringUtils::prune(i));
934  minLanes = MIN2(minLanes, numLanes);
935  }
936  myCurrentEdge->myNoLanes = minLanes;
938  "Using minimum lane number from list (" + value + ") for edge '"
939  + toString(myCurrentEdge->id)
940  + "'.");
941  } catch (NumberFormatException&) {
942  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
943  toString(myCurrentEdge->id) + "'.");
944  }
945  }
946  } catch (EmptyData&) {
947  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
948  toString(myCurrentEdge->id) + "'.");
949  }
950  } else if (key == "lanes:forward") {
951  try {
952  myCurrentEdge->myNoLanesForward = StringUtils::toInt(value);
953  } catch (...) {
954  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
955  toString(myCurrentEdge->id) + "'.");
956  }
957  } else if (key == "lanes:backward") {
958  try {
959  // denote backwards count with a negative sign
960  myCurrentEdge->myNoLanesForward = -StringUtils::toInt(value);
961  } catch (...) {
962  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
963  toString(myCurrentEdge->id) + "'.");
964  }
965  } else if (key == "maxspeed") {
966  if (mySpeedMap.find(value) != mySpeedMap.end()) {
967  myCurrentEdge->myMaxSpeed = mySpeedMap[value];
968  } else {
969  double conversion = 1; // OSM default is km/h
970  if (StringUtils::to_lower_case(value).find("km/h") != std::string::npos) {
971  value = StringUtils::prune(value.substr(0, value.find_first_not_of("0123456789")));
972  } else if (StringUtils::to_lower_case(value).find("mph") != std::string::npos) {
973  value = StringUtils::prune(value.substr(0, value.find_first_not_of("0123456789")));
974  conversion = 1.609344; // kilometers per mile
975  }
976  try {
977  myCurrentEdge->myMaxSpeed = StringUtils::toDouble(value) * conversion;
978  } catch (...) {
979  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
980  toString(myCurrentEdge->id) + "'.");
981  }
982  }
983  } else if (key == "junction") {
984  if ((value == "roundabout") && (myCurrentEdge->myIsOneWay.empty())) {
985  myCurrentEdge->myIsOneWay = "yes";
986  }
987  } else if (key == "oneway") {
988  myCurrentEdge->myIsOneWay = value;
989  } else if (key == "name") {
990  myCurrentEdge->streetName = value;
991  } else if (key == "ref") {
992  myCurrentEdge->ref = value;
993  } else if (key == "layer") {
994  if (myAllAttributes) {
995  myCurrentEdge->setParameter(key, value);
996  }
997  try {
998  myCurrentEdge->myLayer = StringUtils::toInt(value);
999  } catch (...) {
1000  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
1001  toString(myCurrentEdge->id) + "'.");
1002  }
1003  } else if (key == "tracks") {
1004  try {
1005  if (StringUtils::toInt(value) > 1) {
1006  myCurrentEdge->myIsOneWay = "false";
1007  } else {
1008  myCurrentEdge->myIsOneWay = "true";
1009  }
1010  } catch (...) {
1011  WRITE_WARNING("Value of key '" + key + "' is not numeric ('" + value + "') in edge '" +
1012  toString(myCurrentEdge->id) + "'.");
1013  }
1014  } else if (myAllAttributes && key == "postal_code") {
1015  myCurrentEdge->setParameter(key, value);
1016  } else if (key == "railway:preferred_direction") {
1017  if (value == "both") {
1018  myCurrentEdge->myRailDirection = WAY_BOTH;
1019  } else if (value == "backward") {
1020  myCurrentEdge->myRailDirection = WAY_BACKWARD;
1021  }
1022  } else if (key == "railway:bidirectional") {
1023  if (value == "regular") {
1024  myCurrentEdge->myRailDirection = WAY_BOTH;
1025  }
1026  } else if (key == "electrified") {
1027  if (value != "no") {
1028  myCurrentEdge->myCurrentIsElectrified = true;
1029  }
1030  } else if (key == "railway:track_ref") {
1031  myCurrentEdge->setParameter(key, value);
1032  } else if (key == "public_transport" && value == "platform") {
1033  myCurrentEdge->myCurrentIsPlatform = true;
1034  } else if (key == "parking:lane:both" && !StringUtils::startsWith(value, "no")) {
1035  myCurrentEdge->myParkingType |= PARKING_BOTH;
1036  } else if (key == "parking:lane:left" && !StringUtils::startsWith(value, "no")) {
1037  myCurrentEdge->myParkingType |= PARKING_LEFT;
1038  } else if (key == "parking:lane:right" && !StringUtils::startsWith(value, "no")) {
1039  myCurrentEdge->myParkingType |= PARKING_RIGHT;
1040  }
1041  }
1042 }
1043 
1044 void
1046  myParentElements.pop_back();
1047  if (element == SUMO_TAG_WAY && myCurrentEdge != nullptr) {
1048  if (myCurrentEdge->myCurrentIsRoad) {
1049  myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
1050  } else if (myCurrentEdge->myCurrentIsPlatform) {
1051  myPlatformShapesMap[myCurrentEdge->id] = myCurrentEdge;
1052  } else {
1053  delete myCurrentEdge;
1054  }
1055  myCurrentEdge = nullptr;
1056  }
1057 }
1058 
1059 // ---------------------------------------------------------------------------
1060 // definitions of NIImporter_OpenStreetMap::RelationHandler-methods
1061 // ---------------------------------------------------------------------------
1063  const std::map<long long int, NIOSMNode*>& osmNodes,
1064  const std::map<long long int, Edge*>& osmEdges, NBPTStopCont* nbptStopCont,
1065  const std::map<long long int, Edge*>& platformShapes,
1066  NBPTLineCont* nbptLineCont,
1067  const OptionsCont& oc)
1068  :
1069  SUMOSAXHandler("osm - file"),
1070  myOSMNodes(osmNodes),
1071  myOSMEdges(osmEdges),
1072  myPlatformShapes(platformShapes),
1073  myNBPTStopCont(nbptStopCont),
1074  myNBPTLineCont(nbptLineCont),
1075  myOptionsCont(oc) {
1076  resetValues();
1077 }
1078 
1080 
1081 void
1083  myCurrentRelation = INVALID_ID;
1084  myIsRestriction = false;
1085  myFromWay = INVALID_ID;
1086  myToWay = INVALID_ID;
1087  myViaNode = INVALID_ID;
1088  myViaWay = INVALID_ID;
1089  myRestrictionType = RESTRICTION_UNKNOWN;
1090  myPlatforms.clear();
1091  myStops.clear();
1092  myWays.clear();
1093  myIsStopArea = false;
1094  myIsRoute = false;
1095  myPTRouteType = "";
1096 }
1097 
1098 void
1100  const SUMOSAXAttributes& attrs) {
1101  myParentElements.push_back(element);
1102  // parse "way" elements
1103  if (element == SUMO_TAG_RELATION) {
1104  bool ok = true;
1105  myCurrentRelation = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
1106  const std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
1107  if (action == "delete" || !ok) {
1108  myCurrentRelation = INVALID_ID;
1109  }
1110  myName = "";
1111  myRef = "";
1112  myInterval = -1;
1113  myNightService = "";
1114  return;
1115  }
1116  if (myCurrentRelation == INVALID_ID) {
1117  return;
1118  }
1119  // parse member elements
1120  if (element == SUMO_TAG_MEMBER) {
1121  bool ok = true;
1122  std::string role = attrs.hasAttribute("role") ? attrs.getStringSecure("role", "") : "";
1123  auto ref = attrs.get<long
1124  long
1125  int>(SUMO_ATTR_REF, nullptr, ok);
1126  if (role == "via") {
1127  // u-turns for divided ways may be given with 2 via-nodes or 1 via-way
1128  std::string memberType = attrs.get<std::string>(SUMO_ATTR_TYPE, nullptr, ok);
1129  if (memberType == "way" && checkEdgeRef(ref)) {
1130  myViaWay = ref;
1131  } else if (memberType == "node") {
1132  if (myOSMNodes.find(ref) != myOSMNodes.end()) {
1133  myViaNode = ref;
1134  } else {
1135  WRITE_WARNING(
1136  "No node found for reference '" + toString(ref) + "' in relation '"
1137  + toString(myCurrentRelation)
1138  + "'");
1139  }
1140  }
1141  } else if (role == "from" && checkEdgeRef(ref)) {
1142  myFromWay = ref;
1143  } else if (role == "to" && checkEdgeRef(ref)) {
1144  myToWay = ref;
1145  } else if (role == "stop") {
1146  myStops.push_back(ref);
1147  } else if (role == "platform") {
1148  std::string memberType = attrs.get<std::string>(SUMO_ATTR_TYPE, nullptr, ok);
1149  if (memberType == "way") {
1150  const std::map<long long int,
1151  NIImporter_OpenStreetMap::Edge*>::const_iterator& wayIt = myPlatformShapes.find(ref);
1152  if (wayIt != myPlatformShapes.end()) {
1153 
1154  NIIPTPlatform platform;
1155  platform.isWay = true;
1156  platform.ref = ref;
1157  myPlatforms.push_back(platform);
1158  }
1159  } else if (memberType == "node") {
1160  NIIPTPlatform platform;
1161  platform.isWay = false;
1162  platform.ref = ref;
1163  myPlatforms.push_back(platform);
1164  }
1165 
1166  } else if (role.empty()) {
1167  std::string memberType = attrs.get<std::string>(SUMO_ATTR_TYPE, nullptr, ok);
1168  if (memberType == "way") {
1169  myWays.push_back(ref);
1170  }
1171  }
1172  return;
1173  }
1174  // parse values
1175  if (element == SUMO_TAG_TAG) {
1176  bool ok = true;
1177  std::string key = attrs.get<std::string>(SUMO_ATTR_K, toString(myCurrentRelation).c_str(), ok, false);
1178  // we check whether the key is relevant (and we really need to transcode the value) to avoid hitting #1636
1179  if (key == "type" || key == "restriction") {
1180  std::string value = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1181  if (key == "type" && value == "restriction") {
1182  myIsRestriction = true;
1183  return;
1184  }
1185  if (key == "type" && value == "route") {
1186  myIsRoute = true;
1187  return;
1188  }
1189  if (key == "restriction") {
1190  // @note: the 'right/left/straight' part is ignored since the information is
1191  // redundantly encoded in the 'from', 'to' and 'via' members
1192  if (value.substr(0, 5) == "only_") {
1193  myRestrictionType = RESTRICTION_ONLY;
1194  } else if (value.substr(0, 3) == "no_") {
1195  myRestrictionType = RESTRICTION_NO;
1196  } else {
1197  WRITE_WARNING(
1198  "Found unknown restriction type '" + value + "' in relation '" + toString(myCurrentRelation)
1199  + "'");
1200  }
1201  return;
1202  }
1203  } else if (key == "public_transport") {
1204  std::string value = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1205  if (value == "stop_area") {
1206  myIsStopArea = true;
1207  }
1208  } else if (key == "route") {
1209  std::string value = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1210  if (value == "train" || value == "subway" || value == "light_rail" || value == "monorail" || value == "tram" || value == "bus"
1211  || value == "trolleybus" || value == "arialway" || value == "ferry") {
1212  myPTRouteType = value;
1213  }
1214 
1215  } else if (key == "name") {
1216  myName = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1217  } else if (key == "ref") {
1218  myRef = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1219  } else if (key == "interval" || key == "headway") {
1220  myInterval = attrs.get<int>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1221  } else if (key == "by_night") {
1222  myNightService = attrs.get<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, false);
1223  }
1224  }
1225 }
1226 
1227 bool
1229  if (myOSMEdges.find(ref) != myOSMEdges.end()) {
1230  return true;
1231  }
1232 
1233  WRITE_WARNING(
1234  "No way found for reference '" + toString(ref) + "' in relation '" + toString(myCurrentRelation) + "'");
1235  return false;
1236 
1237 }
1238 
1239 void
1241  myParentElements.pop_back();
1242  if (element == SUMO_TAG_RELATION) {
1243  if (myIsRestriction) {
1244  assert(myCurrentRelation != INVALID_ID);
1245  bool ok = true;
1246  if (myRestrictionType == RESTRICTION_UNKNOWN) {
1247  WRITE_WARNING("Ignoring restriction relation '" + toString(myCurrentRelation) + "' with unknown type.");
1248  ok = false;
1249  }
1250  if (myFromWay == INVALID_ID) {
1251  WRITE_WARNING(
1252  "Ignoring restriction relation '" + toString(myCurrentRelation) + "' with unknown from-way.");
1253  ok = false;
1254  }
1255  if (myToWay == INVALID_ID) {
1256  WRITE_WARNING(
1257  "Ignoring restriction relation '" + toString(myCurrentRelation) + "' with unknown to-way.");
1258  ok = false;
1259  }
1260  if (myViaNode == INVALID_ID && myViaWay == INVALID_ID) {
1261  WRITE_WARNING("Ignoring restriction relation '" + toString(myCurrentRelation) + "' with unknown via.");
1262  ok = false;
1263  }
1264  if (ok && !applyRestriction()) {
1265  WRITE_WARNING("Ignoring restriction relation '" + toString(myCurrentRelation) + "'.");
1266  }
1267  } else if (myIsStopArea && OptionsCont::getOptions().isSet("ptstop-output")) {
1268  for (long long ref : myStops) {
1269  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
1270  //WRITE_WARNING(
1271  // "Referenced node: '" + toString(ref) + "' in relation: '" + toString(myCurrentRelation)
1272  // + "' does not exist. Probably OSM file is incomplete.");
1273  continue;
1274  }
1275 
1276  NIOSMNode* n = myOSMNodes.find(ref)->second;
1277  NBPTStop* ptStop = myNBPTStopCont->get(toString(n->id));
1278  if (ptStop == nullptr) {
1279  //WRITE_WARNING(
1280  // "Relation '" + toString(myCurrentRelation) + "' refers to a non existing pt stop at node: '"
1281  // + toString(n->id) + "'. Probably OSM file is incomplete.");
1282  continue;
1283  }
1284  for (NIIPTPlatform& myPlatform : myPlatforms) {
1285  if (myPlatform.isWay) {
1286  assert(myPlatformShapes.find(myPlatform.ref) != myPlatformShapes.end()); //already tested earlier
1287  Edge* edge = (*myPlatformShapes.find(myPlatform.ref)).second;
1288  if (edge->myCurrentNodes[0] == *(edge->myCurrentNodes.end() - 1)) {
1289  WRITE_WARNING("Platform '" + toString(myPlatform.ref) + "' in relation: '" + toString(myCurrentRelation)
1290  + "' is given as polygon, which currently is not supported.");
1291  continue;
1292 
1293  }
1294  PositionVector p;
1295  for (auto nodeRef : edge->myCurrentNodes) {
1296  if (myOSMNodes.find(nodeRef) == myOSMNodes.end()) {
1297  //WRITE_WARNING(
1298  // "Referenced node: '" + toString(ref) + "' in relation: '" + toString(myCurrentRelation)
1299  // + "' does not exist. Probably OSM file is incomplete.");
1300  continue;
1301  }
1302  NIOSMNode* pNode = myOSMNodes.find(nodeRef)->second;
1303  Position pNodePos(pNode->lon, pNode->lat, pNode->ele);
1304  if (!NBNetBuilder::transformCoordinate(pNodePos)) {
1305  WRITE_ERROR("Unable to project coordinates for node '" + toString(pNode->id) + "'.");
1306  continue;
1307  }
1308  p.push_back(pNodePos);
1309  }
1310  if (p.size() == 0) {
1311  WRITE_WARNING(
1312  "Referenced platform: '" + toString(myPlatform.ref) + "' in relation: '" + toString(myCurrentRelation)
1313  + "' is corrupt. Probably OSM file is incomplete.");
1314  continue;
1315  }
1316  NBPTPlatform platform(p[(int)p.size() / 2], p.length());
1317  ptStop->addPlatformCand(platform);
1318  } else {
1319  if (myOSMNodes.find(myPlatform.ref) == myOSMNodes.end()) {
1320  //WRITE_WARNING(
1321  // "Referenced node: '" + toString(ref) + "' in relation: '" + toString(myCurrentRelation)
1322  // + "' does not exist. Probably OSM file is incomplete.");
1323  continue;
1324  }
1325  NIOSMNode* pNode = myOSMNodes.find(myPlatform.ref)->second;
1326  Position platformPos(pNode->lon, pNode->lat, pNode->ele);
1327  if (!NBNetBuilder::transformCoordinate(platformPos)) {
1328  WRITE_ERROR("Unable to project coordinates for node '" + toString(pNode->id) + "'.");
1329  }
1330  NBPTPlatform platform(platformPos, myOptionsCont.getFloat(
1331  "osm.stop-output.length"));
1332  ptStop->addPlatformCand(platform);
1333 
1334  }
1335  }
1336  ptStop->setIsMultipleStopPositions(myStops.size() > 1);;
1337  }
1338  } else if (myPTRouteType != "" && myIsRoute && OptionsCont::getOptions().isSet("ptline-output") && myStops.size() > 1) {
1339  NBPTLine* ptLine = new NBPTLine(toString(myCurrentRelation), myName, myPTRouteType, myRef, myInterval, myNightService);
1340  ptLine->setMyNumOfStops((int)myStops.size());
1341  for (long long ref : myStops) {
1342  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
1343  //WRITE_WARNING(
1344  // "Referenced node: '" + toString(ref) + "' in relation: '" + toString(myCurrentRelation)
1345  // + "' does not exist. Probably OSM file is incomplete.");
1346 // resetValues();
1347 // return;
1348  if (!ptLine->getStops().empty()) {
1349  WRITE_WARNING("Done reading first coherent chunk of pt stops. Further stops in relation " + toString(myCurrentRelation) + " are ignored");
1350  break;
1351  }
1352  continue;
1353  }
1354 
1355  NIOSMNode* n = myOSMNodes.find(ref)->second;
1356  NBPTStop* ptStop = myNBPTStopCont->get(toString(n->id));
1357  if (ptStop == nullptr) {
1358  //WRITE_WARNING("Relation '" + toString(myCurrentRelation)
1359  // + "' refers to a non existing pt stop at node: '" + toString(n->id)
1360  // + "'. Probably OSM file is incomplete.");
1361 // resetValues();
1362 // return;
1363  if (!ptLine->getStops().empty()) {
1364  WRITE_WARNING("Done reading first coherent chunk of pt stops. Further stops in relation " + toString(myCurrentRelation) + " are ignored");
1365  break;
1366  }
1367  continue;
1368  }
1369  ptLine->addPTStop(ptStop);
1370  }
1371  for (long long& myWay : myWays) {
1372  auto entr = myOSMEdges.find(myWay);
1373  if (entr != myOSMEdges.end()) {
1374  Edge* edge = entr->second;
1375  for (long long& myCurrentNode : edge->myCurrentNodes) {
1376  ptLine->addWayNode(myWay, myCurrentNode);
1377  }
1378  }
1379  }
1380  if (ptLine->getStops().empty()) {
1381  WRITE_WARNING("PT line in relation " + toString(myCurrentRelation) + " with no stops ignored. Probably OSM file is incomplete.");
1382  resetValues();
1383  return;
1384  }
1385  if (myNBPTLineCont->getLines().count(ptLine->getLineID()) == 0) {
1386  myNBPTLineCont->insert(ptLine);
1387  } else {
1388  WRITE_WARNING("Ignoring duplicate PT line " + toString(myCurrentRelation) + ".");
1389  delete ptLine;
1390  }
1391  }
1392  // other relations might use similar subelements so reset in any case
1393  resetValues();
1394  }
1395 }
1396 
1397 bool
1399  // since OSM ways are bidirectional we need the via to figure out which direction was meant
1400  if (myViaNode != INVALID_ID) {
1401  NBNode* viaNode = myOSMNodes.find(myViaNode)->second->node;
1402  if (viaNode == nullptr) {
1403  WRITE_WARNING("Via-node '" + toString(myViaNode) + "' was not instantiated");
1404  return false;
1405  }
1406  NBEdge* from = findEdgeRef(myFromWay, viaNode->getIncomingEdges());
1407  NBEdge* to = findEdgeRef(myToWay, viaNode->getOutgoingEdges());
1408  if (from == nullptr) {
1409  WRITE_WARNING("from-edge of restriction relation could not be determined");
1410  return false;
1411  }
1412  if (to == nullptr) {
1413  WRITE_WARNING("to-edge of restriction relation could not be determined");
1414  return false;
1415  }
1416  if (myRestrictionType == RESTRICTION_ONLY) {
1417  from->addEdge2EdgeConnection(to);
1418  } else {
1419  from->removeFromConnections(to, -1, -1, true);
1420  }
1421  } else {
1422  // XXX interpreting via-ways or via-node lists not yet implemented
1423  WRITE_WARNING("direction of restriction relation could not be determined");
1424  return false;
1425  }
1426  return true;
1427 }
1428 
1429 NBEdge*
1431  const std::vector<NBEdge*>& candidates) const {
1432  const std::string prefix = toString(wayRef);
1433  const std::string backPrefix = "-" + prefix;
1434  NBEdge* result = nullptr;
1435  int found = 0;
1436  for (auto candidate : candidates) {
1437  if ((candidate->getID().substr(0, prefix.size()) == prefix) ||
1438  (candidate->getID().substr(0, backPrefix.size()) == backPrefix)) {
1439  result = candidate;
1440  found++;
1441  }
1442  }
1443  if (found > 1) {
1444  WRITE_WARNING("Ambigous way reference '" + prefix + "' in restriction relation");
1445  result = nullptr;
1446  }
1447  return result;
1448 }
1449 
1450 void
1452  NBNodeCont& nc = nb.getNodeCont();
1453  NBEdgeCont& ec = nb.getEdgeCont();
1454  // reconstruct elevation from layer info
1455  // build a map of raising and lowering forces (attractor and distance)
1456  // for all nodes unknownElevation
1457  std::map<NBNode*, std::vector<std::pair<double, double> > > layerForces;
1458 
1459  // collect all nodes that belong to a way with layer information
1460  std::set<NBNode*> knownElevation;
1461  for (auto& myEdge : myEdges) {
1462  Edge* e = myEdge.second;
1463  if (e->myLayer != 0) {
1464  for (auto j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
1465  NBNode* node = nc.retrieve(toString(*j));
1466  if (node != nullptr) {
1467  knownElevation.insert(node);
1468  layerForces[node].emplace_back(e->myLayer * layerElevation, POSITION_EPS);
1469  }
1470  }
1471  }
1472  }
1473 #ifdef DEBUG_LAYER_ELEVATION
1474  std::cout << "known elevations:\n";
1475  for (std::set<NBNode*>::iterator it = knownElevation.begin(); it != knownElevation.end(); ++it) {
1476  const std::vector<std::pair<double, double> >& primaryLayers = layerForces[*it];
1477  std::cout << " node=" << (*it)->getID() << " ele=";
1478  for (std::vector<std::pair<double, double> >::const_iterator it_ele = primaryLayers.begin(); it_ele != primaryLayers.end(); ++it_ele) {
1479  std::cout << it_ele->first << " ";
1480  }
1481  std::cout << "\n";
1482  }
1483 #endif
1484  // layer data only provides a lower bound on elevation since it is used to
1485  // resolve the relation among overlapping ways.
1486  // Perform a sanity check for steep inclines and raise the knownElevation if necessary
1487  std::map<NBNode*, double> knownEleMax;
1488  for (auto it : knownElevation) {
1489  double eleMax = -std::numeric_limits<double>::max();
1490  const std::vector<std::pair<double, double> >& primaryLayers = layerForces[it];
1491  for (const auto& primaryLayer : primaryLayers) {
1492  eleMax = MAX2(eleMax, primaryLayer.first);
1493  }
1494  knownEleMax[it] = eleMax;
1495  }
1496  const double gradeThreshold = OptionsCont::getOptions().getFloat("osm.layer-elevation.max-grade") / 100;
1497  bool changed = true;
1498  while (changed) {
1499  changed = false;
1500  for (auto it = knownElevation.begin(); it != knownElevation.end(); ++it) {
1501  std::map<NBNode*, std::pair<double, double> > neighbors = getNeighboringNodes(*it,
1502  knownEleMax[*it]
1503  / gradeThreshold * 3,
1504  knownElevation);
1505  for (auto& neighbor : neighbors) {
1506  if (knownElevation.count(neighbor.first) != 0) {
1507  const double grade = fabs(knownEleMax[*it] - knownEleMax[neighbor.first])
1508  / MAX2(POSITION_EPS, neighbor.second.first);
1509 #ifdef DEBUG_LAYER_ELEVATION
1510  std::cout << " grade at node=" << (*it)->getID() << " ele=" << knownEleMax[*it] << " neigh=" << it_neigh->first->getID() << " neighEle=" << knownEleMax[it_neigh->first] << " grade=" << grade << " dist=" << it_neigh->second.first << " speed=" << it_neigh->second.second << "\n";
1511 #endif
1512  if (grade > gradeThreshold * 50 / 3.6 / neighbor.second.second) {
1513  // raise the lower node to the higher level
1514  const double eleMax = MAX2(knownEleMax[*it], knownEleMax[neighbor.first]);
1515  if (knownEleMax[*it] < eleMax) {
1516  knownEleMax[*it] = eleMax;
1517  } else {
1518  knownEleMax[neighbor.first] = eleMax;
1519  }
1520  changed = true;
1521  }
1522  }
1523  }
1524  }
1525  }
1526 
1527  // collect all nodes within a grade-dependent range around knownElevation-nodes and apply knowElevation forces
1528  std::set<NBNode*> unknownElevation;
1529  for (auto it = knownElevation.begin(); it != knownElevation.end(); ++it) {
1530  const double eleMax = knownEleMax[*it];
1531  const double maxDist = fabs(eleMax) * 100 / layerElevation;
1532  std::map<NBNode*, std::pair<double, double> > neighbors = getNeighboringNodes(*it, maxDist, knownElevation);
1533  for (auto& neighbor : neighbors) {
1534  if (knownElevation.count(neighbor.first) == 0) {
1535  unknownElevation.insert(neighbor.first);
1536  layerForces[neighbor.first].emplace_back(eleMax, neighbor.second.first);
1537  }
1538  }
1539  }
1540 
1541  // apply forces to ground-level nodes (neither in knownElevation nor unknownElevation)
1542  for (auto it = unknownElevation.begin(); it != unknownElevation.end(); ++it) {
1543  double eleMax = -std::numeric_limits<double>::max();
1544  const std::vector<std::pair<double, double> >& primaryLayers = layerForces[*it];
1545  for (const auto& primaryLayer : primaryLayers) {
1546  eleMax = MAX2(eleMax, primaryLayer.first);
1547  }
1548  const double maxDist = fabs(eleMax) * 100 / layerElevation;
1549  std::map<NBNode*, std::pair<double, double> > neighbors = getNeighboringNodes(*it, maxDist, knownElevation);
1550  for (auto& neighbor : neighbors) {
1551  if (knownElevation.count(neighbor.first) == 0 && unknownElevation.count(neighbor.first) == 0) {
1552  layerForces[*it].emplace_back(0, neighbor.second.first);
1553  }
1554  }
1555  }
1556  // compute the elevation for each node as the weighted average of all forces
1557 #ifdef DEBUG_LAYER_ELEVATION
1558  std::cout << "summation of forces\n";
1559 #endif
1560  std::map<NBNode*, double> nodeElevation;
1561  for (auto& layerForce : layerForces) {
1562  const std::vector<std::pair<double, double> >& forces = layerForce.second;
1563  if (knownElevation.count(layerForce.first) != 0) {
1564  // use the maximum value
1565  /*
1566  double eleMax = -std::numeric_limits<double>::max();
1567  for (std::vector<std::pair<double, double> >::const_iterator it_force = forces.begin(); it_force != forces.end(); ++it_force) {
1568  eleMax = MAX2(eleMax, it_force->first);
1569  }
1570  */
1571 #ifdef DEBUG_LAYER_ELEVATION
1572  std::cout << " node=" << it->first->getID() << " knownElevation=" << knownEleMax[it->first] << "\n";
1573 #endif
1574  nodeElevation[layerForce.first] = knownEleMax[layerForce.first];
1575  } else if (forces.size() == 1) {
1576  nodeElevation[layerForce.first] = forces.front().first;
1577  } else {
1578  // use the weighted sum
1579  double distSum = 0;
1580  for (const auto& force : forces) {
1581  distSum += force.second;
1582  }
1583  double weightSum = 0;
1584  double elevation = 0;
1585 #ifdef DEBUG_LAYER_ELEVATION
1586  std::cout << " node=" << it->first->getID() << " distSum=" << distSum << "\n";
1587 #endif
1588  for (const auto& force : forces) {
1589  const double weight = (distSum - force.second) / distSum;
1590  weightSum += weight;
1591  elevation += force.first * weight;
1592 
1593 #ifdef DEBUG_LAYER_ELEVATION
1594  std::cout << " force=" << it_force->first << " dist=" << it_force->second << " weight=" << weight << " ele=" << elevation << "\n";
1595 #endif
1596  }
1597  nodeElevation[layerForce.first] = elevation / weightSum;
1598  }
1599  }
1600 #ifdef DEBUG_LAYER_ELEVATION
1601  std::cout << "final elevations:\n";
1602  for (std::map<NBNode*, double>::iterator it = nodeElevation.begin(); it != nodeElevation.end(); ++it) {
1603  std::cout << " node=" << (it->first)->getID() << " ele=" << it->second << "\n";;
1604  }
1605 #endif
1606  // apply node elevations
1607  for (auto& it : nodeElevation) {
1608  NBNode* n = it.first;
1609  Position pos = n->getPosition();
1610  n->reinit(n->getPosition() + Position(0, 0, it.second), n->getType());
1611  }
1612 
1613  // apply way elevation to all edges that had layer information
1614  for (const auto& it : ec) {
1615  NBEdge* edge = it.second;
1616  const PositionVector& geom = edge->getGeometry();
1617  const double length = geom.length2D();
1618  const double zFrom = nodeElevation[edge->getFromNode()];
1619  const double zTo = nodeElevation[edge->getToNode()];
1620  // XXX if the from- or to-node was part of multiple ways with
1621  // different layers, reconstruct the layer value from origID
1622  double dist = 0;
1623  PositionVector newGeom;
1624  for (auto it_pos = geom.begin(); it_pos != geom.end(); ++it_pos) {
1625  if (it_pos != geom.begin()) {
1626  dist += (*it_pos).distanceTo2D(*(it_pos - 1));
1627  }
1628  newGeom.push_back((*it_pos) + Position(0, 0, zFrom + (zTo - zFrom) * dist / length));
1629  }
1630  edge->setGeometry(newGeom);
1631  }
1632 }
1633 
1634 std::map<NBNode*, std::pair<double, double> >
1635 NIImporter_OpenStreetMap::getNeighboringNodes(NBNode* node, double maxDist, const std::set<NBNode*>& knownElevation) {
1636  std::map<NBNode*, std::pair<double, double> > result;
1637  std::set<NBNode*> visited;
1638  std::vector<NBNode*> open;
1639  open.push_back(node);
1640  result[node] = std::make_pair(0, 0);
1641  while (!open.empty()) {
1642  NBNode* n = open.back();
1643  open.pop_back();
1644  if (visited.count(n) != 0) {
1645  continue;
1646  }
1647  visited.insert(n);
1648  const EdgeVector& edges = n->getEdges();
1649  for (auto e : edges) {
1650  NBNode* s = nullptr;
1651  if (n->hasIncoming(e)) {
1652  s = e->getFromNode();
1653  } else {
1654  s = e->getToNode();
1655  }
1656  const double dist = result[n].first + e->getGeometry().length2D();
1657  const double speed = MAX2(e->getSpeed(), result[n].second);
1658  if (result.count(s) == 0) {
1659  result[s] = std::make_pair(dist, speed);
1660  } else {
1661  result[s] = std::make_pair(MIN2(dist, result[s].first), MAX2(speed, result[s].second));
1662  }
1663  if (dist < maxDist && knownElevation.count(s) == 0) {
1664  open.push_back(s);
1665  }
1666  }
1667  }
1668  result.erase(node);
1669  return result;
1670 }
1671 
1672 
1673 std::string
1674 NIImporter_OpenStreetMap::usableType(const std::string& type, const std::string& id, NBTypeCont& tc) {
1675  if (tc.knows(type)) {
1676  return type;
1677  }
1678  if (myUnusableTypes.count(type) > 0) {
1679  return "";
1680  }
1681  if (myKnownCompoundTypes.count(type) > 0) {
1682  return myKnownCompoundTypes[type];
1683  }
1684  // this edge has a type which does not yet exist in the TypeContainer
1686  std::vector<std::string> types;
1687  while (tok.hasNext()) {
1688  std::string t = tok.next();
1689  if (tc.knows(t)) {
1690  if (std::find(types.begin(), types.end(), t) == types.end()) {
1691  types.push_back(t);
1692  }
1693  } else if (tok.size() > 1) {
1694  WRITE_WARNING(
1695  "Discarding unknown compound '" + t + "' in type '" + type + "' (first occurence for edge '"
1696  + id
1697  + "').");
1698  }
1699  }
1700  if (types.empty()) {
1701  WRITE_WARNING("Discarding unusable type '" + type + "' (first occurence for edge '" + id + "').");
1702  myUnusableTypes.insert(type);
1703  return "";
1704  }
1705  const std::string newType = joinToString(types, "|");
1706  if (tc.knows(newType)) {
1707  myKnownCompoundTypes[type] = newType;
1708  return newType;
1709  } else if (myKnownCompoundTypes.count(newType) > 0) {
1710  return myKnownCompoundTypes[newType];
1711  } else {
1712  // build a new type by merging all values
1713  int numLanes = 0;
1714  double maxSpeed = 0;
1715  int prio = 0;
1716  double width = NBEdge::UNSPECIFIED_WIDTH;
1717  double sidewalkWidth = NBEdge::UNSPECIFIED_WIDTH;
1718  double bikelaneWidth = NBEdge::UNSPECIFIED_WIDTH;
1719  bool defaultIsOneWay = false;
1720  SVCPermissions permissions = 0;
1721  bool discard = true;
1722  for (auto& type2 : types) {
1723  if (!tc.getShallBeDiscarded(type2)) {
1724  numLanes = MAX2(numLanes, tc.getNumLanes(type2));
1725  maxSpeed = MAX2(maxSpeed, tc.getSpeed(type2));
1726  prio = MAX2(prio, tc.getPriority(type2));
1727  defaultIsOneWay &= tc.getIsOneWay(type2);
1728  //std::cout << "merging component " << type2 << " into type " << newType << " allows=" << getVehicleClassNames(tc.getPermissions(type2)) << "\n";
1729  permissions |= tc.getPermissions(type2);
1730  width = MAX2(width, tc.getWidth(type2));
1731  sidewalkWidth = MAX2(sidewalkWidth, tc.getSidewalkWidth(type2));
1732  bikelaneWidth = MAX2(bikelaneWidth, tc.getBikeLaneWidth(type2));
1733  discard = false;
1734  }
1735  }
1736  if (width != NBEdge::UNSPECIFIED_WIDTH) {
1737  width = MAX2(width, SUMO_const_laneWidth);
1738  }
1739  // ensure pedestrians don't run into trains
1740  if (sidewalkWidth == NBEdge::UNSPECIFIED_WIDTH
1741  && (permissions & SVC_PEDESTRIAN) != 0
1742  && (permissions & SVC_RAIL_CLASSES) != 0) {
1743  //std::cout << "patching sidewalk for type '" << newType << "' which allows=" << getVehicleClassNames(permissions) << "\n";
1744  sidewalkWidth = OptionsCont::getOptions().getFloat("default.sidewalk-width");
1745  }
1746 
1747  if (discard) {
1748  WRITE_WARNING(
1749  "Discarding compound type '" + newType + "' (first occurence for edge '" + id + "').");
1750  myUnusableTypes.insert(newType);
1751  return "";
1752  }
1753 
1754  WRITE_MESSAGE("Adding new type '" + type + "' (first occurence for edge '" + id + "').");
1755  tc.insert(newType, numLanes, maxSpeed, prio, permissions, width, defaultIsOneWay,
1756  sidewalkWidth, bikelaneWidth, 0, 0, 0);
1757  for (auto& type3 : types) {
1758  if (!tc.getShallBeDiscarded(type3)) {
1759  tc.copyRestrictionsAndAttrs(type3, newType);
1760  }
1761  }
1762  myKnownCompoundTypes[type] = newType;
1763  return newType;
1764  }
1765 }
1766 
1767 void
1769  const std::string id = toString(e->id);
1770  std::string type = usableType(e->myHighWayType, id, tc);
1771  if (type != "" && isRailway(tc.getPermissions(type))) {
1772  std::vector<NIOSMNode*> nodes;
1773  std::vector<double> usablePositions;
1774  std::vector<int> usableIndex;
1775  int i = 0;
1776  for (long long int n : e->myCurrentNodes) {
1777  NIOSMNode* node = myOSMNodes[n];
1778  node->positionMeters = interpretDistance(node);
1779  if (node->positionMeters != std::numeric_limits<double>::max()) {
1780  usablePositions.push_back(node->positionMeters);
1781  usableIndex.push_back(i);
1782  }
1783  i++;
1784  nodes.push_back(node);
1785  }
1786  if (usablePositions.size() == 0) {
1787  return;
1788  } else {
1789  bool forward = true;
1790  if (usablePositions.size() == 1) {
1791  WRITE_WARNING("Ambiguous railway kilometrage direction for way '" + id + "' (assuming forward)");
1792  } else {
1793  forward = usablePositions.front() < usablePositions.back();
1794  }
1795  // check for consistency
1796  for (int i = 1; i < (int)usablePositions.size(); i++) {
1797  if ((usablePositions[i - 1] < usablePositions[i]) != forward) {
1798  WRITE_WARNING("Inconsistent railway kilometrage direction for way '" + id + "': " + toString(usablePositions) + " (skipping)");
1799  return;
1800  }
1801  }
1802  if (nodes.size() > usablePositions.size()) {
1803  // complete missing values
1804  PositionVector shape;
1805  for (NIOSMNode* node : nodes) {
1806  shape.push_back(Position(node->lon, node->lat, 0));
1807  }
1808  if (!NBNetBuilder::transformCoordinates(shape)) {
1809  return; // error will be given later
1810  }
1811  double sign = forward ? 1 : -1;
1812  // extend backward before first usable value
1813  for (int i = usableIndex.front() - 1; i >= 0; i--) {
1814  nodes[i]->positionMeters = nodes[i + 1]->positionMeters - sign * shape[i].distanceTo2D(shape[i + 1]);
1815  }
1816  // extend forward
1817  for (int i = usableIndex.front() + 1; i < (int)nodes.size(); i++) {
1818  if (nodes[i]->positionMeters == std::numeric_limits<double>::max()) {
1819  nodes[i]->positionMeters = nodes[i - 1]->positionMeters + sign * shape[i].distanceTo2D(shape[i - 1]);
1820  }
1821  }
1822  //std::cout << " way=" << id << " usable=" << toString(usablePositions) << "\n indices=" << toString(usableIndex)
1823  // << " final:\n";
1824  //for (auto n : nodes) {
1825  // std::cout << " " << n->id << " " << n->positionMeters << " " << n->position<< "\n";
1826  //}
1827  }
1828  }
1829  }
1830 }
1831 
1832 
1833 double
1835  if (node->position.size() > 0) {
1836  try {
1837  if (StringUtils::startsWith(node->position, "mi:")) {
1838  return StringUtils::toDouble(node->position.substr(3)) * 1609.344; // meters per mile
1839  } else {
1840  return StringUtils::toDouble(node->position) * 1000;
1841  }
1842  } catch (...) {
1843  WRITE_WARNING("Value of railway:position is not numeric ('" + node->position + "') in node '" +
1844  toString(node->id) + "'.");
1845  }
1846  }
1847  return std::numeric_limits<double>::max();
1848 }
1849 
1850 /****************************************************************************/
1851 
SVC_RAIL_FAST
vehicle that is allowed to drive on high-speed rail tracks
Definition: SUMOVehicleClass.h:193
NIImporter_OpenStreetMap::NIOSMNode::name
std::string name
The name of the node.
Definition: NIImporter_OpenStreetMap.h:112
NBTypeCont::copyRestrictionsAndAttrs
bool copyRestrictionsAndAttrs(const std::string &fromId, const std::string &toId)
Copy restrictions to a type.
Definition: NBTypeCont.cpp:111
OptionsCont::isSet
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
Definition: OptionsCont.cpp:136
NIImporter_OpenStreetMap::Edge::myIsOneWay
std::string myIsOneWay
Information whether this is an one-way road.
Definition: NIImporter_OpenStreetMap.h:186
SUMO_ATTR_TYPE
Definition: SUMOXMLDefinitions.h:382
NBEdge::UNSPECIFIED_OFFSET
static const double UNSPECIFIED_OFFSET
unspecified lane offset
Definition: NBEdge.h:306
SVC_PEDESTRIAN
pedestrian
Definition: SUMOVehicleClass.h:157
Parameterised::updateParameter
void updateParameter(const std::map< std::string, std::string > &mapArg)
Adds or updates all given parameters from the map.
Definition: Parameterised.cpp:57
NBPTStop::setIsMultipleStopPositions
void setIsMultipleStopPositions(bool multipleStopPositions)
Definition: NBPTStop.cpp:155
NIImporter_OpenStreetMap::myKnownCompoundTypes
std::map< std::string, std::string > myKnownCompoundTypes
The compound types that have already been mapped to other known types.
Definition: NIImporter_OpenStreetMap.h:258
ToString.h
XMLSubSys::runParser
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:113
SUMOSAXAttributes::hasAttribute
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
NIImporter_OpenStreetMap::insertNodeChecking
NBNode * insertNodeChecking(long long int id, NBNodeCont &nc, NBTrafficLightLogicCont &tlsc)
Builds an NBNode.
Definition: NIImporter_OpenStreetMap.cpp:267
MIN2
T MIN2(T a, T b)
Definition: StdDefs.h:74
joinToStringSorting
std::string joinToStringSorting(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:263
NBPTStopCont
Definition: NBPTStopCont.h:28
NIImporter_OpenStreetMap::NIOSMNode
An internal representation of an OSM-node.
Definition: NIImporter_OpenStreetMap.h:78
NIImporter_OpenStreetMap::loadNetwork
static void loadNetwork(const OptionsCont &oc, NBNetBuilder &nb)
Loads content of the optionally given OSM file.
Definition: NIImporter_OpenStreetMap.cpp:103
WRITE_WARNING
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:239
NIImporter_OpenStreetMap::NIOSMNode::ele
double ele
The elevation of this node.
Definition: NIImporter_OpenStreetMap.h:98
NIImporter_OpenStreetMap::Edge::id
const long long int id
The edge's id.
Definition: NIImporter_OpenStreetMap.h:172
NIImporter_OpenStreetMap::Edge::myBuswayType
WayType myBuswayType
Information about the kind of busway along this road.
Definition: NIImporter_OpenStreetMap.h:190
NBEdgeCont
Storage for edges, including some functionality operating on multiple edges.
Definition: NBEdgeCont.h:61
NIImporter_OpenStreetMap::NIOSMNode::ptStopLength
double ptStopLength
The length of the pt stop.
Definition: NIImporter_OpenStreetMap.h:110
NIImporter_OpenStreetMap::PARKING_RIGHT
Definition: NIImporter_OpenStreetMap.h:143
SUMOSAXHandler
SAX-handler base for SUMO-files.
Definition: SUMOSAXHandler.h:42
NBNetBuilder
Instance responsible for building networks.
Definition: NBNetBuilder.h:110
NBTrafficLightLogicCont
A container for traffic light definitions and built programs.
Definition: NBTrafficLightLogicCont.h:58
GeomConvHelper.h
SUMO_TAG_MEMBER
Definition: SUMOXMLDefinitions.h:237
OptionsCont.h
StringTokenizer::hasNext
bool hasNext()
returns the information whether further substrings exist
Definition: StringTokenizer.cpp:95
LANESPREAD_RIGHT
Definition: SUMOXMLDefinitions.h:1093
StringUtils::toDouble
static double toDouble(const std::string &sData)
converts a string into the double value described by it by calling the char-type converter
Definition: StringUtils.cpp:313
SUMOSAXAttributes::get
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
Definition: SUMOSAXAttributes.h:493
NBPTLine::getStops
std::vector< NBPTStop * > getStops()
Definition: NBPTLine.cpp:41
NIImporter_OpenStreetMap::Edge::myCurrentIsElectrified
bool myCurrentIsElectrified
Information whether this is railway is electrified.
Definition: NIImporter_OpenStreetMap.h:206
NIImporter_OpenStreetMap::NIOSMNode::railwayCrossing
bool railwayCrossing
Whether this is a railway crossing.
Definition: NIImporter_OpenStreetMap.h:102
MsgHandler.h
NIImporter_OpenStreetMap::RelationHandler::~RelationHandler
~RelationHandler() override
Destructor.
EdgeVector
std::vector< NBEdge * > EdgeVector
container for (sorted) edges
Definition: NBCont.h:35
NIImporter_OpenStreetMap::RelationHandler::resetValues
void resetValues()
reset members to their defaults for parsing a new relation
Definition: NIImporter_OpenStreetMap.cpp:1082
NIImporter_OpenStreetMap.h
NBNodeCont::insert
bool insert(const std::string &id, const Position &position, NBDistrict *district=0)
Inserts a node into the map.
Definition: NBNodeCont.cpp:79
SUMOSAXHandler.h
NBNode::getOutgoingEdges
const EdgeVector & getOutgoingEdges() const
Returns this node's outgoing edges (The edges which start at this node)
Definition: NBNode.h:264
FileHelpers.h
NBPTLine
Definition: NBPTLine.h:34
NBEdge::addEdge2EdgeConnection
bool addEdge2EdgeConnection(NBEdge *dest)
Adds a connection to another edge.
Definition: NBEdge.cpp:990
TrafficLightType
TrafficLightType
Definition: SUMOXMLDefinitions.h:1192
NBPTStopCont::cleanupDeleted
void cleanupDeleted(NBEdgeCont &cont)
remove stops on non existing (removed) edges
Definition: NBPTStopCont.cpp:300
StringUtils::to_lower_case
static std::string to_lower_case(std::string str)
Transfers the content to lower case.
Definition: StringUtils.cpp:58
NBNetBuilder::transformCoordinates
static bool transformCoordinates(PositionVector &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
Definition: NBNetBuilder.cpp:690
NIImporter_OpenStreetMap::NIOSMNode::railwayBufferStop
bool railwayBufferStop
Whether this is a railway buffer stop.
Definition: NIImporter_OpenStreetMap.h:106
NBEdgeCont.h
GeoConvHelper.h
OptionsCont::getBool
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
Definition: OptionsCont.cpp:223
NBOwnTLDef
A traffic light logics which must be computed (only nodes/edges are given)
Definition: NBOwnTLDef.h:47
SVC_BICYCLE
vehicle is a bicycle
Definition: SUMOVehicleClass.h:180
NIImporter_OpenStreetMap::NIOSMNode::tlsControlled
bool tlsControlled
Whether this is a tls controlled junction.
Definition: NIImporter_OpenStreetMap.h:100
EmptyData
Definition: UtilExceptions.h:69
NBTypeCont::insert
void insert(const std::string &id, int numLanes, double maxSpeed, int prio, SVCPermissions permissions, double width, bool oneWayIsDefault, double sidewalkWidth, double bikeLaneWidth, double widthResolution, double maxWidth, double minWidth)
Adds a type into the list.
Definition: NBTypeCont.cpp:54
OptionsCont::getOptions
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
NBNode::getType
SumoXMLNodeType getType() const
Returns the type of this node.
Definition: NBNode.h:276
NIImporter_OpenStreetMap::RelationHandler::myStartElement
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
Definition: NIImporter_OpenStreetMap.cpp:1099
StringTokenizer::next
std::string next()
returns the next substring when it exists. Otherwise the behaviour is undefined
Definition: StringTokenizer.cpp:100
SUMO_TAG_ND
Definition: SUMOXMLDefinitions.h:234
NIImporter_OpenStreetMap::Edge
An internal definition of a loaded edge.
Definition: NIImporter_OpenStreetMap.h:154
SUMO_const_laneWidth
const double SUMO_const_laneWidth
Definition: StdDefs.h:50
NIImporter_OpenStreetMap::NodesHandler
A class which extracts OSM-nodes from a parsed OSM-file.
Definition: NIImporter_OpenStreetMap.h:318
NBEdge::setDistance
void setDistance(double distance)
set lane specific speed (negative lane implies set for all lanes)
Definition: NBEdge.h:1263
NBNetBuilder::transformCoordinate
static bool transformCoordinate(Position &from, bool includeInBoundary=true, GeoConvHelper *from_srs=0)
transforms loaded coordinates handles projections, offsets (using GeoConvHelper) and import of height...
Definition: NBNetBuilder.cpp:663
NBEdgeCont::insert
bool insert(NBEdge *edge, bool ignorePrunning=false)
Adds an edge to the dictionary.
Definition: NBEdgeCont.cpp:152
SUMO_ATTR_ID
Definition: SUMOXMLDefinitions.h:379
PositionVector::length
double length() const
Returns the length.
Definition: PositionVector.cpp:476
NIImporter_OpenStreetMap::Edge::myCurrentNodes
std::vector< long long int > myCurrentNodes
The list of nodes this edge is made of.
Definition: NIImporter_OpenStreetMap.h:200
NBEdge::setPermissions
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:3413
NBEdge::getPermissions
SVCPermissions getPermissions(int lane=-1) const
get the union of allowed classes over all lanes or for a specific lane
Definition: NBEdge.cpp:3441
NIImporter_OpenStreetMap::WAY_NONE
Definition: NIImporter_OpenStreetMap.h:133
NIImporter_OpenStreetMap::reconstructLayerElevation
void reconstructLayerElevation(double layerElevation, NBNetBuilder &nb)
reconstruct elevation from layer info
Definition: NIImporter_OpenStreetMap.cpp:1451
NBPTLine::setMyNumOfStops
void setMyNumOfStops(int numStops)
Definition: NBPTLine.cpp:113
PositionVector
A list of positions.
Definition: PositionVector.h:46
SUMO_ATTR_V
Definition: SUMOXMLDefinitions.h:817
NIImporter_OpenStreetMap::load
void load(const OptionsCont &oc, NBNetBuilder &nb)
Definition: NIImporter_OpenStreetMap.cpp:126
NBTypeCont::knows
bool knows(const std::string &type) const
Returns whether the named type is in the container.
Definition: NBTypeCont.cpp:72
LANESPREAD_CENTER
Definition: SUMOXMLDefinitions.h:1094
NIImporter_OpenStreetMap::RelationHandler::myEndElement
void myEndElement(int element) override
Called when a closing tag occurs.
Definition: NIImporter_OpenStreetMap.cpp:1240
SVC_RAIL
vehicle is a not electrified rail
Definition: SUMOVehicleClass.h:189
NIImporter_OpenStreetMap::NIOSMNode::id
const long long int id
The node's id.
Definition: NIImporter_OpenStreetMap.h:92
NIImporter_OpenStreetMap::WAY_UNKNOWN
Definition: NIImporter_OpenStreetMap.h:137
SVC_RAIL_URBAN
vehicle is a city rail
Definition: SUMOVehicleClass.h:187
NBPTLine::getLineID
const std::string & getLineID() const
Definition: NBPTLine.h:42
NIImporter_OpenStreetMap::RelationHandler::findEdgeRef
NBEdge * findEdgeRef(long long int wayRef, const std::vector< NBEdge * > &candidates) const
try to find the way segment among candidates
Definition: NIImporter_OpenStreetMap.cpp:1430
NIImporter_OpenStreetMap::MAXSPEED_UNGIVEN
static const double MAXSPEED_UNGIVEN
Definition: NIImporter_OpenStreetMap.h:310
NBNetBuilder::getEdgeCont
NBEdgeCont & getEdgeCont()
Definition: NBNetBuilder.h:151
NBNodeCont
Container for nodes during the netbuilding process.
Definition: NBNodeCont.h:60
NIImporter_OpenStreetMap::NodesHandler::NodesHandler
NodesHandler(std::map< long long int, NIOSMNode * > &toFill, std::set< NIOSMNode *, CompareNodes > &uniqueNodes, const OptionsCont &cont)
Contructor.
Definition: NIImporter_OpenStreetMap.cpp:594
NBEdge
The representation of a single edge during network building.
Definition: NBEdge.h:86
NIImporter_OpenStreetMap::Edge::myNoLanesForward
int myNoLanesForward
number of lanes in forward direction or 0 if unknown, negative if backwards lanes are meant
Definition: NIImporter_OpenStreetMap.h:180
NIImporter_OpenStreetMap::EdgesHandler::myStartElement
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
Definition: NIImporter_OpenStreetMap.cpp:764
MAX2
T MAX2(T a, T b)
Definition: StdDefs.h:80
SVC_TRAM
vehicle is a light rail
Definition: SUMOVehicleClass.h:185
NBNode::getPosition
const Position & getPosition() const
Definition: NBNode.h:251
NIImporter_OpenStreetMap::NodesHandler::myStartElement
void myStartElement(int element, const SUMOSAXAttributes &attrs) override
Called on the opening of a tag;.
Definition: NIImporter_OpenStreetMap.cpp:612
NumberFormatException
Definition: UtilExceptions.h:96
NODETYPE_RAIL_SIGNAL
Definition: SUMOXMLDefinitions.h:1054
Parameterised::getParametersMap
const std::map< std::string, std::string > & getParametersMap() const
Returns the inner key/value map.
Definition: Parameterised.cpp:105
NBTypeCont::getIsOneWay
bool getIsOneWay(const std::string &type) const
Returns whether edges are one-way per default for the given type.
Definition: NBTypeCont.cpp:190
NBEdge::getToNode
NBNode * getToNode() const
Returns the destination node of the edge.
Definition: NBEdge.h:486
NIImporter_OpenStreetMap::EdgesHandler::mySpeedMap
std::map< std::string, double > mySpeedMap
A map of non-numeric speed descriptions to their numeric values.
Definition: NIImporter_OpenStreetMap.h:452
NBEdge::getGeometry
const PositionVector & getGeometry() const
Returns the geometry of the edge.
Definition: NBEdge.h:680
NBNetBuilder::getPTStopCont
NBPTStopCont & getPTStopCont()
Returns a reference to the pt stop container.
Definition: NBNetBuilder.h:177
NIImporter_OpenStreetMap::CompareEdges::operator()
bool operator()(const Edge *e1, const Edge *e2) const
Definition: NIImporter_OpenStreetMap.cpp:73
NBPTLineCont
Definition: NBPTLineCont.h:27
StringUtils::prune
static std::string prune(const std::string &str)
Removes trailing and leading whitechars.
Definition: StringUtils.cpp:47
NBPTLineCont.h
StringUtils::endsWith
static bool endsWith(const std::string &str, const std::string suffix)
Checks whether a given string ends with the suffix.
Definition: StringUtils.cpp:148
NIImporter_OpenStreetMap::extendRailwayDistances
void extendRailwayDistances(Edge *e, NBTypeCont &tc)
extend kilometrage data for all nodes along railway
Definition: NIImporter_OpenStreetMap.cpp:1768
NBNetBuilder::getPTLineCont
NBPTLineCont & getPTLineCont()
Returns a reference to the pt line container.
Definition: NBNetBuilder.h:182
NIImporter_OpenStreetMap::RelationHandler::RelationHandler
RelationHandler(const std::map< long long int, NIOSMNode * > &osmNodes, const std::map< long long int, Edge * > &osmEdges, NBPTStopCont *nbptStopCont, const std::map< long long int, Edge * > &platfromShapes, NBPTLineCont *nbptLineCont, const OptionsCont &oc)
Constructor.
Definition: NIImporter_OpenStreetMap.cpp:1062
SVCPermissions
int SVCPermissions
bitset where each bit declares whether a certain SVC may use this edge/lane
Definition: SUMOVehicleClass.h:219
SVC_RAIL_CLASSES
classes which drive on tracks
Definition: SUMOVehicleClass.h:205
NIImporter_OpenStreetMap::WAY_BOTH
Definition: NIImporter_OpenStreetMap.h:136
NIImporter_OpenStreetMap::WayType
WayType
Definition: NIImporter_OpenStreetMap.h:132
NIImporter_OpenStreetMap::RelationHandler::NIIPTPlatform::isWay
bool isWay
Definition: NIImporter_OpenStreetMap.h:589
NBNetBuilder::getParkingCont
NBParkingCont & getParkingCont()
Definition: NBNetBuilder.h:187
NBTypeCont::getSpeed
double getSpeed(const std::string &type) const
Returns the maximal velocity for the given type [m/s].
Definition: NBTypeCont.cpp:178
SUMO_TAG_RELATION
Definition: SUMOXMLDefinitions.h:236
StringBijection::get
T get(const std::string &str) const
Definition: StringBijection.h:98
NIImporter_OpenStreetMap::Edge::myCyclewayType
WayType myCyclewayType
Information about the kind of cycleway along this road.
Definition: NIImporter_OpenStreetMap.h:188
StringTokenizer
Definition: StringTokenizer.h:62
StringUtils::escapeXML
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
Definition: StringUtils.cpp:158
NIImporter_OpenStreetMap::NIOSMNode::permissions
SVCPermissions permissions
type of pt stop
Definition: NIImporter_OpenStreetMap.h:114
NIImporter_OpenStreetMap::RelationHandler::checkEdgeRef
bool checkEdgeRef(long long int ref) const
check whether a referenced way has a corresponding edge
Definition: NIImporter_OpenStreetMap.cpp:1228
SVC_RAIL_ELECTRIC
rail vehicle that requires electrified tracks
Definition: SUMOVehicleClass.h:191
NIImporter_OpenStreetMap::insertEdge
int insertEdge(Edge *e, int index, NBNode *from, NBNode *to, const std::vector< long long int > &passed, NBNetBuilder &nb)
Builds an NBEdge.
Definition: NIImporter_OpenStreetMap.cpp:308
NBNetBuilder.h
ProcessError
Definition: UtilExceptions.h:40
NIImporter_OpenStreetMap::myOSMNodes
std::map< long long int, NIOSMNode * > myOSMNodes
the map from OSM node ids to actual nodes
Definition: NIImporter_OpenStreetMap.h:237
NBPTLine::addPTStop
void addPTStop(NBPTStop *pStop)
Definition: NBPTLine.cpp:36
isRailway
bool isRailway(SVCPermissions permissions)
Returns whether an edge with the given permission is a railway edge.
Definition: SUMOVehicleClass.cpp:364
NIImporter_OpenStreetMap::INVALID_ID
static const long long int INVALID_ID
Definition: NIImporter_OpenStreetMap.h:311
NIImporter_OpenStreetMap::myUnusableTypes
std::set< std::string > myUnusableTypes
The compounds types that do not contain known types.
Definition: NIImporter_OpenStreetMap.h:255
NIImporter_OpenStreetMap::interpretDistance
static double interpretDistance(NIOSMNode *node)
read distance value from node and return value in m
Definition: NIImporter_OpenStreetMap.cpp:1834
Position
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:39
NIImporter_OpenStreetMap::WAY_BACKWARD
Definition: NIImporter_OpenStreetMap.h:135
NIImporter_OpenStreetMap::Edge::myParkingType
int myParkingType
Information about road-side parking.
Definition: NIImporter_OpenStreetMap.h:196
NIImporter_OpenStreetMap::NIOSMNode::position
std::string position
kilometrage/mileage
Definition: NIImporter_OpenStreetMap.h:116
UtilExceptions.h
NIImporter_OpenStreetMap::EdgesHandler::~EdgesHandler
~EdgesHandler() override
Destructor.
NIImporter_OpenStreetMap::EdgesHandler::myEndElement
void myEndElement(int element) override
Called when a closing tag occurs.
Definition: NIImporter_OpenStreetMap.cpp:1045
OptionsCont
A storage for options typed value containers)
Definition: OptionsCont.h:90
NBTypeCont::getShallBeDiscarded
bool getShallBeDiscarded(const std::string &type) const
Returns the information whether edges of this type shall be discarded.
Definition: NBTypeCont.cpp:196
NBNode::getEdges
const EdgeVector & getEdges() const
Returns all edges which participate in this node (Edges that start or end at this node)
Definition: NBNode.h:269
NBTypeCont::getPriority
int getPriority(const std::string &type) const
Returns the priority for the given type.
Definition: NBTypeCont.cpp:184
StringUtils::startsWith
static bool startsWith(const std::string &str, const std::string prefix)
Checks whether a given string starts with the prefix.
Definition: StringUtils.cpp:142
NIImporter_OpenStreetMap::WAY_FORWARD
Definition: NIImporter_OpenStreetMap.h:134
NIImporter_OpenStreetMap::NIImporter_OpenStreetMap
NIImporter_OpenStreetMap()
NBEdge::addSidewalk
void addSidewalk(double width)
add a pedestrian sidewalk of the given width and shift existing connctions
Definition: NBEdge.cpp:3577
NBEdge::addBikeLane
void addBikeLane(double width)
add a bicycle lane of the given width and shift existing connctions
Definition: NBEdge.cpp:3589
PositionVector::length2D
double length2D() const
Returns the length.
Definition: PositionVector.cpp:489
NIImporter_OpenStreetMap::NIOSMNode::positionMeters
double positionMeters
position converted to m (using highest precision available)
Definition: NIImporter_OpenStreetMap.h:118
NIImporter_OpenStreetMap::Edge::myMaxSpeed
double myMaxSpeed
maximum speed in km/h, or MAXSPEED_UNGIVEN
Definition: NIImporter_OpenStreetMap.h:182
NIImporter_OpenStreetMap::myUniqueNodes
std::set< NIOSMNode *, CompareNodes > myUniqueNodes
the set of unique nodes used in NodesHandler, used when freeing memory
Definition: NIImporter_OpenStreetMap.h:245
NIImporter_OpenStreetMap::PARKING_LEFT
Definition: NIImporter_OpenStreetMap.h:142
NBEdge::removeFromConnections
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:1293
StringTokenizer::size
int size() const
returns the number of existing substrings
Definition: StringTokenizer.cpp:138
NBPTPlatform
Definition: NBPTPlatform.h:23
NIImporter_OpenStreetMap::Edge::ref
std::string ref
The edge's track name.
Definition: NIImporter_OpenStreetMap.h:176
NODETYPE_RAIL_CROSSING
Definition: SUMOXMLDefinitions.h:1055
NIImporter_OpenStreetMap::CompareEdges
Functor which compares two Edges.
Definition: NIImporter_OpenStreetMap.cpp:71
NIImporter_OpenStreetMap::RelationHandler
A class which extracts relevant relation information from a parsed OSM-file.
Definition: NIImporter_OpenStreetMap.h:471
NBNodeCont::retrieve
NBNode * retrieve(const std::string &id) const
Returns the node with the given name.
Definition: NBNodeCont.cpp:108
NIImporter_OpenStreetMap::compoundTypeSeparator
static const std::string compoundTypeSeparator
The separator within newly created compound type names.
Definition: NIImporter_OpenStreetMap.h:235
NIImporter_OpenStreetMap::Edge::mySidewalkType
WayType mySidewalkType
Information about the kind of sidwalk along this road.
Definition: NIImporter_OpenStreetMap.h:192
NIImporter_OpenStreetMap::EdgesHandler::myAllAttributes
bool myAllAttributes
whether additional way attributes shall be added to the edge
Definition: NIImporter_OpenStreetMap.h:455
NIImporter_OpenStreetMap::myPlatformShapes
std::map< long long int, Edge * > myPlatformShapes
the map from OSM way ids to platform shapes
Definition: NIImporter_OpenStreetMap.h:252
OptionsCont::getFloat
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
Definition: OptionsCont.cpp:209
NIImporter_OpenStreetMap::NIOSMNode::ptStopPosition
bool ptStopPosition
Whether this is a public transport stop position.
Definition: NIImporter_OpenStreetMap.h:108
NBNodeCont.h
toString
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:48
StringUtils.h
NIImporter_OpenStreetMap::RelationHandler::applyRestriction
bool applyRestriction() const
try to apply the parsed restriction and return whether successful
Definition: NIImporter_OpenStreetMap.cpp:1398
StringUtils::toInt
static int toInt(const std::string &sData)
converts a string into the integer value described by it by calling the char-type converter,...
Definition: StringUtils.cpp:246
NBPTStop::registerAdditionalEdge
void registerAdditionalEdge(std::string wayId, std::string edgeId)
Definition: NBPTStop.cpp:174
NILoader.h
NIImporter_OpenStreetMap::PARKING_BOTH
Definition: NIImporter_OpenStreetMap.h:144
NIImporter_OpenStreetMap::Edge::myLayer
int myLayer
Information about the relative z-ordering of ways.
Definition: NIImporter_OpenStreetMap.h:198
PROGRESS_BEGIN_MESSAGE
#define PROGRESS_BEGIN_MESSAGE(msg)
Definition: MsgHandler.h:241
NBTypeCont::getPermissions
SVCPermissions getPermissions(const std::string &type) const
Returns allowed vehicle classes for the given type.
Definition: NBTypeCont.cpp:222
NIImporter_OpenStreetMap::usableType
std::string usableType(const std::string &type, const std::string &id, NBTypeCont &tc)
check whether the type is known or consists of known type compounds. return empty string otherwise
Definition: NIImporter_OpenStreetMap.cpp:1674
NIImporter_OpenStreetMap::Edge::myNoLanes
int myNoLanes
number of lanes, or -1 if unknown
Definition: NIImporter_OpenStreetMap.h:178
NIImporter_OpenStreetMap::RelationHandler::NIIPTPlatform::ref
long long int ref
Definition: NIImporter_OpenStreetMap.h:588
NBTypeCont
A storage for available types of edges.
Definition: NBTypeCont.h:55
NBParking
The representation of a single pt stop.
Definition: NBParking.h:44
PositionVector::reverse
PositionVector reverse() const
reverse position vector
Definition: PositionVector.cpp:1069
NBNetBuilder::getTLLogicCont
NBTrafficLightLogicCont & getTLLogicCont()
Returns a reference to the traffic light logics container.
Definition: NBNetBuilder.h:166
NBPTStopCont::get
NBPTStop * get(std::string id)
Retrieve a previously inserted pt stop.
Definition: NBPTStopCont.cpp:51
NIImporter_OpenStreetMap::NIOSMNode::node
NBNode * node
the NBNode that was instantiated
Definition: NIImporter_OpenStreetMap.h:120
SUMO_ATTR_LAT
Definition: SUMOXMLDefinitions.h:812
SUMO_ATTR_K
Definition: SUMOXMLDefinitions.h:816
NBNode::getIncomingEdges
const EdgeVector & getIncomingEdges() const
Returns this node's incoming edges (The edges which yield in this node)
Definition: NBNode.h:259
PROGRESS_DONE_MESSAGE
#define PROGRESS_DONE_MESSAGE()
Definition: MsgHandler.h:242
SUMO_TAG_TAG
Definition: SUMOXMLDefinitions.h:235
NBTypeCont::getWidth
double getWidth(const std::string &type) const
Returns the lane width for the given type [m].
Definition: NBTypeCont.cpp:228
NBTypeCont::getNumLanes
int getNumLanes(const std::string &type) const
Returns the number of lanes for the given type.
Definition: NBTypeCont.cpp:172
NIImporter_OpenStreetMap::Edge::myHighWayType
std::string myHighWayType
The type, stored in "highway" key.
Definition: NIImporter_OpenStreetMap.h:184
joinToString
std::string joinToString(const std::vector< T > &v, const T_BETWEEN &between, std::streamsize accuracy=gPrecision)
Definition: ToString.h:247
NBEdge::UNSPECIFIED_WIDTH
static const double UNSPECIFIED_WIDTH
unspecified lane width
Definition: NBEdge.h:303
Parameterised::setParameter
void setParameter(const std::string &key, const std::string &value)
Sets a parameter.
Definition: Parameterised.cpp:45
NIImporter_OpenStreetMap::Edge::myCurrentIsRoad
bool myCurrentIsRoad
Information whether this is a road.
Definition: NIImporter_OpenStreetMap.h:202
SUMOXMLDefinitions::TrafficLightTypes
static StringBijection< TrafficLightType > TrafficLightTypes
traffic light types
Definition: SUMOXMLDefinitions.h:1387
LaneSpreadFunction
LaneSpreadFunction
Numbers representing special SUMO-XML-attribute values Information how the edge's lateral offset shal...
Definition: SUMOXMLDefinitions.h:1092
SUMO_TAG_WAY
Definition: SUMOXMLDefinitions.h:233
NBPTLine.h
FileHelpers::isReadable
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:49
NIImporter_OpenStreetMap::EdgesHandler
A class which extracts OSM-edges from a parsed OSM-file.
Definition: NIImporter_OpenStreetMap.h:396
NIImporter_OpenStreetMap::NIOSMNode::railwaySignal
bool railwaySignal
Whether this is a railway (main) signal.
Definition: NIImporter_OpenStreetMap.h:104
NBNode::hasIncoming
bool hasIncoming(const NBEdge *const e) const
Returns whether the given edge ends at this node.
Definition: NBNode.cpp:1534
StringTokenizer::getVector
std::vector< std::string > getVector()
return vector of strings
Definition: StringTokenizer.cpp:192
config.h
NIImporter_OpenStreetMap
Importer for networks stored in OpenStreetMap format.
Definition: NIImporter_OpenStreetMap.h:59
NIImporter_OpenStreetMap::EdgesHandler::EdgesHandler
EdgesHandler(const std::map< long long int, NIOSMNode * > &osmNodes, std::map< long long int, Edge * > &toFill, std::map< long long int, Edge * > &platformShapes)
Constructor.
Definition: NIImporter_OpenStreetMap.cpp:743
SVC_BUS
vehicle is a bus
Definition: SUMOVehicleClass.h:166
NIImporter_OpenStreetMap::NodesHandler::myEndElement
void myEndElement(int element) override
Called when a closing tag occurs.
Definition: NIImporter_OpenStreetMap.cpp:732
StringTokenizer.h
NBPTLine::addWayNode
void addWayNode(long long int way, long long int node)
Definition: NBPTLine.cpp:90
SUMO_ATTR_REF
Definition: SUMOXMLDefinitions.h:818
NIImporter_OpenStreetMap::~NIImporter_OpenStreetMap
~NIImporter_OpenStreetMap()
Definition: NIImporter_OpenStreetMap.cpp:110
NIImporter_OpenStreetMap::NIOSMNode::lat
const double lat
The latitude the node is located at.
Definition: NIImporter_OpenStreetMap.h:96
NBTypeCont::getSidewalkWidth
double getSidewalkWidth(const std::string &type) const
Returns the lane width for a sidewalk to be added [m].
Definition: NBTypeCont.cpp:234
NBNode
Represents a single node (junction) during network building.
Definition: NBNode.h:68
NIImporter_OpenStreetMap::NodesHandler::~NodesHandler
~NodesHandler() override
Destructor.
SUMOSAXAttributes::getStringSecure
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
NBOwnTLDef.h
NBPTStopCont::insert
bool insert(NBPTStop *ptStop)
Inserts a node into the map.
Definition: NBPTStopCont.cpp:39
SUMO_ATTR_LON
Definition: SUMOXMLDefinitions.h:811
NIImporter_OpenStreetMap::RelationHandler::NIIPTPlatform
Definition: NIImporter_OpenStreetMap.h:587
NBNetBuilder::getNodeCont
NBNodeCont & getNodeCont()
Returns a reference to the node container.
Definition: NBNetBuilder.h:156
NBPTStop
The representation of a single pt stop.
Definition: NBPTStop.h:45
NBTrafficLightLogicCont::insert
bool insert(NBTrafficLightDefinition *logic, bool forceInsert=false)
Adds a logic definition to the dictionary.
Definition: NBTrafficLightLogicCont.cpp:74
NBNetBuilder::getTypeCont
NBTypeCont & getTypeCont()
Returns a reference to the type container.
Definition: NBNetBuilder.h:161
NBNode.h
SUMOSAXAttributes
Encapsulated SAX-Attributes.
Definition: SUMOSAXAttributes.h:57
Named::getID
const std::string & getID() const
Returns the id.
Definition: Named.h:77
POSITION_EPS
#define POSITION_EPS
Definition: config.h:169
WRITE_ERROR
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:245
NIImporter_OpenStreetMap::NIOSMNode::lon
const double lon
The longitude the node is located at.
Definition: NIImporter_OpenStreetMap.h:94
NBTypeCont::getBikeLaneWidth
double getBikeLaneWidth(const std::string &type) const
Returns the lane width for a bike lane to be added [m].
Definition: NBTypeCont.cpp:240
NBEdge::getFromNode
NBNode * getFromNode() const
Returns the origin node of the edge.
Definition: NBEdge.h:479
NIImporter_OpenStreetMap::Edge::myRailDirection
WayType myRailDirection
Information about the direction(s) of railway usage.
Definition: NIImporter_OpenStreetMap.h:194
WRITE_MESSAGE
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:240
OptionsCont::getStringVector
std::vector< std::string > getStringVector(const std::string &name) const
Returns the list of string-vector-value of the named option (only for Option_String)
Definition: OptionsCont.cpp:921
NBPTStop::addPlatformCand
void addPlatformCand(NBPTPlatform platform)
Definition: NBPTStop.cpp:137
SUMOXMLDefinitions.h
NIImporter_OpenStreetMap::getNeighboringNodes
std::map< NBNode *, std::pair< double, double > > getNeighboringNodes(NBNode *node, double maxDist, const std::set< NBNode * > &knownElevation)
collect neighboring nodes with their road distance and maximum between-speed. Search does not continu...
Definition: NIImporter_OpenStreetMap.cpp:1635
NBEdge::setGeometry
void setGeometry(const PositionVector &g, bool inner=false)
(Re)sets the edge's geometry
Definition: NBEdge.cpp:574
NBNode::reinit
void reinit(const Position &position, SumoXMLNodeType type, bool updateEdgeGeometries=false)
Resets initial values.
Definition: NBNode.cpp:304
NBEdge.h
GenericSAXHandler::setFileName
void setFileName(const std::string &name)
Sets the current file name.
Definition: GenericSAXHandler.cpp:69
XMLSubSys.h
NIImporter_OpenStreetMap::myEdges
std::map< long long int, Edge * > myEdges
the map from OSM way ids to edge objects
Definition: NIImporter_OpenStreetMap.h:249
NIImporter_OpenStreetMap::Edge::streetName
std::string streetName
The edge's street name.
Definition: NIImporter_OpenStreetMap.h:174
SUMO_TAG_NODE
alternative definition for junction
Definition: SUMOXMLDefinitions.h:209