Учет высоты при расчете геодезического расстояния - PullRequest
11 голосов
/ 10 июля 2009

В настоящее время я имею дело с данными GPS в сочетании с точным измерением высоты. Я хочу рассчитать расстояние между двумя последовательными точками. Есть много информации о расчете расстояния между двумя точками с использованием эллипсоида WGS84 и т. д.

однако, я не нашел никакой информации, которая принимает Высота изменения для этого Расчет расстояния.

Кто-нибудь знает о некоторых веб-сайтах, газетах, книгах и т. Д., В которых описан такой метод? спасибо

edit : географические расширения Sql Server 2008 также не учитывают информацию о высоте при расчете расстояния.

Ответы [ 5 ]

8 голосов
/ 11 августа 2009

Я реализовал функцию расстояния WGS84, используя среднее значение начальной и конечной высоты в качестве постоянной высоты. Если вы уверены, что на вашем пути будет относительно небольшое изменение высоты, это работает приемлемо хорошо (ошибка связана с разницей высоты ваших двух точек LLA).

Вот мой код (C #):

    /// <summary>
    /// Gets the geodesic distance between two pathpoints in the current mode's coordinate system
    /// </summary>
    /// <param name="point1">First point</param>
    /// <param name="point2">Second point</param>
    /// <param name="mode">Coordinate mode that both points are in</param>
    /// <returns>Distance between the two points in the current coordinate mode</returns>
    public static double GetGeodesicDistance(PathPoint point1, PathPoint point2, CoordMode mode) {
        // calculate proper geodesics for LLA paths
        if (mode == CoordMode.LLA) {
            // meeus approximation
            double f = (point1.Y + point2.Y) / 2 * LatLonAltTransformer.DEGTORAD;
            double g = (point1.Y - point2.Y) / 2 * LatLonAltTransformer.DEGTORAD;
            double l = (point1.X - point2.X) / 2 * LatLonAltTransformer.DEGTORAD;

            double sinG = Math.Sin(g);
            double sinL = Math.Sin(l);
            double sinF = Math.Sin(f);

            double s, c, w, r, d, h1, h2;
            // not perfect but use the average altitude
            double a = (LatLonAltTransformer.A + point1.Z + LatLonAltTransformer.A + point2.Z) / 2.0;

            sinG *= sinG;
            sinL *= sinL;
            sinF *= sinF;

            s = sinG * (1 - sinL) + (1 - sinF) * sinL;
            c = (1 - sinG) * (1 - sinL) + sinF * sinL;

            w = Math.Atan(Math.Sqrt(s / c));
            r = Math.Sqrt(s * c) / w;
            d = 2 * w * a;
            h1 = (3 * r - 1) / 2 / c;
            h2 = (3 * r + 1) / 2 / s;

            return d * (1 + (1 / LatLonAltTransformer.RF) * (h1 * sinF * (1 - sinG) - h2 * (1 - sinF) * sinG));
        }

        PathPoint diff = new PathPoint(point2.X - point1.X, point2.Y - point1.Y, point2.Z - point1.Z, 0);
        return Math.Sqrt(diff.X * diff.X + diff.Y * diff.Y + diff.Z * diff.Z);
    }

На практике мы обнаружили, что разница высот редко имеет большое значение, наши трассы, как правило, имеют длину 1-2 км, а высота варьируется в пределах порядка 100 м, и мы видим изменение в среднем на ~ 5 м по сравнению с использованием эллипсоида WGS84 без изменений .

Edit:

Чтобы добавить к этому, если вы ожидаете значительных изменений высоты, вы можете преобразовать ваши координаты WGS84 в ECEF (фиксированная земля-ориентированная земля) и оценить прямые пути, как показано в нижней части моей функции. Преобразовать точку в ECEF просто:

    /// <summary>
    /// Converts a point in the format (Lon, Lat, Alt) to ECEF
    /// </summary>
    /// <param name="point">Point as (Lon, Lat, Alt)</param>
    /// <returns>Point in ECEF</returns>
    public static PathPoint WGS84ToECEF(PathPoint point) {
        PathPoint outPoint = new PathPoint(0);

        double lat = point.Y * DEGTORAD;
        double lon = point.X * DEGTORAD;
        double e2 = 1.0 / RF * (2.0 - 1.0 / RF);
        double sinLat = Math.Sin(lat), cosLat = Math.Cos(lat);

        double chi = A / Math.Sqrt(1 - e2 * sinLat * sinLat);
        outPoint.X = (chi + point.Z) * cosLat * Math.Cos(lon);
        outPoint.Y = (chi + point.Z) * cosLat * Math.Sin(lon);
        outPoint.Z = (chi * (1 - e2) + point.Z) * sinLat;

        return outPoint;
    }

Редактировать 2:

Меня спросили о некоторых других переменных в моем коде:

// RF is the eccentricity of the WGS84 ellipsoid
public const double RF = 298.257223563;

// A is the radius of the earth in meters
public const double A = 6378137.0;

LatLonAltTransformer - это класс, который я использовал для преобразования координат LatLonAlt в координаты ECEF и определяет константы выше.

1 голос
/ 27 ноября 2012

Вы, вероятно, не заботитесь о высоте для больших двухмерных расстояний. Таким образом, если расстояние, которое вы получаете, превышает, скажем, 20 (или, возможно, 50) км, то кого волнует разница в высоте (зависит от ваших потребностей). Под, скажем, 20 км, подача в простом пифагорейском дополнении к разнице высот Подайте это плавно.

Расстояние между двумя географическими точками?

0 голосов
/ 11 августа 2009

Для начала вам нужна модель, которая сообщает вам, как изменяется высота над уровнем моря на линии между двумя точками. Без такой модели у вас нет единого определения расстояния между двумя точками.

Если у вас была линейная модель (прохождение 50% расстояния между точками также означает, что вы прошли 50% высоты над уровнем моря), то вы, вероятно, можете притвориться, что все это был прямоугольный треугольник; то есть вы действуете так, как будто мир плоский, чтобы определить, как сдвиг высоты влияет на расстояние. Расстояние по земле - это основание, изменение высоты - это высота треугольника, а гипотенуза - это ваше предполагаемое истинное расстояние перемещения от точки к точке.

Если вы хотите уточнить это далее, то вы можете заметить, что приведенная выше модель идеально подходит для бесконечно малых расстояний, что означает, что вы можете перебирать отдельные дельты расстояния в стиле исчисления, каждый раз используя текущую высоту для вычислите расстояние от земли и затем используйте то же тригонометрическое отношение, чтобы вычислить вклад изменения высоты в пройденное расстояние. Я бы, вероятно, сделал это в цикле for () с 10 до 100 кусочками сегмента, и, возможно, методом проб и ошибок определил количество кусочков, необходимое для получения в эпсилоне истинного значения. Также было бы возможно определить линейный интеграл, чтобы вычислить фактическое расстояние между двумя точками в этой модели.

0 голосов
/ 11 августа 2009

Для того, чтобы сделать это, первой проблемой, которую вы должны решить, является определение изменения высоты над уровнем моря. Нормальные уравнения работают, потому что они находятся на двухмерной поверхности, однако добавление третьего измерения означает, что простое определение кратчайшего расстояния больше не применимо, например, теперь в третьем измерении «в игре» ваше кратчайшее расстояние может пробиться через оригинал. эллипсоид. Это немного быстро и грязно, но вашим лучшим решением может быть предположение, что скорость изменения высоты постоянна вдоль первоначальной двухмерной траектории на эллипсоиде. Затем вы можете рассчитать 2D-расстояние как длину, определить скорость изменения высоты, а затем просто использовать Пифагор, чтобы рассчитать увеличение длины, когда одна сторона треугольника является 2D-расстоянием, а высота - второй длиной.

0 голосов
/ 12 июля 2009

Я бы предположил, что на любом расстоянии, где использование WGS84 даст вам значительно большую точность, разница в высоте не будет иметь значения. И на любом расстоянии, где разница в высотах имеет значение, вам, вероятно, следует использовать приближение по прямой.

...