`

根据经纬度查询附近的点

 
阅读更多
大致思想:根据给定经纬度(lat,lng)求出其左上角(left_top),右上角(right_top),左下角(left_bottom),右下角(right_bottom)的四个位置。所有在这个区域的范围都在该点附近。
参照:http://blog.charlee.li/location-search/

java代码:
package com.show.common.util;

public class Location {
	private double latitude;
	private double longitude;

	public Location(double latitude, double longitude) {
		this.latitude = latitude;
		this.longitude = longitude;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

}

package com.show.common.util;

public class LatitudeLontitudeUtil {

	// http://blog.charlee.li/location-search/

	/** 地球半径 */
	private static final double EARTH_RADIUS = 6371000;
	/** 范围距离 */
	private double distance;
	/** 左上角 */
	private Location left_top = null;
	/** 右上角 */
	private Location right_top = null;
	/** 左下角 */
	private Location left_bottom = null;
	/** 右下角 */
	private Location right_bottom = null;

	private LatitudeLontitudeUtil(double distance) {
		this.distance = distance;
	}

	private void getRectangle4Point(double lat, double lng) {

		// float dlng = 2 * asin(sin(distance / (2 * EARTH_RADIUS)) / cos(lat));
		// float dlng = degrees(dlng) // 弧度转换成角度
		double dlng = 2 * Math.asin(Math.sin(distance / (2 * EARTH_RADIUS))
				/ Math.cos(lat));
		dlng = Math.toDegrees(dlng);

		// dlat = distance / EARTH_RADIUS
		// dlng = degrees(dlat) # 弧度转换成角度
		double dlat = distance / EARTH_RADIUS;
		dlat = Math.toDegrees(dlat); // # 弧度转换成角度

		// left-top : (lat + dlat, lng - dlng)
		// right-top : (lat + dlat, lng + dlng)
		// left-bottom : (lat - dlat, lng - dlng)
		// right-bottom: (lat - dlat, lng + dlng)
		left_top = new Location(lat + dlat, lng - dlng);
		right_top = new Location(lat + dlat, lng + dlng);
		left_bottom = new Location(lat - dlat, lng - dlng);
		right_bottom = new Location(lat - dlat, lng + dlng);

	}

	public static double hav(double theta) {
		double s = Math.sin(theta / 2);
		return s * s;
	}

	public static double getDistance(double lat0, double lng0, double lat1,
			double lng1) {
		// from math import sin, asin, cos, radians, fabs, sqrt

		// def hav(theta):
		// s = sin(theta / 2)
		// return s * s

		// def get_distance_hav(lat0, lng0, lat1, lng1):
		// "用haversine公式计算球面两点间的距离。"
		// # 经纬度转换成弧度
		// lat0 = radians(lat0)
		// lat1 = radians(lat1)
		// lng0 = radians(lng0)
		// lng1 = radians(lng1)

		// dlng = fabs(lng0 - lng1)
		// dlat = fabs(lat0 - lat1)
		// h = hav(dlat) + cos(lat0) * cos(lat1) * hav(dlng)
		// distance = 2 * EARTH_RADIUS * asin(sqrt(h))

		// return distance
		lat0 = Math.toRadians(lat0);
		lat1 = Math.toRadians(lat1);
		lng0 = Math.toRadians(lng0);
		lng1 = Math.toRadians(lng1);

		double dlng = Math.abs(lng0 - lng1);
		double dlat = Math.abs(lat0 - lat1);
		double h = hav(dlat) + Math.cos(lat0) * Math.cos(lat1) * hav(dlng);
		double distance = 2 * EARTH_RADIUS * Math.asin(Math.sqrt(h));

		return distance;
	}

	public static Location[] getRectangle4Point(double lat, double lng,
			double distance) {
		LatitudeLontitudeUtil llu = new LatitudeLontitudeUtil(distance);
		llu.getRectangle4Point(lat, lng);
		Location[] locations = new Location[4];
		locations[0] = llu.left_top;
		locations[1] = llu.right_top;
		locations[2] = llu.left_bottom;
		locations[3] = llu.right_bottom;
		return locations;
	}

	public static void main(String[] args) {
		double lat = 30.500;
		double lng = 120.500;
		double distance = 500d;
		Location[] locations = LatitudeLontitudeUtil.getRectangle4Point(lat,
				lng, distance);
		String sql = "SELECT * FROM place WHERE lat > "
				+ locations[2].getLatitude() + " AND lat < "
				+ locations[0].getLatitude() + " AND lng > "
				+ locations[0].getLongitude() + " AND lng < "
				+ locations[1].getLongitude();
		System.out.println(sql);

		double lat1 = 30.495503391970406;
		double lng1 = 120.49261708577215;
		double d = LatitudeLontitudeUtil.getDistance(lat, lng, lat1, lng1);
		System.out.println(d);
	}
}
分享到:
评论
2 楼 dongbiying 2014-09-11  
我找到原因啦。。。

// float dlng = 2 * asin(sin(distance / (2 * EARTH_RADIUS)) / cos(lat)); 
// float dlng = degrees(dlng) // 弧度转换成角度 
        double dlng = 2 * Math.asin(Math.sin(distance / (2 * EARTH_RADIUS)) 
                / Math.cos(lat)); 
        dlng = Math.toDegrees(dlng);

这里的公式有误!

应该是这样的:


// $dlng =  2 * asin(
// sin($distance / (2 * EARTH_RADIUS))
// /
// cos(deg2rad($lat))
// );
// $dlng = rad2deg($dlng);//转换弧度

double dlng = 2 * Math.asin(Math.sin(distance/(2*EARTH_RADIUS))/Math.cos(Math.toRadians(lat)));
dlng = Math.toDegrees(dlng);
1 楼 dongbiying 2014-09-11  
请问楼主。我现在传的值是
double lat = 39.905529;
double lng = 116.475395;
这时
double dlng = 2 * Math.asin(Math.sin(distance / (2 * EARTH_RADIUS))
/ Math.cos(lat));
dlng = Math.toDegrees(dlng);
最后 dlng 为负值

最后导致

SELECT * FROM F_LOCATION WHERE lat > 39.90103239197041 AND lat < 39.91002560802959 AND lng > 116.48296916308891 AND lng < 116.4678208369111

肯定不会有结果集的呀!

请问怎么解呀。。。

相关推荐

Global site tag (gtag.js) - Google Analytics