我正在尝试编写一个接受纬度/经度对并返回其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)
子句)处理lng
和lat
的方法)。
更新资料
经过进一步调查,您似乎得到意外结果的另一个原因似乎是,base32和base2之间显然存在多个转换。我尝试了一些可以找到的在线解码器/编码器,它们都给了我您在问题中提到的结果。但是,在阅读Wikipedia页面Geohash时,似乎用于将geohash编码从base2编码为base32的算法是不同的。
例如,让我们检查一下您实际得到的geohash(因此,对于缺失的数字没有任何歧义)。您的方法返回101001000100000011011010100011
,您声称将其转换为kh0dl3
。是的,当我输入here时,我也会得到这个结果。但是,让我们仔细看看。前5个字符为10100
,或者转换为十进制符号12
(base2字符串中的5个字符对应于base32字符串中的一个字符,因此我们需要一次获取5个字符)。像预期的那样,在我刚刚链接到的页面中输入10100
会产生K
(kh0dl3
的第一个字符)。但是,根据Wikipedia Geohash页面中的表,12
不会转换为k
,而是会转换为d
。因此,显然,用于哈希的base32-base2-conversion算法与用于获得预期结果的算法不同。
关于java - GeoHash函数未返回正确结果,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45402360/