Hitung titik tengah dari pasangan koordinat lintang dan bujur

148

Diberikan satu set titik lintang dan bujur, bagaimana saya bisa menghitung garis lintang dan bujur dari titik pusat set itu (alias titik yang akan memusatkan tampilan pada semua titik)?

EDIT: Solusi Python yang saya gunakan:

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)
Zeke
sumber
2
Mengenai solusi Anda: Mungkin kesalahan Anda tidak akan terlalu besar dengan asumsi bumi bulat, tetapi bumi lebih baik digambarkan sebagai ellipsoid.
John
1
Tulis ini sebagai fungsi python dan bagikan di gist.github.com/3718961
Alvin
14
Sangat penting untuk dicatat bahwa ini mengasumsikan bahwa lat dan long Anda ada dalam radian! Aku menggaruk kepalaku untuk sementara waktu tidak menyadarinya. Untuk mengkonversi ke radian dari desimal, kalikan desimal * pi / 180. Kemudian untuk mengkonversi kembali dari radian ke desimal, kalikan dengan 180 / pi. HTH
Ryan Guill
1
Maaf terlambat, tapi saya bertanya-tanya, apa matematika di balik algoritma ini, dapatkah seseorang menyarankan saya beberapa bacaan di mana ini dijelaskan? Terima kasih!
tonix
1
Apa itu z, pls?
SoS

Jawaban:

48

Pendekatan sederhana hanya rata-rata mereka memiliki kasus tepi aneh dengan sudut ketika mereka membungkus dari 359 'kembali ke 0'.

Sebuah pertanyaan yang jauh lebih awal pada SO bertanya tentang menemukan rata-rata satu set sudut kompas

Perluasan pendekatan yang direkomendasikan di sana untuk koordinat bola adalah:

  • Ubah setiap pasangan lat / panjang menjadi vektor 3D satuan-panjang.
  • Jumlahkan masing-masing vektor tersebut
  • Normalisasi vektor yang dihasilkan
  • Konversi kembali ke koordinat bola
Alnitak
sumber
6
Sepertinya bagus, saya melakukan sesuatu yang serupa berdasarkan apa yang saya temukan di situs web ini: geomidpoint.com/calculation.html .
zeke
4
downvoter - tolong jelaskan, dan tawarkan solusi yang lebih baik jika Anda bisa.
Alnitak
90

Terima kasih! Berikut adalah versi C # dari solusi OP menggunakan derajat. Ini menggunakan kelas 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);
    }
Yodache
sumber
40

Saya menemukan posting ini sangat berguna jadi inilah solusinya dalam PHP. Saya telah menggunakan ini dengan sukses dan hanya ingin menghemat waktu lain.

/**
 * 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());
}
Tom Tucker
sumber
1
Saya telah menggunakan solusi ini tetapi entah bagaimana memberikan solusi yang salah - jika saya mencari pusat dari beberapa koordinat pada peta itu semacam "menimbang" poin dan cenderung untuk tetap di tempat ada lebih banyak poin.
LowFieldTheory
2
@Alnitak Di sini kita ingin mencari pusat area yang dibatasi oleh koordinat. Apakah Anda yakin mengomentari tempat yang tepat?
LowFieldTheory
29

Posting yang sangat berguna! Saya sudah menerapkan ini dalam JavaScript, dengan ini kode saya. Saya telah menggunakan ini dengan sukses.

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

Gio
sumber
1
Saya tahu posting sudah lama, tetapi bisakah Anda memposting referensi atau sesuatu yang menjelaskan matematika di balik algoritma yang Anda posting? Terima kasih!
tonix
Bekerja dengan sempurna! Terima kasih
andrewoodleyjr
Saya menguji skrip dengan Google Apps Script tetapi hasilnya bukan titik tengah yang tepat dari sebuah lagu. Itu adalah suatu tempat di dekatnya tetapi tidak langsung di trek. Apakah ada formula yang lebih baik untuk mendapatkan middlepoint ON THE TRACK?
Dirk
12

Versi Javascript dari fungsi aslinya

/**
 * 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);
}
Kelvin Spencer
sumber
12

Untuk kepentingan menyelamatkan seseorang satu atau dua menit, berikut adalah solusi yang digunakan dalam Objective-C, bukan python. Versi ini mengambil NSArray of NSValues ​​yang berisi MKMapCoordinates, yang dipanggil dalam implementasi saya:

#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;
}
Daryll H.
sumber
2
Bagi siapa pun di luar sana, untuk apa nilainya, Alih-alih menggunakan makro Anda sendiri untuk derajat ke radian, impor <GLKit/GLKMath.h>dan gunakan GLKMathDegreesToRadiansdanGLKMathRadiansToDegrees
pnizzle
8

solusi yang sangat bagus, hanya apa yang saya butuhkan untuk proyek cepat saya, jadi inilah port cepat. terima kasih & ini juga proyek taman bermain: 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)")
Peter Pohlmann
sumber
4

Jika Anda tertarik untuk mendapatkan 'pusat' poin yang sangat disederhanakan (misalnya, untuk hanya memusatkan peta ke pusat poligon gmaps Anda), maka inilah pendekatan dasar yang bekerja untuk saya.

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

Ini mengembalikan koordinat lat / lng tengah untuk pusat poligon.

Kerry Emerson
sumber
4

Di Django ini sepele (dan benar-benar berfungsi, saya punya masalah dengan sejumlah solusi yang tidak mengembalikan negatif untuk lintang dengan benar).

Sebagai contoh, katakanlah Anda menggunakan django-geopostcodes (saya penulisnya).

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

pointadalah Pointcontoh Django yang kemudian dapat digunakan untuk melakukan hal-hal seperti mengambil semua objek yang berada dalam jarak 10 km dari titik pusat itu;

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

Mengubah ini menjadi Python mentah itu sepele;

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

Di bawah tenda Django menggunakan GEOS - detail lebih lanjut di https://docs.djangoproject.com/en/1.10/ref/contrib/gis/geos/

alexhayes
sumber
3

Versi Java jika ada yang membutuhkannya. Konstanta didefinisikan statis untuk tidak menghitungnya dua kali.

/**************************************************************************************************************
 *   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);
}
Stan Sokolov
sumber
3

Berikut ini adalah versi Android berdasarkan jawaban C # @ Yodacheese menggunakan Google Maps api:

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

}

di app build.gradle tambahkan:

implementation 'com.google.android.gms:play-services-maps:17.0.0'
Hossein Amini
sumber
2

Implementasi Dart untuk Flutter untuk menemukan titik Tengah untuk Multiple Latitude, Longitude.

paket impor matematika

import 'dart:math' as math;

Daftar Lintang dan Bujur

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);
}
MSARKrish
sumber
1

Ini sama dengan masalah rata-rata tertimbang di mana semua bobotnya sama, dan ada dua dimensi.

Temukan rata-rata semua garis lintang untuk garis lintang pusat dan rata-rata semua garis bujur untuk garis bujur pusat.

Caveat Emptor: Ini adalah perkiraan jarak dekat dan kesalahan akan menjadi sulit ketika penyimpangan dari rata-rata lebih dari beberapa mil karena kelengkungan Bumi. Ingatlah bahwa garis lintang dan bujur adalah derajat (bukan benar-benar kotak).

jpredham
sumber
1
[-179,0], [+ 179,0] rata-rata pada [0,0], yang agak jauh dari hasil yang benar;)
Piskvor meninggalkan gedung
1

Keluar dari objek dalam PHP. Diberikan array pasangan koordinat, pusat pengembalian.

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

Diambil ide dari # 4

DabitNG
sumber
1
Ini tidak akan berfungsi untuk koordinat yang melintasi meridian ke-180. Misalnya, dua titik longitudal, -175 dan 175 akan mengembalikan pusat 0 dalam algoritme Anda, di mana pusat sesungguhnya adalah -180 atau 180.
Winch
1

Berikut adalah Versi python untuk menemukan titik pusat. Lat1 dan lon1 adalah daftar lintang dan bujur. itu akan mengembalikan garis lintang dan bujur dari titik pusat.

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
Faisal
sumber
1

Dart / Flutter Menghitung titik pusat dari beberapa koordinat koordinat lintang / bujur

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)
    };
  }
Miguel Chiquin
sumber
0

Jika Anda ingin semua titik terlihat dalam gambar, Anda ingin ekstrema dalam lintang dan bujur dan pastikan bahwa tampilan Anda menyertakan nilai-nilai itu dengan batas apa pun yang Anda inginkan.

(Dari jawaban Alnitak, bagaimana Anda menghitung ekstrem mungkin sedikit bermasalah, tetapi jika mereka beberapa derajat di kedua sisi garis bujur yang membungkus, maka Anda akan memanggil tembakan dan mengambil kisaran yang tepat.)

Jika Anda tidak ingin mendistorsi peta apa pun yang ada pada titik-titik ini, maka sesuaikan rasio aspek kotak pembatas sehingga cocok dengan piksel apa pun yang telah Anda alokasikan untuk tampilan tetapi masih menyertakan ekstrema.

Untuk menjaga agar titik-titik tetap di tengah pada beberapa tingkat pembesaran sewenang-wenang, hitung pusat dari kotak pembatas yang "pas" dengan titik-titik di atas, dan pertahankan titik itu sebagai titik tengah.

John
sumber
0

Saya melakukan tugas ini dalam javascript seperti di bawah ini

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;
}
Renish Gotecha
sumber
0

Sebagai penghargaan untuk utas ini, berikut adalah kontribusi kecil saya dengan implementasi di Ruby, berharap bahwa saya akan menyelamatkan seseorang beberapa menit dari waktu berharga mereka:

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
Fatos Morina
sumber
0

Saya menggunakan formula yang saya dapatkan dari www.geomidpoint.com dan menulis implementasi C ++ berikut. Itu arraydan geocoordsadalah kelas saya sendiri yang fungsinya harus jelas.

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