Commit 766cf0a6 authored by Volker Krause's avatar Volker Krause
Browse files

Support coverage areas consisting of disjoint polygons

This exists in a few places (AT-7 is an obvious example), merging those
during loading can actually cause more problems than it solves in
overlapping areas, so handle those separately. The bounding box is still
united for a quick pre-check before full hit detection.
parent d3e6289d
Pipeline #59453 passed with stage
in 25 seconds
......@@ -21,7 +21,7 @@ class CoverageAreaPrivate : public QSharedData {
public:
CoverageArea::Type type = CoverageArea::Any;
QStringList regions;
QPolygonF area;
std::vector<QPolygonF> areas;
QRectF boundingBox;
};
}
......@@ -32,7 +32,7 @@ KPUBLICTRANSPORT_MAKE_PROPERTY(CoverageArea, QStringList, regions, setRegions)
bool CoverageArea::isEmpty() const
{
return d->regions.isEmpty() && d->area.isEmpty();
return d->regions.isEmpty() && d->areas.empty();
}
bool CoverageArea::isGlobal() const
......@@ -51,9 +51,13 @@ static QStringView countryCode(QStringView isoCode)
bool CoverageArea::coversLocation(const Location &loc) const
{
if (loc.hasCoordinate() && !d->area.isEmpty()) {
return d->boundingBox.contains({loc.longitude(), loc.latitude()})
&& d->area.containsPoint({loc.longitude(), loc.latitude()}, Qt::WindingFill);
if (loc.hasCoordinate() && !d->areas.empty()) {
if (d->boundingBox.contains({loc.longitude(), loc.latitude()})) {
return std::any_of(d->areas.begin(), d->areas.end(), [&loc](const auto &area) {
return area.containsPoint({loc.longitude(), loc.latitude()}, Qt::WindingFill);
});
}
return false;
}
// TODO we could do a more precise check for ISO 3166-2 subdivision codes when available
......@@ -76,8 +80,10 @@ CoverageArea CoverageArea::fromJson(const QJsonObject &obj)
CoverageArea ca;
ca.setRegions(Json::toStringList(obj.value(QLatin1String("region"))));
std::sort(ca.d->regions.begin(), ca.d->regions.end());
ca.d->area = GeoJson::readOuterPolygon(obj.value(QLatin1String("area")).toObject());
ca.d->boundingBox = ca.d->area.boundingRect();
ca.d->areas = GeoJson::readOuterPolygons(obj.value(QLatin1String("area")).toObject());
for (const auto &area : ca.d->areas) {
ca.d->boundingBox |= area.boundingRect();
}
return ca;
}
......
......@@ -48,28 +48,102 @@
"coordinates": [
[
[
13.0081,
46.6172
],
[
12.5874,
47.7814
],
[
10.1625,
47.5524
],
[
10.0635,
46.8041
],
[
11.2584158,
46.8392307
],
[
12.3030975,
46.9592349
],
[
12.2514788,
47.1605428
],
[
12.5433903,
47.1946092
],
[
12.8846958,
47.6338374
],
[
12.1864845,
47.9199471
],
[
12.1116382,
47.7413158
],
[
11.6082864,
47.7308048
],
[
11.10706,
47.5395618
],
[
10.3666854,
47.7448997
],
[
9.9328311,
46.9066702
],
[
10.1347009,
46.6679679
],
[
10.3405402,
46.8047264
],
[
10.3801386,
46.7308226
],
[
11.0785569,
46.6181216
],
[
11.2584158,
46.8392307
]
]
],
[
[
13.0081,
46.6172
[
13.0881854,
46.6865655
],
[
13.1153523,
46.8408643
],
[
12.5213606,
47.3128549
],
[
11.8575753,
47.0442922
],
[
12.53246,
46.5006243
],
[
13.0881854,
46.6865655
]
]
]
],
"type": "Polygon"
"type": "MultiPolygon"
},
"region": [
"AT-7"
......
......@@ -49,28 +49,126 @@
"coordinates": [
[
[
1.797,
51.1
],
[
5.55,
49.124
],
[
6.598,
50.464
],
[
5.154,
51.837
],
[
6.0519939,
49.4607568
],
[
5.9446655,
49.8874072
],
[
6.5970368,
50.2810579
],
[
6.3682911,
50.7706328
],
[
5.8756124,
50.8690119
],
[
6.0047267,
51.2633052
],
[
4.7791655,
51.6578714
],
[
3.8723668,
51.3506123
],
[
3.4908777,
51.3866896
],
[
3.1054104,
51.7190807
],
[
2.1602145,
51.3306752
],
[
2.7227737,
50.568554
],
[
3.0671458,
50.627914
],
[
3.1934769,
50.3897759
],
[
3.51578,
50.3577501
],
[
3.6171509,
50.1633289
],
[
4.0273538,
50.137955
],
[
3.9595257,
49.8479179
],
[
4.5604469,
49.8018995
],
[
4.7112855,
49.8905831
],
[
4.6979444,
49.7047812
],
[
5.449393,
49.3452747
],
[
6.0519939,
49.4607568
]
]
],
[
[
1.797,
51.1
[
5.1039445,
51.6039645
],
[
4.7635155,
51.6039645
],
[
4.7635155,
51.2813755
],
[
5.1039445,
51.2813755
],
[
5.1039445,
51.6039645
]
]
]
],
"type": "Polygon"
"type": "MultiPolygon"
},
"region": [
"BE"
......
......@@ -49,28 +49,98 @@
"coordinates": [
[
[
9.8333,
51.7011
],
[
9.8812,
50.2173
],
[
12.5934,
50.1455
],
[
12.71307,
51.5734
],
[
10.5414778,
51.1997778
],
[
10.0257222,
51.1997778
],
[
10.0257222,
50.7834222
],
[
10.5414778,
50.7834222
],
[
10.5414778,
51.1997778
]
]
],
[
[
9.8333,
51.7011
[
12.0852775,
50.3011012
],
[
12.0449711,
50.6989758
],
[
12.0976295,
50.6370828
],
[
12.2704187,
50.6823594
],
[
12.3398951,
51.0389726
],
[
11.6793414,
51.2614133
],
[
11.1372982,
51.1598371
],
[
10.6997626,
51.2702005
],
[
10.2433784,
50.9276748
],
[
10.2635174,
50.7643417
],
[
10.7592162,
50.5556557
],
[
10.7965901,
50.5763203
],
[
10.8593232,
50.4002098
],
[
11.3449839,
50.3733695
],
[
11.4560854,
50.217322
],
[
12.0852775,
50.3011012
]
]
]
],
"type": "Polygon"
"type": "MultiPolygon"
},
"region": [
"DE-TH"
......
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