Tính điểm trung tâm của nhiều cặp tọa độ vĩ độ / kinh độ


148

Cho một tập hợp các điểm vĩ độ và kinh độ, làm thế nào tôi có thể tính toán vĩ độ và kinh độ của điểm trung tâm của tập hợp đó (còn gọi là một điểm sẽ tập trung quan điểm trên tất cả các điểm)?

EDIT: Giải pháp Python tôi đã sử dụng:

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)

2
Về giải pháp của bạn: Có lẽ lỗi của bạn sẽ không quá lớn với giả định của bạn về một trái đất hình cầu, nhưng trái đất được mô tả tốt hơn như một hình elip.
Giăng

1
Đã viết điều này như một hàm python và chia sẻ nó tại gist.github.com/3718961
Alvin

14
Điều rất quan trọng cần lưu ý là điều này giả định rằng lat và long của bạn là bằng radian! Tôi gãi đầu một lúc không nhận ra điều đó. Để chuyển đổi sang radian từ số thập phân, nhân số thập phân * pi / 180. Sau đó, để chuyển đổi trở lại từ radian sang thập phân, nhân với 180 / pi. HTH
Ryan Guill

1
Xin lỗi vì đã đến muộn, nhưng tôi đã tự hỏi, toán học đằng sau thuật toán này là gì, ai đó có thể tư vấn cho tôi một số bài đọc mà điều này được giải thích không? Cảm ơn!
tonix 4/11/2015

1
Là gì z, pls?
SoS

Câu trả lời:


48

Cách tiếp cận đơn giản chỉ cần tính trung bình cho chúng có các trường hợp cạnh kỳ lạ với các góc khi chúng quấn từ 359 'trở về 0'.

Một câu hỏi trước đó rất nhiều về SO đã hỏi về việc tìm trung bình của một tập hợp các góc la bàn.

Một mở rộng của cách tiếp cận được đề xuất ở đó cho tọa độ hình cầu sẽ là:

  • Chuyển đổi mỗi cặp lat / long thành một vector 3D có độ dài đơn vị.
  • Tính tổng mỗi vectơ đó
  • Bình thường hóa vector kết quả
  • Chuyển đổi trở lại tọa độ hình cầu

6
Có vẻ tốt, tôi đã làm một cái gì đó tương tự dựa trên những gì tôi tìm thấy tại trang web này: geomidpoint.com/calculation.html .
zeke

4
downvoter - vui lòng giải thích và đưa ra giải pháp tốt hơn nếu bạn có thể.
Alnitak

90

Cảm ơn! Đây là phiên bản C # của các giải pháp của OP sử dụng độ. Nó sử dụng lớp System.Device.Location.GeoCoordine

    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);
    }

40

Tôi thấy bài viết này rất hữu ích vì vậy đây là giải pháp trong PHP. Tôi đã sử dụng thành công và chỉ muốn tiết kiệm một thời gian nữa.

/**
 * 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());
}

1
Tôi đã sử dụng giải pháp này nhưng nó đưa ra một giải pháp sai lầm nào đó - nếu tôi tìm kiếm trung tâm của một số tọa độ trên bản đồ, nó sẽ "cân" các điểm và có xu hướng ở nơi có nhiều điểm hơn.
LowFieldTheory

2
@Alnitak Ở đây chúng tôi muốn tìm kiếm trung tâm của khu vực được bao quanh bởi tọa độ. Bạn có chắc là bạn nhận xét đúng nơi?
LowFieldTheory

29

Bài viết rất hữu ích! Tôi đã triển khai điều này trong JavaScript, bằng mã của tôi. Tôi đã sử dụng thành công.

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)]);
}


1
Tôi biết bài viết đã cũ, nhưng bạn có thể vui lòng gửi một tài liệu tham khảo hoặc một cái gì đó giải thích Toán học đằng sau thuật toán bạn đã đăng không? Cảm ơn!
tonix 4/11/2015

Làm việc hoàn hảo! Cảm ơn
andrewoodleyjr

Tôi đã thử nghiệm tập lệnh với Google Apps Script nhưng kết quả không phải là điểm trung tâm chính xác của bản nhạc. Nó ở đâu đó gần đó nhưng không trực tiếp trên đường đua. Có một công thức tốt hơn để có được điểm giữa chính xác TRACK?
Dirk

12

Phiên bản Javascript của chức năng ban đầu

/**
 * 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);
}

12

Để có thể cứu ai đó một hoặc hai phút, đây là giải pháp đã được sử dụng trong Objective-C thay vì python. Phiên bản này lấy NSArray của NSValues ​​có chứa MKMapCoordins, được gọi để thực hiện:

#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;
}

2
Đối với bất kỳ ai ở ngoài đó, vì giá trị của nó, Thay vì sử dụng macro của riêng bạn để lấy độ cho radian, hãy nhập <GLKit/GLKMath.h>và sử dụng GLKMathDegreesToRadiansGLKMathRadiansToDegrees
pnizzle

8

các giải pháp rất hay, chỉ là những gì tôi cần cho dự án swift của mình, vì vậy đây là một cổng nhanh chóng. cảm ơn & đây cũng là một dự án sân chơi: https://github.com/ppoh71/playgound/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)")

4

Nếu bạn quan tâm đến việc có được một 'trung tâm' rất đơn giản của các điểm (ví dụ: chỉ đơn giản là căn giữa bản đồ đến trung tâm của đa giác gmaps của bạn), thì đây là một cách tiếp cận cơ bản phù hợp với tôi.

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;
}

Điều này trả về tọa độ lat / lng giữa cho tâm của đa giác.


4

Trong Django, điều này là không đáng kể (và thực sự hoạt động, tôi đã gặp vấn đề với một số giải pháp không trả lại chính xác các tiêu cực cho vĩ độ).

Chẳng hạn, giả sử bạn đang sử dụng django-geopostcodes (trong đó tôi là tác giả).

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

pointlà một Pointví dụ Django sau đó có thể được sử dụng để thực hiện những việc như lấy tất cả các đối tượng trong phạm vi 10km từ điểm trung tâm đó;

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

Thay đổi điều này thành Python thô là chuyện nhỏ;

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 đang sử dụng GEOS - chi tiết hơn tại https://docs.djangoproject.com/en/1.10/ref/contrib/gis/geos/


3

Phiên bản Java nếu có ai cần. Các hằng số xác định tĩnh để không tính toán chúng hai lần.

/**************************************************************************************************************
 *   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);
}

3

Đây là phiên bản Android dựa trên câu trả lời C # của @ Yodacheese bằng api của Google Maps:

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);

}

trong ứng dụng build.gradle thêm:

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

1

Đây là giống như một vấn đề trung bình có trọng số trong đó tất cả các trọng số là như nhau, và có hai chiều.

Tìm trung bình của tất cả các vĩ độ cho vĩ độ trung tâm của bạn và trung bình của tất cả các kinh độ cho kinh độ trung tâm.

Caveat Emptor: Đây là một xấp xỉ khoảng cách gần và lỗi sẽ trở nên ngang bướng khi sai lệch so với giá trị trung bình có hơn một vài dặm do độ cong của Trái Đất. Hãy nhớ rằng vĩ độ và kinh độ là độ (không thực sự là một lưới).


1
[-179,0], [+ 179,0] trung bình ở [0,0], hơi xa so với kết quả chính xác;)
Piskvor rời khỏi tòa nhà


1

Hết đối tượng trong PHP. Cho mảng của các cặp tọa độ, trả về trung tâm.

/**
 * 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);
}

Lấy ý tưởng từ # 4


1
Điều này sẽ không hoạt động cho các tọa độ vượt qua kinh tuyến 180. Ví dụ: hai điểm theo chiều dọc, -175 và 175 sẽ trả về tâm 0 trong thuật toán của bạn, theo đó trung tâm thực sẽ là -180 hoặc 180.
Winch

1

Đây là phiên bản python để tìm điểm trung tâm. Lat1 và lon1 là danh sách vĩ độ và kinh độ. nó sẽ lấy lại vĩ độ và kinh độ của điểm trung tâm.

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

1

Phi tiêu thực hiện cho Flutter để tìm Trung tâm điểm cho Nhiều Latitude, Longitude.

nhập khẩu gói toán

import 'dart:math' as math;

Danh sách Vĩ độ và Kinh độ

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

void 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 = loadList.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);
}

0

Nếu bạn muốn tất cả các điểm được hiển thị trong hình ảnh, bạn sẽ muốn điểm cực trị theo vĩ độ và kinh độ và đảm bảo rằng chế độ xem của bạn bao gồm các giá trị đó với bất kỳ đường viền nào bạn muốn.

(Từ câu trả lời của Alnitak, cách bạn tính toán điểm cực trị có thể có một chút vấn đề, nhưng nếu chúng ở một vài độ ở hai bên của kinh độ bao quanh, thì bạn sẽ gọi cú đánh và đi đúng tầm.)

Nếu bạn không muốn làm biến dạng bất kỳ bản đồ nào có các điểm này, thì hãy điều chỉnh tỷ lệ khung hình của khung giới hạn sao cho phù hợp với bất kỳ pixel nào bạn đã phân bổ cho chế độ xem nhưng vẫn bao gồm điểm cực trị.

Để giữ các điểm được căn giữa ở một số mức thu phóng tùy ý, hãy tính tâm của hộp giới hạn "vừa với" các điểm như trên và giữ điểm đó làm điểm chính giữa.


0

Tôi đã làm nhiệm vụ này trong javascript như dưới đây

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;
}

0

Như một sự đánh giá cao cho chủ đề này, đây là đóng góp nhỏ của tôi với việc triển khai trong Ruby, hy vọng rằng tôi sẽ cứu ai đó vài phút khỏi thời gian quý giá của họ:

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

0

Tôi đã sử dụng một công thức mà tôi nhận được từ www.geomidpoint.com và đã viết cách thực hiện C ++ sau đây. Các arraygeocoordslà các lớp của riêng tôi có chức năng nên tự giải thích.

/*
 * 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;
   }

0

Phi tiêu / Rung hình Tính điểm trung tâm của nhiều cặp tọa độ vĩ độ / kinh độ

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)
    };
  }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.