Eclipse SUMO - Simulation of Urban MObility
PCLoaderOSM.cpp
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2008-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
22 // A reader of pois and polygons stored in OSM-format
23 /****************************************************************************/
24 #include <config.h>
25 
26 #include <string>
27 #include <map>
28 #include <fstream>
31 #include <utils/common/ToString.h>
33 #include <utils/common/StdDefs.h>
34 #include <utils/common/SysUtils.h>
35 #include <utils/common/RGBColor.h>
36 #include <utils/geom/GeomHelper.h>
37 #include <utils/geom/Position.h>
39 #include <utils/xml/XMLSubSys.h>
43 #include <utils/options/Option.h>
45 #include "PCLoaderOSM.h"
46 
47 // static members
48 // ---------------------------------------------------------------------------
50 
51 // ===========================================================================
52 // method definitions
53 // ===========================================================================
54 // ---------------------------------------------------------------------------
55 // static interface
56 // ---------------------------------------------------------------------------
57 std::set<std::string> PCLoaderOSM::initMyKeysToInclude() {
58  std::set<std::string> result;
59  result.insert("highway");
60  result.insert("railway");
61  result.insert("railway:position");
62  result.insert("railway:position:exact");
63  result.insert("waterway");
64  result.insert("aeroway");
65  result.insert("aerialway");
66  result.insert("power");
67  result.insert("man_made");
68  result.insert("building");
69  result.insert("leisure");
70  result.insert("amenity");
71  result.insert("shop");
72  result.insert("tourism");
73  result.insert("historic");
74  result.insert("landuse");
75  result.insert("natural");
76  result.insert("military");
77  result.insert("boundary");
78  result.insert("admin_level");
79  result.insert("sport");
80  result.insert("polygon");
81  result.insert("place");
82  result.insert("population");
83  result.insert("barrier");
84  result.insert("openGeoDB:population");
85  result.insert("openGeoDB:name");
86  return result;
87 }
88 
89 void
91  PCTypeMap& tm) {
92  if (!oc.isSet("osm-files")) {
93  return;
94  }
95  // parse file(s)
96  std::vector<std::string> files = oc.getStringVector("osm-files");
97  // load nodes, first
98  std::map<long long int, PCOSMNode*> nodes;
99  bool withAttributes = oc.getBool("all-attributes");
101  NodesHandler nodesHandler(nodes, withAttributes, *m);
102  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
103  // nodes
104  if (!FileHelpers::isReadable(*file)) {
105  WRITE_ERROR("Could not open osm-file '" + *file + "'.");
106  return;
107  }
108  const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
109  if (!XMLSubSys::runParser(nodesHandler, *file)) {
110  for (std::map<long long int, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
111  delete (*i).second;
112  }
113  throw ProcessError();
114  }
115  PROGRESS_TIME_MESSAGE(before);
116  }
117  // load relations to see which additional ways may be relevant
118  Relations relations;
119  RelationsMap additionalWays;
120  RelationsHandler relationsHandler(additionalWays, relations, withAttributes, *m);
121  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
122  // edges
123  const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing relations from osm-file '" + *file + "'");
124  XMLSubSys::runParser(relationsHandler, *file);
125  PROGRESS_TIME_MESSAGE(before);
126  }
127 
128  // load ways
129  EdgeMap edges;
130  EdgesHandler edgesHandler(nodes, edges, additionalWays, withAttributes, *m);
131  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
132  // edges
133  const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing edges from osm-file '" + *file + "'");
134  XMLSubSys::runParser(edgesHandler, *file);
135  PROGRESS_TIME_MESSAGE(before);
136  }
137 
138  // build all
139  const bool useName = oc.getBool("osm.use-name");
140  const double mergeRelationsThreshold = OptionsCont::getOptions().getFloat("osm.merge-relations");
141  // create polygons from relations
142  if (mergeRelationsThreshold >= 0) {
143  for (PCOSMRelation* rel : relations) {
144  if (!rel->keep || rel->myWays.empty()) {
145  continue;
146  }
147  // filter unknown and empty ways
148  int numNodes = 0;
149  for (auto it = rel->myWays.begin(); it != rel->myWays.end();) {
150  if (edges.count(*it) == 0 || edges[*it]->myCurrentNodes.empty()) {
151  it = rel->myWays.erase(it);
152  } else {
153  numNodes += (int)edges[*it]->myCurrentNodes.size();
154  it++;
155  }
156  }
157  if (numNodes == 0) {
158  WRITE_WARNING("Could not import polygon from relation '" + toString(rel->id) + "' (missing ways)");
159  continue;
160  }
161  PCOSMEdge* e = new PCOSMEdge();
162  e->id = rel->id;
163  e->name = rel->name;
164  e->myAttributes = rel->myAttributes;
165  e->myIsClosed = false;
166  e->standalone = true;
167 
168  std::set<long long int> remaining(rel->myWays.begin(), rel->myWays.end());
169  PCOSMEdge* minEdge = edges[rel->myWays.front()];
170  e->myCurrentNodes.insert(e->myCurrentNodes.end(), minEdge->myCurrentNodes.begin(), minEdge->myCurrentNodes.end());
171  Position prev(convertNodePosition(nodes[minEdge->myCurrentNodes.back()]));
172  minEdge->standalone = false;
173  remaining.erase(minEdge->id);
174  bool ok = true;
175  while (!remaining.empty()) {
176  // assemble in an order that greedily reduces jump size
177  double minDist = std::numeric_limits<double>::max();
178  bool minFront = false;
179  for (long long int wayID : remaining) {
180  PCOSMEdge* part = edges[wayID];
181  Position frontPos(convertNodePosition(nodes.find(part->myCurrentNodes.front())->second));
182  const double frontDist = prev.distanceTo2D(frontPos);
183  Position backPos(convertNodePosition(nodes.find(part->myCurrentNodes.back())->second));
184  const double backDist = prev.distanceTo2D(backPos);
185  if (frontDist < minDist) {
186  minDist = frontDist;
187  minEdge = part;
188  minFront = true;
189  }
190  if (backDist < minDist) {
191  minDist = backDist;
192  minEdge = part;
193  minFront = false;
194  }
195  }
196  if (minDist > mergeRelationsThreshold) {
197  double length = 0.;
198  for (long long int wayID : remaining) {
199  PCOSMEdge* part = edges[wayID];
201  for (long long int nodeID : part->myCurrentNodes) {
202  Position nodePos(convertNodePosition(nodes[nodeID]));
203  if (last != Position::INVALID) {
204  length += last.distanceTo2D(nodePos);
205  }
206  last = nodePos;
207  }
208  if (part->myIsClosed) {
209  length += last.distanceTo2D(convertNodePosition(nodes[part->myCurrentNodes.front()]));
210  }
211  }
212  if (length > mergeRelationsThreshold) {
213  WRITE_WARNING("Could not import polygon from relation '" + toString(rel->id) +
214  "' (name:" + e->name + " reason: found gap of " + toString(minDist) +
215  "m to way '" + toString(minEdge->id) +
216  "')\n Total length of remaining ways: " + toString(length) + "m.");
217  ok = false;
218  }
219  break;
220  }
221  if (minFront) {
222  e->myCurrentNodes.insert(e->myCurrentNodes.end(), minEdge->myCurrentNodes.begin(), minEdge->myCurrentNodes.end());
223  prev = convertNodePosition(nodes[minEdge->myCurrentNodes.back()]);
224  } else {
225  e->myCurrentNodes.insert(e->myCurrentNodes.end(), minEdge->myCurrentNodes.rbegin(), minEdge->myCurrentNodes.rend());
226  prev = convertNodePosition(nodes[minEdge->myCurrentNodes.front()]);
227  }
228  minEdge->standalone = false;
229  remaining.erase(minEdge->id);
230  }
231  if (ok) {
232  edges[e->id] = e;
233  WRITE_MESSAGE("Assembled polygon from relation '" + toString(rel->id) + "' (name:" + e->name + ")");
234  } else {
235  delete e;
236  // export ways by themselves
237  for (long long int wayID : rel->myWays) {
238  PCOSMEdge* part = edges[wayID];
239  part->standalone = true;
240  }
241  }
242  }
243  }
244 
245  // instatiate polygons
246  for (EdgeMap::iterator i = edges.begin(); i != edges.end(); ++i) {
247  PCOSMEdge* e = (*i).second;
248  if (e->myAttributes.size() == 0) {
249  // cannot be relevant as a polygon
250  continue;
251  }
252  if (!e->standalone && mergeRelationsThreshold >= 0) {
253  // part of a relation
254  continue;
255  }
256  if (e->myCurrentNodes.size() == 0) {
257  WRITE_ERROR("Polygon '" + toString(e->id) + "' has no shape.");
258  continue;
259  }
260  // compute shape
261  PositionVector vec;
262  for (std::vector<long long int>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
263  PCOSMNode* n = nodes.find(*j)->second;
264  Position pos(n->lon, n->lat);
265  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
266  WRITE_WARNING("Unable to project coordinates for polygon '" + toString(e->id) + "'.");
267  }
268  vec.push_back_noDoublePos(pos);
269  }
270  const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(e->id));
271  // add as many polygons as keys match defined types
272  int index = 0;
273  std::string unknownPolyType = "";
274  for (std::map<std::string, std::string>::iterator it = e->myAttributes.begin(); it != e->myAttributes.end(); ++it) {
275  const std::string& key = it->first;
276  const std::string& value = it->second;
277  const std::string fullType = key + "." + value;
278  if (tm.has(key + "." + value)) {
279  index = addPolygon(e, vec, tm.get(fullType), fullType, index, useName, toFill, ignorePruning, withAttributes);
280  } else if (tm.has(key)) {
281  index = addPolygon(e, vec, tm.get(key), fullType, index, useName, toFill, ignorePruning, withAttributes);
282  } else if (MyKeysToInclude.count(key) > 0) {
283  unknownPolyType = fullType;
284  }
285  }
286  const PCTypeMap::TypeDef& def = tm.getDefault();
287  if (index == 0 && !def.discard && unknownPolyType != "") {
288  addPolygon(e, vec, def, unknownPolyType, index, useName, toFill, ignorePruning, withAttributes);
289  }
290  }
291 
292 
293  // instantiate pois
294  for (std::map<long long int, PCOSMNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i) {
295  PCOSMNode* n = (*i).second;
296  if (n->myAttributes.size() == 0) {
297  // cannot be relevant as a poi
298  continue;
299  }
300  Position pos(n->lon, n->lat);
301  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
302  WRITE_WARNING("Unable to project coordinates for POI '" + toString(n->id) + "'.");
303  }
304  const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(n->id));
305  // add as many POIs as keys match defined types
306  int index = 0;
307  std::string unKnownPOIType = "";
308  for (std::map<std::string, std::string>::iterator it = n->myAttributes.begin(); it != n->myAttributes.end(); ++it) {
309  const std::string& key = it->first;
310  const std::string& value = it->second;
311  const std::string fullType = key + "." + value;
312  if (tm.has(key + "." + value)) {
313  index = addPOI(n, pos, tm.get(fullType), fullType, index, useName, toFill, ignorePruning, withAttributes);
314  } else if (tm.has(key)) {
315  index = addPOI(n, pos, tm.get(key), fullType, index, useName, toFill, ignorePruning, withAttributes);
316  } else if (MyKeysToInclude.count(key) > 0) {
317  unKnownPOIType = fullType;
318  }
319  }
320  const PCTypeMap::TypeDef& def = tm.getDefault();
321  if (index == 0 && !def.discard && unKnownPOIType != "") {
322  addPOI(n, pos, def, unKnownPOIType, index, useName, toFill, ignorePruning, withAttributes);
323  }
324  }
325  // delete nodes
326  for (std::map<long long int, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
327  delete (*i).second;
328  }
329  // delete edges
330  for (EdgeMap::iterator i = edges.begin(); i != edges.end(); ++i) {
331  delete (*i).second;
332  }
333  // delete relations
334  for (Relations::iterator i = relations.begin(); i != relations.end(); ++i) {
335  delete (*i);
336  }
337 }
338 
339 
340 Position
342  Position pos(n->lon, n->lat);
344  return pos;
345 }
346 
347 
348 int
349 PCLoaderOSM::addPolygon(const PCOSMEdge* edge, const PositionVector& vec, const PCTypeMap::TypeDef& def, const std::string& fullType, int index, bool useName, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
350  if (def.discard) {
351  return index;
352  } else {
353  const bool closedShape = vec.front() == vec.back();
354  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
355  const std::string id = def.prefix + (useName && edge->name != "" ? edge->name : toString(edge->id)) + idSuffix;
356  SUMOPolygon* poly = new SUMOPolygon(
358  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
359  def.color, vec, false, def.allowFill && closedShape, 1, def.layer);
360  if (withAttributes) {
361  poly->updateParameters(edge->myAttributes);
362  }
363  if (!toFill.add(poly, ignorePruning)) {
364  return index;
365  } else {
366  return index + 1;
367  }
368  }
369 }
370 
371 
372 int
373 PCLoaderOSM::addPOI(const PCOSMNode* node, const Position& pos, const PCTypeMap::TypeDef& def, const std::string& fullType,
374  int index, bool useName, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
375  if (def.discard) {
376  return index;
377  } else {
378  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
379  const std::string id = def.prefix + (useName && node->name != "" ? node->name : toString(node->id)) + idSuffix;
380  PointOfInterest* poi = new PointOfInterest(
382  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
383  def.color, pos, false, "", 0, 0, (double)def.layer);
384  if (withAttributes) {
385  poi->updateParameters(node->myAttributes);
386  }
387  if (!toFill.add(poi, ignorePruning)) {
388  return index;
389  } else {
390  return index + 1;
391  }
392  }
393 }
394 
395 
396 // ---------------------------------------------------------------------------
397 // definitions of PCLoaderOSM::NodesHandler-methods
398 // ---------------------------------------------------------------------------
399 PCLoaderOSM::NodesHandler::NodesHandler(std::map<long long int, PCOSMNode*>& toFill,
400  bool withAttributes, MsgHandler& errorHandler) :
401  SUMOSAXHandler("osm - file"), myWithAttributes(withAttributes), myErrorHandler(errorHandler),
402  myToFill(toFill), myLastNodeID(-1) {}
403 
404 
406 
407 
408 void
410  myParentElements.push_back(element);
411  if (element == SUMO_TAG_NODE) {
412  bool ok = true;
413  long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
414  if (!ok) {
415  return;
416  }
417  myLastNodeID = -1;
418  if (myToFill.find(id) == myToFill.end()) {
419  myLastNodeID = id;
420  // assume we are loading multiple files...
421  // ... so we won't report duplicate nodes
422  PCOSMNode* toAdd = new PCOSMNode();
423  toAdd->id = id;
424  bool ok = true;
425  toAdd->lon = attrs.get<double>(SUMO_ATTR_LON, toString(id).c_str(), ok);
426  toAdd->lat = attrs.get<double>(SUMO_ATTR_LAT, toString(id).c_str(), ok);
427  if (!ok) {
428  delete toAdd;
429  return;
430  }
431  myToFill[toAdd->id] = toAdd;
432  }
433  }
434  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_NODE
435  && myLastNodeID != -1) {
436  bool ok = true;
437  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok, "", false);
438  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, "", false);
439  if (key == "name") {
440  myToFill[myLastNodeID]->name = value;
441  } else if (key == "") {
442  myErrorHandler.inform("Empty key in a a tag while parsing node '" + toString(myLastNodeID) + "' occurred.");
443  ok = false;
444  }
445  if (!ok) {
446  return;
447  }
448  myToFill[myLastNodeID]->myAttributes[key] = value;
449  }
450 }
451 
452 
453 void
455  if (element == SUMO_TAG_NODE) {
456  myLastNodeID = -1;
457  }
458  myParentElements.pop_back();
459 }
460 
461 
462 // ---------------------------------------------------------------------------
463 // definitions of PCLoaderOSM::RelationsHandler-methods
464 // ---------------------------------------------------------------------------
466  Relations& relations,
467  bool withAttributes,
468  MsgHandler& errorHandler) :
469  SUMOSAXHandler("osm - file"),
470  myAdditionalWays(additionalWays),
471  myRelations(relations),
472  myWithAttributes(withAttributes),
473  myErrorHandler(errorHandler),
474  myCurrentRelation(nullptr) {
475 }
476 
477 
479 }
480 
481 
482 void
484  myParentElements.push_back(element);
485  // parse "relation" elements
486  if (element == SUMO_TAG_RELATION) {
487  myCurrentWays.clear();
488  const std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
489  if (action == "delete") {
490  myCurrentRelation = nullptr;
491  } else {
492  myCurrentRelation = new PCOSMRelation();
493  myCurrentRelation->keep = false;
494  bool ok = true;
495  myCurrentRelation->id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
496  myRelations.push_back(myCurrentRelation);
497  }
498  return;
499  } else if (myCurrentRelation == nullptr) {
500  return;
501  }
502  // parse member elements
503  if (element == SUMO_TAG_MEMBER) {
504  bool ok = true;
505  std::string role = attrs.hasAttribute("role") ? attrs.getStringSecure("role", "") : "";
506  long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
507  if (role == "outer" || role == "inner") {
508  std::string memberType = attrs.get<std::string>(SUMO_ATTR_TYPE, nullptr, ok);
509  if (memberType == "way") {
510  myCurrentWays.push_back(ref);
511  }
512  }
513  return;
514  }
515  // parse values
516  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_RELATION
517  && myCurrentRelation != nullptr) {
518  bool ok = true;
519  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentRelation).c_str(), ok, "", false);
520  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, "", false);
521  if (key == "") {
522  myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentRelation) + "' occurred.");
523  ok = false;
524  }
525  if (!ok) {
526  return;
527  }
528  if (key == "name") {
529  myCurrentRelation->name = value;
530  } else if (MyKeysToInclude.count(key) > 0) {
531  myCurrentRelation->keep = true;
532  for (std::vector<long long int>::iterator it = myCurrentWays.begin(); it != myCurrentWays.end(); ++it) {
533  myAdditionalWays[*it] = myCurrentRelation;
534  }
535  }
536  myCurrentRelation->myAttributes[key] = value;
537  }
538 }
539 
540 
541 void
543  myParentElements.pop_back();
544  if (element == SUMO_TAG_RELATION) {
545  myCurrentRelation->myWays = myCurrentWays;
546  myCurrentRelation = nullptr;
547  myCurrentWays.clear();
548  }
549 }
550 
551 
552 // ---------------------------------------------------------------------------
553 // definitions of PCLoaderOSM::EdgesHandler-methods
554 // ---------------------------------------------------------------------------
555 PCLoaderOSM::EdgesHandler::EdgesHandler(const std::map<long long int, PCOSMNode*>& osmNodes,
556  EdgeMap& toFill,
557  const RelationsMap& additionalWays,
558  bool withAttributes, MsgHandler& errorHandler) :
559  SUMOSAXHandler("osm - file"),
560  myWithAttributes(withAttributes),
561  myErrorHandler(errorHandler),
562  myOSMNodes(osmNodes),
563  myEdgeMap(toFill),
564  myAdditionalWays(additionalWays) {
565 }
566 
567 
569 }
570 
571 
572 void
574  myParentElements.push_back(element);
575  // parse "way" elements
576  if (element == SUMO_TAG_WAY) {
577  bool ok = true;
578  const long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
579  const std::string action = attrs.hasAttribute("action") ? attrs.getStringSecure("action", "") : "";
580  if (action == "delete" || !ok) {
581  myCurrentEdge = nullptr;
582  return;
583  }
584  myCurrentEdge = new PCOSMEdge();
585  myCurrentEdge->id = id;
586  myCurrentEdge->myIsClosed = false;
587  myCurrentEdge->standalone = false;
588  myKeep = (myAdditionalWays.find(id) != myAdditionalWays.end());
589  }
590  // parse "nd" (node) elements
591  if (element == SUMO_TAG_ND && myCurrentEdge != nullptr) {
592  bool ok = true;
593  const long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
594  if (ok) {
595  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
596  WRITE_WARNING("The referenced geometry information (ref='" + toString(ref) + "') is not known");
597  return;
598  }
599  myCurrentEdge->myCurrentNodes.push_back(ref);
600  }
601  }
602  // parse values
603  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY
604  && myCurrentEdge != nullptr) {
605  bool ok = true;
606  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok, "", false);
607  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok, "", false);
608  if (key == "") {
609  myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentEdge->id) + "' occurred.");
610  ok = false;
611  }
612  if (!ok) {
613  return;
614  }
615  if (key == "name") {
616  myCurrentEdge->name = value;
617  } else if (MyKeysToInclude.count(key) > 0) {
618  myKeep = true;
619  myCurrentEdge->standalone = true;
620  }
621  myCurrentEdge->myAttributes[key] = value;
622  }
623 }
624 
625 
626 void
628  myParentElements.pop_back();
629  if (element == SUMO_TAG_WAY && myCurrentEdge != nullptr) {
630  if (myKeep) {
631  RelationsMap::const_iterator it = myAdditionalWays.find(myCurrentEdge->id);
632  if (it != myAdditionalWays.end()) {
633  myCurrentEdge->myAttributes.insert((*it).second->myAttributes.begin(), (*it).second->myAttributes.end());
634  }
635  myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
636  } else {
637  delete myCurrentEdge;
638  }
639  myCurrentEdge = nullptr;
640  }
641 }
642 
643 
644 /****************************************************************************/
#define WRITE_MESSAGE(msg)
Definition: MsgHandler.h:278
#define WRITE_ERROR(msg)
Definition: MsgHandler.h:284
#define WRITE_WARNING(msg)
Definition: MsgHandler.h:276
#define PROGRESS_BEGIN_TIME_MESSAGE(msg)
Definition: MsgHandler.h:281
#define PROGRESS_TIME_MESSAGE(before)
Definition: MsgHandler.h:282
@ SUMO_TAG_MEMBER
@ SUMO_TAG_ND
@ SUMO_TAG_WAY
@ SUMO_TAG_NODE
alternative definition for junction
@ SUMO_TAG_RELATION
@ SUMO_TAG_TAG
@ SUMO_ATTR_LON
@ SUMO_ATTR_V
@ SUMO_ATTR_REF
@ SUMO_ATTR_LAT
@ SUMO_ATTR_TYPE
@ SUMO_ATTR_ID
@ SUMO_ATTR_K
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:44
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:48
static GeoConvHelper & getProcessing()
the coordinate transformation to use for input conversion and processing
Definition: GeoConvHelper.h:84
bool x2cartesian(Position &from, bool includeInBoundary=true)
Converts the given coordinate into a cartesian and optionally update myConvBoundary.
static MsgHandler * getErrorInstance()
Returns the instance to add errors to.
Definition: MsgHandler.cpp:80
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:67
A storage for options typed value containers)
Definition: OptionsCont.h:89
bool isSet(const std::string &name, bool failOnNonExistant=true) const
Returns the information whether the named option is set.
double getFloat(const std::string &name) const
Returns the double-value of the named option (only for Option_Float)
bool getBool(const std::string &name) const
Returns the boolean-value of the named option (only for Option_Bool)
const StringVector & getStringVector(const std::string &name) const
Returns the list of string-value of the named option (only for Option_StringVector)
static OptionsCont & getOptions()
Retrieves the options.
Definition: OptionsCont.cpp:58
bool isInStringVector(const std::string &optionName, const std::string &itemName) const
Returns the named option is a list of string values containing the specified item.
A class which extracts OSM-edges from a parsed OSM-file.
Definition: PCLoaderOSM.h:293
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
void myEndElement(int element)
Called when a closing tag occurs.
EdgesHandler(const std::map< long long int, PCOSMNode * > &osmNodes, EdgeMap &toFill, const RelationsMap &additionalWays, bool withAttributes, MsgHandler &errorHandler)
Constructor.
A class which extracts OSM-nodes from a parsed OSM-file.
Definition: PCLoaderOSM.h:143
NodesHandler(std::map< long long int, PCOSMNode * > &toFill, bool withAttributes, MsgHandler &errorHandler)
Contructor.
void myEndElement(int element)
Called when a closing tag occurs.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
A class which extracts relevant way-ids from relations in a parsed OSM-file.
Definition: PCLoaderOSM.h:211
void myEndElement(int element)
Called when a closing tag occurs.
void myStartElement(int element, const SUMOSAXAttributes &attrs)
Called on the opening of a tag;.
RelationsHandler(RelationsMap &additionalWays, Relations &relations, bool withAttributes, MsgHandler &errorHandler)
Constructor.
static int addPolygon(const PCOSMEdge *edge, const PositionVector &vec, const PCTypeMap::TypeDef &def, const std::string &fullType, int index, bool useName, PCPolyContainer &toFill, bool ignorePruning, bool withAttributes)
try add the polygon and return the next index on success
std::map< long long int, PCOSMEdge * > EdgeMap
Definition: PCLoaderOSM.h:117
static Position convertNodePosition(PCOSMNode *n)
retrieve cartesian coordinate for given node
static int addPOI(const PCOSMNode *node, const Position &pos, const PCTypeMap::TypeDef &def, const std::string &fullType, int index, bool useName, PCPolyContainer &toFill, bool ignorePruning, bool withAttributes)
try add the POI and return the next index on success
static void loadIfSet(OptionsCont &oc, PCPolyContainer &toFill, PCTypeMap &tm)
Loads pois/polygons assumed to be stored as OSM-XML.
Definition: PCLoaderOSM.cpp:90
std::vector< PCOSMRelation * > Relations
Definition: PCLoaderOSM.h:115
static const std::set< std::string > MyKeysToInclude
Definition: PCLoaderOSM.h:130
std::map< long long int, PCOSMRelation * > RelationsMap
Definition: PCLoaderOSM.h:116
static std::set< std::string > initMyKeysToInclude()
Definition: PCLoaderOSM.cpp:57
A storage for loaded polygons and pois.
bool add(SUMOPolygon *poly, bool ignorePruning=false)
Adds a polygon to the storage.
A storage for type mappings.
Definition: PCTypeMap.h:42
const TypeDef & get(const std::string &id)
Returns a type definition.
Definition: PCTypeMap.cpp:69
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition: PCTypeMap.cpp:75
const TypeDef & getDefault()
get the default type according to the given options
Definition: PCTypeMap.h:112
void updateParameters(const std::map< std::string, std::string > &mapArg)
Adds or updates all given parameters from the map.
A point-of-interest.
A point in 2D or 3D with translation and scaling methods.
Definition: Position.h:36
static const Position INVALID
used to indicate that a position is valid
Definition: Position.h:282
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:241
A list of positions.
void push_back_noDoublePos(const Position &p)
insert in back a non double position
Encapsulated SAX-Attributes.
T getOpt(int attr, const char *objectid, bool &ok, T defaultValue, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual std::string getStringSecure(int id, const std::string &def) const =0
Returns the string-value of the named (by its enum-value) attribute.
T get(int attr, const char *objectid, bool &ok, bool report=true) const
Tries to read given attribute assuming it is an int.
virtual bool hasAttribute(int id) const =0
Returns the information whether the named (by its enum-value) attribute is within the current list.
SAX-handler base for SUMO-files.
static std::string escapeXML(const std::string &orig, const bool maskDoubleHyphen=false)
Replaces the standard escapes by their XML entities.
static bool runParser(GenericSAXHandler &handler, const std::string &file, const bool isNet=false, const bool isRoute=false)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:148
An internal definition of a loaded edge.
Definition: PCLoaderOSM.h:100
bool myIsClosed
Information whether this area is closed.
Definition: PCLoaderOSM.h:106
long long int id
The edge's id.
Definition: PCLoaderOSM.h:102
std::map< std::string, std::string > myAttributes
Additional attributes.
Definition: PCLoaderOSM.h:110
std::vector< long long int > myCurrentNodes
The list of nodes this edge is made of.
Definition: PCLoaderOSM.h:108
std::string name
The edge's name (if any)
Definition: PCLoaderOSM.h:104
An internal representation of an OSM-node.
Definition: PCLoaderOSM.h:68
double lat
The latitude the node is located at.
Definition: PCLoaderOSM.h:74
double lon
The longitude the node is located at.
Definition: PCLoaderOSM.h:72
std::string name
The nodes name (if any)
Definition: PCLoaderOSM.h:76
long long int id
The node's id.
Definition: PCLoaderOSM.h:70
std::map< std::string, std::string > myAttributes
Additional attributes.
Definition: PCLoaderOSM.h:78
An internal definition of a loaded relation.
Definition: PCLoaderOSM.h:84
A single definition of values that shall be used for a given type.
Definition: PCTypeMap.h:56
bool discard
Information whether polygons of this type shall be discarded.
Definition: PCTypeMap.h:70
std::string prefix
The prefix to use.
Definition: PCTypeMap.h:62
double layer
The layer to use.
Definition: PCTypeMap.h:64
bool allowFill
Information whether polygons of this type can be filled.
Definition: PCTypeMap.h:72
std::string id
The new type id to use.
Definition: PCTypeMap.h:58
RGBColor color
The color to use.
Definition: PCTypeMap.h:60