Commit d5dadf11 authored by Volker Krause's avatar Volker Krause
Browse files

Store whether we have an unambiguous or equivalent timezone

This uses the last bit we still had unused in the index, but due to the
extra information impact the run-length encoding and thus slightly
increases the number of entries.

Having this available however allows us to further increase precision,
and gives us a coordinate to country mapping essentially for free.
parent ff25fc84
......@@ -176,12 +176,15 @@ namespace KnowledgeDb {
out.write('static constexpr TimezoneZIndexEntry timezone_index[] = {\n')
prevFeature = ""
prevAmbiguous = False
for task in self.tasks:
for (z,res) in task.result:
feature = ""
isAmbiguous = False
if len(res) > 1:
self.conflictTiles += 1
isAmbiguous = True
if len(res) > 1 and self.isConflict(res):
feature = "Undefined"
self.hardConflictTiles += 1
......@@ -189,10 +192,14 @@ namespace KnowledgeDb {
feature = res[0][0].replace('/', '_').replace('-', '_')
coverage = res[0][1]
if prevFeature == feature:
if prevFeature == feature and prevAmbiguous == isAmbiguous:
continue
prevFeature = feature
out.write(" { " + str(z) + ", Tz::" + feature + " }, // " + str(coverage) + "\n")
prevAmbiguous = isAmbiguous
if isAmbiguous:
out.write(" { " + str(z) + ", Tz::" + feature + ", true }, // " + str(coverage) + "\n")
else:
out.write(" { " + str(z) + ", Tz::" + feature + ", false },\n")
out.write("};\n}\n}\n")
out.close()
......
......@@ -53,7 +53,7 @@ KnowledgeDb::CountryId KnowledgeDb::countryForTimezone(KnowledgeDb::Tz tz)
}
#if 0
KnowledgeDb::Tz KnowledgeDb::timezoneForCoordinate(float lat, float lon)
KnowledgeDb::Tz KnowledgeDb::timezoneForCoordinate(float lat, float lon, bool *ambiguous)
{
// see arctic latitude filter in the generator script, we only cover 65°S to 80°N
if (lat < -65.0f || lat > 80.0f) {
......@@ -74,6 +74,9 @@ KnowledgeDb::Tz KnowledgeDb::timezoneForCoordinate(float lat, float lon)
if (it == std::begin(timezone_index)) {
return Tz::Undefined;
}
if (ambiguous) {
*ambiguous = (*std::prev(it)).isAmbiguous;
}
return (*std::prev(it)).tz;
}
......@@ -107,7 +110,8 @@ static bool isEquivalentTimezone(const QTimeZone &lhs, const QTimeZone &rhs)
KnowledgeDb::Tz KnowledgeDb::timezoneForLocation(float lat, float lon, CountryId country)
{
const auto coordTz = timezoneForCoordinate(lat, lon);
bool ambiguous = false;
const auto coordTz = timezoneForCoordinate(lat, lon, &ambiguous);
const auto countryTz = timezoneForCountry(country);
const auto countryFromCoord = countryForTimezone(coordTz);
......@@ -150,11 +154,21 @@ KnowledgeDb::Tz KnowledgeDb::timezoneForLocation(float lat, float lon, CountryId
// if the coordinate-based timezone is also in @p country, that takes precedence
// example: the various AR sub-zones, or the MY sub-zone
if (country == countryFromCoord) {
if (country == countryFromCoord || !ambiguous) {
return coordTz;
}
// if both timezones are equivalent, the country-based one wins, otherwise we use the coordinate one
return isEquivalentTimezone(toQTimeZone(coordTz), toQTimeZone(countryTz)) ? countryTz : coordTz;
}
KnowledgeDb::CountryId KnowledgeDb::countryForCoordinate(float lat, float lon)
{
bool ambiguous = false;
const auto tz = timezoneForCoordinate(lat, lon, &ambiguous);
if (!ambiguous) {
return countryForTimezone(tz);
}
return {};
}
#endif
......@@ -50,13 +50,20 @@ namespace KnowledgeDb {
/** Returns the timezone for the given coordinate.
* The result can be @c Tz::Undefined if this cannot be clearly determined.
*/
KITINERARY_EXPORT Tz timezoneForCoordinate(float lat, float lon);
KITINERARY_EXPORT Tz timezoneForCoordinate(float lat, float lon, bool *ambiguous = nullptr);
/** Returns the timezone for the given location consisting of coordinates and country.
* This combines the results of the two above individual queries
* to obtain better results close to borders.
*/
KITINERARY_EXPORT Tz timezoneForLocation(float lat, float lon, CountryId country);
/** Returns the country for the given coordinate.
* The result will be the country identifier only if the underlying
* spatial index has no ambiguity at the requested locations, ie. this
* will return less results than timezoneForCoordinate() for example.
*/
KITINERARY_EXPORT CountryId countryForCoordinate(float lat, float lon);
#endif
}
}
......
......@@ -41,8 +41,11 @@ inline constexpr bool operator<(const CountryTimezoneMap lhs, const CountryId rh
struct TimezoneZIndexEntry {
uint32_t z: 22;
Tz tz: 9;
bool isAmbiguous: 1;
};
static_assert(sizeof(TimezoneZIndexEntry) == 4, "structure is size-sensitive");
inline constexpr bool operator<(uint32_t lhs, TimezoneZIndexEntry rhs)
{
return lhs < rhs.z;
......
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