我正在尝试编写一个接受纬度/经度对并返回其base2(geohash一旦转换为base32)的字符串的geohashing函数。但是,这给了我错误的结果。怎么了

public static void main(String[] args) {
    float latitude = 45.512794f;
    float longitude = -122.679565f;
    System.out.println(geoHash(latitude, longitude));
}

private static String geoHash(float lat, float lng) {
    float lowLat = -90.0f;
    float highLat = 90.0f;
    float lowLng = -180.0f;
    float highLng = 180.0f;
    return geoHash(lowLng, highLng, lowLat, highLat, lat, lng, "");
}

private static String geoHash(float lowLng, float highLng, float lowLat, float highLat, float lat, float lng, String hash) {
    if (hash.length() == 30)
        return hash;

    float midLat = (lowLat + highLat) / 2;
    float midLng = (lowLng + highLng) / 2;
    if (lng <= midLng && lat <= midLat) {
        return geoHash(lowLng, midLng, lowLat, midLat, lat, lng, hash + "00");
    } else if (lng > midLng && lat <= midLat) {
        return geoHash(midLng, highLng, lowLat, midLat, lat, lng, hash + "01");
    } else if (lng <= midLng && lat > midLat) {
        return geoHash(lowLng, midLng, midLat, highLat, lat, lng, hash + "10");
    } else {
        return geoHash(midLng, highLng, midLat, highLat, lat, lng, hash + "11");
    }
}


我正在获取101001000100000011011010100011,它将转换为kh0dl3 base32,并且我期望11000001000000011110101110110将其转换为c20fbm。

我不明白的是,我从函数(1010)获得的结果中前两对位是相同的,这意味着它两次击中了同一象限。在实际的转换后的geohash中,我在网上发现它们是两个不同的象限(1100)。

编辑:经过进一步调试,并在所选答案的帮助下,我发现我解码的基数不正确(我使用的是4位而不是5位)。我也应该使用https://en.wikipedia.org/wiki/Geohash中的表。我的代码中还有一个错误,已修复如下:

private static String geoHash(float lowLng, float highLng, float lowLat, float highLat, float lat, float lng, String hash) {
    if (hash.length() == 30)
        return hash;

    float midLng = (lowLng + highLng) / 2.0f;
    float midLat = (lowLat + highLat) / 2.0f;
    if (lng <= midLng && lat <= midLat) {
        return geoHash(lowLng, midLng, lowLat, midLat, lat, lng, hash + "00");
    } else if (lng <= midLng && lat > midLat) {
        return geoHash(lowLng, midLng, midLat, highLat, lat, lng, hash + "01");
    } else if (lng > midLng && lat <= midLat) {
        return geoHash(midLng, highLng, lowLat, midLat, lat, lng, hash + "10");
    } else {
        return geoHash(midLng, highLng, midLat, highLat, lat, lng, hash + "11");
    }
}

最佳答案

无论您从何处获得期望的字符串,该来源都会撒谎。首先,您期望的字符串只有29个字符长,这意味着缺少1个字符。另外,前两位必须为01,因为经度为负,而纬度为正。

但是,您的代码中仍然存在一个错误:如果我正确理解了地哈希的组成,您将切换附加到hash的经度和纬度位(if中的第二个和第三个geoHash(float, float, float, float, float, float, String)子句)处理lnglat的方法)。

更新资料

经过进一步调查,您似乎得到意外结果的另一个原因似乎是,base32和base2之间显然存在多个转换。我尝试了一些可以找到的在线解码器/编码器,它们都给了我您在问题中提到的结果。但是,在阅读Wikipedia页面Geohash时,似乎用于将geohash编码从base2编码为base32的算法是不同的。

例如,让我们检查一下您实际得到的geohash(因此,对于缺失的数字没有任何歧义)。您的方法返回101001000100000011011010100011,您声称将其转换为kh0dl3。是的,当我输入here时,我也会得到这个结果。但是,让我们仔细看看。前5个字符为10100,或者转换为十进制符号12(base2字符串中的5个字符对应于base32字符串中的一个字符,因此我们需要一次获取5个字符)。像预期的那样,在我刚刚链接到的页面中输入10100会产生Kkh0dl3的第一个字符)。但是,根据Wikipedia Geohash页面中的表,12不会转换为k,而是会转换为d。因此,显然,用于哈希的base32-base2-conversion算法与用于获得预期结果的算法不同。

关于java - GeoHash函数未返回正确结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45402360/

10-10 16:48