Commit 30a73505 authored by Volker Krause's avatar Volker Krause
Browse files

Handle more station types, and prioritize them

This fixes the DEN and DUS tests, and makes some progress on PDX/HKG/PVG.
parent 412cfbea
......@@ -219,7 +219,7 @@ private Q_SLOTS:
QTest::newRow("AGP") << s("AGP") << 36.67608f << -4.49095f << 100;
QTest::newRow("AMS") << s("AMS") << 52.3095230f << 4.7621813f << 50;
QTest::newRow("ARN") << s("ARN") << 59.64927f << 17.92956f << 100;
QTest::newRow("ARN") << s("ARN") << 59.64927f << 17.92956f << 50;
QTest::newRow("BLR") << s("BLR") << 13.20023f << 77.70972f << 150;
QTest::newRow("BRE") << s("BRE") << 53.05266f << 8.78692f << 150;
QTest::newRow("BRU") << s("BRU") << 50.8985255f << 4.4830282f << 50;
......@@ -227,9 +227,9 @@ private Q_SLOTS:
QTest::newRow("CGN") << s("CGN") << 50.87856f << 7.12107f << 150;
QTest::newRow("CPH") << s("CPH") << 55.6295693f << 12.6492994f << 50;
QTest::newRow("DEL") << s("DEL") << 28.55681f << 77.08718f << 100;
QTest::newRow("DEN") << s("DEN") << 39.84790f << -104.67340f << 200;
QTest::newRow("DUB") << s("DUB") << 53.4273328f << -6.2437352f << 200;
QTest::newRow("DUS") << s("DUS") << 51.27889f << 6.76566f << 100;
QTest::newRow("DEN") << s("DEN") << 39.84790f << -104.67340f << 150;
QTest::newRow("DUB") << s("DUB") << 53.4273328f << -6.2437352f << 150;
QTest::newRow("DUS") << s("DUS") << 51.27889f << 6.76566f << 150;
QTest::newRow("EAP") << s("EAP") << 47.59960f << 7.53144f << 150;
QTest::newRow("EDI") << s("EDI") << 55.9483110f << -3.36353370f << 100;
QTest::newRow("EWR") << s("EWR") << 40.69049f << -74.17765f << 250;
......@@ -251,7 +251,7 @@ private Q_SLOTS:
QTest::newRow("LIS") << s("LIS") << 38.76876f << -9.12844f << 100;
QTest::newRow("LUX") << s("LUX") << 49.63506f << 6.21650f << 200;
QTest::newRow("LYS") << s("LYS") << 45.72065f << 5.07807f << 150;
QTest::newRow("MUC") << s("MUC") << 48.35378f << 11.78633f << 100;
QTest::newRow("MUC") << s("MUC") << 48.35378f << 11.78633f << 50;
QTest::newRow("NRT") << s("NRT") << 35.77059f << 140.38679f << 300;
QTest::newRow("NUE") << s("NUE") << 49.49411f << 11.07867f << 100;
QTest::newRow("ORD") << s("ORD") << 41.97779f << -87.90269f << 300;
......@@ -265,15 +265,15 @@ private Q_SLOTS:
QTest::newRow("SFO") << s("SFO") << 37.6162238f << -122.3915235f << 50;
QTest::newRow("SHA") << s("SHA") << 31.19624f << 121.32377f << 100;
QTest::newRow("STR") << s("STR") << 48.69052f << 9.19302f << 50;
QTest::newRow("SXB") << s("SXB") << 48.54444f << 7.62783f << 100;
QTest::newRow("SXB") << s("SXB") << 48.54444f << 7.62783f << 50;
QTest::newRow("SXF") << s("SXF") << 52.38856f << 13.51809f << 100;
QTest::newRow("TLL") << s("TLL") << 59.41685f << 24.79899f << 150;
QTest::newRow("TLS") << s("TLS") << 43.63146f << 1.37364f << 100;
QTest::newRow("TPE") << s("TPE") << 25.07719f << 121.23250f << 350; // still ok-ish
QTest::newRow("TXL") << s("TXL") << 52.55392f << 13.29208f << 100;
QTest::newRow("VIE") << s("VIE") << 48.12024f << 16.56431f << 100;
QTest::newRow("VIE") << s("VIE") << 48.12024f << 16.56431f << 50;
QTest::newRow("YOW") << s("YOW") << 45.32277f << -75.66726f << 100;
QTest::newRow("ZRH") << s("ZRH") << 47.45024f << 8.56207f << 100;
QTest::newRow("ZRH") << s("ZRH") << 47.45024f << 8.56207f << 50;
// too complex to work with this approach: LHR, CDG, MAD, MXP, ICN, BCN, PEK
}
......@@ -289,24 +289,22 @@ private Q_SLOTS:
QVERIFY(coord.isValid());
const auto d = LocationUtil::distance(coord.latitude, coord.longitude, lat, lon);
qDebug() << coord.latitude << coord.longitude << d;
qDebug() << coord.latitude << coord.longitude << d << (dist - d);
#if 0
QEXPECT_FAIL("BUD", "not optimized yet", Continue);
QEXPECT_FAIL("DEN", "not optimized yet", Continue);
QEXPECT_FAIL("DUS", "not optimized yet", Continue);
QEXPECT_FAIL("BUD", "closed terminal 1 (w8557242) interfering", Continue);
QEXPECT_FAIL("FRA", "spurious entrance node in OSM data", Continue);
QEXPECT_FAIL("GDN", "railway=halt stations not handled yet", Continue);
QEXPECT_FAIL("GDN", "station/terminal proximity metric is too simple", Continue);
QEXPECT_FAIL("GLA", "airport is not a polygon in OSM", Continue);
QEXPECT_FAIL("GRU", "not optimized yet", Continue);
QEXPECT_FAIL("HKG", "not optimized yet", Continue);
QEXPECT_FAIL("GRU", "w777206182 interfering", Continue);
QEXPECT_FAIL("HKG", "way-type station elements not handled yet", Continue);
QEXPECT_FAIL("LIS", "station/terminal proximity metric is too simple", Continue);
QEXPECT_FAIL("PDX", "stop_position::railway::tram_stop not handled yet", Continue);
QEXPECT_FAIL("PRG", "not optimized yet", Continue);
QEXPECT_FAIL("PVG", "not optimized yet", Continue);
QEXPECT_FAIL("PDX", "stop clustering missing", Continue);
QEXPECT_FAIL("PRG", "private/military terminals 3 and 4 interfering", Continue);
QEXPECT_FAIL("PVG", "needs way-type station element support, and subway vs generic type filter", Continue);
QEXPECT_FAIL("RIG", "open polygon in OSM", Continue);
QEXPECT_FAIL("SHA", "not optimized yet", Continue);
QEXPECT_FAIL("SXF", "not optimized yet", Continue);
QEXPECT_FAIL("SXF", "w630509626 (government terminal) interfering", Continue);
QVERIFY(d <= dist);
#endif
}
......
......@@ -32,7 +32,7 @@ add_custom_command(
)
# extract all elements we are interested in (airports, terminals, stations at airports)
osm_filter(OUTPUT airports.o5m FILTER --keep=\"iata=* or aeroway=terminal or public_transport=station or railway=station\")
osm_filter(OUTPUT airports.o5m FILTER --keep=\"iata=* or aeroway=terminal or public_transport=station or railway=station or railway=halt or railway=tram_stop\")
# augment bounding box information
osm_convert(INPUT airports.o5m OUTPUT airports-bbox.o5m ADD_BBOX ON)
......
......@@ -90,6 +90,9 @@ void OSMAirportDb::load(const QString &path)
for (const auto &node : m_dataset.nodes) {
loadStation(node);
}
for (auto &a : m_iataMap) {
filterStations(a.second);
}
qDebug() << "airports:" << m_iataMap.size();
qDebug() << " with a single terminal:" << std::count_if(m_iataMap.begin(), m_iataMap.end(), [](const auto &a) { return a.second.terminalBboxes.size() == 1; } );
......@@ -268,7 +271,7 @@ void OSMAirportDb::loadTerminal(const OSM::Way &elem)
void OSMAirportDb::loadStation(const OSM::Node &elem)
{
const auto railway = OSM::tagValue(elem, QLatin1String("railway"));
if (railway != QLatin1String("station")) {
if (railway != QLatin1String("station") && railway != QLatin1String("halt") && railway != QLatin1String("tram_stop")) {
return;
}
......@@ -287,7 +290,7 @@ void OSMAirportDb::loadStation(const OSM::Node &elem)
continue;
}
const auto onPremise = airport.airportPolygon.containsPoint(QPointF(elem.coordinate.latF(), elem.coordinate.lonF()), Qt::WindingFill);
const auto onPremises = airport.airportPolygon.containsPoint(QPointF(elem.coordinate.latF(), elem.coordinate.lonF()), Qt::WindingFill);
// one would assume that terminals are always within the airport bounds, but that's not the case
// they sometimes expand beyond them. A station inside a terminal is however most likely something relevant for us
const auto inTerminal = std::any_of(airport.terminalBboxes.begin(), airport.terminalBboxes.end(), [&elem](const auto &terminal) {
......@@ -298,13 +301,33 @@ void OSMAirportDb::loadStation(const OSM::Node &elem)
return OSM::distance(terminal.center(), elem.coordinate) < 100;
});
if (onPremise || inTerminal || isCloseToTerminal) {
//qDebug() << "found station for airport:" << elem.url() << (*it).first << (*it).second.source;
(*it).second.stations.push_back(elem.coordinate);
if (onPremises || inTerminal || isCloseToTerminal) {
//qDebug() << "found station for airport:" << elem.url() << (*it).first << (*it).second.source << onPremises << inTerminal << isCloseToTerminal;
(*it).second.stations.push_back(&elem);
}
}
}
void OSMAirportDb::filterStations(OSMAirportData &airport)
{
// if we have a full station, drop halts
// TODO similar filters are probably needed for various tram/subway variants for on-premises transport lines
auto it = std::partition(airport.stations.begin(), airport.stations.end(), [](auto station) {
return OSM::tagValue(*station, QLatin1String("railway")) == QLatin1String("station");
});
if (it != airport.stations.begin() && it != airport.stations.end()) {
airport.stations.erase(it, airport.stations.end());
}
// "creative" way of separating "real" and on-premises stations: only real ones tend to have Wikidata tags
it = std::partition(airport.stations.begin(), airport.stations.end(), [](auto station) {
return !OSM::tagValue(*station, QLatin1String("wikidata")).isEmpty();
});
if (it != airport.stations.begin() && it != airport.stations.end()) {
airport.stations.erase(it, airport.stations.end());
}
}
OSM::Coordinate OSMAirportDb::lookup(const QString &iata, float lat, float lon)
{
const auto it = m_iataMap.find(iata);
......@@ -334,10 +357,10 @@ OSM::Coordinate OSMAirportDb::lookup(const QString &iata, float lat, float lon)
return airport.terminalBboxes[0].center();
}
// single on-premise station
// single station
if (airport.stations.size() == 1) {
qDebug() << " by station:" << airport.stations[0];
return airport.stations[0];
qDebug() << " by station:" << airport.stations[0]->url();
return airport.stations[0]->coordinate;
}
// multiple terminals: take the center of the sum of all bounding boxes, and TODO check the result isn't ridiculously large
......@@ -345,6 +368,7 @@ OSM::Coordinate OSMAirportDb::lookup(const QString &iata, float lat, float lon)
const auto terminalBbox = std::accumulate(airport.terminalBboxes.begin(), airport.terminalBboxes.end(), OSM::BoundingBox(), OSM::unite);
// if the original coordinate is outside the terminal bounding box, this is highly likely an improvement,
// otherwise we cannot be sure (see MUC, where the Wikidata coordinate is ideal).
//qDebug() << " considering terminal bbox:" << terminalBbox;
if (!OSM::contains(terminalBbox, wdCoord)) {
qDebug() << " by terminal bbox center:" << terminalBbox.center();
return terminalBbox.center();
......
......@@ -35,7 +35,7 @@ struct OSMAirportData
std::vector<OSM::BoundingBox> terminalBboxes;
std::vector<OSM::Coordinate> terminalEntrances;
std::vector<OSM::Coordinate> stations;
std::vector<const OSM::Node*> stations;
};
/** OSM airport database for optimizing geo coordinates. */
......@@ -52,6 +52,7 @@ private:
void loadTerminal(const OSM::Relation &elem);
void loadTerminal(const OSM::Way &elem);
void loadStation(const OSM::Node &elem);
void filterStations(OSMAirportData &airport);
template <typename Iter>
void appendPointsFromWay(QVector<QPointF> &points, const Iter &nodeEegin, const Iter &nodeEnd) const;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment