views:

512

answers:

4

I am trying to write something that will determine the distance between to sets of lat/lon coordinates.

I am using the following code which I found on this site:

public static double distance (double lat1, double lon1, double lat2, double lon2) { 
    double lat1 = Convert.ToDouble(latitude);
    double lon1 = Convert.ToDouble(longitude);
    double lat2 = Convert.ToDouble(destlat);
    double lon2 = Convert.ToDouble(destlon);

    double theta = toRadians(lon1-lon2); 
    lat1 = toRadians(lat1); 
    lon1 = toRadians(lon1); 
    lat2 = toRadians(lat2); 
    lon2 = toRadians(lon2); 

    double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta); 
    dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000; 

    return dist; 
} 

My problem is that I am running into the compile error "The name 'toRadians'/'cos'/'sin/'toDegrees' does not exist in the current context..." What am I doing wrong???

+5  A: 

You can write a toRadians function like this:

double ToRadians(double degrees) { return degrees * Math.PI / 180; }

You can write a toDegrees function like this:

double ToDegrees(double radians) { return radians * 180 / Math.PI; }

You should replace sin and cos with Math.Sin and Math.Cos.

SLaks
If you call this function often, create two constants for PI / 180 and 180 / PI if your code is running slow.
mat_geek
+2  A: 

This looks like C#.

First you need to define toRadians and toDegrees:

double toRadians(double degrees) {
    double sign = Math.Sign(degrees);
    while(Math.Abs(degrees) > 360) {
        degrees -= sign * 360;
    }
    return Math.PI * degrees / 180;
}

double toDegrees(double radians) {
    double sign = Math.Sign(radians);
    while(Math.Abs(radians) > 2 * Math.PI) {
        radians -= sign * 2 * Math.PI;
    }
    return 180 * radians / Math.PI;
}

Then, to use the trigonometric functions you need to use Math.Sin, Math.Cos, etc.

double dist = Math.Sin(lat1) * Math.Sin(lat2)
                + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(theta);

and

dist = toDegrees(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000; 

Comments:

public static double distance (double lat1, double lon1, double lat2, double lon2) { 
double lat1 = Convert.ToDouble(latitude);
double lon1 = Convert.ToDouble(longitude);
double lat2 = Convert.ToDouble(destlat);
double lon2 = Convert.ToDouble(destlon);

What is this? Where are latitude, longitude, destlat and destlon defined? Further, it appears you have lat1, lon1 lat2 and lon2 as parameters to this method so that you can not define locals here with the same name.

double theta = toRadians(lon1-lon2); 
lat1 = toRadians(lat1); 
lon1 = toRadians(lon1); 
lat2 = toRadians(lat2); 
lon2 = toRadians(lon2); 

This is bad style. If lat1 represents a latitude in degrees it is far better to compute a radians-equivalent value of lat1 like this:

double lat1Radians = toRadians(lat1);

Thus replace the above with:

double theta = toRadians(lon1-lon2); 
double lat1Radians = toRadians(lat1); 
double lon1Radians = toRadians(lon1); 
double lat2Radians = toRadians(lat2); 
double lon2Radians = toRadians(lon2);

Lastly:

double dist = sin(lat1) * sin(lat2)
                + cos(lat1) * cos(lat2) * cos(theta); 
dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000; 

This is bad style too. The first formula and the second formula can not both possibly represent the distance that you are trying to calculate. You should assign the result of the first formula to a variable with a more meaningful name. As a worst case, at least do the following:

double temp = Math.Sin(lat1) * Math.Sin(lat2)
                + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(theta);
double dist = toDegrees(Math.Acos(dist)) * 60 * 1.1515 * 1.609344 * 1000; 

return dist;
Jason
You probably don't need to limit it to less than 2π.
SLaks
Almost definitely don't need to perform wrapping -- latitude and longitude tend to have decent ranges =)
Mark E
@Jason, you could get away with the while with `double deg = 180 * radians / Mapth.Pi; return (deg % 360) + (deg - Math.Truncate(deg));`
Paulo Santos
@SLaks I believe he wanted to make a generic function.
Paulo Santos
now I get "System.Math' does not contain a definition for 'Pi"
Brodie
never mind it needed to be "PI"
Brodie
@unknown(google): Oops. Sorry about that. I wrote the code here and not in an IDE.
Jason
now it's putting out the distance as "-0.156050990122983"Any ideas??
Brodie
+1  A: 

You're going to need to adapt this code a bit.

As SLaks, says, you will need to define your own toRadians() method because .NET does not have a native version.

You will also need to change the calls to cos() and sin() to be: Math.Cos() and Math.Sin()

LBushkin
+1  A: 

You may want to use the following C# class:

public static class GeoCodeCalc
{
    public const double EarthRadiusInMiles = 3956.0;
    public const double EarthRadiusInKilometers = 6367.0;

    public static double ToRadian(double val) { return val * (Math.PI / 180); }
    public static double DiffRadian(double val1, double val2) { return ToRadian(val2) - ToRadian(val1); }

    public static double CalcDistance(double lat1, double lng1, double lat2, double lng2) 
    {
        return CalcDistance(lat1, lng1, lat2, lng2, GeoCodeCalcMeasurement.Miles);
    }

    public static double CalcDistance(double lat1, double lng1, double lat2, double lng2, GeoCodeCalcMeasurement m) 
    {
        double radius = GeoCodeCalc.EarthRadiusInMiles;

        if (m == GeoCodeCalcMeasurement.Kilometers) { radius = GeoCodeCalc.EarthRadiusInKilometers; }
        return radius * 2 * Math.Asin( Math.Min(1, Math.Sqrt( ( Math.Pow(Math.Sin((DiffRadian(lat1, lat2)) / 2.0), 2.0) + Math.Cos(ToRadian(lat1)) * Math.Cos(ToRadian(lat2)) * Math.Pow(Math.Sin((DiffRadian(lng1, lng2)) / 2.0), 2.0) ) ) ) );
    }
}

public enum GeoCodeCalcMeasurement : int
{
    Miles = 0,
    Kilometers = 1
}

Usage:

// Calculate Distance in Miles
GeoCodeCalc.CalcDistance(47.8131545175277, -122.783203125, 42.0982224111897, -87.890625);

// Calculate Distance in Kilometers
GeoCodeCalc.CalcDistance(47.8131545175277, -122.783203125, 42.0982224111897, -87.890625, GeoCodeCalcMeasurement.Kilometers);

Source: Chris Pietschmann - Calculate Distance Between Geocodes in C# and JavaScript

Daniel Vassallo