2010-01-06 11 views
10

Estoy tratando de escribir algo que determine la distancia entre conjuntos de coordenadas lat/lon.¿Cómo puedo determinar la distancia entre dos conjuntos de coordenadas de latitud/longitud?

estoy usando el siguiente código que encontré en 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; 
} 

Mi problema es que estoy corriendo en el error de compilación "El nombre 'toRadians'// 'pecado /' 'cos' toDegrees 'no existe en el contexto actual ... " ¿Qué estoy haciendo mal?

+0

Probablemente esté usando C#. – SLaks

+2

¿Por qué llamas a 'Convert.ToDouble' en un' doble'? – SLaks

+0

@SLaks: De acuerdo, acabo de notar el 'Convert.ToDouble'. – jason

Respuesta

24

Es posible que desee utilizar la siguiente clase C#:

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 
} 

Uso:

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

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

5

Usted puede escribir una función toRadians así:

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

Usted puede escribir una función toDegrees así:

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

Debe reemplazar sin y cos con Math.Sin y Math.Cos.

+0

Si llama a esta función con frecuencia, cree dos constantes para PI/180 y 180/PI si su código se está ejecutando lentamente. –

2

Esto se parece a C#.

En primer lugar debe definir toRadians y 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; 
} 

A continuación, utilizar las funciones trigonométricas que necesita para utilizar Math.Sin, Math.Cos, etc.

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

y

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

Comentarios:

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

¿Qué es? ¿Dónde se definen latitude, longitude, destlat y destlon definidos? Además, parece que tiene lat1, lon1lat2 y lon2 como parámetros de este método, por lo que no puede definir locales aquí con el mismo nombre.

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

Esto es un mal estilo. Si lat1 representa una latitud en grados, es mucho mejor para calcular un valor radianes equivalente de lat1 así:

double lat1Radians = toRadians(lat1); 

Así remover lo anterior con:

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

Por último:

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

Esto también es un mal estilo. La primera y la segunda fórmula no pueden representar la distancia que estás tratando de calcular. Debe asignar el resultado de la primera fórmula a una variable con un nombre más significativo.En el peor de los casos, al menos haga lo siguiente:

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; 
+0

Probablemente no necesite limitarlo a menos de 2π. – SLaks

+0

Casi definitivamente no es necesario realizar la envoltura - la latitud y la longitud tienden a tener rangos decentes =) –

+0

@Jason, podría salirse con la suya con 'doble deg = 180 * radianes/Mapth.Pi; return (deg% 360) + (deg - Math.Truncate (deg)); ' –

0

Necesitará adaptar este código un poco.

Como dice SLaks, tendrá que definir su propio método toRadians() porque .NET no tiene una versión nativa.

También tendrá que cambiar las llamadas a cos() y sin() a ser: Math.cos() y Math.sin()

2

sé esta búsqueda ion es muy viejo, pero en caso de que alguien se tropieza otra persona a través de esto, el uso de GeoCoordinateSystem.Device:

var distanceInMeters = new GeoCoordinate(lat1, lon1) 
    .GetDistanceTo(new GeoCoordinate(lat2, lon2)); 
1

calcular la distancia entre los puntos de latitud y longitud, sino ...

doble Lat1 = Convert.ToDouble (latitud);

double Long1 = Convert.ToDouble(longitude); 

    double Lat2 = 30.678; 
    double Long2 = 45.786; 
    double circumference = 40000.0; // Earth's circumference at the equator in km 
    double distance = 0.0; 
    double latitude1Rad = DegreesToRadians(Lat1); 
    double latititude2Rad = DegreesToRadians(Lat2); 
    double longitude1Rad = DegreesToRadians(Long1); 
    double longitude2Rad = DegreesToRadians(Long2); 
    double logitudeDiff = Math.Abs(longitude1Rad - longitude2Rad); 
    if (logitudeDiff > Math.PI) 
    { 
     logitudeDiff = 2.0 * Math.PI - logitudeDiff; 
    } 
    double angleCalculation = 
     Math.Acos(
      Math.Sin(latititude2Rad) * Math.Sin(latitude1Rad) + 
      Math.Cos(latititude2Rad) * Math.Cos(latitude1Rad) * Math.Cos(logitudeDiff)); 
    distance = circumference * angleCalculation/(2.0 * Math.PI); 
    return distance; 
Cuestiones relacionadas