KOSMIndoorMap

osm-download-data.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Volker Krause <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include <KOSMIndoorMap/MapData>
8 #include <KOSMIndoorMap/MapLoader>
9 
10 #include <osm/datatypes.h>
11 #include <osm/xmlwriter.h>
12 
13 #include <QCommandLineParser>
14 #include <QCoreApplication>
15 #include <QDebug>
16 #include <QFile>
17 
18 using namespace KOSMIndoorMap;
19 
20 static void filterByBbox(OSM::DataSet &dataSet, OSM::BoundingBox bbox)
21 {
22  dataSet.relations.erase(std::remove_if(dataSet.relations.begin(), dataSet.relations.end(), [bbox](const auto &rel) {
23  return !OSM::intersects(rel.bbox, bbox);
24  }), dataSet.relations.end());
25  dataSet.ways.erase(std::remove_if(dataSet.ways.begin(), dataSet.ways.end(), [bbox](const auto &way) {
26  return !OSM::intersects(way.bbox, bbox);
27  }), dataSet.ways.end());
28  dataSet.nodes.erase(std::remove_if(dataSet.nodes.begin(), dataSet.nodes.end(), [bbox](const auto &nd) {
29  return !OSM::contains(bbox, nd.coordinate);
30  }), dataSet.nodes.end());
31 }
32 
33 template <typename Elem>
34 static bool containsElement(const std::vector<Elem> &elems, OSM::Id id)
35 {
36  const auto it = std::lower_bound(elems.begin(), elems.end(), id, [](const Elem &lhs, OSM::Id rhs) { return lhs.id < rhs; });
37  return it != elems.end() && (*it).id == id;
38 }
39 
40 static void purgeDanglingReferences(OSM::DataSet &dataSet)
41 {
42  for (auto &rel : dataSet.relations) {
43  rel.members.erase(std::remove_if(rel.members.begin(), rel.members.end(), [&dataSet](const auto &mem) {
44  switch (mem.type()) {
45  case OSM::Type::Null:
46  Q_UNREACHABLE();
47  case OSM::Type::Node:
48  return !containsElement(dataSet.nodes, mem.id);
49  case OSM::Type::Way:
50  return !containsElement(dataSet.ways, mem.id);
51  case OSM::Type::Relation:
52  return !containsElement(dataSet.relations, mem.id);
53  }
54  return false;
55  }), rel.members.end());
56  }
57 }
58 
59 int main(int argc, char **argv)
60 {
61  QCoreApplication app(argc, argv);
62  QCommandLineParser parser;
63  parser.addHelpOption();
64  QCommandLineOption bboxOpt({QStringLiteral("b"), QStringLiteral("bbox")}, QStringLiteral("bounding box to download"), QStringLiteral("minlat,minlon,maxlat,maxlon"));
65  parser.addOption(bboxOpt);
66  QCommandLineOption outOpt({QStringLiteral("o"), QStringLiteral("out")}, QStringLiteral("output file"), QStringLiteral("file"));
67  parser.addOption(outOpt);
68  parser.process(app);
69 
70  if (!parser.isSet(bboxOpt) || !parser.isSet(outOpt)) {
71  parser.showHelp(1);
72  return 1;
73  }
74 
75  OSM::BoundingBox bbox;
76  const auto coords = parser.value(bboxOpt).splitRef(QLatin1Char(','));
77  if (coords.size() == 4) {
78  bbox.min = OSM::Coordinate(coords[0].toDouble(), coords[1].toDouble());
79  bbox.max = OSM::Coordinate(coords[2].toDouble(), coords[3].toDouble());
80  }
81  if (!bbox.isValid()) {
82  qCritical() << "Invalid bounding box!";
83  return 1;
84  }
85  qDebug() << bbox << bbox.center();
86 
87  MapLoader loader;
88  loader.loadForCoordinate(bbox.center().latF(), bbox.center().lonF()); // TODO add the ability to load an entire bbox
90  app.exec();
91 
92  auto data = loader.takeData();
93  filterByBbox(data.dataSet(), bbox);
94  purgeDanglingReferences(data.dataSet());
95 
96  QFile f(parser.value(outOpt));
97  if (!f.open(QFile::WriteOnly)) {
98  qCritical() << f.errorString();
99  return 1;
100  }
101  OSM::XmlWriter::write(data.dataSet(), &f);
102  return 0;
103 }
OSM-based multi-floor indoor maps for buildings.
Loader for OSM data for a single station or airport.
Definition: maploader.h:24
QString errorString() const const
Coordinate, stored as 1e7 * degree to avoid floating point precision issues, and offset to unsigned v...
Definition: datatypes.h:37
QCommandLineOption addHelpOption()
Q_INVOKABLE void loadForCoordinate(double lat, double lon)
Load map for the given coordinates.
Definition: maploader.cpp:99
bool isSet(const QString &name) const const
int64_t Id
OSM element identifier.
Definition: datatypes.h:27
void done()
Emitted when the requested data has been loaded.
void process(const QStringList &arguments)
MapData && takeData()
Take out the completely loaded result.
Definition: maploader.cpp:120
void showHelp(int exitCode)
QVector< QStringRef > splitRef(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
A set of nodes, ways and relations.
Definition: datatypes.h:283
bool addOption(const QCommandLineOption &option)
Bounding box, ie.
Definition: datatypes.h:95
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString value(const QString &optionName) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 23 2021 23:03:45 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.