PDA

Ver la Versión Completa : Distancia entre dos puntos


DanielMC
13-06-2016, 17:11:15
Saludos a todos
Necesito saber cómo calcular la distancia(km) entre dos puntos especificados por latitud y longitud.

He visto algunos ejemplos en C# y Java, pero nada en C++.
Muchas gracias de antemano..

Casimiro Notevi
13-06-2016, 17:29:19
http://www.clubdelphi.com/foros/showthread.php?t=77870

Neftali [Germán.Estévez]
13-06-2016, 18:31:37
En su momento utilicé esta con bastates buenos resultados.
No es de mi autoría, pero no recuerdo de dónde salió para poner el link. La he tenido que buscar en el código del proyecto.


// distance in meters onto the WGS84 geoid between two Coordinates
// some data are exageretely precise (way beyond GPS's capacity) so I
// added the AlmostNul switch, as arccos(1) returns an error when two points
// are too close (and therefore distance is 0)
function WGS84Distance(plon1, plat1, plon2, plat2: Double;
Almostnul: boolean = False): Double;
var
d, s, c: Double;
lat1: Double;
lon1: Double;
lat2: Double;
lon2: Double;
almost1: Double;
Const
R = 6378137; // Medium earth radius in meter
begin
// d = R x arcos [ sin(lat1) x sin(lat2) + cos(lat1) x cos(lat2) x cos(lon2-lon1) ]
lat1 := DegToRad(plat1);
lon1 := DegToRad(plon1);
lat2 := DegToRad(plat2);
lon2 := DegToRad(plon2);
if (lon1 = lon2) AND (lat1 = lat2) then
d := 0
else begin
s := sin(lat1) * sin(lat2);
c := cos(lat1) * cos(lat2) * cos(lon2 - lon1);

if Almostnul then
almost1 := round((s + c) * 100000000) / 100000000
else
almost1 := (s + c);

if almost1 <> 1 then
d := R * arccos(s + c)
else
d := 0;
end;
Result := d;
end;

DanielMC
13-06-2016, 21:47:30
Gracias a ambos por responder, mirando el enlace que puso el Sr. Casimiro me aclara unas cuantas cosas, pero la solución final la dan en PHP, la cual probé y funciona perfectamente. Lo de restar las longitudes y latitudes, elevarla y luego sacarle la raíz cuadrada, lo probare a ver qué tal su precisión
Alguien pudiera traducir el código que puso el Sr.Neftali a c++!!!.

escafandra
14-06-2016, 00:00:31
Alguien pudiera traducir el código que puso el Sr.Neftali a c++!!!.

Mira a ver si esta traducción a C++ Builder te sirve.

#include <Math.hpp>
#include <Math.h>

double RoundTo(double F, int d=0)
{
double p = pow10(d);
return floor(F*p+0.5)/p;
}

double WGS84Distance(double plon1, double plat1, double plon2, double plat2, BOOL Almostnul = false)
{
double d, s, c;
double lat1, lon1, lat2, lon2, almost1;
int R = 6378137; // Medium earth radius in meter

// d = R x arcos [ sin(lat1) x sin(lat2) + cos(lat1) x cos(lat2) x cos(lon2-lon1) ]
lat1 = DegToRad(plat1);
lon1 = DegToRad(plon1);
lat2 = DegToRad(plat2);
lon2 = DegToRad(plon2);
if (lon1 == lon2 && lat1 == lat2)
d = 0;
else{
s = sin(lat1) * sin(lat2);
c = cos(lat1) * cos(lat2) * cos(lon2 - lon1);

if(Almostnul)
almost1 = RoundTo((s + c) * 100000000) / 100000000;
else
almost1 = (s + c);

if(almost1 !=1)
d = R * ArcCos(s + c);
else
d = 0;
}
return d;
}


Saludos.

Delphius
14-06-2016, 00:55:34
Gracias a ambos por responder, mirando el enlace que puso el Sr. Casimiro me aclara unas cuantas cosas, pero la solución final la dan en PHP, la cual probé y funciona perfectamente. Lo de restar las longitudes y latitudes, elevarla y luego sacarle la raíz cuadrada, lo probare a ver qué tal su precisión
Alguien pudiera traducir el código que puso el Sr.Neftali a c++!!!.
Esto va a funcionar siempre y cuando estés hablando en el sistema euclideano.
La función de la distancia, de nuevo, en el sistema euclideano, no es más que ¡el Teorema de Pitágoras aplicado en dos dimensiones! :D :rolleyes: Ahora bien si vas a hacerlo por esta vía tal función debe ser revisada.
Teóricamente es como dices: Sqrt((x2-x1)^2 + (y2-y1)^2)) pero... en el mundo de las computadoras donde aplica la aritemética de punto flotante las cosas deben encararse un pelín diferente.
Tanto para números pequeños como grandes esa fórmula dará underflow y/o overflow respectivamente. En su lugar se emplea la función Hypot (https://en.wikipedia.org/wiki/Hypot), cuya implementación previene ese problema. Está demás decir que la mayoría de los lenguajes ya cuentan con esta función implementada.

Ahora bien, tengo entendido que lo ideal sería que emplearas el desarrollo por medio de la geometría esférica (una geometría NO euclideana). Desconozco si es que el desarrollo propuesto por Neftali y el que te recomendaron que revises en el link con código en PHP aplica esto.

Lo que si me permito hacer un buen llamado de atención. Existen varios sistemas de coordenadas... tienes las geodésicas (como Gauss Kruger), y las geográficas (Longitud/Latitud). Ahora bien... Hay diferentes sistemas de medición... y de donde ponen el punto de origen... Un sistema pone el 0 en UTM, mientras que otros se manejan con el falso este y falso sur... Es decir no cuentan con S, O. Simplemente tienen N y E.

En diferentes partes del mundo emplean diferentes sistemas. ¡Yo que vos acudo a un agrimensor!

Saludos,

Neftali [Germán.Estévez]
14-06-2016, 09:52:59
Alguien pudiera traducir el código que puso el Sr.Neftali a c++!!!.

Perdón por colocar código Delphi.
Ya me ha pasado más de una vez, que no me fijo en el título del foro.
:o:o

DanielMC
15-06-2016, 16:31:31
El codigo que tradujo escafandra funciona perfectamente, gracias por la ayuda!.
Ahora lo que me preocupa es que he probado el resultado y existe diferencia con respecto a otros calculos.
Por ejemplo utilizando esta formula en excel me da 304.306 km:
=ACOS((SENO(3.1415926*Latitud/180)*SENO(3.1415926*Latitud2/180)+COS(3.1415926*Latitud/180)*COS(3.1415926*Latitud2/180)*COS((Longitud-Longitud2)*3.1415926/180)))*180/3.1415926*1.852*60

con el codigo c++ me da:299.91

escafandra
16-06-2016, 00:01:52
La única diferencia entre los dos cálculos es el radio terrestre. Dado que la Tierra no es una esfera perfecta, según donde te muevas el radio es distinto.

En el método que expuso Neftali se considera el radio medio como R = 6.378.137 metros
En el segundo método R = 6.366,707 Km (180/M_PI*1.852*60)
En general se considera el radio R = 6.371Km.

Si te interesa una traducción a C del método que expones para Excel, esta sería la traducción:

#include <math.h>
double Distancia(double Latitud, double Longitud, double Latitud2, double Longitud2)
{
return acos((sin(M_PI*Latitud/180)*sin(M_PI*Latitud2/180)+cos(M_PI*Latitud/180)*cos(M_PI*Latitud2/180)*cos((Longitud-Longitud2)*M_PI/180)))*180/M_PI*1.852*60;
}




Saludos.

DanielMC
16-06-2016, 14:48:08
Ustedes son lo máximo en este foro!!!, gracias por la ayuda!.