Виконувати перетворення координат стало простіше

  1. Виконувати перетворення координат стало простіше Посібник з перетворення між різними системами координат...
  2. Широта і довгота
  3. Малюнок 1. Земля з показаними лініями паралелей і меридіанів
  4. Поперечна проекція Меркатора
  5. Малюнок 2. Поперечна проекція Меркатора
  6. Малюнок 3. Зони UTM в Європі
  7. Військова система координат
  8. перетворення координат
  9. Перетворення десяткових градусів в градуси / хвилини / секунди і назад
  10. Перетворення довготи / широти в UTM і назад
  11. Перетворення координат в Java коді
  12. клас CoordinateConversion
  13. Лістинг 1. CoordinateConversion
  14. Перетворення від широти / довготи до UTM
  15. Лістинг 2. public String convertLatLonToUTM (double latitude, double longitude)
  16. Лістинг 3. protected void setVariables (double latitude, double longitude)
  17. Лістинг 4. protected String getLongZone (double longitude)
  18. Лістинг 5. protected double getNorthing (double latitude)
  19. Лістинг 6. protected double getEasting ()
  20. Лістинг 7. Тестові перетворення від широти / довготи до значень в UTM
  21. Перетворення від UTM до широти / довготі
  22. Лістинг 8. public double [] convertUTMToLatLong (String UTM)
  23. Лістинг 9. protected void setVariables ()
  24. інші методи
  25. висновок
  26. Ресурси для скачування
  27. Виконувати перетворення координат стало простіше
  28. Дві різні системи координат
  29. Широта і довгота
  30. Малюнок 1. Земля з показаними лініями паралелей і меридіанів
  31. Поперечна проекція Меркатора
  32. Малюнок 2. Поперечна проекція Меркатора
  33. Малюнок 3. Зони UTM в Європі
  34. Військова система координат
  35. перетворення координат
  36. Перетворення десяткових градусів в градуси / хвилини / секунди і назад
  37. Перетворення довготи / широти в UTM і назад
  38. Перетворення координат в Java коді
  39. клас CoordinateConversion
  40. Лістинг 1. CoordinateConversion
  41. Перетворення від широти / довготи до UTM
  42. Лістинг 2. public String convertLatLonToUTM (double latitude, double longitude)
  43. Лістинг 3. protected void setVariables (double latitude, double longitude)
  44. Лістинг 4. protected String getLongZone (double longitude)
  45. Лістинг 5. protected double getNorthing (double latitude)
  46. Лістинг 6. protected double getEasting ()
  47. Лістинг 7. Тестові перетворення від широти / довготи до значень в UTM
  48. Перетворення від UTM до широти / довготі
  49. Лістинг 8. public double [] convertUTMToLatLong (String UTM)
  50. Лістинг 9. protected void setVariables ()
  51. інші методи
  52. висновок
  53. Ресурси для скачування
  54. Виконувати перетворення координат стало простіше
  55. Дві різні системи координат
  56. Широта і довгота
  57. Малюнок 1. Земля з показаними лініями паралелей і меридіанів
  58. Поперечна проекція Меркатора
  59. Малюнок 2. Поперечна проекція Меркатора
  60. Малюнок 3. Зони UTM в Європі
  61. Військова система координат
  62. перетворення координат
  63. Перетворення десяткових градусів в градуси / хвилини / секунди і назад
  64. Перетворення довготи / широти в UTM і назад
  65. Перетворення координат в Java коді
  66. клас CoordinateConversion
  67. Лістинг 1. CoordinateConversion
  68. Перетворення від широти / довготи до UTM
  69. Лістинг 2. public String convertLatLonToUTM (double latitude, double longitude)
  70. Лістинг 3. protected void setVariables (double latitude, double longitude)
  71. Лістинг 4. protected String getLongZone (double longitude)
  72. Лістинг 5. protected double getNorthing (double latitude)
  73. Лістинг 6. protected double getEasting ()
  74. Лістинг 7. Тестові перетворення від широти / довготи до значень в UTM
  75. Перетворення від UTM до широти / довготі
  76. Лістинг 8. public double [] convertUTMToLatLong (String UTM)
  77. Лістинг 9. protected void setVariables ()
  78. інші методи
  79. висновок
  80. Ресурси для скачування

Виконувати перетворення координат стало простіше

Посібник з перетворення між різними системами координат

Служби позиціонування, включаючи навігацію на основі GPS і картографічні сайти, такі як Google Maps і Yahoo! Maps, стають популярними серед користувачів. Безліч організацій вже використовують сервіси, пов'язані з використанням інформації про географічні координати, і ще більше компаній підуть цим шляхом, як тільки усвідомлюють переваги і потенціал подібних додатків. У 2006 році аналітична компанія Gartner зазначила, що "додатка, пов'язані з позиціонуванням, стануть масовими протягом наступних двох-п'яти років" і що вже "значне число організацій розгорнули мобільні бізнес-функції, які залежать позиціонування". (В розділі ресурси наведено посилання на цей звіт.)

Коли організація вирішує реалізувати програму, яка використовує географічну систему координат, зазвичай написання такого додатка стає завданням розробника. Побудова програми, що використовує географічні координати, включає в себе багато великих і маленьких завдань, і однією з таких завдань, відносно простий, буде перетворення координат з однієї системи в іншу. У цій статті представлений код, який виконує таке перетворення і може допомогти заощадити безліч годин роботи.

Дві різні системи координат

Перш ніж зануритися в код, представлений в цій статті, необхідно обговорити координатні системи, для підтримки яких цей код призначений: відома система широти і довготи і універсальна поперечна проекція Меркатора (Universal Transverse Mercator - UTM). Також потрібно торкнутися військової системи координат (Military Grid Reference System - MGRS), яка заснована на UTM.

Широта і довгота

Системи широти і довготи, ймовірно, найвідоміший спосіб визначення географічних координат. У ній місце розташування представляється двома числами. Широта - це кут від центру землі до деякої паралелі на земній поверхні. Довгота - це кут від центру землі до деякого меридіану на земній поверхні. Широта і довгота можуть бути виражені в десяткових градусах (DD) або градусах, хвилинах і секунда (DMS); в останньому випадку виходять числа в такому форматі - 49 ° 30'00 "S 12 ° 30'00" E. Цей формат зазвичай використовується в GPS-навігаторах.

Земля розділена екватором (0 ° широти) на північну і південну півкулі, і нульовим меридіаном (0 ° довготи), уявною лінією від північного до південного полюса, яка проходітчерез місто Грінвіч в Великобританії і ділить планету на східне і західне півкуля. Діапазон широт в північній півкулі від 0 до 90 градусів, а в південній півкулі - від 0 до -90 градусів. Діапазон східної півкулі від 0 до 180 градусів, а західної півкулі від 0 до -180 градусів.

Наприклад, точка з координатами 61.44, 25.40 (в форматі DD) або 61 ° 26'24''N, 25 ° 23'60''E (в форматі DMS) знаходиться в південній Фінляндії. А точка з координатами -47.04, -73.48 (DD) або 47 ° 02'24 ''S, 73 ° 28'48''W (DMS) знаходиться в південному Чилі. На малюнку 1 наведено зображення Землі з перекриваються лініями паралелей і меридіанів:

Малюнок 1. Земля з показаними лініями паралелей і меридіанів

Додаткову інформацію можна знайти в розділі ресурси .

Поперечна проекція Меркатора

Система координат UTM - це метод, який використовує сітку для визначення координат. Система UTM ділить Землю на 60 зон, кожна з яких заснована на поперечної проекції Меркатора. Проекція карти в картографії - це спосіб представити двовимірну нерівну поверхню на площині, як звичайну карту. на малюнку 2 приведена поперечна проекція Меркатора:

Малюнок 2. Поперечна проекція Меркатора

Зони довготи в UTM пронумеровані від 1 до 60; всі зони окрім двох, про яких буде розказано пізніше, мають ширину 6 ° від сходу до заходу. Зони довготи повністю покривають поверхню Землі між широтами 80 ° S і 84 ° N.

Також є 20 зон широти, кожна в 8 ° заввишки; ці зони пронумеровані від C до X, літери I і O пропущені. Зони A, B, Y і Z знаходяться за межами цієї системи, вони покривають Арктику і Антарктику. на малюнку 3 наведені UTM зони для Європи. На цьому малюнку видно дві нестандартні зони довготи: зона 32V розширена для покриття всієї південної Норвегії, а зона 31V скорочена, щоб покривати тільки водний простір.

Малюнок 3. Зони UTM в Європі

Координати в UTM представлені в форматі зона довготи зона широти східне схиляння північне відмінювання, де східне схиляння - це проекційне відстань від центрального меридіана зони довготи, північне відмінювання - це проекційне відстань від екватора. Значення східного і північного відмін задаються в метрах. Наприклад, координати широти / довготи 61.44, 25.40 в UTM представлені як 35 V 414668 6812844; координати широти / довготи -47.04, -73.48 відповідають координатам 18 G 615471 4789269 в UTM.

В розділі ресурси приведена додаткова інформація по UTM і поперечної проекції Меркатора.

Військова система координат

Система координат MGRS - стандарт, використовуваний військовими НАТО. MGRS заснована на UTM і далі ділить кожну зону на квадрати 100х100 км. Ці квадрати ідентифікуються з двох літер кодом, перша буква - східно-західна позиція в зоні довготи, а друга буква - північно-південна позиція.

Наприклад, координата в UTM 35 V 414668 6812844 еквівалента координаті MGRS 35VMJ1466812844. Точність координати в MGRS задається з точністю в один метр і представлена ​​за допомогою 15 символів, де останні 10 символів представляють значення східного і північного відмін у зазначеній сітці. У MGRS координати можуть бути представлені 15 символами, як в попередньому випадку, або 13, 11, 9 або 7 символами; представлені таким чином значення будуть відповідно мати точність 1, 10, 100, 1000 або 10000 метрів.

У цій статті докладно не розбирається MGRS, але скачуваний код включає в себе перетворення між широтою / довготою і MGRS. В розділі ресурси приведена додаткова інформація.

перетворення координат

Щоб визначити ширину і довготу - координати місця розташування на Землі, як мінімум потрібно мати можливість бачити зірки або Сонце, мати секстан і годинник, що показує час на меридіані GMT. Можна визначити широту з кута між небесним тілом і горизонтом, а довготу можна обчислити з обертання Землі. Ця стаття не занурюється в подібні подробиці, але в розділі ресурси про них можна дізнатися більше. Замість цього, припустимо, що у нас вже є координати в форматі DD, DMS або UTM.

Перетворення десяткових градусів в градуси / хвилини / секунди і назад

Вкрай просто перетворити координати з формату DD в DMS. Нижче наведена формула для подібного перетворення:

DD: dd.ff DMS: dd mm ss dd = dd mm.gg = 60 * ff ss = 60 * gg

У цьому прикладі gg - це дрібна частина обчислення. Негативна широта означає розташування в південній півкулі (S), а негативна довгота - в західній півкулі (W). Наприклад, припустимо, що є координати в форматі DD - 61.44, 25.40. Їх можна перетворити в такий спосіб:

lat dd = 61 lat mm.gg = 60 * 0.44 = 26.4 lat ss = 60 * 0.4 = 24

далі:

lon dd = 25 lon mm.gg = 60 * 0.40 = 24.0 lon ss = 60 * 0.0 = 0

Таким чином, в форматі DMS отримуємо наступні координати - 61 ° 26'24''N 25 ° 24'00''E.

Нижче наведена формула для переходу від DMS до DD:

DD: dd.ff DMS: dd mm ss dd.ff = dd + mm / 60 + ss / 3600

Нагадаємо, що місця, розташовані в південній півкулі (S), мають негативну широту, а місця в західній півкулі (W) мають негативну довготу.

Тепер виконаємо перетворення DMS координат 47 ° 02'24 ''S, 73 ° 28'48''W в формат DD:

lat dd.ff = - (47 + 2/60 + 24/3600) = - 47.04 lon dd.ff = - (73 + 28/60 + 48/3600) = - 73.48

Таким чином, координати в DD рівні -47.04, -73.48.

Перетворення довготи / широти в UTM і назад

На відміну від десяткових координат, які можна визначити за допомогою хронометра і годин, координати UTM неможливо визначити без допомоги обчислень. Хоча ці обчислення ніщо інше, як проста тригонометрія і алгебра, формули у них досить складні. Якщо ознайомитися зі статтею "The Universal Grids: Universal Transverse Mercator (UTM) and Universal Polar Stereographic (UPS)" (посилання на неї наведена в розділі ресурси ), То стане зрозуміло, що я маю на увазі.

Формули для перетворення UTM тут не наводяться, але вихідний код в наступному розділі трохи висвітлює цю проблему, а в розділі ресурси є посилання на додаткову інформацію.

Перетворення координат в Java коді

У цьому розділі наведено вихідний код класу бібліотеки, який виконує перетворення координат між десятковими градусами і UTM. Цей Java-клас називається com.ibm.util.CoordinateConversion і я хотів створити окремий клас з методами для перетворення. Цей клас включає внутрішні класи, які насправді виконують перетворення, і при необхідності ці класи можуть бути винесені з класу CoordinateConversion за допомогою рефакторінга, щоб створити пакет бібліотеки або додати класи в існуючий пакет. Перетворення, що виконуються цим класом, мають точність в 1 метр.

У вихідному коді CoordinateConversion близько 750 рядків, так що в цій статті він представлений не повністю. Істотні методи описані в наступних розділах, а повністю код доступний в розділі Матеріали для скачування .

клас CoordinateConversion

CoordinateConversion - це головний клас, об'єкти якого створюються при необхідності виконання перетворення координат. У лістингу 1 наведені істотні public методи разом з внутрішніми private класами, що входять в клас CoordinateConversion:

Лістинг 1. CoordinateConversion

public class CoordinateConversion {public CoordinateConversion () {} public double [] utm2LatLon (String UTM) {UTM2LatLon c = new UTM2LatLon (); return c.convertUTMToLatLong (UTM); } Public String latLon2UTM (double latitude, double longitude) {LatLon2UTM c = new LatLon2UTM (); return c.convertLatLonToUTM (latitude, longitude); } //..Реалізація пропущена private class LatLon2UTM {public String convertLatLonToUTM (double latitude, double longitude) {//..реалізація пропущена} //..реалізація пропущена} private class LatLon2MGRUTM extends LatLon2UTM {public String convertLatLonToMGRUTM (double latitude, double longitude) {//..реалізація пропущена} //..реалізація пропущена} private class MGRUTM2LatLon extends UTM2LatLon {public double [] convertMGRUTMToLatLong (String mgrutm) {//..реалізація пропущена} //..реалізація пропущена} private class UTM2LatLon {public double [] convertUTMToLatLong (String UTM) {//..реалізація пропущена} //..реалізація пропущена} private class Digraphs {// використовується для отримання двобуквений кодів // при перетворенні від довготи / широт до MGRS //..реалізація пропущена} private class LatZones {// включає методи для визначення зон широти //..реалізація пропущена}

У наступному розділі докладно розглядаються перетворення між довготою / широтою і UTM.

Перетворення від широти / довготи до UTM

Координати перетворюються від широти / довготи в UTM за допомогою методу String latLon2UTM (double latitude, double longitude). Реалізація цього методу створює екземпляр внутрішнього класу LatLon2UTM c = new LatLon2UTM (); і повертає координати UTM у вигляді 15-символьного рядка з точністю 1 метр. Реалізація методів класу LatLon2UTM приведена в лістингу 2:

Лістинг 2. public String convertLatLonToUTM (double latitude, double longitude)

public String convertLatLonToUTM (double latitude, double longitude) {validate (latitude, longitude); String UTM = ""; setVariables (latitude, longitude); String longZone = getLongZone (longitude); LatZones latZones = new LatZones (); String latZone = latZones.getLatZone (latitude); double _easting = getEasting (); double _northing = getNorthing (latitude); UTM = longZone + "" + latZone + "" + ((int) _easting) + "" + ((int) _northing); return UTM; }

Цей метод може конвертувати, викликаючи різні методи для отримання зони широти і зони довготи, обчислення східного і північного схиляння і т.д. Вхідні дані перевіряються в методі validate (), якщо вираз (latitude <-90.0 || latitude> 90.0 || longitude <-180.0 || longitude> = 180.0) приймає значення true, то скидається виняткова ситуація IllegalArgumentException.

Метод setVariables () в лістингу 3 встановлює різні змінні, що вимагаються для обчислення перетворень (додаткова інформація представлена ​​в статті "The Universal Grids", посилання на яку наведено в розділі ресурси :

Лістинг 3. protected void setVariables (double latitude, double longitude)

protected void setVariables (double latitude, double longitude) {latitude = degreeToRadian (latitude); rho = equatorialRadius * (1 - e * e) / POW (1 - POW (e * SIN (latitude), 2), 3 / 2.0); nu = equatorialRadius / POW (1 - POW (e * SIN (latitude), 2), (1 / 2.0)); double var1; if (longitude <0.0) {var1 = ((int) ((180 + longitude) / 6.0)) + 1; } Else {var1 = ((int) (longitude / 6)) + 31; } Double var2 = (6 * var1) - 183; double var3 = longitude - var2; p = var3 * 3600/10000; S = A0 * latitude - B0 * SIN (2 * latitude) + C0 * SIN (4 * latitude) - D0 * SIN (6 * latitude) + E0 * SIN (8 * latitude); K1 = S * k0; K2 = nu * SIN (latitude) * COS (latitude) * POW (sin1, 2) * k0 * (100000000) / 2; K3 = ((POW (sin1, 4) * nu * SIN (latitude) * Math.pow (COS (latitude), 3)) / 24) * (5 - POW (TAN (latitude), 2) + 9 * e1sq * POW (COS (latitude), 2) + 4 * POW (e1sq, 2) * POW (COS (latitude), 4)) * k0 * (10000000000000000L); K4 = nu * COS (latitude) * sin1 * k0 * 10000; K5 = POW (sin1 * COS (latitude), 3) * (nu / 6) * (1 - POW (TAN (latitude), 2) + e1sq * POW (COS (latitude), 2)) * k0 * 1000000000000L; A6 = (POW (p * sin1, 6) * nu * SIN (latitude) * POW (COS (latitude), 5) / 720) * (61 - 58 * POW (TAN (latitude), 2) + POW (TAN (latitude), 4) + 270 * e1sq * POW (COS (latitude), 2) - 330 * e1sq * POW (SIN (latitude), 2)) * k0 * (1E + 24); }

Метод getLongZone () в лістингу 4 або LatZones, доступний в вихідному коді , Використовуються, щоб дізнатися зону довготи і зону широти. Зона довготи обчислюється по параметру longitude, а зони широти зазвичай представлені як константи, за допомогою масиву в класі LatZones.

Лістинг 4. protected String getLongZone (double longitude)

protected String getLongZone (double longitude) {double longZone = 0; if (longitude <0.0) {longZone = ((180.0 + longitude) / 6) + 1; } Else {longZone = (longitude / 6) + 31; } String val = String.valueOf ((int) longZone); if (val.length () == 1) {val = "0" + val; } Return val; }

Метод getNorthing () в лістингу 5 і метод getEasting () в лістингу 6 обчислюють значення північного і східного відмінювання. Обидва методи використовують змінні, встановлені в методі setVariables () з лістингу 3 .

Лістинг 5. protected double getNorthing (double latitude)

protected double getNorthing (double latitude) {double northing = K1 + K2 * p * p + K3 * POW (p, 4); if (latitude <0.0) {northing = 10000000 + northing; } Return northing; }

Лістинг 6. protected double getEasting ()

protected double getEasting () {return 500000 + (K4 * p + K5 * POW (p, 3)); }

У лістингу 7 наведено кілька прикладів результатів роботи програми, включаючи координати в форматі широта / довгота і відповідні їм UTM координати:

Лістинг 7. Тестові перетворення від широти / довготи до значень в UTM

(0.0000 0.0000) "31 N 166021 0" (0.1300 -0.2324) "30 N 808084 14385" (-45.6456 23.3545) "34 G 683473 4942631" (-12.7650 -33.8765) "25 L 404 859 8588690" (-80.5434 -170.6540) "02 C 506 346 1057742" (90.0000 177.0000) "60 Z 500000 9997964" (-90.0000 -177.0000) "01 A 500000 2035" (90.0000 3.0000) "31 Z 500000 9997964" (23.4578 -135.4545) "08 Q 453 580 2594272" ( 77.3450 156.9876) "57 X 450 793 8586116" (-89.3454 -48.9306) "22 A 502639 75072"

Перетворення від UTM до широти / довготі

Перетворення від координат в форматі UTM до широти / довготі виконується трохи простіше, ніж зворотний процес. У статті "The Universal Grids" в розділі ресурси ) Наведені формули перетворень. У лістингу 8 наведено код методу convertUTMToLatLong (). Цей метод повертає масив double значень, де перший елемент (з індексом масиву [0]) - це широта, а другий елемент (з індексом масиву [1]) - це довгота. Так як строковий параметр містить координати UTM з точністю до 1 метра, то і координати в широті / довготі матимуть таку ж точність.

Лістинг 8. public double [] convertUTMToLatLong (String UTM)

public double [] convertUTMToLatLong (String UTM) {double [] latlon = {0.0, 0.0}; String [] utm = UTM.split ( ""); zone = Integer.parseInt (utm [0]); String latZone = utm [1]; easting = Double.parseDouble (utm [2]); northing = Double.parseDouble (utm [3]); String hemisphere = getHemisphere (latZone); double latitude = 0,0; double longitude = 0,0; if (hemisphere.equals ( "S")) {northing = 10000000 - northing; } SetVariables (); latitude = 180 * (phi1 - fact1 * (fact2 + fact3 + fact4)) / Math.PI; if (zone> 0) {zoneCM = 6 * zone - 183.0; } Else {zoneCM = 3.0; } Longitude = zoneCM - _a3; if (hemisphere.equals ( "S")) {latitude = -latitude; } Latlon [0] = latitude; latlon [1] = longitude; return latlon; }

Метод convertUTMToLatLong () розбиває координати UTM у вхідному строковому параметрі, які мають формат 34 G 683473 4942631, і використовує метод getHemisphere () для визначення півкулі, де знаходиться місце з вказаними координатами. Визначити півкуля просто: зони широти A, C, D, E, F, G, H, J, K, L і M знаходяться в південній півкулі, а решта зони знаходяться в північній півкулі.

Метод setVariables (), показаний в лістингу 9, встановлює значення змінних, необхідних для обчислення, і потім негайно обчислюють широту. Довгота обчислюється з використанням зони довготи.

Лістинг 9. protected void setVariables ()

protected void setVariables () {arc = northing / k0; mu = arc / (a ​​* (1 - POW (e, 2) / 4.0 - 3 * POW (e, 4) / 64.0 - 5 * POW (e, 6) / 256,0)); ei = (1 - POW ((1 - e * e), (1 / 2.0))) / (1 + POW ((1 - e * e), (1 / 2.0))); ca = 3 * ei / 2 - 27 * POW (ei, 3) / 32.0; cb = 21 * POW (ei, 2) / 16 - 55 * POW (ei, 4) / 32; cc = 151 * POW (ei, 3) / 96; cd = одна тисяча дев'яносто сім * POW (ei, 4) / 512; phi1 = mu + ca * SIN (2 * mu) + cb * SIN (4 * mu) + cc * SIN (6 * mu) + cd * SIN (8 * mu); n0 = a / POW ((1 - POW ((e * SIN (phi1)), 2)), (1 / 2.0)); r0 = a * (1 - e * e) / POW ((1 - POW ((e * SIN (phi1)), 2)), (3 / 2.0)); fact1 = n0 * TAN (phi1) / r0; _a1 = 500000 - easting; dd0 = _a1 / (n0 * k0); fact2 = dd0 * dd0 / 2; t0 = POW (TAN (phi1), 2); Q0 = e1sq * POW (COS (phi1), 2); fact3 = (5 + 3 * t0 + 10 * Q0 - 4 * Q0 * Q0 - 9 * e1sq) * POW (dd0, 4) / 24; fact4 = (61 + 90 * t0 + 298 * Q0 + 45 * t0 * t0 - 252 * e1sq - 3 * Q0 * Q0) * POW (dd0, 6) / 720; lof1 = _a1 / (n0 * k0); lof2 = (1 + 2 * t0 + Q0) * POW (dd0, 3) / 6.0; lof3 = (5 - 2 * Q0 + 28 * t0 - 3 * POW (Q0, 2) + 8 * e1sq + 24 * POW (t0, 2)) * POW (dd0, 5) / 120; _a2 = (lof1 - lof2 + lof3) / COS (phi1); _a3 = _a2 * 180 / Math.PI; }

Метод setVariables () використовує значення східного і північного відмін для установки необхідних змінних. Ці змінні належать обом класам і встановлюються в методі convertUTMToLatLong (String UTM) з лістингу 8 .

інші методи

Вихідний код також містить інші public і private методи і класи. Наприклад, туди включені методи і класи для перетворення координат між широтою / довготою і MGRS разом з допоміжними методами, які виконують перетворення градусів в радіани і навпаки, і різними математичними операціями, такими як POW, SIN, COS, and TAN.

висновок

У цій статті наведено трохи теорії за світовими системам координат разом з Java-класів для виконання перетворення координат з однієї системи в іншу. Хоча не всі формули для перетворення координат були детально тут розглянуті, вони доступні в розділі ресурси . Зазвичай теоретичні відомості не потрібні в щоденному процесі розробки, крім рідкісних випадків, коли немає іншого способу, як я недавно переконався, коли мені довелося виконувати завдання перетворення координат.

Мені треба було виконувати перетворення між широтою і довготою, UTM і MGRS, так що я виконав базові дослідження і реалізував ці перетворення в Java-класі. Для мене розробка зайняла кілька годин, і я сподіваюся, що і інші також зможуть заощадити кілька годин для інших завдань і вважатимуть корисним використання класу CoordinateConversion в своїй роботі.

Ресурси для скачування

Схожі тими

  • Coordinate conversions made easy (EN) : Оригінал статті
  • Gartner's 2006 emerging technologies hype cycle highlights key technology themes (EN) : Прес-реліз від Gartner містить цікаві відомості про поширеність додатків, що використовують географічні координати.
  • The Universal Grids: Universal TransverseMercator (UTM) and Universal Polar Stereographic (UPS) (EN) : Стаття Національного Графічного і Картографічного Агентства (National Imagery and Mapping Agency - NIMA) містить формули UTM і іншу інформацію про систему координат UTM. (Стаття представлена ​​в форматі PDF.)
  • Location-based services (EN) : (Valerie Bennett і Andrew Capella, developerWorks, березень 2002): стаття з введенням в основні принципи, що лежать в основі систем, пов'язаних з позиціонуванням.
  • Put yourself on the map with Google Maps API, DB2 / Informix, and PHP on Linux (EN) : (Marty Lurie and Aron Y. Lurie, developerWorks, березень 2006): стаття з вихідним кодом, що перетворює ZIP-код у координати широти і довготи.
  • Creating an automatically maintained spatial table from latitude-longitude column data (EN) : (EN) (Robert Uleman, developerWorks, квітень 2006): стаття про те як DB2 може допомогти в перетворенні необроблених координат в корисну інформацію.
  • У Wikipedia можна дізнатися про основні концепції, представлених в цій статті: (EN)
  • developerWorks Java technology zone : Сотні статей про всі аспекти Java-програмування.

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів

Виконувати перетворення координат стало простіше

Посібник з перетворення між різними системами координат

Служби позиціонування, включаючи навігацію на основі GPS і картографічні сайти, такі як Google Maps і Yahoo! Maps, стають популярними серед користувачів. Безліч організацій вже використовують сервіси, пов'язані з використанням інформації про географічні координати, і ще більше компаній підуть цим шляхом, як тільки усвідомлюють переваги і потенціал подібних додатків. У 2006 році аналітична компанія Gartner зазначила, що "додатка, пов'язані з позиціонуванням, стануть масовими протягом наступних двох-п'яти років" і що вже "значне число організацій розгорнули мобільні бізнес-функції, які залежать позиціонування". (В розділі ресурси наведено посилання на цей звіт.)

Коли організація вирішує реалізувати програму, яка використовує географічну систему координат, зазвичай написання такого додатка стає завданням розробника. Побудова програми, що використовує географічні координати, включає в себе багато великих і маленьких завдань, і однією з таких завдань, відносно простий, буде перетворення координат з однієї системи в іншу. У цій статті представлений код, який виконує таке перетворення і може допомогти заощадити безліч годин роботи.

Дві різні системи координат

Перш ніж зануритися в код, представлений в цій статті, необхідно обговорити координатні системи, для підтримки яких цей код призначений: відома система широти і довготи і універсальна поперечна проекція Меркатора (Universal Transverse Mercator - UTM). Також потрібно торкнутися військової системи координат (Military Grid Reference System - MGRS), яка заснована на UTM.

Широта і довгота

Системи широти і довготи, ймовірно, найвідоміший спосіб визначення географічних координат. У ній місце розташування представляється двома числами. Широта - це кут від центру землі до деякої паралелі на земній поверхні. Довгота - це кут від центру землі до деякого меридіану на земній поверхні. Широта і довгота можуть бути виражені в десяткових градусах (DD) або градусах, хвилинах і секунда (DMS); в останньому випадку виходять числа в такому форматі - 49 ° 30'00 "S 12 ° 30'00" E. Цей формат зазвичай використовується в GPS-навігаторах.

Земля розділена екватором (0 ° широти) на північну і південну півкулі, і нульовим меридіаном (0 ° довготи), уявною лінією від північного до південного полюса, яка проходітчерез місто Грінвіч в Великобританії і ділить планету на східне і західне півкуля. Діапазон широт в північній півкулі від 0 до 90 градусів, а в південній півкулі - від 0 до -90 градусів. Діапазон східної півкулі від 0 до 180 градусів, а західної півкулі від 0 до -180 градусів.

Наприклад, точка з координатами 61.44, 25.40 (в форматі DD) або 61 ° 26'24''N, 25 ° 23'60''E (в форматі DMS) знаходиться в південній Фінляндії. А точка з координатами -47.04, -73.48 (DD) або 47 ° 02'24 ''S, 73 ° 28'48''W (DMS) знаходиться в південному Чилі. На малюнку 1 наведено зображення Землі з перекриваються лініями паралелей і меридіанів:

Малюнок 1. Земля з показаними лініями паралелей і меридіанів

Додаткову інформацію можна знайти в розділі ресурси .

Поперечна проекція Меркатора

Система координат UTM - це метод, який використовує сітку для визначення координат. Система UTM ділить Землю на 60 зон, кожна з яких заснована на поперечної проекції Меркатора. Проекція карти в картографії - це спосіб представити двовимірну нерівну поверхню на площині, як звичайну карту. на малюнку 2 приведена поперечна проекція Меркатора:

Малюнок 2. Поперечна проекція Меркатора

Зони довготи в UTM пронумеровані від 1 до 60; всі зони окрім двох, про яких буде розказано пізніше, мають ширину 6 ° від сходу до заходу. Зони довготи повністю покривають поверхню Землі між широтами 80 ° S і 84 ° N.

Також є 20 зон широти, кожна в 8 ° заввишки; ці зони пронумеровані від C до X, літери I і O пропущені. Зони A, B, Y і Z знаходяться за межами цієї системи, вони покривають Арктику і Антарктику. на малюнку 3 наведені UTM зони для Європи. На цьому малюнку видно дві нестандартні зони довготи: зона 32V розширена для покриття всієї південної Норвегії, а зона 31V скорочена, щоб покривати тільки водний простір.

Малюнок 3. Зони UTM в Європі

Координати в UTM представлені в форматі зона довготи зона широти східне схиляння північне відмінювання, де східне схиляння - це проекційне відстань від центрального меридіана зони довготи, північне відмінювання - це проекційне відстань від екватора. Значення східного і північного відмін задаються в метрах. Наприклад, координати широти / довготи 61.44, 25.40 в UTM представлені як 35 V 414668 6812844; координати широти / довготи -47.04, -73.48 відповідають координатам 18 G 615471 4789269 в UTM.

В розділі ресурси приведена додаткова інформація по UTM і поперечної проекції Меркатора.

Військова система координат

Система координат MGRS - стандарт, використовуваний військовими НАТО. MGRS заснована на UTM і далі ділить кожну зону на квадрати 100х100 км. Ці квадрати ідентифікуються з двох літер кодом, перша буква - східно-західна позиція в зоні довготи, а друга буква - північно-південна позиція.

Наприклад, координата в UTM 35 V 414668 6812844 еквівалента координаті MGRS 35VMJ1466812844. Точність координати в MGRS задається з точністю в один метр і представлена ​​за допомогою 15 символів, де останні 10 символів представляють значення східного і північного відмін у зазначеній сітці. У MGRS координати можуть бути представлені 15 символами, як в попередньому випадку, або 13, 11, 9 або 7 символами; представлені таким чином значення будуть відповідно мати точність 1, 10, 100, 1000 або 10000 метрів.

У цій статті докладно не розбирається MGRS, але скачуваний код включає в себе перетворення між широтою / довготою і MGRS. В розділі ресурси приведена додаткова інформація.

перетворення координат

Щоб визначити ширину і довготу - координати місця розташування на Землі, як мінімум потрібно мати можливість бачити зірки або Сонце, мати секстан і годинник, що показує час на меридіані GMT. Можна визначити широту з кута між небесним тілом і горизонтом, а довготу можна обчислити з обертання Землі. Ця стаття не занурюється в подібні подробиці, але в розділі ресурси про них можна дізнатися більше. Замість цього, припустимо, що у нас вже є координати в форматі DD, DMS або UTM.

Перетворення десяткових градусів в градуси / хвилини / секунди і назад

Вкрай просто перетворити координати з формату DD в DMS. Нижче наведена формула для подібного перетворення:

DD: dd.ff DMS: dd mm ss dd = dd mm.gg = 60 * ff ss = 60 * gg

У цьому прикладі gg - це дрібна частина обчислення. Негативна широта означає розташування в південній півкулі (S), а негативна довгота - в західній півкулі (W). Наприклад, припустимо, що є координати в форматі DD - 61.44, 25.40. Їх можна перетворити в такий спосіб:

lat dd = 61 lat mm.gg = 60 * 0.44 = 26.4 lat ss = 60 * 0.4 = 24

далі:

lon dd = 25 lon mm.gg = 60 * 0.40 = 24.0 lon ss = 60 * 0.0 = 0

Таким чином, в форматі DMS отримуємо наступні координати - 61 ° 26'24''N 25 ° 24'00''E.

Нижче наведена формула для переходу від DMS до DD:

DD: dd.ff DMS: dd mm ss dd.ff = dd + mm / 60 + ss / 3600

Нагадаємо, що місця, розташовані в південній півкулі (S), мають негативну широту, а місця в західній півкулі (W) мають негативну довготу.

Тепер виконаємо перетворення DMS координат 47 ° 02'24 ''S, 73 ° 28'48''W в формат DD:

lat dd.ff = - (47 + 2/60 + 24/3600) = - 47.04 lon dd.ff = - (73 + 28/60 + 48/3600) = - 73.48

Таким чином, координати в DD рівні -47.04, -73.48.

Перетворення довготи / широти в UTM і назад

На відміну від десяткових координат, які можна визначити за допомогою хронометра і годин, координати UTM неможливо визначити без допомоги обчислень. Хоча ці обчислення ніщо інше, як проста тригонометрія і алгебра, формули у них досить складні. Якщо ознайомитися зі статтею "The Universal Grids: Universal Transverse Mercator (UTM) and Universal Polar Stereographic (UPS)" (посилання на неї наведена в розділі ресурси ), То стане зрозуміло, що я маю на увазі.

Формули для перетворення UTM тут не наводяться, але вихідний код в наступному розділі трохи висвітлює цю проблему, а в розділі ресурси є посилання на додаткову інформацію.

Перетворення координат в Java коді

У цьому розділі наведено вихідний код класу бібліотеки, який виконує перетворення координат між десятковими градусами і UTM. Цей Java-клас називається com.ibm.util.CoordinateConversion і я хотів створити окремий клас з методами для перетворення. Цей клас включає внутрішні класи, які насправді виконують перетворення, і при необхідності ці класи можуть бути винесені з класу CoordinateConversion за допомогою рефакторінга, щоб створити пакет бібліотеки або додати класи в існуючий пакет. Перетворення, що виконуються цим класом, мають точність в 1 метр.

У вихідному коді CoordinateConversion близько 750 рядків, так що в цій статті він представлений не повністю. Істотні методи описані в наступних розділах, а повністю код доступний в розділі Матеріали для скачування .

клас CoordinateConversion

CoordinateConversion - це головний клас, об'єкти якого створюються при необхідності виконання перетворення координат. У лістингу 1 наведені істотні public методи разом з внутрішніми private класами, що входять в клас CoordinateConversion:

Лістинг 1. CoordinateConversion

public class CoordinateConversion {public CoordinateConversion () {} public double [] utm2LatLon (String UTM) {UTM2LatLon c = new UTM2LatLon (); return c.convertUTMToLatLong (UTM); } Public String latLon2UTM (double latitude, double longitude) {LatLon2UTM c = new LatLon2UTM (); return c.convertLatLonToUTM (latitude, longitude); } //..Реалізація пропущена private class LatLon2UTM {public String convertLatLonToUTM (double latitude, double longitude) {//..реалізація пропущена} //..реалізація пропущена} private class LatLon2MGRUTM extends LatLon2UTM {public String convertLatLonToMGRUTM (double latitude, double longitude) {//..реалізація пропущена} //..реалізація пропущена} private class MGRUTM2LatLon extends UTM2LatLon {public double [] convertMGRUTMToLatLong (String mgrutm) {//..реалізація пропущена} //..реалізація пропущена} private class UTM2LatLon {public double [] convertUTMToLatLong (String UTM) {//..реалізація пропущена} //..реалізація пропущена} private class Digraphs {// використовується для отримання двобуквений кодів // при перетворенні від довготи / широт до MGRS //..реалізація пропущена} private class LatZones {// включає методи для визначення зон широти //..реалізація пропущена}

У наступному розділі докладно розглядаються перетворення між довготою / широтою і UTM.

Перетворення від широти / довготи до UTM

Координати перетворюються від широти / довготи в UTM за допомогою методу String latLon2UTM (double latitude, double longitude). Реалізація цього методу створює екземпляр внутрішнього класу LatLon2UTM c = new LatLon2UTM (); і повертає координати UTM у вигляді 15-символьного рядка з точністю 1 метр. Реалізація методів класу LatLon2UTM приведена в лістингу 2:

Лістинг 2. public String convertLatLonToUTM (double latitude, double longitude)

public String convertLatLonToUTM (double latitude, double longitude) {validate (latitude, longitude); String UTM = ""; setVariables (latitude, longitude); String longZone = getLongZone (longitude); LatZones latZones = new LatZones (); String latZone = latZones.getLatZone (latitude); double _easting = getEasting (); double _northing = getNorthing (latitude); UTM = longZone + "" + latZone + "" + ((int) _easting) + "" + ((int) _northing); return UTM; }

Цей метод може конвертувати, викликаючи різні методи для отримання зони широти і зони довготи, обчислення східного і північного схиляння і т.д. Вхідні дані перевіряються в методі validate (), якщо вираз (latitude <-90.0 || latitude> 90.0 || longitude <-180.0 || longitude> = 180.0) приймає значення true, то скидається виняткова ситуація IllegalArgumentException.

Метод setVariables () в лістингу 3 встановлює різні змінні, що вимагаються для обчислення перетворень (додаткова інформація представлена ​​в статті "The Universal Grids", посилання на яку наведено в розділі ресурси :

Лістинг 3. protected void setVariables (double latitude, double longitude)

protected void setVariables (double latitude, double longitude) {latitude = degreeToRadian (latitude); rho = equatorialRadius * (1 - e * e) / POW (1 - POW (e * SIN (latitude), 2), 3 / 2.0); nu = equatorialRadius / POW (1 - POW (e * SIN (latitude), 2), (1 / 2.0)); double var1; if (longitude <0.0) {var1 = ((int) ((180 + longitude) / 6.0)) + 1; } Else {var1 = ((int) (longitude / 6)) + 31; } Double var2 = (6 * var1) - 183; double var3 = longitude - var2; p = var3 * 3600/10000; S = A0 * latitude - B0 * SIN (2 * latitude) + C0 * SIN (4 * latitude) - D0 * SIN (6 * latitude) + E0 * SIN (8 * latitude); K1 = S * k0; K2 = nu * SIN (latitude) * COS (latitude) * POW (sin1, 2) * k0 * (100000000) / 2; K3 = ((POW (sin1, 4) * nu * SIN (latitude) * Math.pow (COS (latitude), 3)) / 24) * (5 - POW (TAN (latitude), 2) + 9 * e1sq * POW (COS (latitude), 2) + 4 * POW (e1sq, 2) * POW (COS (latitude), 4)) * k0 * (10000000000000000L); K4 = nu * COS (latitude) * sin1 * k0 * 10000; K5 = POW (sin1 * COS (latitude), 3) * (nu / 6) * (1 - POW (TAN (latitude), 2) + e1sq * POW (COS (latitude), 2)) * k0 * 1000000000000L; A6 = (POW (p * sin1, 6) * nu * SIN (latitude) * POW (COS (latitude), 5) / 720) * (61 - 58 * POW (TAN (latitude), 2) + POW (TAN (latitude), 4) + 270 * e1sq * POW (COS (latitude), 2) - 330 * e1sq * POW (SIN (latitude), 2)) * k0 * (1E + 24); }

Метод getLongZone () в лістингу 4 або LatZones, доступний в вихідному коді , Використовуються, щоб дізнатися зону довготи і зону широти. Зона довготи обчислюється по параметру longitude, а зони широти зазвичай представлені як константи, за допомогою масиву в класі LatZones.

Лістинг 4. protected String getLongZone (double longitude)

protected String getLongZone (double longitude) {double longZone = 0; if (longitude <0.0) {longZone = ((180.0 + longitude) / 6) + 1; } Else {longZone = (longitude / 6) + 31; } String val = String.valueOf ((int) longZone); if (val.length () == 1) {val = "0" + val; } Return val; }

Метод getNorthing () в лістингу 5 і метод getEasting () в лістингу 6 обчислюють значення північного і східного відмінювання. Обидва методи використовують змінні, встановлені в методі setVariables () з лістингу 3 .

Лістинг 5. protected double getNorthing (double latitude)

protected double getNorthing (double latitude) {double northing = K1 + K2 * p * p + K3 * POW (p, 4); if (latitude <0.0) {northing = 10000000 + northing; } Return northing; }

Лістинг 6. protected double getEasting ()

protected double getEasting () {return 500000 + (K4 * p + K5 * POW (p, 3)); }

У лістингу 7 наведено кілька прикладів результатів роботи програми, включаючи координати в форматі широта / довгота і відповідні їм UTM координати:

Лістинг 7. Тестові перетворення від широти / довготи до значень в UTM

(0.0000 0.0000) "31 N 166021 0" (0.1300 -0.2324) "30 N 808084 14385" (-45.6456 23.3545) "34 G 683473 4942631" (-12.7650 -33.8765) "25 L 404 859 8588690" (-80.5434 -170.6540) "02 C 506 346 1057742" (90.0000 177.0000) "60 Z 500000 9997964" (-90.0000 -177.0000) "01 A 500000 2035" (90.0000 3.0000) "31 Z 500000 9997964" (23.4578 -135.4545) "08 Q 453 580 2594272" ( 77.3450 156.9876) "57 X 450 793 8586116" (-89.3454 -48.9306) "22 A 502639 75072"

Перетворення від UTM до широти / довготі

Перетворення від координат в форматі UTM до широти / довготі виконується трохи простіше, ніж зворотний процес. У статті "The Universal Grids" в розділі ресурси ) Наведені формули перетворень. У лістингу 8 наведено код методу convertUTMToLatLong (). Цей метод повертає масив double значень, де перший елемент (з індексом масиву [0]) - це широта, а другий елемент (з індексом масиву [1]) - це довгота. Так як строковий параметр містить координати UTM з точністю до 1 метра, то і координати в широті / довготі матимуть таку ж точність.

Лістинг 8. public double [] convertUTMToLatLong (String UTM)

public double [] convertUTMToLatLong (String UTM) {double [] latlon = {0.0, 0.0}; String [] utm = UTM.split ( ""); zone = Integer.parseInt (utm [0]); String latZone = utm [1]; easting = Double.parseDouble (utm [2]); northing = Double.parseDouble (utm [3]); String hemisphere = getHemisphere (latZone); double latitude = 0,0; double longitude = 0,0; if (hemisphere.equals ( "S")) {northing = 10000000 - northing; } SetVariables (); latitude = 180 * (phi1 - fact1 * (fact2 + fact3 + fact4)) / Math.PI; if (zone> 0) {zoneCM = 6 * zone - 183.0; } Else {zoneCM = 3.0; } Longitude = zoneCM - _a3; if (hemisphere.equals ( "S")) {latitude = -latitude; } Latlon [0] = latitude; latlon [1] = longitude; return latlon; }

Метод convertUTMToLatLong () розбиває координати UTM у вхідному строковому параметрі, які мають формат 34 G 683473 4942631, і використовує метод getHemisphere () для визначення півкулі, де знаходиться місце з вказаними координатами. Визначити півкуля просто: зони широти A, C, D, E, F, G, H, J, K, L і M знаходяться в південній півкулі, а решта зони знаходяться в північній півкулі.

Метод setVariables (), показаний в лістингу 9, встановлює значення змінних, необхідних для обчислення, і потім негайно обчислюють широту. Довгота обчислюється з використанням зони довготи.

Лістинг 9. protected void setVariables ()

protected void setVariables () {arc = northing / k0; mu = arc / (a ​​* (1 - POW (e, 2) / 4.0 - 3 * POW (e, 4) / 64.0 - 5 * POW (e, 6) / 256,0)); ei = (1 - POW ((1 - e * e), (1 / 2.0))) / (1 + POW ((1 - e * e), (1 / 2.0))); ca = 3 * ei / 2 - 27 * POW (ei, 3) / 32.0; cb = 21 * POW (ei, 2) / 16 - 55 * POW (ei, 4) / 32; cc = 151 * POW (ei, 3) / 96; cd = 1097 * POW (ei, 4) / 512; phi1 = mu + ca * SIN (2 * mu) + cb * SIN (4 * mu) + cc * SIN (6 * mu) + cd * SIN (8 * mu); n0 = a / POW ((1 - POW ((e * SIN (phi1)), 2)), (1 / 2.0)); r0 = a * (1 - e * e) / POW ((1 - POW ((e * SIN (phi1)), 2)), (3 / 2.0)); fact1 = n0 * TAN (phi1) / r0; _a1 = 500000 - easting; dd0 = _a1 / (n0 * k0); fact2 = dd0 * dd0 / 2; t0 = POW (TAN (phi1), 2); Q0 = e1sq * POW (COS (phi1), 2); fact3 = (5 + 3 * t0 + 10 * Q0 - 4 * Q0 * Q0 - 9 * e1sq) * POW (dd0, 4) / 24; fact4 = (61 + 90 * t0 + 298 * Q0 + 45 * t0 * t0 - 252 * e1sq - 3 * Q0 * Q0) * POW (dd0, 6) / 720; lof1 = _a1 / (n0 * k0); lof2 = (1 + 2 * t0 + Q0) * POW (dd0, 3) / 6.0; lof3 = (5 - 2 * Q0 + 28 * t0 - 3 * POW (Q0, 2) + 8 * e1sq + 24 * POW (t0, 2)) * POW (dd0, 5) / 120; _a2 = (lof1 - lof2 + lof3) / COS (phi1); _a3 = _a2 * 180 / Math.PI; }

Метод setVariables () використовує значення східного і північного відмін для установки необхідних змінних. Ці змінні належать обом класам і встановлюються в методі convertUTMToLatLong (String UTM) з лістингу 8 .

інші методи

Вихідний код також містить інші public і private методи і класи. Наприклад, туди включені методи і класи для перетворення координат між широтою / довготою і MGRS разом з допоміжними методами, які виконують перетворення градусів в радіани і навпаки, і різними математичними операціями, такими як POW, SIN, COS, and TAN.

висновок

У цій статті наведено трохи теорії за світовими системам координат разом з Java-класів для виконання перетворення координат з однієї системи в іншу. Хоча не всі формули для перетворення координат були детально тут розглянуті, вони доступні в розділі ресурси . Зазвичай теоретичні відомості не потрібні в щоденному процесі розробки, крім рідкісних випадків, коли немає іншого способу, як я недавно переконався, коли мені довелося виконувати завдання перетворення координат.

Мені треба було виконувати перетворення між широтою і довготою, UTM і MGRS, так що я виконав базові дослідження і реалізував ці перетворення в Java-класі. Для мене розробка зайняла кілька годин, і я сподіваюся, що і інші також зможуть заощадити кілька годин для інших завдань і вважатимуть корисним використання класу CoordinateConversion в своїй роботі.

Ресурси для скачування

Схожі тими

  • Coordinate conversions made easy (EN) : Оригінал статті
  • Gartner's 2006 emerging technologies hype cycle highlights key technology themes (EN) : Прес-реліз від Gartner містить цікаві відомості про поширеність додатків, що використовують географічні координати.
  • The Universal Grids: Universal TransverseMercator (UTM) and Universal Polar Stereographic (UPS) (EN) : Стаття Національного Графічного і Картографічного Агентства (National Imagery and Mapping Agency - NIMA) містить формули UTM і іншу інформацію про систему координат UTM. (Стаття представлена ​​в форматі PDF.)
  • Location-based services (EN) : (Valerie Bennett і Andrew Capella, developerWorks, березень 2002): стаття з введенням в основні принципи, що лежать в основі систем, пов'язаних з позиціонуванням.
  • Put yourself on the map with Google Maps API, DB2 / Informix, and PHP on Linux (EN) : (Marty Lurie and Aron Y. Lurie, developerWorks, березень 2006): стаття з вихідним кодом, що перетворює ZIP-код у координати широти і довготи.
  • Creating an automatically maintained spatial table from latitude-longitude column data (EN) : (EN) (Robert Uleman, developerWorks, квітень 2006): стаття про те як DB2 може допомогти в перетворенні необроблених координат в корисну інформацію.
  • У Wikipedia можна дізнатися про основні концепції, представлених в цій статті: (EN)
  • developerWorks Java technology zone : Сотні статей про всі аспекти Java-програмування.

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів

Виконувати перетворення координат стало простіше

Посібник з перетворення між різними системами координат

Служби позиціонування, включаючи навігацію на основі GPS і картографічні сайти, такі як Google Maps і Yahoo! Maps, стають популярними серед користувачів. Безліч організацій вже використовують сервіси, пов'язані з використанням інформації про географічні координати, і ще більше компаній підуть цим шляхом, як тільки усвідомлюють переваги і потенціал подібних додатків. У 2006 році аналітична компанія Gartner зазначила, що "додатка, пов'язані з позиціонуванням, стануть масовими протягом наступних двох-п'яти років" і що вже "значне число організацій розгорнули мобільні бізнес-функції, які залежать позиціонування". (В розділі ресурси наведено посилання на цей звіт.)

Коли організація вирішує реалізувати програму, яка використовує географічну систему координат, зазвичай написання такого додатка стає завданням розробника. Побудова програми, що використовує географічні координати, включає в себе багато великих і маленьких завдань, і однією з таких завдань, відносно простий, буде перетворення координат з однієї системи в іншу. У цій статті представлений код, який виконує таке перетворення і може допомогти заощадити безліч годин роботи.

Дві різні системи координат

Перш ніж зануритися в код, представлений в цій статті, необхідно обговорити координатні системи, для підтримки яких цей код призначений: відома система широти і довготи і універсальна поперечна проекція Меркатора (Universal Transverse Mercator - UTM). Також потрібно торкнутися військової системи координат (Military Grid Reference System - MGRS), яка заснована на UTM.

Широта і довгота

Системи широти і довготи, ймовірно, найвідоміший спосіб визначення географічних координат. У ній місце розташування представляється двома числами. Широта - це кут від центру землі до деякої паралелі на земній поверхні. Довгота - це кут від центру землі до деякого меридіану на земній поверхні. Широта і довгота можуть бути виражені в десяткових градусах (DD) або градусах, хвилинах і секунда (DMS); в останньому випадку виходять числа в такому форматі - 49 ° 30'00 "S 12 ° 30'00" E. Цей формат зазвичай використовується в GPS-навігаторах.

Земля розділена екватором (0 ° широти) на північну і південну півкулі, і нульовим меридіаном (0 ° довготи), уявною лінією від північного до південного полюса, яка проходітчерез місто Грінвіч в Великобританії і ділить планету на східне і західне півкуля. Діапазон широт в північній півкулі від 0 до 90 градусів, а в південній півкулі - від 0 до -90 градусів. Діапазон східної півкулі від 0 до 180 градусів, а західної півкулі від 0 до -180 градусів.

Наприклад, точка з координатами 61.44, 25.40 (в форматі DD) або 61 ° 26'24''N, 25 ° 23'60''E (в форматі DMS) знаходиться в південній Фінляндії. А точка з координатами -47.04, -73.48 (DD) або 47 ° 02'24 ''S, 73 ° 28'48''W (DMS) знаходиться в південному Чилі. На малюнку 1 наведено зображення Землі з перекриваються лініями паралелей і меридіанів:

Малюнок 1. Земля з показаними лініями паралелей і меридіанів

Додаткову інформацію можна знайти в розділі ресурси .

Поперечна проекція Меркатора

Система координат UTM - це метод, який використовує сітку для визначення координат. Система UTM ділить Землю на 60 зон, кожна з яких заснована на поперечної проекції Меркатора. Проекція карти в картографії - це спосіб представити двовимірну нерівну поверхню на площині, як звичайну карту. на малюнку 2 приведена поперечна проекція Меркатора:

Малюнок 2. Поперечна проекція Меркатора

Зони довготи в UTM пронумеровані від 1 до 60; всі зони окрім двох, про яких буде розказано пізніше, мають ширину 6 ° від сходу до заходу. Зони довготи повністю покривають поверхню Землі між широтами 80 ° S і 84 ° N.

Також є 20 зон широти, кожна в 8 ° заввишки; ці зони пронумеровані від C до X, літери I і O пропущені. Зони A, B, Y і Z знаходяться за межами цієї системи, вони покривають Арктику і Антарктику. на малюнку 3 наведені UTM зони для Європи. На цьому малюнку видно дві нестандартні зони довготи: зона 32V розширена для покриття всієї південної Норвегії, а зона 31V скорочена, щоб покривати тільки водний простір.

Малюнок 3. Зони UTM в Європі

Координати в UTM представлені в форматі зона довготи зона широти східне схиляння північне відмінювання, де східне схиляння - це проекційне відстань від центрального меридіана зони довготи, північне відмінювання - це проекційне відстань від екватора. Значення східного і північного відмін задаються в метрах. Наприклад, координати широти / довготи 61.44, 25.40 в UTM представлені як 35 V 414668 6812844; координати широти / довготи -47.04, -73.48 відповідають координатам 18 G 615471 4789269 в UTM.

В розділі ресурси приведена додаткова інформація по UTM і поперечної проекції Меркатора.

Військова система координат

Система координат MGRS - стандарт, використовуваний військовими НАТО. MGRS заснована на UTM і далі ділить кожну зону на квадрати 100х100 км. Ці квадрати ідентифікуються з двох літер кодом, перша буква - східно-західна позиція в зоні довготи, а друга буква - північно-південна позиція.

Наприклад, координата в UTM 35 V 414668 6812844 еквівалента координаті MGRS 35VMJ1466812844. Точність координати в MGRS задається з точністю в один метр і представлена ​​за допомогою 15 символів, де останні 10 символів представляють значення східного і північного відмін у зазначеній сітці. У MGRS координати можуть бути представлені 15 символами, як в попередньому випадку, або 13, 11, 9 або 7 символами; представлені таким чином значення будуть відповідно мати точність 1, 10, 100, 1000 або 10000 метрів.

У цій статті докладно не розбирається MGRS, але скачуваний код включає в себе перетворення між широтою / довготою і MGRS. В розділі ресурси приведена додаткова інформація.

перетворення координат

Щоб визначити ширину і довготу - координати місця розташування на Землі, як мінімум потрібно мати можливість бачити зірки або Сонце, мати секстан і годинник, що показує час на меридіані GMT. Можна визначити широту з кута між небесним тілом і горизонтом, а довготу можна обчислити з обертання Землі. Ця стаття не занурюється в подібні подробиці, але в розділі ресурси про них можна дізнатися більше. Замість цього, припустимо, що у нас вже є координати в форматі DD, DMS або UTM.

Перетворення десяткових градусів в градуси / хвилини / секунди і назад

Вкрай просто перетворити координати з формату DD в DMS. Нижче наведена формула для подібного перетворення:

DD: dd.ff DMS: dd mm ss dd = dd mm.gg = 60 * ff ss = 60 * gg

У цьому прикладі gg - це дрібна частина обчислення. Негативна широта означає розташування в південній півкулі (S), а негативна довгота - в західній півкулі (W). Наприклад, припустимо, що є координати в форматі DD - 61.44, 25.40. Їх можна перетворити в такий спосіб:

lat dd = 61 lat mm.gg = 60 * 0.44 = 26.4 lat ss = 60 * 0.4 = 24

далі:

lon dd = 25 lon mm.gg = 60 * 0.40 = 24.0 lon ss = 60 * 0.0 = 0

Таким чином, в форматі DMS отримуємо наступні координати - 61 ° 26'24''N 25 ° 24'00''E.

Нижче наведена формула для переходу від DMS до DD:

DD: dd.ff DMS: dd mm ss dd.ff = dd + mm / 60 + ss / 3600

Нагадаємо, що місця, розташовані в південній півкулі (S), мають негативну широту, а місця в західній півкулі (W) мають негативну довготу.

Тепер виконаємо перетворення DMS координат 47 ° 02'24 ''S, 73 ° 28'48''W в формат DD:

lat dd.ff = - (47 + 2/60 + 24/3600) = - 47.04 lon dd.ff = - (73 + 28/60 + 48/3600) = - 73.48

Таким чином, координати в DD рівні -47.04, -73.48.

Перетворення довготи / широти в UTM і назад

На відміну від десяткових координат, які можна визначити за допомогою хронометра і годин, координати UTM неможливо визначити без допомоги обчислень. Хоча ці обчислення ніщо інше, як проста тригонометрія і алгебра, формули у них досить складні. Якщо ознайомитися зі статтею "The Universal Grids: Universal Transverse Mercator (UTM) and Universal Polar Stereographic (UPS)" (посилання на неї наведена в розділі ресурси ), То стане зрозуміло, що я маю на увазі.

Формули для перетворення UTM тут не наводяться, але вихідний код в наступному розділі трохи висвітлює цю проблему, а в розділі ресурси є посилання на додаткову інформацію.

Перетворення координат в Java коді

У цьому розділі наведено вихідний код класу бібліотеки, який виконує перетворення координат між десятковими градусами і UTM. Цей Java-клас називається com.ibm.util.CoordinateConversion і я хотів створити окремий клас з методами для перетворення. Цей клас включає внутрішні класи, які насправді виконують перетворення, і при необхідності ці класи можуть бути винесені з класу CoordinateConversion за допомогою рефакторінга, щоб створити пакет бібліотеки або додати класи в існуючий пакет. Перетворення, що виконуються цим класом, мають точність в 1 метр.

У вихідному коді CoordinateConversion близько 750 рядків, так що в цій статті він представлений не повністю. Істотні методи описані в наступних розділах, а повністю код доступний в розділі Матеріали для скачування .

клас CoordinateConversion

CoordinateConversion - це головний клас, об'єкти якого створюються при необхідності виконання перетворення координат. У лістингу 1 наведені істотні public методи разом з внутрішніми private класами, що входять в клас CoordinateConversion:

Лістинг 1. CoordinateConversion

public class CoordinateConversion {public CoordinateConversion () {} public double [] utm2LatLon (String UTM) {UTM2LatLon c = new UTM2LatLon (); return c.convertUTMToLatLong (UTM); } Public String latLon2UTM (double latitude, double longitude) {LatLon2UTM c = new LatLon2UTM (); return c.convertLatLonToUTM (latitude, longitude); } //..Реалізація пропущена private class LatLon2UTM {public String convertLatLonToUTM (double latitude, double longitude) {//..реалізація пропущена} //..реалізація пропущена} private class LatLon2MGRUTM extends LatLon2UTM {public String convertLatLonToMGRUTM (double latitude, double longitude) {//..реалізація пропущена} //..реалізація пропущена} private class MGRUTM2LatLon extends UTM2LatLon {public double [] convertMGRUTMToLatLong (String mgrutm) {//..реалізація пропущена} //..реалізація пропущена} private class UTM2LatLon {public double [] convertUTMToLatLong (String UTM) {//..реалізація пропущена} //..реалізація пропущена} private class Digraphs {// використовується для отримання двобуквений кодів // при перетворенні від довготи / широт до MGRS //..реалізація пропущена} private class LatZones {// включає методи для визначення зон широти //..реалізація пропущена}

У наступному розділі докладно розглядаються перетворення між довготою / широтою і UTM.

Перетворення від широти / довготи до UTM

Координати перетворюються від широти / довготи в UTM за допомогою методу String latLon2UTM (double latitude, double longitude). Реалізація цього методу створює екземпляр внутрішнього класу LatLon2UTM c = new LatLon2UTM (); і повертає координати UTM у вигляді 15-символьного рядка з точністю 1 метр. Реалізація методів класу LatLon2UTM приведена в лістингу 2:

Лістинг 2. public String convertLatLonToUTM (double latitude, double longitude)

public String convertLatLonToUTM (double latitude, double longitude) {validate (latitude, longitude); String UTM = ""; setVariables (latitude, longitude); String longZone = getLongZone (longitude); LatZones latZones = new LatZones (); String latZone = latZones.getLatZone (latitude); double _easting = getEasting (); double _northing = getNorthing (latitude); UTM = longZone + "" + latZone + "" + ((int) _easting) + "" + ((int) _northing); return UTM; }

Цей метод може конвертувати, викликаючи різні методи для отримання зони широти і зони довготи, обчислення східного і північного схиляння і т.д. Вхідні дані перевіряються в методі validate (), якщо вираз (latitude <-90.0 || latitude> 90.0 || longitude <-180.0 || longitude> = 180.0) приймає значення true, то скидається виняткова ситуація IllegalArgumentException.

Метод setVariables () в лістингу 3 встановлює різні змінні, що вимагаються для обчислення перетворень (додаткова інформація представлена ​​в статті "The Universal Grids", посилання на яку наведено в розділі ресурси :

Лістинг 3. protected void setVariables (double latitude, double longitude)

protected void setVariables (double latitude, double longitude) {latitude = degreeToRadian (latitude); rho = equatorialRadius * (1 - e * e) / POW (1 - POW (e * SIN (latitude), 2), 3 / 2.0); nu = equatorialRadius / POW (1 - POW (e * SIN (latitude), 2), (1 / 2.0)); double var1; if (longitude <0.0) {var1 = ((int) ((180 + longitude) / 6.0)) + 1; } Else {var1 = ((int) (longitude / 6)) + 31; } Double var2 = (6 * var1) - 183; double var3 = longitude - var2; p = var3 * 3600/10000; S = A0 * latitude - B0 * SIN (2 * latitude) + C0 * SIN (4 * latitude) - D0 * SIN (6 * latitude) + E0 * SIN (8 * latitude); K1 = S * k0; K2 = nu * SIN (latitude) * COS (latitude) * POW (sin1, 2) * k0 * (100000000) / 2; K3 = ((POW (sin1, 4) * nu * SIN (latitude) * Math.pow (COS (latitude), 3)) / 24) * (5 - POW (TAN (latitude), 2) + 9 * e1sq * POW (COS (latitude), 2) + 4 * POW (e1sq, 2) * POW (COS (latitude), 4)) * k0 * (10000000000000000L); K4 = nu * COS (latitude) * sin1 * k0 * 10000; K5 = POW (sin1 * COS (latitude), 3) * (nu / 6) * (1 - POW (TAN (latitude), 2) + e1sq * POW (COS (latitude), 2)) * k0 * 1000000000000L; A6 = (POW (p * sin1, 6) * nu * SIN (latitude) * POW (COS (latitude), 5) / 720) * (61 - 58 * POW (TAN (latitude), 2) + POW (TAN (latitude), 4) + 270 * e1sq * POW (COS (latitude), 2) - 330 * e1sq * POW (SIN (latitude), 2)) * k0 * (1E + 24); }

Метод getLongZone () в лістингу 4 або LatZones, доступний в вихідному коді , Використовуються, щоб дізнатися зону довготи і зону широти. Зона довготи обчислюється по параметру longitude, а зони широти зазвичай представлені як константи, за допомогою масиву в класі LatZones.

Лістинг 4. protected String getLongZone (double longitude)

protected String getLongZone (double longitude) {double longZone = 0; if (longitude <0.0) {longZone = ((180.0 + longitude) / 6) + 1; } Else {longZone = (longitude / 6) + 31; } String val = String.valueOf ((int) longZone); if (val.length () == 1) {val = "0" + val; } Return val; }

Метод getNorthing () в лістингу 5 і метод getEasting () в лістингу 6 обчислюють значення північного і східного відмінювання. Обидва методи використовують змінні, встановлені в методі setVariables () з лістингу 3 .

Лістинг 5. protected double getNorthing (double latitude)

protected double getNorthing (double latitude) {double northing = K1 + K2 * p * p + K3 * POW (p, 4); if (latitude <0.0) {northing = 10000000 + northing; } Return northing; }

Лістинг 6. protected double getEasting ()

protected double getEasting () {return 500000 + (K4 * p + K5 * POW (p, 3)); }

У лістингу 7 наведено кілька прикладів результатів роботи програми, включаючи координати в форматі широта / довгота і відповідні їм UTM координати:

Лістинг 7. Тестові перетворення від широти / довготи до значень в UTM

(0.0000 0.0000) "31 N 166021 0" (0.1300 -0.2324) "30 N 808084 14385" (-45.6456 23.3545) "34 G 683473 4942631" (-12.7650 -33.8765) "25 L 404 859 8588690" (-80.5434 -170.6540) "02 C 506 346 1057742" (90.0000 177.0000) "60 Z 500000 9997964" (-90.0000 -177.0000) "01 A 500000 2035" (90.0000 3.0000) "31 Z 500000 9997964" (23.4578 -135.4545) "08 Q 453 580 2594272" ( 77.3450 156.9876) "57 X 450 793 8586116" (-89.3454 -48.9306) "22 A 502639 75072"

Перетворення від UTM до широти / довготі

Перетворення від координат в форматі UTM до широти / довготі виконується трохи простіше, ніж зворотний процес. У статті "The Universal Grids" в розділі ресурси ) Наведені формули перетворень. У лістингу 8 наведено код методу convertUTMToLatLong (). Цей метод повертає масив double значень, де перший елемент (з індексом масиву [0]) - це широта, а другий елемент (з індексом масиву [1]) - це довгота. Так як строковий параметр містить координати UTM з точністю до 1 метра, то і координати в широті / довготі матимуть таку ж точність.

Лістинг 8. public double [] convertUTMToLatLong (String UTM)

public double [] convertUTMToLatLong (String UTM) {double [] latlon = {0.0, 0.0}; String [] utm = UTM.split ( ""); zone = Integer.parseInt (utm [0]); String latZone = utm [1]; easting = Double.parseDouble (utm [2]); northing = Double.parseDouble (utm [3]); String hemisphere = getHemisphere (latZone); double latitude = 0,0; double longitude = 0,0; if (hemisphere.equals ( "S")) {northing = 10000000 - northing; } SetVariables (); latitude = 180 * (phi1 - fact1 * (fact2 + fact3 + fact4)) / Math.PI; if (zone> 0) {zoneCM = 6 * zone - 183.0; } Else {zoneCM = 3.0; } Longitude = zoneCM - _a3; if (hemisphere.equals ( "S")) {latitude = -latitude; } Latlon [0] = latitude; latlon [1] = longitude; return latlon; }

Метод convertUTMToLatLong () розбиває координати UTM у вхідному строковому параметрі, які мають формат 34 G 683473 4942631, і використовує метод getHemisphere () для визначення півкулі, де знаходиться місце з вказаними координатами. Визначити півкуля просто: зони широти A, C, D, E, F, G, H, J, K, L і M знаходяться в південній півкулі, а решта зони знаходяться в північній півкулі.

Метод setVariables (), показаний в лістингу 9, встановлює значення змінних, необхідних для обчислення, і потім негайно обчислюють широту. Довгота обчислюється з використанням зони довготи.

Лістинг 9. protected void setVariables ()

protected void setVariables () {arc = northing / k0; mu = arc / (a ​​* (1 - POW (e, 2) / 4.0 - 3 * POW (e, 4) / 64.0 - 5 * POW (e, 6) / 256,0)); ei = (1 - POW ((1 - e * e), (1 / 2.0))) / (1 + POW ((1 - e * e), (1 / 2.0))); ca = 3 * ei / 2 - 27 * POW (ei, 3) / 32.0; cb = 21 * POW (ei, 2) / 16 - 55 * POW (ei, 4) / 32; cc = 151 * POW (ei, 3) / 96; cd = 1097 * POW (ei, 4) / 512; phi1 = mu + ca * SIN (2 * mu) + cb * SIN (4 * mu) + cc * SIN (6 * mu) + cd * SIN (8 * mu); n0 = a / POW ((1 - POW ((e * SIN (phi1)), 2)), (1 / 2.0)); r0 = a * (1 - e * e) / POW ((1 - POW ((e * SIN (phi1)), 2)), (3 / 2.0)); fact1 = n0 * TAN (phi1) / r0; _a1 = 500000 - easting; dd0 = _a1 / (n0 * k0); fact2 = dd0 * dd0 / 2; t0 = POW (TAN (phi1), 2); Q0 = e1sq * POW (COS (phi1), 2); fact3 = (5 + 3 * t0 + 10 * Q0 - 4 * Q0 * Q0 - 9 * e1sq) * POW (dd0, 4) / 24; fact4 = (61 + 90 * t0 + 298 * Q0 + 45 * t0 * t0 - 252 * e1sq - 3 * Q0 * Q0) * POW (dd0, 6) / 720; lof1 = _a1 / (n0 * k0); lof2 = (1 + 2 * t0 + Q0) * POW (dd0, 3) / 6.0; lof3 = (5 - 2 * Q0 + 28 * t0 - 3 * POW (Q0, 2) + 8 * e1sq + 24 * POW (t0, 2)) * POW (dd0, 5) / 120; _a2 = (lof1 - lof2 + lof3) / COS (phi1); _a3 = _a2 * 180 / Math.PI; }

Метод setVariables () використовує значення східного і північного відмін для установки необхідних змінних. Ці змінні належать обом класам і встановлюються в методі convertUTMToLatLong (String UTM) з лістингу 8 .

інші методи

Вихідний код також містить інші public і private методи і класи. Наприклад, туди включені методи і класи для перетворення координат між широтою / довготою і MGRS разом з допоміжними методами, які виконують перетворення градусів в радіани і навпаки, і різними математичними операціями, такими як POW, SIN, COS, and TAN.

висновок

У цій статті наведено трохи теорії за світовими системам координат разом з Java-класів для виконання перетворення координат з однієї системи в іншу. Хоча не всі формули для перетворення координат були детально тут розглянуті, вони доступні в розділі ресурси . Зазвичай теоретичні відомості не потрібні в щоденному процесі розробки, крім рідкісних випадків, коли немає іншого способу, як я недавно переконався, коли мені довелося виконувати завдання перетворення координат.

Мені треба було виконувати перетворення між широтою і довготою, UTM і MGRS, так що я виконав базові дослідження і реалізував ці перетворення в Java-класі. Для мене розробка зайняла кілька годин, і я сподіваюся, що і інші також зможуть заощадити кілька годин для інших завдань і вважатимуть корисним використання класу CoordinateConversion в своїй роботі.

Ресурси для скачування

Схожі теми

  • Coordinate conversions made easy (EN) : Оригінал статті
  • Gartner's 2006 emerging technologies hype cycle highlights key technology themes (EN) : Прес-реліз від Gartner містить цікаві відомості про поширеність додатків, що використовують географічні координати.
  • The Universal Grids: Universal TransverseMercator (UTM) and Universal Polar Stereographic (UPS) (EN) : Стаття Національного Графічного і Картографічного Агентства (National Imagery and Mapping Agency - NIMA) містить формули UTM і іншу інформацію про систему координат UTM. (Стаття представлена ​​в форматі PDF.)
  • Location-based services (EN) : (Valerie Bennett і Andrew Capella, developerWorks, березень 2002): стаття з введенням в основні принципи, що лежать в основі систем, пов'язаних з позиціонуванням.
  • Put yourself on the map with Google Maps API, DB2 / Informix, and PHP on Linux (EN) : (Marty Lurie and Aron Y. Lurie, developerWorks, березень 2006): стаття з вихідним кодом, що перетворює ZIP-код у координати широти і довготи.
  • Creating an automatically maintained spatial table from latitude-longitude column data (EN) : (EN) (Robert Uleman, developerWorks, квітень 2006): стаття про те як DB2 може допомогти в перетворенні необроблених координат в корисну інформацію.
  • У Wikipedia можна дізнатися про основні концепції, представлених в цій статті: (EN)
  • developerWorks Java technology zone : Сотні статей про всі аспекти Java-програмування.

Підпишіть мене на повідомлення до коментарів

Дополнительная информация

rss
Карта