Як я можу обчислити середнє значення між кількома плямами широти та довготи?
Чи варто просто обчислити середнє арифметичне як для лата, так і для lng?
Як я можу обчислити середнє значення між кількома плямами широти та довготи?
Чи варто просто обчислити середнє арифметичне як для лата, так і для lng?
Відповіді:
Для простого середнього значення ви не хочете порівнювати координати довготи та широти. Це може працювати досить добре на нижчих широтах, але на більш високих широтах воно почне давати погані результати і повністю руйнується біля полюсів.
Метод, який я використовував для цього типу речей, полягає в перетворенні координат довготи / широти в 3d декартові координати (x, y, z). Порівняйте їх (для отримання декартового вектора), а потім знову конвертуйте. Зауважте, що вам, мабуть, не потрібно нормалізувати вектор, тому фактичний середній процес може бути простою сумою.
Редагувати, ось мій c # код:
Наступні перетворюють декартові координати у широту / довготу (у градусах): Видаліть RAD2DEG
константи радіанів.
Latitude = MPUtility.RAD2DEG * Math.Atan2(z, Math.Sqrt(x * x + y * y));
Longitude = MPUtility.RAD2DEG * Math.Atan2(-y, x);
І тут ми обчислюємо декартові координати з широти / довготи (вказані в радіанах):
private void CalcCartesianCoord()
{
_x = Math.Sin(LatitudeRadians) * Math.Cos(LongitudeRadians);
_y = Math.Sin(LatitudeRadians) * Math.Sin(LongitudeRadians);
_z = Math.Cos(LatitudeRadians);
}
Обидва вирізані та вставлені з реального коду, отже, суміш градусів та радіанів. Тут є властивості, які виконують деякі перетворення (наприклад LatitudeRadians
, це властивість, яка повертає радіанне значення).
Зауважте, що можлива оптимізація: наприклад, дублювання синусових обчислень. Також обчислення тригерів може бути кешованим, якщо ви їх називаєте багато.
Параметри кластеризації : Я думаю, що концептуальне слово, яке охоплює цей тип операцій, є "кластеризацією". Усереднення на сьогоднішній день є найпростішим у здійсненні і добре працює для більшості цілей. Єдиний раз, коли б я скористався чимось іншим, це якщо ти турбуєшся про людей, що вийшли з ладу [Правка] ->, або жердинами або міжнародними дателінами. [Редагувати] -> також усереднення, хоча це дасть вам щось, що виглядає близько до центру кластеру, буде трохи відхилено через неточності проекції, спричинені тим, що градуси lat lng не завжди однакові відстані крім км / миль. Чим більша площа, середня середня величина, тим більше спотворення.
Ось порівняння кількох варіантів кластеризації
Середня (проста, найшвидша, неточна): просто підсумовуйте значення lat і діліть на кількість і зробіть те ж саме для значень lng. Обов’язково слідкуйте за переповненням, якщо ви використовуєте Int32, деякі системи (зокрема c #) мовчки переповнюватимуться до низьких чисел. Ви можете уникнути цих помилок, використовуючи точність з плаваючою комою для свого акумулятора. Однією з проблем цього методу є те, що люди, які пережили люди, можуть перекосити ваше місцезнаходження. [Редагувати] -> Інша справа, що математика біля полюсів та міжнародної лінійки дат не відповідає середньому рівню, а місця розташування погано перекручені.
Найближчий сусід (трохи важче, повільніше, не зовнішній вигляд) Замість того, щоб усереднюватись, можна було йти з фактичним місцем розташування з найменшою середньою відстані до всіх сусідів. Це щось на зразок прийняття «медіани». Суть полягає в тому, що це обчислювально дорого, оскільки ви порівнюєте кожну точку з кожною іншою точкою і обчислюєте відстань між ними. Наприклад, для кластеризації 10000 точок знадобиться 100 мільйонів обчислень відстані. Це не так повільно, але це, безумовно, не добре.
Grid Cell (потрібно трохи додатково налаштувати, набагато швидше, не упереджено) Це схоже на найближчого сусіда, але набагато швидше. Ви можете вибрати довільний рівень точності, скажімо, .01 deg lat lng (який приблизно в 1 км на населених широтах) і згрупувати свої бали у відрі .01 x .01 градуса. Тоді ви можете вибрати відро з найбільшою кількістю очок і взяти середнє значення серед цих балів або провести аналіз найближчого сусіда лише за цими балами. Я багато використовую цей метод із дійсно великими наборами даних (сотні мільярдів записів) і вважаю, що це хороший баланс між точністю та швидкістю.
Опуклий центроїд корпусу (жорсткий, повільніший, акуратніший результат): Ви також можете намалювати смугу навколо точок, щоб визначити форму, яка охоплює їх усі ( див. Вікіпедію ), а потім обчислити центральну точку цієї форми. Типові функції центроїдів не зважуються в центрі, тому вам потрібно буде зробити якийсь зворотний аналіз найближчого сусіда, використовуючи зразки точок всередині вашої форми, поки ви не знайдете найдалі від країв. Цей метод справді цікавіший через сам опуклий корпус, а не власне алгоритм знаходження центру, який не є ні швидким, ні особливо точним .. але форма корпусу може мати інші корисні програми з вашими даними.
Не впевнений у тому, що ви намагаєтесь досягти, але точка, широта якої є середньою широтою вихідного набору точок, а довгота - це середня довжина початкового набору точок, буде середньою точкою вихідного набору точок. [ОНОВЛЕННЯ]: У наведеному вище середній арифметичний середній.