查找我附近半径内的地理位置

时间:2014-01-11 11:02:42

标签: android geopoints

我有一个带Geopoints的数据库。 我需要进行查询以获得半径为X米的所有地理点。

我该怎么做?

我认为最好的方法是获得最小纬度/长度可能点,最大纬度/长点并得到所有这些点:geopoint > minPoint AND geopoint < MaxPoint

其他想法?

3 个答案:

答案 0 :(得分:2)

您可以使用此类来获得点之间的距离:

使用方法:

double distInKm = GeoMath.getDistance(12.345, -8.788, 12.33, -8.77);  

或者,如果point1和point2是GeoPoint:

double distInKm = GeoMath.getDistance(point1, point2);  

您还可以计算一个Geopoint,它是您和轴承之间的距离。

这计算从point1向北5公里的点:

GeoPoint northPointAt5 = GeoMath.getGeoPointAlongBearing(point1, 0, 5);

您可以计算90度,180度和270度的其他点来计算minPoint和MaxPoint。

GeoMath类:

public class GeoMath {

    public static final int EARTH_MEAN_RADIUS = 6371; // earth's mean radius in Km

    public static double getDistance(double startLatitude, double startLongitude,
                                     double endLatitude, double endLongitude){

        return distHaversine(startLatitude,startLongitude,endLatitude,endLongitude);
    }

    public static double getDistance(GeoPoint point1, GeoPoint point2){

        return distHaversine(point1.getLatitudeE6()/1E6, point1.getLongitudeE6()/1E6,
                             point2.getLatitudeE6()/1E6, point2.getLongitudeE6()/1E6);
    }

    private static double getSpanInRadians(double max, double min){

        return Math.toRadians(max - min);
    }

    //Distance in Km between point1 (lat1,lon1) and point2 (lat2,lon2) Haversine formula
    private static double distHaversine(double lat1, double lon1, double lat2, double lon2) {

        double dLat = getSpanInRadians(lat2,lat1);
        double dLon = getSpanInRadians(lon2,lon1);
        lat1 = Math.toRadians(lat1);
        lat2 = Math.toRadians(lat2);
        double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
        Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon/2) * Math.sin(dLon/2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
        double dist = EARTH_MEAN_RADIUS * c;
        return Math.round(dist * 1000)/1000; //3 decimal places
    }

    // Get GeoPoint at distance along a bearing
    // bearing in degrees
    // distance in Km
    public static GeoPoint getGeoPointAlongBearing(GeoPoint location, double bearing, double distance){

        double PI = Math.PI;
        double NM = 1.852; //1 nm = 1.852 Km -> nm = Km/NM

        GeoPoint geoPointAlongBearing;

        double locationLatRad = Math.toRadians(location.getLatitudeE6()/1E6);
        double locationLongRad = Math.toRadians(location.getLongitudeE6()/1E6)*(-1.0d);

        double distanceRad = distance/NM * PI/(180*60);

        double bearingRad = Math.toRadians(bearing);

        double latAlongBearingRad = Math.asin(Math.sin(locationLatRad) * 
                                    Math.cos(distanceRad) +
                                    Math.cos(locationLatRad) *
                                    Math.sin(distanceRad) * 
                                    Math.cos(bearingRad));

        double lonAlongBearingRad = mod(locationLongRad - 
                                    Math.asin(Math.sin(bearingRad) * 
                                    Math.sin(distanceRad) / 
                                    Math.cos(latAlongBearingRad)) + PI, 2 * PI) - PI;

        double latAlongBearing = rad2lat(latAlongBearingRad);
        double lonAlongBearing = rad2lng(lonAlongBearingRad) * (-1);

        geoPointAlongBearing = new GeoPoint((int)(latAlongBearing*1E6),(int)(lonAlongBearing*1E6));
        return geoPointAlongBearing;
    }

    private static double mod(double y, double x) {

        return y - x * Math.floor(y/x);
    }

}

答案 1 :(得分:0)

根据您的查询,我认为您会找到位于您所在位置且边长为X的正方形内的所有点。

之后,yuo可以获得以半径X为中心的圆圈内的所有点。

这个伪代码怎么样:

//create your location
Location yourLocation=new Location("myLoc");
double latitude = geoPointYourLocation.getLatitudeE6() / 1E6;
double longitude = geoPointYourLocation.getLongitudeE6() / 1E6;
yourLocation.setLatitude(latitude);
yourLocation.setLongitude(longitude);
//Browse geopoints from DB, convert to GeoPoint and check if it is at a distance less     than X
for (geoPointTemp in in query geopoint of your DDBB inside square) {
    //create the location of the geopoint
    Location locTemp=new Location("locTemp");
    double latitude = geoPointTemp.getLatitudeE6() / 1E6;
    double longitude = geoPointTemp.getLongitudeE6() / 1E6;
    locTemp.setLatitude(latitude);
    locTemp.setLongitude(longitude);
    //calculate the distance between you and de temporary location
    double distance=yourLocation.distanceTo(locTemp);
    if(distance<X){
        //do something
    }

答案 2 :(得分:0)

使用Mysql,您可以使用内置的空间函数,例如GLength,linestring ....