JAVA实现将GeoHash转化为对应的经纬度坐标

转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/50568428

http://www.llwjy.com/blogdetail/fc484929cff1efac413ec2524680c5d7.html

个人博客站已经上线了,网址 www.llwjy.com ~欢迎各位吐槽~

-------------------------------------------------------------------------------------------------

      在博客JAVA实现空间索引编码(GeoHash)中介绍了什么是GeoHash以及如何将坐标转化为GeoHash,这篇博客就介绍下,如何将GeoHash转化为对应区域中心点的坐标。


Base32的对应关系

      在上次实现中介绍了数值和base32的对应关系,用数组保存这种对应关系;现在我们需要找到一个数据结构,可以快速的查找base32字符和数值对应关系,这样我们可以用map来保存这种关系。

private static final char[] CHARS = {'0', '1', '2', '3', '4', '5', '6', '7', 
			'8', '9', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'j', 'k', 'm', 'n', 
			'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
private static HashMap<Character, Integer> CHARSMAP;

static {
	CHARSMAP = new HashMap<Character, Integer>();
	for (int i = 0; i < CHARS.length; i++) {
		CHARSMAP.put(CHARS[i], i);
	}
}


将数值转化为二进制字符串

      当我们获取每个字符对应的数字之后,需要将数字转化为二进制字符串,我们可以直接调用Integer.toBinaryString方法来实现,由于我们要保证转换之后的二进制要是5位,对于小于16的,我们需要在前部补0,为了实现这个功能,我们对数字统一加上32,在转化成二进制字符串之后,再把第一位的1移除即可。

private String getBase32BinaryString(int i) {
	if (i < 0 || i > 31) {
		return null;
	}
	String str = Integer.toBinaryString(i + 32);
	return str.substring(1);
}

将GeoHash转化为二进制字符串

      上一步是将数值转化为五位的二进制字符串,下面我们就介绍下如何将GeoHash字符串转化为对应的二进制字符串。通过上面介绍的Base32字符和数字的对应关系,我们可以知道每个字符对应的数字,然后将这个数字转化为对应的五位二进制字符串,我们再把这些字符串拼接起来,就构成了一个完整的二进制字符串。

private String getGeoHashBinaryString(String geoHash) {
	if (geoHash == null || "".equals(geoHash)) {
		return null;
	}
	StringBuffer sb = new StringBuffer();
	for (int i = 0; i < geoHash.length(); i++) {
		char c = geoHash.charAt(i);
		if (CHARSMAP.containsKey(c)) {
			String cStr = getBase32BinaryString(CHARSMAP.get(c));
			if (cStr != null) {
				sb.append(cStr);
			}
		}
	}
	return sb.toString();
}


将GeoHash二进制字符串拆分成经纬度二进制字符串

      在上次博客中介绍了GeoHash二进制字符串是由经纬度的二进制字符串整合而成的,其中奇数为是纬度,偶数为是经度

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
Java代码示例如下: ```java import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; public class CoordinateConverter { private static final double a = 6378137; // 长半轴 private static final double b = 6356752.3142; // 短半轴 private static final double f = (a - b) / a; // 扁率 private static final double e1 = Math.sqrt(2 * f - f * f); // 第一偏心率 private static final double e2 = Math.sqrt((a * a - b * b) / (b * b)); // 第二偏心率 public static Vector3D convertXYToLatLon(double x, double y) { // 投影坐标转换为大地坐标 double Bf0 = x / a; double Nf0 = (Math.pow(a, 2) / b) / Math.sqrt(1 + Math.pow(e2, 2) * Math.pow(Math.cos(Bf0), 2)); double Mf0 = a * (1 - Math.pow(e1, 2)) / Math.pow(Math.sqrt(1 - Math.pow(e1, 2) * Math.pow(Math.sin(Bf0), 2)), 3); double nf = Math.sqrt(1 + Math.pow(e2, 2) * Math.pow(Math.cos(Bf0), 2)); double etaf = e2 * Math.cos(Bf0); double T1f = Math.pow(Math.tan(Bf0), 2); double C1f = Math.pow(e1, 2) * Math.pow(Math.cos(Bf0), 2); double R = a * (1 - Math.pow(e1, 2)) / Math.pow(Math.sqrt(1 - Math.pow(e1, 2) * Math.pow(Math.sin(Bf0), 2)), 2); double latitude = Bf0 - (Nf0 * Math.tan(Bf0) / Mf0) * (Math.pow(x, 2) / (2 * R)) + (Nf0 * Math.tan(Bf0) / (24 * Mf0 * Mf0 * Mf0)) * ((5 + 3 * T1f + 10 * C1f - 4 * C1f * C1f - 9 * etaf * etaf) * Math.pow(x, 4) / 24 - (61 + 90 * T1f + 298 * C1f + 45 * T1f * T1f - 252 * etaf * etaf - 3 * C1f * C1f) * Math.pow(x, 6) / 720); double longitude = (x / (nf * Mf0 * Math.cos(Bf0)) - (1 + 2 * T1f + C1f) * Math.pow(x, 3) / (6 * nf * nf * nf * Mf0 * Math.pow(Math.cos(Bf0), 3)) + (5 + 28 * T1f + 24 * T1f * T1f + 6 * C1f + 8 * etaf * etaf) * Math.pow(x, 5) / (120 * Math.pow(nf, 5) * Mf0 * Math.pow(Math.cos(Bf0), 5))) / Math.cos(Bf0); return new Vector3D(Math.toDegrees(latitude), Math.toDegrees(longitude), y); } public static void main(String[] args) { double x = 1000000; // x坐标 double y = 2000000; // y坐标 Vector3D latLon = convertXYToLatLon(x, y); System.out.printf("经度:%f, 纬度:%f, 高程:%f", latLon.getY(), latLon.getX(), latLon.getZ()); } } ``` 该代码实现了cgcs2000大地坐标系的xy值转化对应经纬度。在代码中,首先定义了大地坐标系相关参数,如长半轴、短半轴、扁率、偏心率等。然后通过投影坐标转换为大地坐标的公式,计算出经度、纬度和高程,并将结果返回。在main方法中,我们可以指定xy坐标,然后调用转换函数,将结果输出为经度、纬度和高程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值