平均坐标给出了奇怪的结果

时间:2017-12-15 10:22:57

标签: c# location average

我尝试实现一个函数,该函数从通过纬度和经度值(以度为单位)表示的位置列表中给出平均值。旧版本的函数只是平均这两个值:

public static void CalculateMedianLocation(IEnumerable<GeographyPoint> locations, out Double latitude, out Double longitude)
{
    Double totalLatitude = 0;
    Double totalLongitude = 0;
    var count = 0;
    foreach (var location in locations)
    {
        totalLatitude += location.Latitude;
        totalLongitude += location.Longitude;
        count++;
    }
    if (count <= 0)
    {
        throw new ArgumentOutOfRangeException();
    }
    latitude= totalLatitude / count;
    longitude = totalLongitude / count;
}

然而,这并不是一个很好的方法,因为可能导致扭曲。基于this answer类似的问题,我尝试使用笛卡尔坐标平均值将其更改为更好的方法:

private static Vector3 DegreesToVector(Double latitude, Double longitude)
{
    var latitudeRadians = latitude.ToRadians();
    var longitudeRadians = longitude.ToRadians();
    var x = Math.Sin(latitudeRadians) * Math.Cos(longitudeRadians);
    var y = Math.Sin(latitudeRadians) * Math.Sin(longitudeRadians);
    var z = Math.Cos(latitudeRadians);
    return new Vector3(x, y, z);
}

private static void VectorToDegrees(Vector3 vector, out Double latitude, out Double longitude)
{
    latitude = Math.Atan2(vector.Z, Math.Sqrt(vector.X * vector.X + vector.Y * vector.Y)).ToDegrees();
    longitude = Math.Atan2(-vector.Y, vector.X).ToDegrees();
}

public static void CalculateMedianLocation(IEnumerable<GeographyPoint> locations, out Double latitude, out Double longitude)
{
    var total = new Vector3();
    var count = 0;
    foreach (var location in locations)
    {
        total += DegreesToVector(location.Latitude, location.Longitude);
        count++;
    }
    if (count <= 0)
    {
        throw new ArgumentOutOfRangeException();
    }
    VectorToDegrees(total / count, out latitude, out longitude);
}

然而,这给了我完全错误的价值观,我不明白为什么。我检查了这个解决方案基于的数学,似乎一切都是正确的。我错过了什么?

编辑:我使用here中的Vector3实现,扩展ToDegrees()ToRadians()实现如下:

public static Double ToRadians(this Double val)
{
    return (Math.PI / 180.0) * val;
}

public static Double ToDegrees(this Double val)
{
    return val * (180.0 / Math.PI);
}

这些都不应成为这个问题的原因。

0 个答案:

没有答案