0

I am calculating the Distance between two Latitudes and Longitudes. I get the results for some distances but sometimes,I get the results as NAN.

This is the Latitude and Longitude which I have got for 2 places.

For eg: 38.655553,-121.091611

38.654875,-121.091324

I am using the below code to calculate the distance with reference to the below link

Calculating distance between two geographic locations

public static double distanceBetween (double currentLat2, double currentLong2, double mallLat2, double mallLong2)
{
     float pk = (float) (180/3.14169);

        double a1 = currentLat2 / pk;
        double a2 = currentLong2 / pk;
        double b1 = mallLat2 / pk;
        double b2 = mallLong2 / pk;

        double t1 = FloatMath.cos((float) a1)*FloatMath.cos((float) a2)*FloatMath.cos((float) b1)*FloatMath.cos((float) b2);
        double t2 = FloatMath.cos((float) a1)*FloatMath.sin((float) a2)*FloatMath.cos((float) b1)*FloatMath.sin((float) b2);
        double t3 = FloatMath.sin((float) a1)*FloatMath.sin((float) b1);
        double tt = Math.acos(t1 + t2 + t3);

       return 6366000*tt;               
}

Any Help?

Thanks.

Community
  • 1
  • 1
DevAndro
  • 205
  • 1
  • 6
  • 18

3 Answers3

1

the doc for Location.distanceTo(LOcation) says:

Returns the approximate distance in meters between this location and the given location. Distance is defined using the WGS84 ellipsoid.

So you can try this way:

public static float distanceBetween (double currentLat2, double currentLong2, double mallLat2, double mallLong2) {
        Location loc1 = new Location("");
        loc1.setLatitude(currentLat2);
        loc1.setLongitude(currentLong2);

        Location loc2 = new Location("");
        loc2.setLatitude(mallLat2);
        loc2.setLongitude(mallLong2);

        return loc1.distanceTo(loc2);
}
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
1

MathFloat together with float casts is the cause of your problem.

I rewrote, now it works, it gives 79.34m

But the main problem is that you use the wrong formula for this task, you use here the greater circle distance formula with law of cosines, which is well know to be "ill conditioned" for floating point arithmetic. Then to make it even worse, you use that with single precision only, instead of double.

The more robust formula is the haversine formula. It was designed to overcome the disadvantage of the greater circle formula.

Here your original code fixed, (but i still recommend use the haversine formula instead)

public void test1() {

    // 79.34253285803419
    double lat1 = 38.655553;
    double lon1 = -121.091611;

    double lat2 = 38.654875;
    double lon2 = -121.091324;

    System.out.println(distanceBetween(lat1,  lon1,  lat2,  lon2));
}

public static double distanceBetween (double currentLat2, double currentLong2, double mallLat2, double mallLong2)
{
        double pk = 180 / Math.PI;
        double a1 = currentLat2 / pk;
        double a2 = currentLong2 / pk;
        double b1 = mallLat2 / pk;
        double b2 = mallLong2 / pk;

        double t1 = Math.cos( a1) * Math.cos(a2) * Math.cos(b1) * Math.cos(b2);
        double t2 = Math.cos( a1) * Math.sin(a2) * Math.cos(b1) * Math.sin(b2);
        double t3 = Math.sin( a1) * Math.sin(b1);
        double tt = Math.acos(t1 + t2 + t3);

       return 6366000*tt;
}
AlexWien
  • 28,470
  • 6
  • 53
  • 83
0

Can you log the outputs for t1, t2, t3? I have a feeling that the argument for Math.acos() is out of range. Also not sure why you're needlessly casting to float and back to double when you can just use Math.sin and Math.cos.

Edit

Use Math.PI instead of 3.14169. This approximation is causing your error.

Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
  • below are the details: t1: 0.043878812342882156 t2: 0.0023341665510088205 t3: 0.9537870287895203 dist: NaN – DevAndro Apr 23 '13 at 13:12
  • And those add up to 1.0000000076834112765, so you're passing a number greater than 1 to `Math.acos`, when the domain is [-1, 1]. See my edit above. – Michael Zajac Apr 23 '13 at 13:34