File indexing completed on 2024-04-21 03:54:30

0001 /*
0002     SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "data/spatial_index_data.cpp"
0008 #include "data/spatial_index_parameters_p.h"
0009 #include "data/spatial_index_properties.cpp"
0010 #include "spatial_index_p.h"
0011 
0012 #include <cmath>
0013 #include <cstdint>
0014 
0015 constexpr const float XEnd = XStart + XRange;
0016 constexpr const float YEnd = YStart + YRange;
0017 
0018 // verify the null entry is first in the property table
0019 static_assert(spatial_index_properties[0].m_tz == Tz::Undefined);
0020 static_assert(spatial_index_properties[0].m_subdiv == 0);
0021 
0022 // z index conversions
0023 constexpr uint32_t latlonToZ(float lat, float lon)
0024 {
0025     const uint32_t x = ((lon - XStart) / XRange) * (1 << ZDepth);
0026     const uint32_t y = ((lat - YStart) / YRange) * (1 << ZDepth);
0027     uint32_t z = 0;
0028     for (int i = ZDepth - 1; i >= 0; --i) {
0029         z <<= 1;
0030         z += (y & (1 << i)) ? 1 : 0;
0031         z <<= 1;
0032         z += (x & (1 << i)) ? 1 : 0;
0033     }
0034     return z;
0035 }
0036 
0037 // "unit tests" for the z index conversion
0038 static_assert(latlonToZ(YStart, XStart) == 0);
0039 static_assert(latlonToZ(YEnd - 1.0f / (1 << ZDepth), XEnd - 1.0f / (1 << ZDepth)) == (1 << (2 * ZDepth)) - 1);
0040 static_assert(latlonToZ(YStart + YRange / 2.0f, 0.0f) == ((1 << (2 * ZDepth - 1)) | (1 << (2 * ZDepth - 2))));
0041 
0042 SpatialIndexProperty SpatialIndex::lookup(float lat, float lon)
0043 {
0044     if (std::isnan(lat) || std::isnan(lon) || lon < XStart || lon >= XEnd || lat < YStart || lat >= YEnd) {
0045         return spatial_index_properties[0];
0046     }
0047 
0048     const auto z = latlonToZ(lat, lon);
0049     const auto it = std::upper_bound(std::begin(spatial_index), std::end(spatial_index), z);
0050     if (it == std::begin(spatial_index)) {
0051         return spatial_index_properties[0];
0052     }
0053 
0054     return spatial_index_properties[(*std::prev(it)).propertyIndex()];
0055 }