Find geopoints in a radius near me

2019-06-12 10:47发布

问题:

I have a DB with Geopoints. I need to do a query to get all geopoints in the radius of X meters of me.

How can i do this?

I think the best way is get the minimal lat/long possible point, and the max lat/long point and get all of them for which: geopoint > minPoint AND geopoint < MaxPoint

Other ideas?

回答1:

You can use this class to get de distance between to points:

How to use:

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

Or, if point1 and point2 are GeoPoint:

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

You can also calculate a Geopoint that is a distance of you and along a bearing.

This computes a point that is 5 km northward from point1:

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

You can calculate the other points at 90 degrees, 180 degrees and 270 degrees to calculate minPoint AND MaxPoint.

GeoMath class:

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);
    }

}


回答2:

With your query I think that you will find all points inside a square centered at your location and with a side length X.

After that, yuo can get all the points that are inside a circle centered at your location with radius X.

What about this pseudo code:

//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
    }


回答3:

With Mysql, you can use built-in spacial functions such as GLength, linestring ....