Почему взвешенные вычисления по Lon / lat дают в JavaScript другой результат, чем в SQL - PullRequest
0 голосов
/ 09 апреля 2019

Основано на этом сайте: https://carto.com/blog/center-of-points/ Я пытаюсь вычислить средневзвешенное значение для набора точек лон / лат. На сайте приведены расчеты в SQL-коде, и я специально смотрю на набор тестовых данных следующим образом:

Data Table

country    lat         lon
-------    --------    ---------
Tonga      -21.1333    -175.2
Tuvalu     -8.53333     179.2167

Где результат:

avg_lon    avg_lon_naive    avg_lat
-------    -------------    -------
-177.992   2.00833          -14.9333

Теперь я пытаюсь преобразовать это в JavaScript следующим образом:

// Calculate weighted average of points in lat/lon

// mypoint = [lat, lon ]
var mypoint1 = [-21.1333, -175.2];
var mypoint2 = [-8.53333, 179.2167];

//Weighted LON
var zeta = (Math.sin(Math.PI * mypoint1[1] / 180) + Math.sin(Math.PI *         
mypoint2[1] / 180)) / 2;
console.log(zeta);
var xi = (Math.cos(Math.PI * mypoint1[1] / 180) + Math.sin(Math.PI *         
mypoint2[1] / 180)) / 2;
console.log(xi);

var avglon = 180 * Math.atan2(zeta, xi) / Math.PI;
console.log("Average longitude: " + avglon);


//Weighted LAT
var avglat = (mypoint1[0] + mypoint2[0]) / 2;
console.log("Average latitude: " + avglat);

Что дает этот результат:

-0.03500355257793927
-0.49141106053653333
Average longitude: -175.92566317222995
Average latitude: -14.833314999999999
Press any key to continue...

Почему я получаю другой результат в моем случае JavaScript? Я сделал что-то не так в коде? Что-то пропустили, какое-то преобразование или подобное?

Или есть какие-либо различия в atan2 или PI в SQL против JavaScript?

Любые указатели будут высоко оценены.


Редактировать: Для расчета LAT я начал верить, что в исходной записи есть ошибка Поскольку вычисление Lat является относительно простым, мы можем видеть, что:

 2 x -14.9333 = 29,8666 

Что не является результатом исходных точек лат, заданных

 -21.1333 +(-8.53333) = -29.6666299

1 Ответ

1 голос
/ 10 апреля 2019

На самом деле, я думаю, что оба метода не верны.На сфере я бы усреднил трехмерные векторы.В python это будет выглядеть следующим образом:

import numpy as np

DEGREE = np.pi/180.
RAD = 1./DEGREE

def lon_lat_naive( inList ):
    return np.mean( inList,axis=0)

def lon_lat_full_vector( inList ):
    vec = [ [ np.cos( lat * DEGREE ) * np.cos( lon * DEGREE ), np.cos(lat* DEGREE ) * np.sin( lon * DEGREE  ), np.sin( lat * DEGREE ) ] for  lon, lat in inList ]
    # ~ print vec
    vec = np.sum( vec, axis=0)
    vec /= np.linalg.norm( vec )
    # ~ print vec
    lat = np.arcsin( vec[2] ) * RAD
    lon = np.arctan2( vec[1], vec[0] ) * RAD
    return [ lon, lat ]


a = np.array( [10, 60 ])
b = np.array( [20, 80 ])

print( lon_lat_naive( np.array( [ a, b ] ) ) )
print( lon_lat_full_vector( np.array( [ a, b ] ) ) )


Tonga = np.array( [ -175.2, -21.1333 ])
Tuvalu = np.array( [ 179.2167, -8.53333 ])

tt = np.array( [Tonga, Tuvalu ] )
print( lon_lat_naive( tt ) )
print( lon_lat_full_vector( tt ) )

, обеспечивающий:

[15. 70.]
[12.573012941928377, 70.05362118882975]
[  2.00835  -14.833315]
[-178.07333636886855, -14.850146658102775]

, который отличается как от вашей, так и от веб-страницы, но должен дать вам --- в случаедве точки --- средняя точка дуги, соединяющей две.

...