关于知道区块的geohash值,求区块中点坐标和四角坐标

条件:先知道该区块geohash值或者该区块任意一点gps
推荐测试工具:geohash在线
geohash工具类

public class GeoHash {
	private LocationBean location;
	/**
	 * 1 2500km;2 630km;3 78km;4 20km
	 * 5 2.4km; 6 610m; 7 76m; 8 19m
	 */
	private int hashLength = 7; //经纬度转化为geohash长度
	private int latLength = 20; //纬度转化为二进制长度
	private int lngLength = 20; //经度转化为二进制长度
	
	private double minLat;//每格纬度的单位大小
	private double minLng;//每个经度的单位大小
	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);
		}
	}
	
	public GeoHash(double lat, double lng) {
		location = new LocationBean(lat, lng);
		setMinLatLng();
	}
	public GeoHash() {
		super();
	}
	public int gethashLength() {
		return hashLength;
	}
	
	/**
	 * 
	 * @Description: 设置经纬度的最小单位
	 */
	private void setMinLatLng() {
		minLat = LocationBean.MAXLAT - LocationBean.MINLAT;
		for (int i = 0; i < latLength; i++) {
			minLat /= 2.0;
		}
		minLng = LocationBean.MAXLNG - LocationBean.MINLNG;
		for (int i = 0; i < lngLength; i++) {
			minLng /= 2.0;
		}
	}
	
	/**
	 * @return
	 * @Description: 求所在坐标点及周围点组成的九个
	 */
	public List<String> getGeoHashBase32For9() {
		double leftLat = location.getLat() - minLat;
		double rightLat = location.getLat() + minLat;
		double upLng = location.getLng() - minLng;
		double downLng = location.getLng() + minLng;
		List<String> base32For9 = new ArrayList<String>();
		//左侧从上到下 3个
		String leftUp = getGeoHashBase32(leftLat, upLng);
		if (!(leftUp == null || "".equals(leftUp))) {
			base32For9.add(leftUp);
		}
		String leftMid = getGeoHashBase32(leftLat, location.getLng());
		if (!(leftMid == null || "".equals(leftMid))) {
			base32For9.add(leftMid);
		}
		String leftDown = getGeoHashBase32(leftLat, downLng);
		if (!(leftDown == null || "".equals(leftDown))) {
			base32For9.add(leftDown);
		}
		//中间从上到下 3个
		String midUp = getGeoHashBase32(location.getLat(), upLng);
		if (!(midUp == null || "".equals(midUp))) {
			base32For9.add(midUp);
		}
		String midMid = getGeoHashBase32(location.getLat(), location.getLng());
		if (!(midMid == null || "".equals(midMid))) {
			base32For9.add(midMid);
		}
		String midDown = getGeoHashBase32(location.getLat(), downLng);
		if (!(midDown == null || "".equals(midDown))) {
			base32For9.add(midDown);
		}
		//右侧从上到下 3个
		String rightUp = getGeoHashBase32(rightLat, upLng);
		if (!(rightUp == null || "".equals(rightUp))) {
			base32For9.add(rightUp);
		}
		String rightMid = getGeoHashBase32(rightLat, location.getLng());
		if (!(rightMid == null || "".equals(rightMid))) {
			base32For9.add(rightMid);
		}
		String rightDown = getGeoHashBase32(rightLat, downLng);
		if (!(rightDown == null || "".equals(rightDown))) {
			base32For9.add(rightDown);
		}
		return base32For9;
	}

	/**
	 * @param length
	 * @return
	 * @Description: 设置经纬度转化为geohash长度
	 */
	public boolean sethashLength(int length) {
		if (length < 1) {
			return false;
		}
		hashLength = length;
		latLength = (length * 5) / 2;
		if (length % 2 == 0) {
			lngLength = latLength;
		} else {
			lngLength = latLength + 1;
		}
		setMinLatLng();
		return true;
	}
	
	/**
	 * @return
	 * @Description: 获取经纬度的base32字符串
	 */
	public String getGeoHashBase32() {
		return getGeoHashBase32(location.getLat(), location.getLng());
	}
	
	/**
	 * @param lat
	 * @param lng
	 * @return
	 * @Description: 获取经纬度的base32字符串
	 */
	private String getGeoHashBase32(double lat, double lng) {
		boolean[] bools = getGeoBinary(lat, lng);
		if (bools == null) {
			return null;
		}
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < bools.length; i = i + 5) {
			boolean[] base32 = new boolean[5];
			for (int j = 0; j < 5; j++) {
				base32[j] = bools[i + j];
			}
			char cha = getBase32Char(base32);
			if (' ' == cha) {
				return null;
			}
			sb.append(cha);
		}
		return sb.toString();
	}
	
	/**
	 * @param base32
	 * @return
	 * @Description: 将五位二进制转化为base32
	 */
	private char getBase32Char(boolean[] base32) {
		if (base32 == null || base32.length != 5) {
			return ' ';
		}
		int num = 0;
		for (boolean bool : base32) {
			num <<= 1;
			if (bool) {
				num += 1;
			}
		}
		return CHARS[num % CHARS.length];
	}
	
	/**
	 * @param i
	 * @return
	 * @Description: 将数字转化为二进制字符串
	 */
	private String getBase32BinaryString(int i) {
		if (i < 0 || i > 31) {
			return null;
		}
		String str = Integer.toBinaryString(i + 32);
		return str.substring(1);
	}
	
	/**
	 * @param geoHash
	 * @return
	 * @Description: 将geoHash转化为二进制字符串
	 */
	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();
	}
	
	/**
	 * @param geoHash
	 * @return
	 * @Description: 返回geoHash 对应的坐标
	 */
	public LocationBean getLocation(String geoHash) {
		String geoHashBinaryStr = getGeoHashBinaryString(geoHash);
		if (geoHashBinaryStr == null) {
			return null;
		}
		StringBuffer lat = new StringBuffer();
		StringBuffer lng = new StringBuffer();
		for (int i = 0; i < geoHashBinaryStr.length(); i++) {
			if (i % 2 != 0) {
				lat.append(geoHashBinaryStr.charAt(i));
			} else {
				lng.append(geoHashBinaryStr.charAt(i));
			}
		}
		double latValue = getGeoHashMid(lat.toString(), LocationBean.MINLAT, LocationBean.MAXLAT);
		double lngValue = getGeoHashMid(lng.toString(), LocationBean.MINLNG, LocationBean.MAXLNG);
		LocationBean location = new LocationBean(latValue, lngValue);
		location.setGeohash(geoHash);
		return location;
	}
	
	/**
	 * @param binaryStr
	 * @param min
	 * @param max
	 * @return
	 * @Description: 返回二进制对应的中间值
	 */
	private double getGeoHashMid(String binaryStr, double min, double max) {
		if (binaryStr == null || binaryStr.length() < 1) {
			return (min + max) / 2.0;
		}
		if (binaryStr.charAt(0) == '1') {
			return getGeoHashMid(binaryStr.substring(1), (min + max) / 2.0, max);
		} else {
			return getGeoHashMid(binaryStr.substring(1), min, (min + max) / 2.0);
		}
	}
	
	/**
	 * @param lat
	 * @param lng
	 * @return
	 * @Description: 获取坐标的geo二进制字符串
	 */
	private boolean[] getGeoBinary(double lat, double lng) {
		boolean[] latArray = getHashArray(lat, LocationBean.MINLAT, LocationBean.MAXLAT, latLength);
		boolean[] lngArray = getHashArray(lng, LocationBean.MINLNG, LocationBean.MAXLNG, lngLength);
		return merge(latArray, lngArray);
	}
	
	/**
	 * @param latArray
	 * @param lngArray
	 * @return
	 * @Description: 合并经纬度二进制
	 */
	private boolean[] merge(boolean[] latArray, boolean[] lngArray) {
		if (latArray == null || lngArray == null) {
			return null;
		}
		boolean[] result = new boolean[lngArray.length + latArray.length];
		Arrays.fill(result, false);
		for (int i = 0; i < lngArray.length; i++) {
			result[2 * i] = lngArray[i];
		}
		for (int i = 0; i < latArray.length; i++) {
			result[2 * i + 1] = latArray[i];
		}
		return result;
	}
	
	/**
	 * @param value
	 * @param min
	 * @param max
	 * @return
	 * @Description: 将数字转化为geohash二进制字符串
	 */
	private boolean[] getHashArray(double value, double min, double max, int length) {
		if (value < min || value > max) {
			return null;
		}
		if (length < 1) {
			return null;
		}
		boolean[] result = new boolean[length];
		for (int i = 0; i < length; i++) {
			double mid = (min + max) / 2.0;
			if (value > mid) {
				result[i] = true;
				min = mid;
			} else {
				result[i] = false;
				max = mid;
			}
		}
		return result;
	}
	

	public static void main(String[] args) {
		GeoHash g = new GeoHash();
		//String geoHash = g.getGeoHashBase32();
		//String geoHash = GeoHashUtil.getGeohash(23.155883,113.396009,10);
		String geoHash="ws0eh9k";
		System.out.println(geoHash);
		LocationBean bean = g.getLocation(geoHash);
		System.out.println(JSONObject.fromObject(bean));
		System.out.println(JSONObject.fromObject(bean).get("lng")+","+JSONObject.fromObject(bean).get("lat"));
		System.out.println(new GeoHash(bean.getLat(), bean.getLng()).getGeoHashBase32());
		//System.out.println(g.getGeoHashBase32For9());
		//System.out.println(DistanceUtil.getDistance(bean.getLat(), bean.getLng(), bean.getLat() - g.minLat, bean.getLng() - g.minLng));
		double dis=GpsUtil.getDis(113.449974,23.154875,113.449790,23.154830);
		System.out.println("distance:"+dis);
	}

}

LocationBean实体类

public class LocationBean {

	public static final double MAXLAT = 90.0;

	public static final double MAXLNG = 180.0;

	public static final double MINLAT = -90.0;

	public static final double MINLNG = -180.0;
	private double lat;
	private double lng;
	
	private String geohash;
	
	public double getLng() {
		return lng;
	}
	public void setLng(double lng) {
		this.lng = lng;
	}
	public double getLat() {
		return lat;
	}
	public void setLat(double lat) {
		this.lat = lat;
	}
	
	public String getGeohash() {
		return geohash;
	}
	public void setGeohash(String geohash) {
		this.geohash = geohash;
	}
	public LocationBean(double lat, double lng) {
		super();
		this.lng = lng;
		this.lat = lat;
	}
	@Override
	public String toString() {
		return "LocationBean [lat=" + lat + ", lng=" + lng + "]";
	}
	
	
}

获取四角坐标工具类(可以自己优化,写成通用传值的方法,我还没优化)

//利用二分法算区域四角坐标
	//右边坐标(经度)
	public static double getRightGps(String geohash,double lng,double lat,double f){
		//该中心点水平方向0度方向f距离远的坐标
		String h1=GpsUtil.computerThatLonLat(lng, lat, 90, f);
		double lng1=Double.parseDouble(h1.split(",")[0]);
		System.out.println("lng1:"+lng1);
		double min=lng;
		double max=lng1;
		double mid=0.0;
		String g=null;
		System.out.println("-----开始------");
		int i=0;
		while(min<=max){
			i++;
			System.out.println("i:"+i);
			mid=(min+max)/2;
			g=GeoHashUtil.getGeohash(lat, mid, geohash.length());
			System.out.println("g:"+g);
			if(geohash==g||geohash.equals(g)){
				min=mid;
			}else{
				max=mid;
			}
			System.out.println("方法内mid:"+mid);
			if(i==10){
				break;
			}else{
				continue;
			}
		}
		System.out.println("------结束------");
		return mid;
	}
	//左边坐标(经度)
	public static double getLeftGps(String geohash,double lng,double lat,double f){
		//该中心点水平方向0度方向f距离远的坐标
		String h1=GpsUtil.computerThatLonLat(lng, lat, -90, f);
		double lng1=Double.parseDouble(h1.split(",")[0]);
		System.out.println("lng1:"+lng1);
		double min=lng1;
		double max=lng;
		double mid=0.0;
		String g=null;
		System.out.println("-----开始------");
		int i=0;
		while(min<=max){
			i++;
			System.out.println("i:"+i);
			mid=(min+max)/2;
			g=GeoHashUtil.getGeohash(lat, mid, geohash.length());
			System.out.println("g:"+g);
			if(geohash==g||geohash.equals(g)){
				max=mid;
			}else{
				min=mid;
			}
			System.out.println("方法内mid:"+mid);
			if(i==10){
				break;
			}else{
				continue;
			}
		}
		System.out.println("------结束------");
		return mid;
	}
	//上边坐标(纬度)
	public static double getTopGps(String geohash,double lng,double lat,double f){
		//该中心点水平方向0度方向f距离远的坐标
		String h1=GpsUtil.computerThatLonLat(lng, lat, 0, f);
		double lat1=Double.parseDouble(h1.split(",")[1]);
		System.out.println("lat1:"+lat1);
		double min=lat;
		double max=lat1;
		double mid=0.0;
		String g=null;
		System.out.println("-----开始------");
		int i=0;
		while(min<=max){
			i++;
			System.out.println("i:"+i);
			mid=(min+max)/2;
			g=GeoHashUtil.getGeohash(mid, lng, geohash.length());
			System.out.println("g:"+g);
			if(geohash==g||geohash.equals(g)){
				min=mid;
			}else{
				max=mid;
			}
			System.out.println("方法内mid:"+mid);
			if(i==10){
				break;
			}else{
				continue;
			}
		}
		System.out.println("------结束------");
		return mid;
	}
	//下边坐标(纬度)
	public static double getBottomGps(String geohash,double lng,double lat,double f){
		//该中心点水平方向0度方向f距离远的坐标
		String h1=GpsUtil.computerThatLonLat(lng, lat, 180, f);
		double lat1=Double.parseDouble(h1.split(",")[1]);
		System.out.println("lat1:"+lat1);
		double min=lat1;
		double max=lat;
		double mid=0.0;
		String g=null;
		System.out.println("-----开始------");
		int i=0;
		while(min<=max){
			i++;
			System.out.println("i:"+i);
			mid=(min+max)/2;
			g=GeoHashUtil.getGeohash(mid, lng, geohash.length());
			System.out.println("g:"+g);
			if(geohash==g||geohash.equals(g)){
				max=mid;
			}else{
				min=mid;
			}
			System.out.println("方法内mid:"+mid);
			if(i==10){
				break;
			}else{
				continue;
			}
		}
		System.out.println("------结束------");
		return mid;
	}
	public static Map<String,Double> getAreaGps(double longitude,double latitude){
		//获取geohash
		String geohash=GeoHashUtil.getGeohash(latitude,longitude,7);
		//通过geohash获取该区域中心点坐标
		JSONObject json=GeoGpsUtil.getCenterByGeo(geohash);
		double lng=(double) json.get("lng");
		double lat=(double) json.get("lat");
		double f=GeoGpsUtil.getLengthByGeo(geohash);
		double rightlng=GeoGpsUtil.getRightGps(geohash, lng, lat, f);
		double leftlng=GeoGpsUtil.getLeftGps(geohash, lng, lat, f);
		double toplat=GeoGpsUtil.getTopGps(geohash, lng, lat, f);
		double bottomlat=GeoGpsUtil.getBottomGps(geohash, lng, lat, f);
		Map<String,Double> map=new HashMap<String,Double>();
		map.put("rightlng", rightlng);
		map.put("leftlng", leftlng);
		map.put("toplat", toplat);
		map.put("bottomlat", bottomlat);
		return map;
	}

测试

 Map<String,Double> map=GeoGpsUtil.getAreaGps(113.513381,23.151167);
       System.out.println("map:"+map);
       System.out.println("左下:"+map.get("leftlng")+","+map.get("bottomlat"));
       System.out.println("右下:"+map.get("rightlng")+","+map.get("bottomlat"));
       System.out.println("左上:"+map.get("leftlng")+","+map.get("toplat"));
       System.out.println("右上:"+map.get("rightlng")+","+map.get("toplat"));
发布了21 篇原创文章 · 获赞 4 · 访问量 3万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 书香水墨 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览