ChatGPT解决这个技术问题 Extra ChatGPT

计算多个经纬度坐标对的中心点

给定一组纬度和经度点,我如何计算该组中心点的纬度和经度(也就是将视图集中在所有点上的点)?

编辑:我使用过的 Python 解决方案:

Convert lat/lon (must be in radians) to Cartesian coordinates for each location.
X = cos(lat) * cos(lon)
Y = cos(lat) * sin(lon)
Z = sin(lat)

Compute average x, y and z coordinates.
x = (x1 + x2 + ... + xn) / n
y = (y1 + y2 + ... + yn) / n
z = (z1 + z2 + ... + zn) / n

Convert average x, y, z coordinate to latitude and longitude.
Lon = atan2(y, x)
Hyp = sqrt(x * x + y * y)
Lat = atan2(z, hyp)
关于您的解决方案:对于球形地球的假设,您的错误可能不会太大,但最好将地球描述为椭圆体。
将其编写为 python 函数并在 gist.github.com/3718961 共享
需要注意的是,这是假设您的纬度和经度以弧度为单位的,这一点非常重要!我挠了挠头,没有意识到这一点。要从十进制转换为弧度,请乘以十进制 * pi/180。然后从弧度转换回十进制,乘以 180/pi。高温高压
抱歉迟到了,但我想知道,这个算法背后的数学是什么,有人可以告诉我一些解释这个问题的读物吗?谢谢!
请问什么是z

G
Gio

谢谢!这是使用度数的 OP 解决方案的 C# 版本。它利用 System.Device.Location.GeoCoordinate

    public static GeoCoordinate GetCentralGeoCoordinate(
        IList<GeoCoordinate> geoCoordinates)
    {
        if (geoCoordinates.Count == 1)
        {
            return geoCoordinates.Single();
        }

        double x = 0;
        double y = 0;
        double z = 0;

        foreach (var geoCoordinate in geoCoordinates)
        {
            var latitude = geoCoordinate.Latitude * Math.PI / 180;
            var longitude = geoCoordinate.Longitude * Math.PI / 180;

            x += Math.Cos(latitude) * Math.Cos(longitude);
            y += Math.Cos(latitude) * Math.Sin(longitude);
            z += Math.Sin(latitude);
        }

        var total = geoCoordinates.Count;

        x = x / total;
        y = y / total;
        z = z / total;

        var centralLongitude = Math.Atan2(y, x);
        var centralSquareRoot = Math.Sqrt(x * x + y * y);
        var centralLatitude = Math.Atan2(z, centralSquareRoot);

        return new GeoCoordinate(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);
    }

C
Community

当它们从 359' 回绕到 0' 时,仅平均它们的简单方法会出现带有角度的奇怪边缘情况。

A much earlier question on SO 询问如何找到一组罗盘角度的平均值。

那里为球坐标推荐的方法的扩展将是:

将每个纬度/经度对转换为单位长度的 3D 向量。

对每个向量求和

归一化结果向量

转换回球坐标


看起来不错,我根据在此网站上找到的内容做了类似的事情:geomidpoint.com/calculation.html
G
Gio

我发现这篇文章非常有用,所以这里是 PHP 中的解决方案。我一直在成功使用它,只是想为另一个开发者节省一些时间。

/**
 * Get a center latitude,longitude from an array of like geopoints
 *
 * @param array data 2 dimensional array of latitudes and longitudes
 * For Example:
 * $data = array
 * (
 *   0 = > array(45.849382, 76.322333),
 *   1 = > array(45.843543, 75.324143),
 *   2 = > array(45.765744, 76.543223),
 *   3 = > array(45.784234, 74.542335)
 * );
*/
function GetCenterFromDegrees($data)
{
    if (!is_array($data)) return FALSE;

    $num_coords = count($data);

    $X = 0.0;
    $Y = 0.0;
    $Z = 0.0;

    foreach ($data as $coord)
    {
        $lat = $coord[0] * pi() / 180;
        $lon = $coord[1] * pi() / 180;

        $a = cos($lat) * cos($lon);
        $b = cos($lat) * sin($lon);
        $c = sin($lat);

        $X += $a;
        $Y += $b;
        $Z += $c;
    }

    $X /= $num_coords;
    $Y /= $num_coords;
    $Z /= $num_coords;

    $lon = atan2($Y, $X);
    $hyp = sqrt($X * $X + $Y * $Y);
    $lat = atan2($Z, $hyp);

    return array($lat * 180 / pi(), $lon * 180 / pi());
}

我使用了这个解决方案,但它给出了一个错误的解决方案——如果我在地图上搜索某些坐标的中心,它会“权衡”这些点,并倾向于停留在有更多点的地方。
@Alnitak在这里我们要搜索由坐标包围的区域的中心。你确定你评论的地方是对的吗?
G
Gio

很有用的帖子!我已经在 JavaScript 中实现了这个,特此我的代码。我已经成功使用了这个。

function rad2degr(rad) { return rad * 180 / Math.PI; }
function degr2rad(degr) { return degr * Math.PI / 180; }

/**
 * @param latLngInDeg array of arrays with latitude and longtitude
 *   pairs in degrees. e.g. [[latitude1, longtitude1], [latitude2
 *   [longtitude2] ...]
 *
 * @return array with the center latitude longtitude pairs in 
 *   degrees.
 */
function getLatLngCenter(latLngInDegr) {
    var LATIDX = 0;
    var LNGIDX = 1;
    var sumX = 0;
    var sumY = 0;
    var sumZ = 0;

    for (var i=0; i<latLngInDegr.length; i++) {
        var lat = degr2rad(latLngInDegr[i][LATIDX]);
        var lng = degr2rad(latLngInDegr[i][LNGIDX]);
        // sum of cartesian coordinates
        sumX += Math.cos(lat) * Math.cos(lng);
        sumY += Math.cos(lat) * Math.sin(lng);
        sumZ += Math.sin(lat);
    }

    var avgX = sumX / latLngInDegr.length;
    var avgY = sumY / latLngInDegr.length;
    var avgZ = sumZ / latLngInDegr.length;

    // convert average x, y, z coordinate to latitude and longtitude
    var lng = Math.atan2(avgY, avgX);
    var hyp = Math.sqrt(avgX * avgX + avgY * avgY);
    var lat = Math.atan2(avgZ, hyp);

    return ([rad2degr(lat), rad2degr(lng)]);
}


我知道这篇文章很旧,但是您能否发布参考资料或解释您发布的算法背后的数学的东西?谢谢!
完美工作!谢谢
我使用 Google Apps Script 测试了该脚本,但结果不是轨道的确切中心点。它在附近的某个地方,但不是直接在赛道上。有没有更好的公式来获得赛道上的确切中间点?
K
Kelvin Spencer

原函数的Javascript版本

/**
 * Get a center latitude,longitude from an array of like geopoints
 *
 * @param array data 2 dimensional array of latitudes and longitudes
 * For Example:
 * $data = array
 * (
 *   0 = > array(45.849382, 76.322333),
 *   1 = > array(45.843543, 75.324143),
 *   2 = > array(45.765744, 76.543223),
 *   3 = > array(45.784234, 74.542335)
 * );
*/
function GetCenterFromDegrees(data)
{       
    if (!(data.length > 0)){
        return false;
    } 

    var num_coords = data.length;

    var X = 0.0;
    var Y = 0.0;
    var Z = 0.0;

    for(i = 0; i < data.length; i++){
        var lat = data[i][0] * Math.PI / 180;
        var lon = data[i][1] * Math.PI / 180;

        var a = Math.cos(lat) * Math.cos(lon);
        var b = Math.cos(lat) * Math.sin(lon);
        var c = Math.sin(lat);

        X += a;
        Y += b;
        Z += c;
    }

    X /= num_coords;
    Y /= num_coords;
    Z /= num_coords;

    var lon = Math.atan2(Y, X);
    var hyp = Math.sqrt(X * X + Y * Y);
    var lat = Math.atan2(Z, hyp);

    var newX = (lat * 180 / Math.PI);
    var newY = (lon * 180 / Math.PI);

    return new Array(newX, newY);
}

A
Argus

为了可能节省一两分钟的时间,这里是在 Objective-C 中而不是 python 中使用的解决方案。此版本采用包含 MKMapCoordinates 的 NSValues 的 NSArray,这在我的实现中被调用:

#import <MapKit/MKGeometry.h>
+ (CLLocationCoordinate2D)centerCoordinateForCoordinates:(NSArray *)coordinateArray {
    double x = 0;
    double y = 0;
    double z = 0;

    for(NSValue *coordinateValue in coordinateArray) {
        CLLocationCoordinate2D coordinate = [coordinateValue MKCoordinateValue];

        double lat = GLKMathDegreesToRadians(coordinate.latitude);
        double lon = GLKMathDegreesToRadians(coordinate.longitude);
        x += cos(lat) * cos(lon);
        y += cos(lat) * sin(lon);
        z += sin(lat);
    }

    x = x / (double)coordinateArray.count;
    y = y / (double)coordinateArray.count;
    z = z / (double)coordinateArray.count;

    double resultLon = atan2(y, x);
    double resultHyp = sqrt(x * x + y * y);
    double resultLat = atan2(z, resultHyp);

    CLLocationCoordinate2D result = CLLocationCoordinate2DMake(GLKMathRadiansToDegrees(resultLat), GLKMathRadiansToDegrees(resultLon));
    return result;
}

对于那里的任何人,无论其价值如何,不要使用您自己的宏将度数转换为弧度,而是导入 <GLKit/GLKMath.h> 并使用 GLKMathDegreesToRadiansGLKMathRadiansToDegrees
P
Peter Pohlmann

非常好的解决方案,正是我的 swift 项目所需要的,所以这里有一个 swift 端口。谢谢&这里还有一个游乐场项目:https://github.com/ppoh71/playgounds/tree/master/centerLocationPoint.playground

/*
* calculate the center point of multiple latitude longitude coordinate-pairs
*/

import CoreLocation
import GLKit

var LocationPoints = [CLLocationCoordinate2D]()

//add some points to Location ne, nw, sw, se , it's a rectangle basicaly
LocationPoints.append(CLLocationCoordinate2D(latitude: 37.627512369999998, longitude: -122.38780611999999))
LocationPoints.append(CLLocationCoordinate2D(latitude: 37.627512369999998, longitude:  -122.43105867))
LocationPoints.append(CLLocationCoordinate2D(latitude: 37.56502528, longitude: -122.43105867))
LocationPoints.append(CLLocationCoordinate2D(latitude: 37.56502528, longitude: -122.38780611999999))

// center func
func getCenterCoord(LocationPoints: [CLLocationCoordinate2D]) -> CLLocationCoordinate2D{

    var x:Float = 0.0;
    var y:Float = 0.0;
    var z:Float = 0.0;

    for points in LocationPoints {

     let lat = GLKMathDegreesToRadians(Float(points.latitude));
     let long = GLKMathDegreesToRadians(Float(points.longitude));

        x += cos(lat) * cos(long);
        y += cos(lat) * sin(long);
        z += sin(lat);
    }

    x = x / Float(LocationPoints.count);
    y = y / Float(LocationPoints.count);
    z = z / Float(LocationPoints.count);

    let resultLong = atan2(y, x);
    let resultHyp = sqrt(x * x + y * y);
    let resultLat = atan2(z, resultHyp);



    let result = CLLocationCoordinate2D(latitude: CLLocationDegrees(GLKMathRadiansToDegrees(Float(resultLat))), longitude: CLLocationDegrees(GLKMathRadiansToDegrees(Float(resultLong))));

    return result;

}

//get the centerpoint
var centerPoint = getCenterCoord(LocationPoints)
print("Latitude: \(centerPoint.latitude) / Longitude: \(centerPoint.longitude)")

S
Stan Sokolov

Java 版本,如果有人需要的话。常量定义为 static 以不计算两次。

/**************************************************************************************************************
 *   Center of geometry defined by coordinates
 **************************************************************************************************************/
private static double pi = Math.PI / 180;
private static double xpi = 180 / Math.PI;

public static Coordinate center(Coordinate... arr) {
    if (arr.length == 1) {
        return arr[0];
    }
    double x = 0, y = 0, z = 0;

    for (Coordinate c : arr) {
        double latitude = c.lat() * pi, longitude = c.lon() * pi;
        double cl = Math.cos(latitude);//save it as we need it twice
        x += cl * Math.cos(longitude);
        y += cl * Math.sin(longitude);
        z += Math.sin(latitude);
    }

    int total = arr.length;

    x = x / total;
    y = y / total;
    z = z / total;

    double centralLongitude = Math.atan2(y, x);
    double centralSquareRoot = Math.sqrt(x * x + y * y);
    double centralLatitude = Math.atan2(z, centralSquareRoot);

    return new Coordinate(centralLatitude * xpi, centralLongitude * xpi);
}

K
Kerry Emerson

如果您有兴趣获得一个非常简化的点“中心”(例如,简单地将地图居中到 gmaps 多边形的中心),那么这里有一个对我有用的基本方法。

public function center() {
    $minlat = false;
    $minlng = false;
    $maxlat = false;
    $maxlng = false;
    $data_array = json_decode($this->data, true);
    foreach ($data_array as $data_element) {
        $data_coords = explode(',',$data_element);
        if (isset($data_coords[1])) {
            if ($minlat === false) { $minlat = $data_coords[0]; } else { $minlat = ($data_coords[0] < $minlat) ? $data_coords[0] : $minlat; }
            if ($maxlat === false) { $maxlat = $data_coords[0]; } else { $maxlat = ($data_coords[0] > $maxlat) ? $data_coords[0] : $maxlat; }
            if ($minlng === false) { $minlng = $data_coords[1]; } else { $minlng = ($data_coords[1] < $minlng) ? $data_coords[1] : $minlng; }
            if ($maxlng === false) { $maxlng = $data_coords[1]; } else { $maxlng = ($data_coords[1] > $maxlng) ? $data_coords[1] : $maxlng; }
        }
    }
    $lat = $maxlat - (($maxlat - $minlat) / 2);
    $lng = $maxlng - (($maxlng - $minlng) / 2);
    return $lat.','.$lng;
}

这将返回多边形中心的中间 lat/lng 坐标。


a
alexhayes

在 Django 中,这是微不足道的(实际上有效,我遇到了一些解决方案没有正确返回纬度负数的问题)。

例如,假设您正在使用 django-geopostcodes(我是其中的作者)。

from django.contrib.gis.geos import MultiPoint
from django.contrib.gis.db.models.functions import Distance
from django_geopostcodes.models import Locality

qs = Locality.objects.anything_icontains('New York')
points = [locality.point for locality in qs]
multipoint = MultiPoint(*points)
point = multipoint.centroid

point 是一个 Django Point 实例,然后可用于执行诸如检索该中心点 10 公里范围内的所有对象之类的操作;

Locality.objects.filter(point__distance_lte=(point, D(km=10)))\
    .annotate(distance=Distance('point', point))\
    .order_by('distance')

将其更改为原始 Python 是微不足道的;

from django.contrib.gis.geos import Point, MultiPoint

points = [
    Point((145.137075, -37.639981)),
    Point((144.137075, -39.639981)),
]
multipoint = MultiPoint(*points)
point = multipoint.centroid

在幕后,Django 正在使用 GEOS - https://docs.djangoproject.com/en/1.10/ref/contrib/gis/geos/ 上的更多详细信息


H
Hossein Amini

这是基于@Yodacheese 使用 Google Maps api 的 C# 答案的 Android 版本:

public static LatLng GetCentralGeoCoordinate(List<LatLng> geoCoordinates) {        
    if (geoCoordinates.size() == 1)
    {
        return geoCoordinates.get(0);
    }

    double x = 0;
    double y = 0;
    double z = 0;

    for(LatLng geoCoordinate : geoCoordinates)
    {
        double  latitude = geoCoordinate.latitude * Math.PI / 180;
        double longitude = geoCoordinate.longitude * Math.PI / 180;

        x += Math.cos(latitude) * Math.cos(longitude);
        y += Math.cos(latitude) * Math.sin(longitude);
        z += Math.sin(latitude);
    }

    int total = geoCoordinates.size();

    x = x / total;
    y = y / total;
    z = z / total;

    double centralLongitude = Math.atan2(y, x);
    double centralSquareRoot = Math.sqrt(x * x + y * y);
    double centralLatitude = Math.atan2(z, centralSquareRoot);

    return new LatLng(centralLatitude * 180 / Math.PI, centralLongitude * 180 / Math.PI);

}

在应用程序 build.gradle 添加:

implementation 'com.google.android.gms:play-services-maps:17.0.0'

H
Hamed Hamedi

Flutter 的 Dart 实现,用于查找多个纬度、经度的中心点。

导入数学包

import 'dart:math' as math;

经纬度表

List<LatLng> latLongList = [LatLng(12.9824, 80.0603),LatLng(13.0569,80.2425,)];

LatLng getCenterLatLong(List<LatLng> latLongList) {
    double pi = math.pi / 180;
    double xpi = 180 / math.pi;
    double x = 0, y = 0, z = 0;

    if(latLongList.length==1)
    {
        return latLongList[0];
    }
    for (int i = 0; i < latLongList.length; i++) {
      double latitude = latLongList[i].latitude * pi;
      double longitude = latLongList[i].longitude * pi;
      double c1 = math.cos(latitude);
      x = x + c1 * math.cos(longitude);
      y = y + c1 * math.sin(longitude);
      z = z + math.sin(latitude);
    }

    int total = latLongList.length;
    x = x / total;
    y = y / total;
    z = z / total;

    double centralLongitude = math.atan2(y, x);
    double centralSquareRoot = math.sqrt(x * x + y * y);
    double centralLatitude = math.atan2(z, centralSquareRoot);

    return LatLng(centralLatitude*xpi,centralLongitude*xpi);
}

k
kindahero

这是查找中心点的python版本。 lat1 和 lon1 是纬度和经度列表。它将返回中心点的纬度和经度。

import numpy as np

def GetCenterFromDegrees(lat1,lon1):
    if (len(lat1) <= 0):
        return false;

    num_coords = len(lat1)
    X = 0.0
    Y = 0.0
    Z = 0.0

    for i in range (len(lat1)):
        lat = lat1[i] * np.pi / 180
        lon = lon1[i] * np.pi / 180

        a = np.cos(lat) * np.cos(lon)
        b = np.cos(lat) * np.sin(lon)
        c = np.sin(lat);

        X += a
        Y += b
        Z += c

    X /= num_coords
    Y /= num_coords
    Z /= num_coords

    lon = np.arctan2(Y, X)
    hyp = np.sqrt(X * X + Y * Y)
    lat = np.arctan2(Z, hyp)

    newX = (lat * 180 / np.pi)
    newY = (lon * 180 / np.pi)
    return newX, newY

j
jpredham

这与加权平均问题相同,其中所有权重都相同,并且有两个维度。

找到您的中心纬度的所有纬度的平均值和中心经度的所有经度的平均值。

注意事项:这是一个近距离的近似值,当由于地球的曲率与平均值的偏差超过几英里时,误差将变得难以控制。请记住,纬度和经度是度数(不是真正的网格)。


[-179,0],[+179,0] 平均值为 [0,0],与正确结果相差甚远;)
B
Bill

如果您想考虑所使用的椭球体,您可以在此处找到公式 http://www.ordnancesurvey.co.uk/oswebsite/gps/docs/A_Guide_to_Coordinate_Systems_in_Great_Britain.pdf

见附件 B

该文档包含许多其他有用的东西


这是更新后的链接:ordnancesurvey.co.uk/docs/support/…
D
DabitNG

PHP 中的对象不足。给定坐标对数组,返回中心。

/**
 * Calculate center of given coordinates
 * @param  array    $coordinates    Each array of coordinate pairs
 * @return array                    Center of coordinates
 */
function getCoordsCenter($coordinates) {    
    $lats = $lons = array();
    foreach ($coordinates as $key => $value) {
        array_push($lats, $value[0]);
        array_push($lons, $value[1]);
    }
    $minlat = min($lats);
    $maxlat = max($lats);
    $minlon = min($lons);
    $maxlon = max($lons);
    $lat = $maxlat - (($maxlat - $minlat) / 2);
    $lng = $maxlon - (($maxlon - $minlon) / 2);
    return array("lat" => $lat, "lon" => $lng);
}

从#4中获取想法


这不适用于穿过 180 度子午线的坐标。例如,两个经度点 -175 和 175 将在您的算法中返回 0 的中心,因此实际中心将是 -180 或 180。
R
Renish Gotecha

我在javascript中完成了这个任务,如下所示

function GetCenterFromDegrees(data){
    // var data = [{lat:22.281610498720003,lng:70.77577162868579},{lat:22.28065743343672,lng:70.77624369747241},{lat:22.280860953131217,lng:70.77672113067706},{lat:22.281863655593973,lng:70.7762061465462}];
    var num_coords = data.length;
    var X = 0.0;
    var Y = 0.0;
    var Z = 0.0;

    for(i=0; i<num_coords; i++){
        var lat = data[i].lat * Math.PI / 180;
        var lon = data[i].lng * Math.PI / 180;
        var a = Math.cos(lat) * Math.cos(lon);
        var b = Math.cos(lat) * Math.sin(lon);
        var c = Math.sin(lat);

        X += a;
        Y += b;
        Z += c;
    }

    X /= num_coords;
    Y /= num_coords;
    Z /= num_coords;

    lon = Math.atan2(Y, X);
    var hyp = Math.sqrt(X * X + Y * Y);
    lat = Math.atan2(Z, hyp);

    var finalLat = lat * 180 / Math.PI;
    var finalLng =  lon * 180 / Math.PI; 

    var finalArray = Array();
    finalArray.push(finalLat);
    finalArray.push(finalLng);
    return finalArray;
}

M
Miguel Chiquin

Dart/Flutter 计算多个经纬度坐标对的中心点

Map<String, double> getLatLngCenter(List<List<double>> coords) {
    const LATIDX = 0;
    const LNGIDX = 1;
    double sumX = 0;
    double sumY = 0;
    double sumZ = 0;

    for (var i = 0; i < coords.length; i++) {
      var lat = VectorMath.radians(coords[i][LATIDX]);
      var lng = VectorMath.radians(coords[i][LNGIDX]);
      // sum of cartesian coordinates
      sumX += Math.cos(lat) * Math.cos(lng);
      sumY += Math.cos(lat) * Math.sin(lng);
      sumZ += Math.sin(lat);
    }

    var avgX = sumX / coords.length;
    var avgY = sumY / coords.length;
    var avgZ = sumZ / coords.length;

    // convert average x, y, z coordinate to latitude and longtitude
    var lng = Math.atan2(avgY, avgX);
    var hyp = Math.sqrt(avgX * avgX + avgY * avgY);
    var lat = Math.atan2(avgZ, hyp);

    return {
      "latitude": VectorMath.degrees(lat),
      "longitude": VectorMath.degrees(lng)
    };
  }

S
Steven Pena

这些答案中的许多只是一种奇怪方法的变体,它没有找到包含所有点的边界框的真正中心。相反,它会找到大多数点的中心(某种加权中心)。如果您想要所有点的真实中心而不考虑聚类和权重,您可以获得边界框并轻松找到这 4 个角的中心。如果您不关心地球曲率的因素,您可以使用像(C# 代码)这样简单的东西:

var lat = (coordinates.Min(x => x.lat) + coordinates.Max(x => x.lat))/2;
var lon = (coordinates.Min(x => x.lon) + coordinates.Max(x => x.lon))/2;
return new Tuple<double, double>(lat, lon);

J
John

如果您希望图像中的所有点都可见,您需要纬度和经度的极值,并确保您的视图包含这些值以及您想要的任何边框。

(根据 Alnitak 的回答,您如何计算极值可能有点问题,但如果它们在环绕的经度的任一侧有几度,那么您将做主并采取正确的范围。)

如果您不想扭曲这些点所在的任何地图,请调整边界框的纵横比,使其适合您分配给视图但仍包含极值的任何像素。

要将点保持在某个任意缩放级别的中心,请计算“恰好适合”上述点的边界框的中心,并将该点保持为中心点。


F
Fatos Morina

作为对这个线程的感谢,这是我对 Ruby 实现的一点贡献,希望我能从他们宝贵的时间中节省几分钟:

def self.find_center(locations)

 number_of_locations = locations.length

 return locations.first if number_of_locations == 1

 x = y = z = 0.0
 locations.each do |station|
   latitude = station.latitude * Math::PI / 180
   longitude = station.longitude * Math::PI / 180

   x += Math.cos(latitude) * Math.cos(longitude)
   y += Math.cos(latitude) * Math.sin(longitude)
   z += Math.sin(latitude)
 end

 x = x/number_of_locations
 y = y/number_of_locations
 z = z/number_of_locations

 central_longitude =  Math.atan2(y, x)
 central_square_root = Math.sqrt(x * x + y * y)
 central_latitude = Math.atan2(z, central_square_root)

 [latitude: central_latitude * 180 / Math::PI, 
 longitude: central_longitude * 180 / Math::PI]
end

C
Chris Lang

我使用了从 www.geomidpoint.com 获得的公式并编写了以下 C++ 实现。 arraygeocoords 是我自己的类,其功能应该是不言自明的。

/*
 * midpoints calculated using formula from www.geomidpoint.com
 */
   geocoords geocoords::calcmidpoint( array<geocoords>& points )
   {
      if( points.empty() ) return geocoords();

      float cart_x = 0,
            cart_y = 0,
            cart_z = 0;

      for( auto& point : points )
      {
         cart_x += cos( point.lat.rad() ) * cos( point.lon.rad() );
         cart_y += cos( point.lat.rad() ) * sin( point.lon.rad() );
         cart_z += sin( point.lat.rad() );
      }

      cart_x /= points.numelems();
      cart_y /= points.numelems();
      cart_z /= points.numelems();

      geocoords mean;

      mean.lat.rad( atan2( cart_z, sqrt( pow( cart_x, 2 ) + pow( cart_y, 2 ))));
      mean.lon.rad( atan2( cart_y, cart_x ));

      return mean;
   }

P
Pere Barceló

斯卡拉版本:

import scala.math._
    
case class Coordinate(latitude: Double, longitude: Double)
    
def center(coordinates: List[Coordinate]) = {
  val (a: Double, b: Double, c: Double) = coordinates.fold((0.0, 0.0, 0.0)) {
    case ((x: Double, y: Double, z: Double), coord: Coordinate) =>
      val latitude = coord.latitude * Pi / 180
      val longitude = coord.longitude * Pi / 180
      (x + cos(latitude) * cos(longitude), y + cos(latitude) * sin(longitude), z + sin(latitude))
  }
  val total = coordinates.length
  val (x: Double, y: Double, z: Double) = (a / total, b / total, c / total)
  val centralLongitude = atan2(y, x)
  val centralSquareRoot = sqrt(x * x + y * y)
  val centralLatitude = atan2(z, centralSquareRoot)
    
  Coordinate(centralLatitude * 180 / Pi, centralLongitude * 180 / Pi);
}


关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅