intelligent calculating distance between two geo locations in android

473 views Asked by At

Look at this example:

public void start(){

    //...

    locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, TEN_SECONDS, TEN_METERS, this);
}


@Override
public void onLocationChanged(Location location) {

    if(location.distanceTo(_lastLocation) > TEN_KM_IN_METERS){
        actionA(location);
       _lastLocation = location;
    } else {
        actionB(location);
    }

}

The implementation of Location#distanceTo(l) is pretty complicated and CPU-intensive. So i don't want to call this operation on every location update.

Question: is it any proper way to avoid unnecessary Location#distanceTo(l) calls

What i tried so far. According Wiki - Decimal degrees i do it that way:

private boolean closeTogether(Location a, Location b) {

    double changeLat = Math.abs(a.getLatitude() - b.getLatitude());

    final float myNaiveMax = 0.005;

    if (changeLat > myNaiveMax) {
        return false;
    }

    double changeLon = Math.abs(a.getLongitude() - b.getLongitude());

    if (changeLon > myNaiveMax) {
        return false;
    }

    return true;
}

@Override
public void onLocationChanged(Location location) {

    if(!closeTogether(location, _lastLocation) && location.distanceTo(_lastLocation) > TEN_KM_IN_METERS){
        actionA(location);
       _lastLocation = location;
    } else {
        actionB(location);
    }

}
1

There are 1 answers

0
laminatefish On

I've found that the Haversine formula is very good for this. Works well for my delivery tracking application. Here's how I calculate the distance between two points. Should get you started :)

/**
 * getDistanceBetweenTwoPoints
 * @param p1 - First point
 * @param p2 - Second point
 * @return distance between the two specified points (as the crow flys)
 */
public static double getDistanceBetweenTwoPoints(PointF p1, PointF p2) {
    double R = 6371000; // Earth radius
    double dLat = Math.toRadians(p2.x - p1.x);
    double dLon = Math.toRadians(p2.y - p1.y);
    double lat1 = Math.toRadians(p1.x);
    double lat2 = Math.toRadians(p2.x);

    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2)
            * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double d = R * c;

    return d;
}

Edit And another

public static PointF calculateDerivedPosition(PointF point,
        double range, double bearing)
{
    double EarthRadius = 6371000; // m

    double latA = Math.toRadians(point.x);
    double lonA = Math.toRadians(point.y);
    double angularDistance = range / EarthRadius;
    double trueCourse = Math.toRadians(bearing);

    double lat = Math.asin(Math.sin(latA) * Math.cos(angularDistance) +
            Math.cos(latA) * Math.sin(angularDistance) * Math.cos(trueCourse));

    double dlon = Math.atan2(Math.sin(trueCourse) * Math.sin(angularDistance) * Math.cos(latA),
            Math.cos(angularDistance) - Math.sin(latA) * Math.sin(lat));

    double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;

    lat = Math.toDegrees(lat);
    lon = Math.toDegrees(lon);

    PointF newPoint = new PointF((float) lat, (float) lon);

    return newPoint;

}