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.dev/sumo
3 // Copyright (C) 2008-2024 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
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  if (!oc.isSet("osm-files")) {
92  return;
93  }
94  // parse file(s)
95  std::vector<std::string> files = oc.getStringVector("osm-files");
96  // load nodes, first
97  std::map<long long int, PCOSMNode*> nodes;
98  bool withAttributes = oc.getBool("all-attributes");
100  NodesHandler nodesHandler(nodes, withAttributes, *m);
101  for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
102  // nodes
103  if (!FileHelpers::isReadable(*file)) {
104  WRITE_ERRORF(TL("Could not open osm-file '%'."), *file);
105  return;
106  }
107  const long before = PROGRESS_BEGIN_TIME_MESSAGE("Parsing nodes from osm-file '" + *file + "'");
108  if (!XMLSubSys::runParser(nodesHandler, *file)) {
109  for (std::map<long long int, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
110  delete (*i).second;
111  }
112  throw ProcessError();
113  }
114  PROGRESS_TIME_MESSAGE(before);
115  }
116  // load relations to see which additional ways may be relevant
117  Relations relations;
118  RelationsMap additionalWays;
119  std::set<long long int> innerEdges;
120  RelationsHandler relationsHandler(additionalWays, relations, innerEdges, 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 if (innerEdges.count(*it) > 0) {
153  // @note: it would be a good idea to merge inner shapes but
154  // it's difficult since there may be more than one
155  // independent inner shape
156  edges[*it]->standalone = true;
157  it = rel->myWays.erase(it);
158  } else {
159  numNodes += (int)edges[*it]->myCurrentNodes.size();
160  it++;
161  }
162  }
163  if (numNodes == 0) {
164  WRITE_WARNINGF(TL("Could not import polygon from relation '%' (missing ways)"), rel->id);
165  continue;
166  }
167  PCOSMEdge* e = new PCOSMEdge();
168  e->id = rel->id;
169  e->name = rel->name;
170  e->myAttributes = rel->myAttributes;
171  e->myIsClosed = false;
172  e->standalone = true;
173 
174  std::vector<std::vector<long long int> > snippets;
175  for (const long long int wayID : rel->myWays) {
176  PCOSMEdge* edge = edges[wayID];
177  snippets.push_back(edge->myCurrentNodes);
178  }
179  double maxDist = 0.;
180  bool ok = true;
181  while (snippets.size() > 1) {
182  maxDist = MAX2(maxDist, mergeClosest(nodes, snippets));
183  if (maxDist > mergeRelationsThreshold) {
184  ok = false;
185  break;
186  }
187  }
188  if (ok) {
189  e->myCurrentNodes = snippets.front();
190  edges[e->id] = e;
191  double frontBackDist = 0;
192  if (e->myCurrentNodes.front() != e->myCurrentNodes.back()) {
193  // should be filled
194  const Position posFront = convertNodePosition(nodes[e->myCurrentNodes.front()]);
195  const Position posBack = convertNodePosition(nodes[e->myCurrentNodes.back()]);
196  frontBackDist = posFront.distanceTo2D(posBack);
197  if (frontBackDist < mergeRelationsThreshold) {
198  e->myCurrentNodes.push_back(e->myCurrentNodes.front());
199  frontBackDist = 0;
200  }
201  }
202  std::string frontBackMsg = "";
203  if (frontBackDist > 0) {
204  frontBackMsg = TLF(", (front-to-back dist: %)", frontBackDist);
205  }
206  WRITE_MESSAGEF(TL("Assembled polygon from relation '%' (name:%)%"), toString(rel->id), e->name, frontBackMsg);
207  } else {
208  WRITE_WARNINGF(TL("Could not import polygon from relation '%' (name:% reason: found gap of %m)\n."), rel->id, rel->name, maxDist)
209  delete e;
210  // export ways by themselves
211  for (long long int wayID : rel->myWays) {
212  PCOSMEdge* part = edges[wayID];
213  part->standalone = true;
214  }
215  }
216  }
217  }
218 
219  // instatiate polygons
220  for (EdgeMap::iterator i = edges.begin(); i != edges.end(); ++i) {
221  PCOSMEdge* e = (*i).second;
222  if (e->myAttributes.size() == 0) {
223  // cannot be relevant as a polygon
224  continue;
225  }
226  if (!e->standalone && mergeRelationsThreshold >= 0) {
227  // part of a relation
228  continue;
229  }
230  if (e->myCurrentNodes.size() == 0) {
231  WRITE_WARNINGF(TL("Polygon '%' has no shape."), toString(e->id));
232  continue;
233  }
234  // compute shape
235  PositionVector vec;
236  for (std::vector<long long int>::iterator j = e->myCurrentNodes.begin(); j != e->myCurrentNodes.end(); ++j) {
237  PCOSMNode* n = nodes.find(*j)->second;
238  Position pos(n->lon, n->lat);
239  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
240  WRITE_WARNINGF(TL("Unable to project coordinates for polygon '%'."), e->id);
241  }
242  vec.push_back_noDoublePos(pos);
243  }
244  const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(e->id));
245  // add as many polygons as keys match defined types
246  int index = 0;
247  std::string unknownPolyType = "";
248  bool isInner = mergeRelationsThreshold >= 0 && innerEdges.count(e->id) != 0 && tm.has("inner");
249  for (std::map<std::string, std::string>::iterator it = e->myAttributes.begin(); it != e->myAttributes.end(); ++it) {
250  const std::string& key = it->first;
251  const std::string& value = it->second;
252  const std::string fullType = key + "." + value;
253  if (tm.has(key + "." + value)) {
254  auto def = tm.get(isInner ? "inner" : fullType);
255  index = addPolygon(e, vec, def, fullType, index, useName, toFill, ignorePruning, withAttributes);
256  } else if (tm.has(key)) {
257  auto def = tm.get(isInner ? "inner" : key);
258  index = addPolygon(e, vec, def, fullType, index, useName, toFill, ignorePruning, withAttributes);
259  } else if (MyKeysToInclude.count(key) > 0) {
260  unknownPolyType = fullType;
261  }
262  }
263  const PCTypeMap::TypeDef& def = tm.getDefault();
264  if (index == 0 && !def.discard && unknownPolyType != "") {
265  addPolygon(e, vec, def, unknownPolyType, index, useName, toFill, ignorePruning, withAttributes);
266  }
267  }
268 
269 
270  // instantiate pois
271  for (std::map<long long int, PCOSMNode*>::iterator i = nodes.begin(); i != nodes.end(); ++i) {
272  PCOSMNode* n = (*i).second;
273  if (n->myAttributes.size() == 0) {
274  // cannot be relevant as a poi
275  continue;
276  }
277  Position pos(n->lon, n->lat);
278  if (!GeoConvHelper::getProcessing().x2cartesian(pos)) {
279  WRITE_WARNINGF(TL("Unable to project coordinates for POI '%'."), n->id);
280  }
281  const bool ignorePruning = OptionsCont::getOptions().isInStringVector("prune.keep-list", toString(n->id));
282  // add as many POIs as keys match defined types
283  int index = 0;
284  std::string unKnownPOIType = "";
285  for (std::map<std::string, std::string>::iterator it = n->myAttributes.begin(); it != n->myAttributes.end(); ++it) {
286  const std::string& key = it->first;
287  const std::string& value = it->second;
288  const std::string fullType = key + "." + value;
289  if (tm.has(key + "." + value)) {
290  index = addPOI(n, pos, tm.get(fullType), fullType, index, useName, toFill, ignorePruning, withAttributes);
291  } else if (tm.has(key)) {
292  index = addPOI(n, pos, tm.get(key), fullType, index, useName, toFill, ignorePruning, withAttributes);
293  } else if (MyKeysToInclude.count(key) > 0) {
294  unKnownPOIType = fullType;
295  }
296  }
297  const PCTypeMap::TypeDef& def = tm.getDefault();
298  if (index == 0 && !def.discard && unKnownPOIType != "") {
299  addPOI(n, pos, def, unKnownPOIType, index, useName, toFill, ignorePruning, withAttributes);
300  }
301  }
302  // delete nodes
303  for (std::map<long long int, PCOSMNode*>::const_iterator i = nodes.begin(); i != nodes.end(); ++i) {
304  delete (*i).second;
305  }
306  // delete edges
307  for (EdgeMap::iterator i = edges.begin(); i != edges.end(); ++i) {
308  delete (*i).second;
309  }
310  // delete relations
311  for (Relations::iterator i = relations.begin(); i != relations.end(); ++i) {
312  delete (*i);
313  }
314 }
315 
316 
317 Position
319  Position pos(n->lon, n->lat);
321  return pos;
322 }
323 
324 
325 int
326 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) {
327  if (def.discard) {
328  return index;
329  } else {
330  const bool closedShape = vec.front() == vec.back();
331  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
332  const std::string id = def.prefix + (useName && edge->name != "" ? edge->name : toString(edge->id)) + idSuffix;
333  bool fill = def.allowFill == PCTypeMap::Filltype::FORCE || (def.allowFill == PCTypeMap::Filltype::FILL && closedShape);
334  SUMOPolygon* poly = new SUMOPolygon(
336  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
337  def.color, vec, false, fill, 1, def.layer);
338  if (withAttributes) {
339  poly->updateParameters(edge->myAttributes);
340  }
341  if (!toFill.add(poly, ignorePruning)) {
342  return index;
343  } else {
344  return index + 1;
345  }
346  }
347 }
348 
349 
350 int
351 PCLoaderOSM::addPOI(const PCOSMNode* node, const Position& pos, const PCTypeMap::TypeDef& def, const std::string& fullType,
352  int index, bool useName, PCPolyContainer& toFill, bool ignorePruning, bool withAttributes) {
353  if (def.discard) {
354  return index;
355  } else {
356  const std::string idSuffix = (index == 0 ? "" : "#" + toString(index));
357  const std::string id = def.prefix + (useName && node->name != "" ? node->name : toString(node->id)) + idSuffix;
358  PointOfInterest* poi = new PointOfInterest(
360  StringUtils::escapeXML(OptionsCont::getOptions().getBool("osm.keep-full-type") ? fullType : def.id),
361  def.color, pos, false, "", 0, false, 0, def.icon, def.layer);
362  if (withAttributes) {
363  poi->updateParameters(node->myAttributes);
364  }
365  if (!toFill.add(poi, ignorePruning)) {
366  return index;
367  } else {
368  return index + 1;
369  }
370  }
371 }
372 
373 
374 // ---------------------------------------------------------------------------
375 // definitions of PCLoaderOSM::NodesHandler-methods
376 // ---------------------------------------------------------------------------
377 PCLoaderOSM::NodesHandler::NodesHandler(std::map<long long int, PCOSMNode*>& toFill,
378  bool withAttributes, MsgHandler& errorHandler) :
379  SUMOSAXHandler("osm - file"), myWithAttributes(withAttributes), myErrorHandler(errorHandler),
380  myToFill(toFill), myLastNodeID(-1) {}
381 
382 
384 
385 
386 void
388  myParentElements.push_back(element);
389  if (element == SUMO_TAG_NODE) {
390  bool ok = true;
391  long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
392  if (!ok) {
393  return;
394  }
395  myLastNodeID = -1;
396  if (myToFill.find(id) == myToFill.end()) {
397  myLastNodeID = id;
398  // assume we are loading multiple files...
399  // ... so we won't report duplicate nodes
400  PCOSMNode* toAdd = new PCOSMNode();
401  toAdd->id = id;
402  toAdd->lon = attrs.get<double>(SUMO_ATTR_LON, toString(id).c_str(), ok);
403  toAdd->lat = attrs.get<double>(SUMO_ATTR_LAT, toString(id).c_str(), ok);
404  if (!ok) {
405  delete toAdd;
406  return;
407  }
408  myToFill[toAdd->id] = toAdd;
409  }
410  }
411  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_NODE
412  && myLastNodeID != -1) {
413  bool ok = true;
414  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myLastNodeID).c_str(), ok, "", false);
415  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myLastNodeID).c_str(), ok, "", false);
416  if (key == "name") {
417  myToFill[myLastNodeID]->name = value;
418  } else if (key == "") {
419  myErrorHandler.inform("Empty key in a a tag while parsing node '" + toString(myLastNodeID) + "' occurred.");
420  ok = false;
421  }
422  if (!ok) {
423  return;
424  }
425  myToFill[myLastNodeID]->myAttributes[key] = value;
426  }
427 }
428 
429 
430 void
432  if (element == SUMO_TAG_NODE) {
433  myLastNodeID = -1;
434  }
435  myParentElements.pop_back();
436 }
437 
438 
439 // ---------------------------------------------------------------------------
440 // definitions of PCLoaderOSM::RelationsHandler-methods
441 // ---------------------------------------------------------------------------
443  Relations& relations,
444  std::set<long long int>& innerEdges,
445  bool withAttributes,
446  MsgHandler& errorHandler) :
447  SUMOSAXHandler("osm - file"),
448  myAdditionalWays(additionalWays),
449  myRelations(relations),
450  myInnerEdges(innerEdges),
451  myWithAttributes(withAttributes),
452  myErrorHandler(errorHandler),
453  myCurrentRelation(nullptr) {
454 }
455 
456 
458 }
459 
460 
461 void
463  myParentElements.push_back(element);
464  // parse "relation" elements
465  if (element == SUMO_TAG_RELATION) {
466  myCurrentWays.clear();
467  bool ok = true;
468  const std::string& action = attrs.getOpt<std::string>(SUMO_ATTR_ACTION, nullptr, ok);
469  if (action == "delete" || !ok) {
470  myCurrentRelation = nullptr;
471  } else {
472  myCurrentRelation = new PCOSMRelation();
473  myCurrentRelation->keep = false;
474  myCurrentRelation->id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
475  myRelations.push_back(myCurrentRelation);
476  }
477  return;
478  } else if (myCurrentRelation == nullptr) {
479  return;
480  }
481  // parse member elements
482  if (element == SUMO_TAG_MEMBER) {
483  bool ok = true;
484  std::string role = attrs.hasAttribute("role") ? attrs.getStringSecure("role", "") : "";
485  long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
486  if (role == "outer" || role == "inner") {
487  std::string memberType = attrs.get<std::string>(SUMO_ATTR_TYPE, nullptr, ok);
488  if (memberType == "way") {
489  myCurrentWays.push_back(ref);
490  if (role == "inner") {
491  myInnerEdges.insert(ref);
492  }
493  }
494  }
495  return;
496  }
497  // parse values
498  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_RELATION
499  && myCurrentRelation != nullptr) {
500  bool ok = true;
501  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentRelation).c_str(), ok, "", false);
502  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentRelation).c_str(), ok, "", false);
503  if (key == "") {
504  myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentRelation) + "' occurred.");
505  ok = false;
506  }
507  if (!ok) {
508  return;
509  }
510  if (key == "name") {
511  myCurrentRelation->name = value;
512  } else if (MyKeysToInclude.count(key) > 0) {
513  myCurrentRelation->keep = true;
514  for (std::vector<long long int>::iterator it = myCurrentWays.begin(); it != myCurrentWays.end(); ++it) {
515  myAdditionalWays[*it] = myCurrentRelation;
516  }
517  }
518  myCurrentRelation->myAttributes[key] = value;
519  }
520 }
521 
522 
523 void
525  myParentElements.pop_back();
526  if (element == SUMO_TAG_RELATION) {
527  myCurrentRelation->myWays = myCurrentWays;
528  myCurrentRelation = nullptr;
529  myCurrentWays.clear();
530  }
531 }
532 
533 
534 // ---------------------------------------------------------------------------
535 // definitions of PCLoaderOSM::EdgesHandler-methods
536 // ---------------------------------------------------------------------------
537 PCLoaderOSM::EdgesHandler::EdgesHandler(const std::map<long long int, PCOSMNode*>& osmNodes,
538  EdgeMap& toFill,
539  const RelationsMap& additionalWays,
540  bool withAttributes, MsgHandler& errorHandler) :
541  SUMOSAXHandler("osm - file"),
542  myWithAttributes(withAttributes),
543  myErrorHandler(errorHandler),
544  myOSMNodes(osmNodes),
545  myEdgeMap(toFill),
546  myAdditionalWays(additionalWays) {
547 }
548 
549 
551 }
552 
553 
554 void
556  myParentElements.push_back(element);
557  // parse "way" elements
558  if (element == SUMO_TAG_WAY) {
559  bool ok = true;
560  const long long int id = attrs.get<long long int>(SUMO_ATTR_ID, nullptr, ok);
561  const std::string& action = attrs.getOpt<std::string>(SUMO_ATTR_ACTION, nullptr, ok);
562  if (action == "delete" || !ok) {
563  myCurrentEdge = nullptr;
564  return;
565  }
566  myCurrentEdge = new PCOSMEdge();
567  myCurrentEdge->id = id;
568  myCurrentEdge->myIsClosed = false;
569  myCurrentEdge->standalone = false;
570  myKeep = (myAdditionalWays.find(id) != myAdditionalWays.end());
571  }
572  // parse "nd" (node) elements
573  if (element == SUMO_TAG_ND && myCurrentEdge != nullptr) {
574  bool ok = true;
575  const long long int ref = attrs.get<long long int>(SUMO_ATTR_REF, nullptr, ok);
576  if (ok) {
577  if (myOSMNodes.find(ref) == myOSMNodes.end()) {
578  WRITE_WARNINGF(TL("The referenced geometry information (ref='%') is not known"), ref);
579  return;
580  }
581  myCurrentEdge->myCurrentNodes.push_back(ref);
582  }
583  }
584  // parse values
585  if (element == SUMO_TAG_TAG && myParentElements.size() > 2 && myParentElements[myParentElements.size() - 2] == SUMO_TAG_WAY
586  && myCurrentEdge != nullptr) {
587  bool ok = true;
588  std::string key = attrs.getOpt<std::string>(SUMO_ATTR_K, toString(myCurrentEdge->id).c_str(), ok, "", false);
589  std::string value = attrs.getOpt<std::string>(SUMO_ATTR_V, toString(myCurrentEdge->id).c_str(), ok, "", false);
590  if (key == "") {
591  myErrorHandler.inform("Empty key in a a tag while parsing way '" + toString(myCurrentEdge->id) + "' occurred.");
592  ok = false;
593  }
594  if (!ok) {
595  return;
596  }
597  if (key == "name") {
598  myCurrentEdge->name = value;
599  } else if (MyKeysToInclude.count(key) > 0) {
600  myKeep = true;
601  myCurrentEdge->standalone = true;
602  }
603  myCurrentEdge->myAttributes[key] = value;
604  }
605 }
606 
607 
608 void
610  myParentElements.pop_back();
611  if (element == SUMO_TAG_WAY && myCurrentEdge != nullptr) {
612  if (myKeep) {
613  RelationsMap::const_iterator it = myAdditionalWays.find(myCurrentEdge->id);
614  if (it != myAdditionalWays.end()) {
615  myCurrentEdge->myAttributes.insert((*it).second->myAttributes.begin(), (*it).second->myAttributes.end());
616  }
617  myEdgeMap[myCurrentEdge->id] = myCurrentEdge;
618  } else {
619  delete myCurrentEdge;
620  }
621  myCurrentEdge = nullptr;
622  }
623 }
624 
625 
626 double
627 PCLoaderOSM::mergeClosest(const std::map<long long int, PCOSMNode*>& nodes, std::vector<std::vector<long long int> >& snippets) {
628  double best = std::numeric_limits<double>::max();
629  int best_i = 0;
630  int best_j = 1;
631  bool iFW = true;
632  bool jFW = true;
633 
634  for (int i = 0; i < (int)snippets.size(); i++) {
635  for (int j = i + 1; j < (int)snippets.size(); j++) {
636  Position front1(convertNodePosition(nodes.find(snippets[i].front())->second));
637  Position back1(convertNodePosition(nodes.find(snippets[i].back())->second));
638  Position front2(convertNodePosition(nodes.find(snippets[j].front())->second));
639  Position back2(convertNodePosition(nodes.find(snippets[j].back())->second));
640  double dist1 = front1.distanceTo2D(front2);
641  double dist2 = front1.distanceTo2D(back2);
642  double dist3 = back1.distanceTo2D(front2);
643  double dist4 = back1.distanceTo2D(back2);
644  if (dist1 < best) {
645  best = dist1;
646  best_i = i;
647  best_j = j;
648  iFW = false;
649  jFW = true;
650  }
651  if (dist2 < best) {
652  best = dist2;
653  best_i = i;
654  best_j = j;
655  iFW = false;
656  jFW = false;
657  }
658  if (dist3 < best) {
659  best = dist3;
660  best_i = i;
661  best_j = j;
662  iFW = true;
663  jFW = true;
664  }
665  if (dist4 < best) {
666  best = dist4;
667  best_i = i;
668  best_j = j;
669  iFW = true;
670  jFW = false;
671  }
672  }
673  }
674  std::vector<long long int> merged;
675  if (iFW) {
676  merged.insert(merged.end(), snippets[best_i].begin(), snippets[best_i].end());
677  } else {
678  merged.insert(merged.end(), snippets[best_i].rbegin(), snippets[best_i].rend());
679  }
680  if (jFW) {
681  merged.insert(merged.end(), snippets[best_j].begin(), snippets[best_j].end());
682  } else {
683  merged.insert(merged.end(), snippets[best_j].rbegin(), snippets[best_j].rend());
684  }
685  snippets.erase(snippets.begin() + best_j);
686  snippets.erase(snippets.begin() + best_i);
687  snippets.push_back(merged);
688  return best;
689 }
690 
691 /****************************************************************************/
#define WRITE_WARNINGF(...)
Definition: MsgHandler.h:296
#define WRITE_MESSAGEF(...)
Definition: MsgHandler.h:298
#define WRITE_ERRORF(...)
Definition: MsgHandler.h:305
#define PROGRESS_BEGIN_TIME_MESSAGE(msg)
Definition: MsgHandler.h:301
#define TL(string)
Definition: MsgHandler.h:315
#define PROGRESS_TIME_MESSAGE(before)
Definition: MsgHandler.h:302
#define TLF(string,...)
Definition: MsgHandler.h:317
@ 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_ACTION
@ SUMO_ATTR_K
T MAX2(T a, T b)
Definition: StdDefs.h:82
std::string toString(const T &t, std::streamsize accuracy=gPrecision)
Definition: ToString.h:46
static bool isReadable(std::string path)
Checks whether the given file is readable.
Definition: FileHelpers.cpp:51
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:92
static MsgHandler * getWarningInstance()
Returns the instance to add warnings to.
Definition: MsgHandler.cpp:79
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:60
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:299
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:145
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:213
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, std::set< long long int > &innerEdges, 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 double mergeClosest(const std::map< long long int, PCOSMNode * > &nodes, std::vector< std::vector< long long int > > &snippets)
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:70
bool has(const std::string &id)
Returns the information whether the named type is known.
Definition: PCTypeMap.cpp:76
const TypeDef & getDefault()
get the default type according to the given options
Definition: PCTypeMap.h:116
void updateParameters(const Parameterised::Map &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:37
double distanceTo2D(const Position &p2) const
returns the euclidean distance in the x-y-plane
Definition: Position.h:271
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=T(), 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, const bool isExternal=false, const bool catchExceptions=true)
Runs the given handler on the given file; returns if everything's ok.
Definition: XMLSubSys.cpp:157
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:61
std::string icon
the icon to use
Definition: PCTypeMap.h:69
bool discard
Information whether polygons of this type shall be discarded.
Definition: PCTypeMap.h:77
std::string prefix
The prefix to use.
Definition: PCTypeMap.h:67
double layer
The layer to use.
Definition: PCTypeMap.h:71
std::string id
The new type id to use.
Definition: PCTypeMap.h:63
RGBColor color
The color to use.
Definition: PCTypeMap.h:65
Filltype allowFill
Information whether polygons of this type can be filled.
Definition: PCTypeMap.h:79