|
||
|
![]() |
![]() |
Tasker Para hablar de todo lo relacionado con la aplicación tasker |
![]() |
|
Herramientas |
#1
|
||||
|
||||
Calcular la distancia entre dos coordenadas
Comenté en este tema lo de medir la distancia entre dos coordenadas geodésicas y luego se me pasó explicar cuál era la forma menos incorrecta de hacerlo ... mil disculpas
![]() Vamos al tema ... ![]() Calcular la distancia en línea recta ente dos puntos es relativamente sencillo ... Se aplica el "Teorema de Pitágoras" (aquello de H^2=A^2+B^2) teniendo en cuenta lo siguiente: H es la distancia que nos interesa A es la diferencia entre las coordenadas X de los puntos (o las Y) B es la diferencia entre las coordenadas Y de los puntos (o las X) Creo que la siguiente imagen lo explica visualmente bastante bien ... Y se considera como buena la equivalencia entre grados y kilómetros de 111,12 km/gr. Una vez calculado el valor de H se multiplica por 111,12 y tenemos la distancia en Km ... lo dicho, sencillo. ![]() Pues resulta que esto, tan fácil de entender y trasladar a Tasker, no nos vale para calcular la distancia entre dos puntos "sobre la superficie de la tierra" porque no tiene en cuenta que la tierra es "casi" redonda ![]() A muy cortas distancias el error no será demasiado significativo, pero a medida que nos alejemos del ecuador y/o la distancia entre los puntos aumente, el error puede llegar a ser considerable. Para calcular la distancia más corta ente dos puntos de la superficie de un cuerpo esférico (la ortodrómica) se tiene que usar la "Trigonometría Esférica", considerablemente más farragosa de manejar que el Teorema de Pitágoras. Existen varios procedimientos para calcular esa distancia ortodrómica, cada uno con precisiones y complejidades diferentes. Parece ser que los tres más utilizados son: "Teorema del Coseno", "Fórmula de Haversine" y "Fórmulas de Vincenty" (este es para caerse de culo ![]() Después de dar unas pocas vueltas al tema he descartado el sistema de Vincenty por su complejidad y la poca diferencia de precisión con el de Haversine. Y he dejado aparcado el de Haversine un poco forzado también por una pequeña limitación que me he encontrado en Tasker a la hora de hacer cálculos con muchos decimales. Aunque la librería de soporte matemático que usa Tasker (http://softwaremonkey.org/Code/MathEval) parece que puede manejar con soltura número grandes y pequeños los resultados que Tasker proporciona al usuario siempre tienen un máximo de tres decimales, y eso es una faena en este caso porque los sistemas más precisos necesitan varios pasos intermedios en los que perder decimales afecta al resultado. ![]() El sistema de los cosenos es relativamente fácil de implementar en una única fórmula de manera que no sea necesario hacer pasos intermedios y de esa forma evitar las limitaciones matemáticas de Tasker. Creo que también sería posible hacerlo en una única fórmula con el sistema de Haversine, pero no me he entretenido en ello. ![]() En definitiva, y como no se trata de colar un ICBM por la ventana de nadie, me parece que la relación dificultad/precisión del teorema del coseno es muy buena (a pesar de ser el sistema menos preciso de los tres estudiados) y algo mejor que con el teorema de pitágoras. Esta es la fórmula resultante después de desarrollar el teorema del coseno ... Distancia (A, B) = R * arccos (sen (LatA) * sen (LatB) + cos (LatA) * cos (LatB) * cos (LonA-LonB))A y B son los dos puntos en cuestión definidos por sus coordenadas geodésicas (latitud/longitud) que son justo del tipo de las que nos proporciona Android. LatA y LatB son las latitudes. LonA y LonB son las longitudes. Las funciones trigonométricas* no tienen misterio. Y el valor R es el radio de la tierra ... y aquí viene otro dolor de cabeza :-( * Las funciones trigonométricas de Tasker necesitan los ángulos en radianes. Eso no es un problema porque la librería matemática de Tasker dispone de todo lo necesario para hacer una conversión precisa. Resulta que aunque la tierra es "casi" redonda no es una esfera, es un geoide. Tomar este detalle en cuenta añade un nivel de complejidad del que todo el mundo escapa como de la peste, así que se toma como aproximación un esferoide oblato (achatado en el eje vertical), que como todo esferoide que se precie tiene un radio menor y otro mayor. Vale ... ¿y cuánto miden esos radios en el caso de la tierra? ... pues resulta que nuestro sistema de coordenadas usa como DATUM (el modelo matemático de la superficie de la tierra) el WGS84 (el del GPS), y en ese modelo el esferoide que define la tierra tiene un radio mayor de 6.378,137 Km y un radio menor de 6.356,752 Km. Vale ... ¿y cuál cogemos? ... pues la media, pero no cualquier media, lo correcto es coger la media cuadrática que es la que mejor tiene en cuenta la forma exacta de ese dichoso esferoide. En definitiva, el radio medio cuadrático de la tierra es de 6.372,795477598 Km ... toma ya. ![]() Y llegados a este punto (para qué me meteré yo en estos charcos ![]() Esta tarea espera las coordenadas en %par1 y %par2 y nos devolverá un resultado en metros en la variable que le pongamos. Aquí está la tarea ... Código:
DistLatLon (666) A1: Devolver [ Valor:ERROR Detener:Encendido ] Si (if) [ %par1 No ajust. | %par2 No ajust. ] A2: Establecer variable [ Nombre:%radio A:6372795.477598 ] A3: Separar variable [ Nombre:%par1 Separador:, ] A4: Separar variable [ Nombre:%par2 Separador:, ] A5: Establecer variable [ Nombre:%dist A:%radio * acos( sin(torad(%par11)) * sin(torad(%par21)) + cos(torad(%par11)) * cos(torad(%par21)) * cos(torad(%par12-%par22)) ) Calcular:Encendido ] A6: Devolver [ Valor:%dist Detener:Encendido ] ![]() Última edición por WillyWeb Día 09/06/15 a las 11:35:08. Razón: Corrección de errores tipográficos |
Los siguientes 7 usuarios han agradecido a WillyWeb su comentario: | ||
|
#2
|
||||
|
||||
Versión del "Teorema del Coseno" en JavaScript
De los tres sistemas propuestos me decidí por el "Teorema del Coseno" por su simplicidad y porque se podía implementar en una sola ecuación que evita la pequeña limitación en el manejo de los decimales que encontré en la librería matemática de Tasker.
La tarea que propuse hace uso exclusivamente de acciones de Tasker. Esta otra hace exactamente lo mismo pero usando JavaScript... Código:
DistLatLonJS (777) A1: Devolver [ Valor:ERROR Detener:Encendido ] Si (if) [ %par1 No ajust. | %par2 No ajust. ] A2: JavaScriptlet [ Código:pos1=par[0].split(","); pos2=par[1].split(","); radio=6372795.77598; gra2rad=Math.PI/180; lata=pos1[0]*gra2rad; lona=pos1[1]*gra2rad; latb=pos2[0]*gra2rad; lonb=pos2[1]*gra2rad; lond=lona-lonb; dist=radio * Math.acos(Math.sin(lata) * Math.sin(latb) + Math.cos(lata) * Math.cos(latb) * Math.cos(lond)); var dist=dist.toFixed(3);Librerías: Salida Automática:Encendido Cuenta atrás (segundos):1 ] A3: Devolver [ Valor:%dist Detener:Encendido ] Lo malo de este sistema... esta tarea es considerablemente más lenta que su equivalente con acciones de Tasker. Hasta la próxima ... ![]() |
Los siguientes 2 usuarios han agradecido a WillyWeb su comentario: | ||
#3
|
||||
|
||||
Versión de la "Fórmula de Haversine" en JavaScript
Aquí está la tarea para calcular la distancia entre dos coordenadas usando la "Fórmula de Haversine". He usado JavaScript porque no es posible implementarla directamente en Tasker ya que su librería matemática no tiene la función trigonométrica "atan2".
Código:
DistHaversine (333) A1: Devolver [ Valor:ERROR Detener:Encendido ] Si (if) [ %par1 No ajust. | %par2 No ajust. ] A2: JavaScriptlet [ Código:pos1=par[0].split(","); pos2=par[1].split(","); radio=6371000; gra2rad=Math.PI/180; lat1=pos1[0]*gra2rad; lat2=pos2[0]*gra2rad; latd=(pos2[0]-pos1[0])*gra2rad; lond=(pos2[1]-pos1[1])*gra2rad; a = Math.sin(latd/2) * Math.sin(latd/2) + Math.cos(lat1) * Math.cos(lat2) * Math.sin(lond/2) * Math.sin(lond/2); c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); d = radio * c; var dist=d.toFixed(3);Librerías: Salida Automática:Encendido Cuenta atrás (segundos):1 ] A3: Devolver [ Valor:%dist Detener:Encendido ] Nota: En esta ecuación se usa un radio terrestres de 6.371 Km. Curiosamente si se sustituye este valor por el radio medio cuadrático (6.372,795477598 Km) que propuse para el "Teorema del Coseno" los resultados son casi iguales. ![]() Por lo que he visto los resultados con las "Fórmulas de Vincenty" difieren muy poco de los que se obtienen con la "Fórmula de Harversine", en cambio la complejidad del algoritmo es mucho mayor y el esfuerzo de adaptarla a Tasker/JavaScript no merece la pena, así que aquí me planto. ![]() Hasta otra ... ![]() |
Los siguientes 2 usuarios han agradecido a WillyWeb su comentario: | ||
#4
|
||||
|
||||
Aunque el hilo es de hace meses, no lo había visto hasta ahora.
Fantástico trabajo. Gracias. Perplejo estoy por ese dominio de las matemáticas. Con dificultades, mi uso de Tasker había llegado hasta Pitágoras, no más. Nunca se me ocurrió plantearme lo de la esfera. Excelente cuestión, y muy bien resuelta.
__________________
Firmado: Caravantes, miembro del equipo que promueve el Subforo de Tasker
|
Gracias de parte de: | ||
#5
|
||||
|
||||
muy bueno WillyWeb, y pensar que hace unos días decías que no eras de los Máster
![]() es algo muy complejo ![]() gracias por compartir, muy buen manejo.
__________________
![]() "Tanto si piensas que puedes, como si piensas que no puedes, estás en lo cierto"
— Henry Ford — Última edición por Mx WaR HaBiB Día 02/03/16 a las 17:11:20. |
Los siguientes 2 usuarios han agradecido a Mx WaR HaBiB su comentario: | ||
#6
|
||||
|
||||
Hola WillyWeb, encontre estas excelentes tareas que has desarrollado pero disculpa mi ignoracia, no encuentro la forma de ingresar las coordenadas, asi como el formato de estas.
sera mucha molestia si pones un ejemplo? saludos. |
#7
|
||||
|
||||
Para nada.
![]() El formato de las coordenadas es el que usa Tasker en las variables de localización %LOC y %LOCN. Y el mismo que se usa en Google Maps. Es decir LAT,LON estando ambos valores en grados sexagesimales y usando el punto como separador decimal. 48.8583562,2.2945427 ... Torre Eiffel 40.6891802,-74.0446935 ... Estatua de la Libertad Felices Fiestas ![]()
__________________
Miembro del equipo que promueve el [Subforo de Tasker]
Si das pescado a un hombre hambriento le nutres una jornada. Si le enseñas a pescar le nutrirás toda la vida. (Lao-Tsé - Filósofo chino) |
Los siguientes 2 usuarios han agradecido a WillyWeb su comentario: | ||
![]() |
![]() |
||||||
|