General programming

Що ти маєш знати про географічні координати

revised 15 July 2022

Стисла шпаргалка для програмістів.

Стисла шпаргалка для програмістів.

  • Широта, Latitude, lat - збільшується з півдня (South, S) на північ (North, N).

  • Довгота, Longitude, lng - збільшується с заходу (West, W) на схід (East, E).

  • Практично завжди координати записуються в порядку “широта, довгота” - Lat, Lng. У Google Maps, у Вікіпедії, і т.д. На відміну від математики, в географії спочатку йде Y, потім X.

  • І широта, і довгота вимірюються в градусах. Градус можна розуміти як геометричний градус, тобто 1/360 земного кола. Інколи їх записують у вигляді дробового числа, з яким все зрозуміло: 12.3456; інколи - у “часовому” вигляді: 12°34'56" - 12 градусів, 34 хвилини, 56 секунд. Такий запис легко перевести у дріб: deg + min/60.0 + sec/3600.0

  • Довгота приймає значення від -180 до +180; нуль - початковий мерідіан, що проходить через Гринвіч, від’ємні значення - західна півкуля, додатні - східна.

  • Широта приймає значення від -90 до +90. Нуль - екватор, від’ємні значення - південна півкуля, додатні - північна.

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

    def lng_2_km(lat)
        EARTH_RADIUS*(Math::PI/180)*cos(lat*Math::PI/180) # EARTH_RADIUS = 6371
    end
    
  • Довжина одного градусу широти є майже сталою і дорівнює 111 км.

  • Довжина земного кола (тобто фізичний розмір координатної сітки) дорівнює приблизно 4*10⁸ м. В базовому типі числа з рухомою комою вміщується сім розрядів точності. Це значить, що в змінну або стовпчик типу single/float влізуть координати з точністю біля 10 м. А це значить, що для зберігання географічних координат краще використати тип DOUBLE.

  • Відстань між двома координатами не можна рахувати за формулою Євклида (sqrt(x*x+y*y)), оскільки ця відстань вимірюється на сфері, а не на площині (до речі, саме тому літаки на далекі відстані літають по “кривій” траєкторії - ця крива це проєкція “прямої” дуги). Відстань рахуємо за великим колом.

  • Хоча, якщо все, що тобі потрібно - це “знайти довколишні місця”, як це роблять численні додатки, то не потрібно ані тригонометрії, ані географичічних доповнень до бази даних - для довколишніх крапок цілком достатньо Євклидової відстані.

  • А якщо ще спростити нашу модель, то можна взагалі шукати об’єкти, обмежені окремо за кожною з координат: WHERE lat BETWEEN lat1 AND lat 2 AND lng BETWEEN lng1 AND lng2. Особливо якщо результати показувати будеш на прямокутній карті (тобто поле зору буде прямокутне). Алгоритм такий:

    def nearest(lat, lng, radius)
      lat2km = LAT_DEGREE_KM # 111
      lng2km = lng_2_km(lat)
      # lat2km*dlat = lng2km*dlng = lateral_distance_km
      # 2*lateral_distance_km^2 = radius^2
      # lateral_distance_km = radius / sqrt(2)
      dlat = radius / (lat2km * Math.sqrt(2))
      dlng = radius / (lng2km * Math.sqrt(2))
    
      where(:lat => (lat-dlat)..(lat+dlat), :lng => (lng-dlng)..(lng+dlng))
    end
    

    Такі критерії можна легко віддати сервісу повнотекстового пошуку, наприклад, Sphinx Search - саме так працював пошук на моєму колишньому порталі нерухомості Дніпра - Rentfeed.

  • 🇺🇦 І, нарешті, координати Дніпра - 48 градусів північної широти, 35 градусів східної довготи.