¿Cómo calculo el acimut (ángulo hacia el norte) entre dos coordenadas WGS84 en una sola consulta T-SQL?
-
20-08-2019 - |
Pregunta
Encontré la solución para esta pregunta en C # , pero no puedo traducirla a una sola consulta T-SQL, ya que mi implementación de C # requiere ramificación (si es así).
También encontré la siguiente solución de C #, que podría traducirse a una sola consulta T-SQL pero no produce los resultados correctos
public static double GetAzimuth(WGSCoord c1, WGSCoord c2) {
var lat1 = DegToRad(c1.Latitude);
var lon1 = DegToRad(c1.Longitude);
var lat2 = DegToRad(c2.Latitude);
var lon2 = DegToRad(c2.Longitude);
return RadToDeg(Math.Asin(Math.Sin(lon1 – lon2) * Math.Cos(lat2) / Math.Sin(Math.Acos(Math.Sin(lat2) * Math.Sin(lat1) + Math.Cos(lat1) * Math.Cos(lat2) * Math.Cos(lon2 – lon1)))));
}
Código de Tamir Khason & # 8211; Solo codifique
¿Alguien podría corregir el código anterior o proporcionar una solución alternativa?
Solución
Reemplazar ifs con expresiones CASE:
if (latitudinalDifference == 0)
{
if (longitudinalDifference != 0)
{
azimuth = Math.PI / 2d;
}
}
reemplazar con:
SELECT CASE WHEN @latitudinalDifference = 0 AND @longitudinalDifference <> 0 THEN ...
ELSE ... END AS azimuth
reemplazar ifs consecutivos con selecciones anidadas:
if(some condition)
{
i=1;
}
else
{
i=2;
}
if(some other condition)
{
i++;
}
reemplazar con
SELECT i + CASE WHEN (some other condition) THEN 1 ELSE 0 END
FROM(
SELECT CASE WHEN (some condition) THEN 1 ELSE 2 END AS i
) AS t
Otros consejos
¿Ha considerado crear un ensamblado con un SP en C # para el servidor SQL? Esa es la ruta que probablemente seguiría.
Hay bastante trigonometría esférica necesaria en la respuesta a SO 389211 . Copiando y modificando lo que escribí allí:
Considere un triángulo esférico con ángulos A , B , C en los vértices y lados a , < em> b , c opuesto a esos vértices (es decir, el lado a es de B a C , etc.). Aplicando esto al problema, podemos llamar a los dos puntos dados B y C , y creamos un triángulo esférico recto con un ángulo recto en A .
Considere este diagrama:
+ C
/|
/ |
a / | b
| / |
|X/ |
|/ |
B +------+ A
c
Se le otorgan dos puntos B y C , y desea determinar el ángulo X = 90 & # 186; - B. El lado c es igual a la diferencia en longitud, & # 916; & # 955 ;; el lado b es igual a la diferencia de latitud, & # 916; & # 966 ;; el ángulo A es 90 & # 186 ;, entonces sin A = 1 y cos A = 0. Para determinar X, queremos el valor de B dado b , c y A .
Mirando el problema desde los primeros principios, necesitamos las dos ecuaciones principales de trigonometría esférica:
-
La fórmula sinusoidal:
sin A sin B sin C ----- = ----- = ----- sin a sin b sin c
-
La fórmula del coseno:
cos a = cos b . cos c + sin b . sin c . cos A
Por lo tanto, creo que una ecuación para a es:
cos a = cos Δλ . cos Δφ + sin Δλ . sin Δφ . cos 90º
a = arccos (cos Δλ . cos Δφ)
Dados a , b y A , podemos usar la fórmula sinusoidal para determinar B :
sin a sin b
----- = ----
sin A sin B
O
sin b . sin A
sin B = -------------
sin a
O, ya que A = 90 & # 186 ;, sin A = 1, y sin B = sin (90 & # 186; - X) = cos X:
sin b
cos X = -----
sin a
Prefiero sospechar que si me inclino (o lo haces), podrías encontrar una respuesta que no implique el uso de arcos seguidos de pecado.
En T-SQL, puede usar la expresión CASE
por ejemplo
SELECT ...
CASE
WHEN latD = 0 AND longD < 0 THEN ....
WHEN latD < 0 AND longD = 0 THEN ....
etc.