Как преобразовать широту или долготу в метры?

StackOverflow https://stackoverflow.com/questions/639695

  •  11-07-2019
  •  | 
  •  

Вопрос

Если у меня есть показания широты или долготы в стандартном формате NMEA, есть ли простой способ / формула для преобразования этих показаний в метры, которые я затем могу реализовать на Java (J9)?

Редактировать:Хорошо, кажется, то, что я хочу сделать, невозможно легко, однако то , что я действительно хочу сделать , это:

Допустим, у меня есть широта и долгота точки маршрута и широта и долгота пользователя, есть ли простой способ сравнить их, чтобы решить, когда сообщать пользователю, что они находятся в пределах разумно близкое расстояние от точки маршрута?Я понимаю, что разумное - это предмет, но легко ли это выполнимо или все еще слишком математично?

Это было полезно?

Решение

Вот функция javascript:

function measure(lat1, lon1, lat2, lon2){  // generally used geo measurement function
    var R = 6378.137; // Radius of earth in KM
    var dLat = lat2 * Math.PI / 180 - lat1 * Math.PI / 180;
    var dLon = lon2 * Math.PI / 180 - lon1 * Math.PI / 180;
    var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
    Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) *
    Math.sin(dLon/2) * Math.sin(dLon/2);
    var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
    var d = R * c;
    return d * 1000; // meters
}

Объяснение: https://en.wikipedia.org/wiki/Haversine_formula

Формула хаверсина определяет расстояние по большой окружности между двумя точками на сфере с учетом их долготы и широты.

Другие советы

Учитывая, что вы ищете простую формулу, это, вероятно, самый простой способ сделать это, предполагая, что Земля представляет собой сферу с периметром 40075 км.

Длина в метрах на 1 ° широты = всегда 111,32 км

Длина в метрах на 1 ° долготы = 40075 км * cos ( широта ) / 360

Для аппроксимации коротких расстояний между двумя координатами я использовал формулы из http://en.wikipedia.org/wiki/Lat-lon:

m_per_deg_lat = 111132.954 - 559.822 * cos( 2 * latMid ) + 1.175 * cos( 4 * latMid);
m_per_deg_lon = 111132.954 * cos ( latMid );

.

В приведенном ниже коде я оставил необработанные числа, чтобы показать их связь с формулой из Википедии.

double latMid, m_per_deg_lat, m_per_deg_lon, deltaLat, deltaLon,dist_m;

latMid = (Lat1+Lat2 )/2.0;  // or just use Lat1 for slightly less accurate estimate


m_per_deg_lat = 111132.954 - 559.822 * cos( 2.0 * latMid ) + 1.175 * cos( 4.0 * latMid);
m_per_deg_lon = (3.14159265359/180 ) * 6367449 * cos ( latMid );

deltaLat = fabs(Lat1 - Lat2);
deltaLon = fabs(Lon1 - Lon2);

dist_m = sqrt (  pow( deltaLat * m_per_deg_lat,2) + pow( deltaLon * m_per_deg_lon , 2) );

В записи Википедии указано, что расчеты расстояния находятся в пределах 0,6 м для 100 км в продольном направлении и 1 см для 100 км в широтном, но я не проверял это, поскольку для моего использования эта точность близка к нулю.

Широты и долготы указывают точки, а не расстояния, поэтому ваш вопрос несколько бессмысленен.Если вы спрашиваете о кратчайшем расстоянии между двумя точками (широта, lon), смотрите эта статья в Википедии на дистанциях большого круга.

Земля - раздражающе неровная поверхность, поэтому не существует простой формулы, позволяющей сделать это точно.Вы должны жить с приблизительной моделью земли и проецировать на нее свои координаты.Модель, которую я обычно вижу используемой для этого, это WGS 84.Это то, что GPS-устройства обычно используют для решения точно такой же проблемы.

У NOAA есть некоторое программное обеспечение, которое вы можете загрузить, чтобы помочь с этим на их веб-сайте.

Есть много инструментов, которые облегчат это.Видишь ответ монжардена для получения более подробной информации о том, что с этим связано.

Однако сделать это не обязательно сложно.Похоже, вы используете Java, поэтому я бы рекомендовал изучить что-то вроде GDAL ( ГДАЛ ).Он предоставляет java-оболочки для своих подпрограмм, и у них есть все инструменты, необходимые для преобразования из широты / широты (географические координаты) в UTM (проецируемая система координат) или какую-либо другую приемлемую картографическую проекцию.

UTM хорош, потому что это метры, с которыми так легко работать.Однако вам нужно будет получить соответствующий Зона UTM для того, чтобы он хорошо справлялся с работой.Есть несколько простых кодов, доступных через поиск в Google, чтобы найти подходящую зону для пары широта / длина.

Вот R -версия функция b-h-s, на всякий случай:

measure <- function(lon1,lat1,lon2,lat2) {
    R <- 6378.137                                # radius of earth in Km
    dLat <- (lat2-lat1)*pi/180
    dLon <- (lon2-lon1)*pi/180
    a <- sin((dLat/2))^2 + cos(lat1*pi/180)*cos(lat2*pi/180)*(sin(dLon/2))^2
    c <- 2 * atan2(sqrt(a), sqrt(1-a))
    d <- R * c
    return (d * 1000)                            # distance in meters
}

Одна морская миля (1852 метра) определяется как одна угловая минута долготы на экваторе.Однако вам необходимо определить картографическая проекция (см . также UTM), в котором вы работаете над тем, чтобы преобразование действительно имело смысл.

Существует довольно много способов вычислить это.Все они используют аппроксимации сферической тригонометрии, где радиус равен радиусу земли.

попробуй http://www.movable-type.co.uk/scripts/latlong.html для получения информации о методах и коде на разных языках.

Основано на среднем расстоянии для понижения в Земле.

1° = 111 км;

Преобразуя это в радианы и разделив на метры, получим магическое число для RAD в метрах:0.000008998719243599958;

тогда:

const RAD = 0.000008998719243599958;
Math.sqrt(Math.pow(lat1 - lat2, 2) + Math.pow(long1 - long2, 2)) / RAD;
    'below is from
'http://www.zipcodeworld.com/samples/distance.vbnet.html
Public Function distance(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim theta As Double = lon1 - lon2
    Dim dist As Double = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + _
                            Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * _
                            Math.Cos(deg2rad(theta))
    dist = Math.Acos(dist)
    dist = rad2deg(dist)
    dist = dist * 60 * 1.1515
    If unit = "K" Then
        dist = dist * 1.609344
    ElseIf unit = "N" Then
        dist = dist * 0.8684
    End If
    Return dist
End Function
Public Function Haversine(ByVal lat1 As Double, ByVal lon1 As Double, _
                         ByVal lat2 As Double, ByVal lon2 As Double, _
                         Optional ByVal unit As Char = "M"c) As Double
    Dim R As Double = 6371 'earth radius in km
    Dim dLat As Double
    Dim dLon As Double
    Dim a As Double
    Dim c As Double
    Dim d As Double
    dLat = deg2rad(lat2 - lat1)
    dLon = deg2rad((lon2 - lon1))
    a = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(deg2rad(lat1)) * _
            Math.Cos(deg2rad(lat2)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
    c = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a))
    d = R * c
    Select Case unit.ToString.ToUpper
        Case "M"c
            d = d * 0.62137119
        Case "N"c
            d = d * 0.5399568
    End Select
    Return d
End Function
Private Function deg2rad(ByVal deg As Double) As Double
    Return (deg * Math.PI / 180.0)
End Function
Private Function rad2deg(ByVal rad As Double) As Double
    Return rad / Math.PI * 180.0
End Function

Чтобы преобразовать широту и долготу в представлении x и y, вам нужно решить, какой тип картографической проекции использовать.Что касается меня, Эллиптический Меркатор выглядит очень хорошо. Здесь вы можете найти реализацию (тоже на Java).

Если они достаточно близки, вам может сойти с рук рассматривать их как координаты на плоской плоскости.Это работает, скажем, на уровне улицы или города, если абсолютная точность не требуется и все, что вам нужно, - это приблизительное предположение о требуемом расстоянии для сравнения с произвольным пределом.

Если вам нужно простое решение, то используйте Формула Хаверсина как указано в других комментариях.Если у вас приложение, чувствительное к точности, имейте в виду, что формула Haversine не гарантирует точность выше 0,5%, поскольку предполагается, что земля имеет форму круга.Чтобы учесть, что Земля представляет собой сплюснутый сфероид, рассмотрим использование Формулы Винсенти.Кроме того, я не уверен, какой радиус мы должны использовать с формулой Haversine:{Экватор:6378,137 км, Полярный:6 356,752 км, Объемный:6 371,0088 км}.

Вам нужно преобразовать координаты в радианы, чтобы создать сферическую геометрию.После преобразования вы можете вычислить расстояние между двумя точками.Затем расстояние может быть преобразовано в любую меру, которую вы хотите.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top