Fix packing/unpacking of lat lng.

This commit is contained in:
Kishore Nallan 2021-05-12 16:38:33 +05:30
parent eca0d952e9
commit 1f6b4e3cd4
3 changed files with 32 additions and 9 deletions

View File

@ -505,18 +505,20 @@ struct sort_by {
class GeoPoint {
constexpr static const double EARTH_RADIUS = 3958.75;
constexpr static const double METER_CONVERT = 1609.00;
constexpr static const uint64_t MASK_H32_BITS = 0xffffffffUL;
public:
static int64_t pack_lat_lng(double lat, double lng) {
static uint64_t pack_lat_lng(double lat, double lng) {
// https://stackoverflow.com/a/1220393/131050
int32_t ilat = lat * 1000000;
int32_t ilng = lng * 1000000;
int64_t lat_lng = (int64_t(ilat) << 32) | ilng;
const int32_t ilat = lat * 1000000;
const int32_t ilng = lng * 1000000;
// during int32_t -> uint64_t, higher order bits will be 1, so we have to mask that
const uint64_t lat_lng = (uint64_t(ilat) << 32) | (uint64_t)(ilng & MASK_H32_BITS);
return lat_lng;
}
static void unpack_lat_lng(int64_t packed_lat_lng, S2LatLng& latlng) {
double lat = double(packed_lat_lng >> 32) / 1000000;
double lng = double(packed_lat_lng & 0xffffffffUL) / 1000000;
static void unpack_lat_lng(uint64_t packed_lat_lng, S2LatLng& latlng) {
const double lat = double(int32_t((packed_lat_lng >> 32) & MASK_H32_BITS)) / 1000000;
const double lng = double(int32_t(packed_lat_lng & MASK_H32_BITS)) / 1000000;
latlng = S2LatLng::FromDegrees(lat, lng);
}

View File

@ -726,7 +726,9 @@ Option<nlohmann::json> Collection::search(const std::string & query, const std::
return Option<nlohmann::json>(404, error);
}
int64_t lat_lng = GeoPoint::pack_lat_lng(std::stod(geo_coords[0]), std::stod(geo_coords[1]));
double lat = std::stod(geo_coords[0]);
double lng = std::stod(geo_coords[1]);
int64_t lat_lng = GeoPoint::pack_lat_lng(lat, lng);
sort_field_std.name = actual_field_name;
sort_field_std.geopoint = lat_lng;
}

View File

@ -104,4 +104,23 @@ TEST(IndexTest, PointInPolygon180thMeridian) {
ASSERT_FALSE(Index::is_point_in_polygon(poly1, point4));
ASSERT_FALSE(Index::is_point_in_polygon(poly1, point5));
}
}
TEST(IndexTest, GeoPointPackUnpack) {
std::vector<std::pair<double, double>> latlngs = {
{43.677223,-79.630556},
{-0.041935, 65.433296}, // Indian Ocean Equator
{-66.035056, 173.187202}, // Newzealand
{-65.015656, -158.336234}, // Southern Ocean
{84.552144, -159.742483}, // Arctic Ocean
{84.517046, 171.730040} // Siberian Sea
};
for(auto& latlng: latlngs) {
int64_t packed_latlng = GeoPoint::pack_lat_lng(latlng.first, latlng.second);
S2LatLng s2LatLng;
GeoPoint::unpack_lat_lng(packed_latlng, s2LatLng);
ASSERT_FLOAT_EQ(latlng.first, s2LatLng.lat().degrees());
ASSERT_FLOAT_EQ(latlng.second, s2LatLng.lng().degrees());
}
}