Что ты должен знать про географические координаты
May 17, 2012 , revised January 30, 2013 in General programmingКороткая шпаргалка для программистов.
-
Широта, Latitude,
lat
- идет с севера (North, N) на юг (South, S). -
Долгота, Longitude,
lng
- идет с запада (West, W) на восток (East, E). -
Практически всегда координаты идут в порядке “широта, долгота” - Lat, Lng. В Google Maps, в Яндекс-Картах, в Википедии. Это стоит зазубрить: в географии сначала идет Y, потом X.
-
И широта, и долгота измеряются в градусах. Градус можно понимать как геометрический градус, то есть 1/360 земной окружности. Иногда их записывают в виде дробного числа, с которым все понятно; иногда - в “часовом” виде: 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.dp.ua.
-
И, наконец, координаты Днепропетровска - 48 градусов северной широты, 35 градусов восточной долготы.
Понравился пост? Купи мне кофе