Bagaimana cara menghitung jarak antara dua titik yang ditentukan oleh garis lintang dan bujur?
Untuk klarifikasi, saya'd seperti jarak dalam kilometer; poin menggunakan sistem WGS84 dan I'd seperti untuk memahami relatif akurasi dari pendekatan yang tersedia.
Ini link mungkin bisa bermanfaat untuk anda, seperti rincian penggunaan Haversine formula untuk menghitung jarak.
Kutipan:
script Ini [Javascript] menghitung besar-lingkaran jarak antara dua titik – yaitu jarak terpendek di atas permukaan bumi – menggunakan 'Haversine' formula.
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2) {
var R = 6371; // Radius of the earth in km
var dLat = deg2rad(lat2-lat1); // deg2rad below
var dLon = deg2rad(lon2-lon1);
var a =
Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
;
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c; // Distance in km
return d;
}
function deg2rad(deg) {
return deg * (Math.PI/180)
}
Saya perlu untuk menghitung banyak jarak antara titik-titik untuk proyek saya, jadi aku pergi ke depan dan mencoba untuk mengoptimalkan kode, saya telah menemukan berikut ini. Rata-rata di browser yang berbeda saya baru pelaksanaan berjalan 2 kali lebih cepat dari yang paling upvoted menjawab.
function distance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295; // Math.PI / 180
var c = Math.cos;
var a = 0.5 - c((lat2 - lat1) * p)/2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p))/2;
return 12742 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371 km
}
Anda dapat bermain dengan saya jsPerf dan melihat hasil.
Baru-baru ini saya butuhkan untuk melakukan hal yang sama di python, jadi di sini adalah python pelaksanaan:
from math import cos, asin, sqrt
def distance(lat1, lon1, lat2, lon2):
p = 0.017453292519943295 #Pi/180
a = 0.5 - cos((lat2 - lat1) * p)/2 + cos(lat1 * p) * cos(lat2 * p) * (1 - cos((lon2 - lon1) * p)) / 2
return 12742 * asin(sqrt(a)) #2*R*asin...
Dan demi kelengkapan: Haversine pada wiki.
Berikut ini adalah C# Pelaksanaan:
static class DistanceAlgorithm
{
const double PIx = 3.141592653589793;
const double RADIUS = 6378.16;
/// <summary>
/// Convert degrees to Radians
/// </summary>
/// <param name="x">Degrees</param>
/// <returns>The equivalent in radians</returns>
public static double Radians(double x)
{
return x * PIx / 180;
}
/// <summary>
/// Calculate the distance between two places.
/// </summary>
/// <param name="lon1"></param>
/// <param name="lat1"></param>
/// <param name="lon2"></param>
/// <param name="lat2"></param>
/// <returns></returns>
public static double DistanceBetweenPlaces(
double lon1,
double lat1,
double lon2,
double lat2)
{
double dlon = Radians(lon2 - lon1);
double dlat = Radians(lat2 - lat1);
double a = (Math.Sin(dlat / 2) * Math.Sin(dlat / 2)) + Math.Cos(Radians(lat1)) * Math.Cos(Radians(lat2)) * (Math.Sin(dlon / 2) * Math.Sin(dlon / 2));
double angle = 2 * Math.Atan2(Math.Sqrt(a), Math.Sqrt(1 - a));
return angle * RADIUS;
}
}
Berikut ini adalah implementasi java dari Haversine formula.
public final static double AVERAGE_RADIUS_OF_EARTH_KM = 6371;
public int calculateDistanceInKilometer(double userLat, double userLng,
double venueLat, double venueLng) {
double latDistance = Math.toRadians(userLat - venueLat);
double lngDistance = Math.toRadians(userLng - venueLng);
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(userLat)) * Math.cos(Math.toRadians(venueLat))
* Math.sin(lngDistance / 2) * Math.sin(lngDistance / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (int) (Math.round(AVERAGE_RADIUS_OF_EARTH_KM * c));
}
Perhatikan bahwa di sini kita pembulatan jawaban terdekat km.
Terima kasih banyak untuk semua ini. Saya menggunakan kode berikut di Objective-C iPhone app:
const double PIx = 3.141592653589793;
const double RADIO = 6371; // Mean radius of Earth in Km
double convertToRadians(double val) {
return val * PIx / 180;
}
-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {
double dlon = convertToRadians(place2.longitude - place1.longitude);
double dlat = convertToRadians(place2.latitude - place1.latitude);
double a = ( pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))) * cos(convertToRadians(place2.latitude)) * pow(sin(dlon / 2), 2);
double angle = 2 * asin(sqrt(a));
return angle * RADIO;
}
Lintang dan Bujur dalam desimal. Aku't menggunakan min() untuk asin() panggilan sebagai jarak yang saya'm menggunakan begitu kecil bahwa mereka don't membutuhkan itu.
Itu memberi jawaban yang salah sampai aku lulus dalam nilai-nilai dalam Radian - sekarang's cukup banyak yang sama seperti nilai-nilai yang diperoleh dari Apple's Peta app :-)
Tambahan update:
Jika anda menggunakan iOS4 atau lambat maka Apple memberikan beberapa metode untuk melakukan hal ini sehingga fungsi yang sama akan dicapai dengan:
-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {
MKMapPoint start, finish;
start = MKMapPointForCoordinate(place1);
finish = MKMapPointForCoordinate(place2);
return MKMetersBetweenMapPoints(start, finish) / 1000;
}
Ini adalah fungsi PHP sederhana yang akan memberikan sangat wajar pendekatan (di bawah +/-1% margin error).
<?php
function distance($lat1, $lon1, $lat2, $lon2) {
$pi80 = M_PI / 180;
$lat1 *= $pi80;
$lon1 *= $pi80;
$lat2 *= $pi80;
$lon2 *= $pi80;
$r = 6372.797; // mean radius of Earth in km
$dlat = $lat2 - $lat1;
$dlon = $lon2 - $lon1;
$a = sin($dlat / 2) * sin($dlat / 2) + cos($lat1) * cos($lat2) * sin($dlon / 2) * sin($dlon / 2);
$c = 2 * atan2(sqrt($a), sqrt(1 - $a));
$km = $r * $c;
//echo '<br/>'.$km;
return $km;
}
?>
Seperti dikatakan sebelumnya, bumi ini BUKAN bulat. Hal ini seperti orang tua, tua baseball bahwa Mark McGwire memutuskan untuk berlatih dengan penuh lekukan dan benjolan. Sederhana perhitungan (seperti ini) memperlakukannya seperti sebuah bola.
Metode yang berbeda mungkin lebih atau kurang tepat menurut mana yang tidak teratur bulat telur DAN seberapa jauh anda poin (semakin dekat mereka semakin kecil kesalahan mutlak margin). Yang lebih tepat dengan harapan anda, semakin kompleks matematika.
Untuk info lebih lanjut: wikipedia jarak geografis
Saya posting di sini saya bekerja misalnya.
Daftar semua poin di tabel yang memiliki jarak antara titik yang ditentukan (kita menggunakan random titik - lat:45.20327, panjang:23.7806) kurang dari 50 KM, dengan lintang & bujur, di MySQL (tabel bidang coord_lat dan coord_long):
Daftar semua memiliki JARAK<50, di Kilometer (dianggap Bumi radius 6371 KM):
SELECT denumire, (6371 * acos( cos( radians(45.20327) ) * cos( radians( coord_lat ) ) * cos( radians( 23.7806 ) - radians(coord_long) ) + sin( radians(45.20327) ) * sin( radians(coord_lat) ) )) AS distanta
FROM obiective
WHERE coord_lat<>''
AND coord_long<>''
HAVING distanta<50
ORDER BY distanta desc
Contoh di atas telah diuji coba di MySQL 5.0.95 dan 5.5.16 (Linux).
Di lain jawaban implementasi di [tag:r] hilang.
Menghitung jarak antara dua titik cukup mudah dengan distm
fungsi dari geosfer
paket:
distm(p1, p2, fun = distHaversine)
dimana:
p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid
Karena bumi tidak bulat sempurna, yang rumus Vincenty untuk ellipsoids mungkin adalah cara terbaik untuk menghitung jarak. Dengan demikian dalam geosfer
paket yang anda gunakan:
distm(p1, p2, fun = distVincentyEllipsoid)
Tentu saja anda don't harus menggunakan geosfer
paket, anda juga dapat menghitung jarak di dasar R
dengan fungsi:
hav.dist <- function(long1, lat1, long2, lat2) {
R <- 6371
diff.long <- (long2 - long1)
diff.lat <- (lat2 - lat1)
a <- sin(diff.lat/2)^2 + cos(lat1) * cos(lat2) * sin(diff.long/2)^2
b <- 2 * asin(pmin(1, sqrt(a)))
d = R * b
return(d)
}
Yang haversine pasti formula yang baik untuk mungkin kebanyakan kasus, jawaban yang lain sudah seperti itu jadi saya tidak akan mengambil ruang. Tetapi penting untuk dicatat bahwa tidak peduli apa rumus yang digunakan (ya tidak hanya satu). Karena sejumlah besar akurasi mungkin serta perhitungan waktu yang diperlukan. Pilihan formula memerlukan sedikit berpikir lebih dari yang sederhana tidak punya otak jawabannya.
Ini posting dari orang-orang di nasa, adalah salah satu yang terbaik yang saya temukan di mendiskusikan pilihan
http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
Misalnya, jika anda hanya menyortir baris dengan jarak 100 mil radius. Bumi itu datar rumus akan jauh lebih cepat dari haversine.
HalfPi = 1.5707963;
R = 3956; /* the radius gives you the measurement unit*/
a = HalfPi - latoriginrad;
b = HalfPi - latdestrad;
u = a * a + b * b;
v = - 2 * a * b * cos(longdestrad - longoriginrad);
c = sqrt(abs(u + v));
return R * c;
Pemberitahuan hanya ada satu kosinus dan salah satu akar kuadrat. Vs 9 dari mereka pada Haversine formula.
Saya don't seperti menambahkan lagi menjawab, tapi Google maps API v. 3 memiliki spherical geometri (dan lebih). Setelah mengkonversi WGS84 ke derajat desimal anda dapat melakukan ini:
<script src="http://maps.google.com/maps/api/js?sensor=false&libraries=geometry" type="text/javascript"></script>
distance = google.maps.geometry.spherical.computeDistanceBetween(
new google.maps.LatLng(fromLat, fromLng),
new google.maps.LatLng(toLat, toLng));
Tidak ada kata tentang seberapa akurat Google's perhitungan atau bahkan model apa yang digunakan (meskipun itu tidak mengatakan "bola" bukan "geoid". By the way, "garis lurus" jarak jelas akan berbeda dari kejauhan jika salah satu perjalanan di permukaan bumi yang adalah apa yang semua orang tampaknya menganggap.
Anda dapat menggunakan membangun di CLLocationDistance untuk menghitung ini:
CLLocation *location1 = [[CLLocation alloc] initWithLatitude:latitude1 longitude:longitude1];
CLLocation *location2 = [[CLLocation alloc] initWithLatitude:latitude2 longitude:longitude2];
[self distanceInMetersFromLocation:location1 toLocation:location2]
- (int)distanceInMetersFromLocation:(CLLocation*)location1 toLocation:(CLLocation*)location2 {
CLLocationDistance distanceInMeters = [location1 distanceFromLocation:location2];
return distanceInMeters;
}
Dalam kasus anda jika anda ingin kilometer hanya dibagi dengan 1000.
Python terimplementasikan Asal lebih pusat bersebelahan Amerika Serikat.
from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)
Untuk mendapatkan jawabannya di kilometer hanya mengatur km=false.
Mungkin ada solusi yang lebih sederhana, dan lebih benar: keliling bumi adalah 40.000 Km di khatulistiwa, tentang 37,000 di Greenwich (atau bujur) siklus. Dengan demikian:
pythagoras = function (lat1, lon1, lat2, lon2) {
function sqr(x) {return x * x;}
function cosDeg(x) {return Math.cos(x * Math.PI / 180.0);}
var earthCyclePerimeter = 40000000.0 * cosDeg((lat1 + lat2) / 2.0);
var dx = (lon1 - lon2) * earthCyclePerimeter / 360.0;
var dy = 37000000.0 * (lat1 - lat2) / 360.0;
return Math.sqrt(sqr(dx) + sqr(dy));
};
Saya setuju bahwa itu harus fine-tuned, saya sendiri mengatakan bahwa hal itu's ellipsoid, sehingga jari-jari akan dikalikan dengan cosinus bervariasi. Tapi itu's sedikit lebih akurat. Dibandingkan dengan Google Maps, dan itu tidak mengurangi kesalahan secara signifikan.
Semua jawaban diatas mengasumsikan bumi adalah sebuah bola. Namun, yang lebih akurat pendekatan akan menjadi sebuah oblate spheroid.
a= 6378.137#equitorial radius in km
b= 6356.752#polar radius in km
def Distance(lat1, lons1, lat2, lons2):
lat1=math.radians(lat1)
lons1=math.radians(lons1)
R1=(((((a**2)*math.cos(lat1))**2)+(((b**2)*math.sin(lat1))**2))/((a*math.cos(lat1))**2+(b*math.sin(lat1))**2))**0.5 #radius of earth at lat1
x1=R*math.cos(lat1)*math.cos(lons1)
y1=R*math.cos(lat1)*math.sin(lons1)
z1=R*math.sin(lat1)
lat2=math.radians(lat2)
lons2=math.radians(lons2)
R1=(((((a**2)*math.cos(lat2))**2)+(((b**2)*math.sin(lat2))**2))/((a*math.cos(lat2))**2+(b*math.sin(lat2))**2))**0.5 #radius of earth at lat2
x2=R*math.cos(lat2)*math.cos(lons2)
y2=R*math.cos(lat2)*math.sin(lons2)
z2=R*math.sin(lat2)
return ((x1-x2)**2+(y1-y2)**2+(z1-z2)**2)**0.5
Seperti yang ditunjukkan, perhitungan yang akurat harus memperhitungkan bahwa bumi tidak bulat sempurna. Berikut ini adalah beberapa perbandingan dari berbagai algoritma yang ditawarkan di sini:
geoDistance(50,5,58,3)
Haversine: 899 km
Maymenn: 833 km
Keerthana: 897 km
google.maps.geometry.spherical.computeDistanceBetween(): 900 km
geoDistance(50,5,-58,-3)
Haversine: 12030 km
Maymenn: 11135 km
Keerthana: 10310 km
google.maps.geometry.spherical.computeDistanceBetween(): 12044 km
geoDistance(.05,.005,.058,.003)
Haversine: 0.9169 km
Maymenn: 0.851723 km
Keerthana: 0.917964 km
google.maps.geometry.spherical.computeDistanceBetween(): 0.917964 km
geoDistance(.05,80,.058,80.3)
Haversine: 33.37 km
Maymenn: 33.34 km
Keerthana: 33.40767 km
google.maps.geometry.spherical.computeDistanceBetween(): 33.40770 km
Lebih dari jarak kecil, Keerthana's algoritma tampaknya bertepatan dengan Google Maps. Google Maps tampaknya tidak mengikuti algoritma sederhana, yang menunjukkan bahwa hal itu mungkin metode yang paling akurat di sini.
Anyway, di sini adalah sebuah Javascript pelaksanaan Keerthana's algoritma:
function geoDistance(lat1, lng1, lat2, lng2){
const a = 6378.137; // equitorial radius in km
const b = 6356.752; // polar radius in km
var sq = x => (x*x);
var sqr = x => Math.sqrt(x);
var cos = x => Math.cos(x);
var sin = x => Math.sin(x);
var radius = lat => sqr((sq(a*a*cos(lat))+sq(b*b*sin(lat)))/(sq(a*cos(lat))+sq(b*sin(lat))));
lat1 = lat1 * Math.PI / 180;
lng1 = lng1 * Math.PI / 180;
lat2 = lat2 * Math.PI / 180;
lng2 = lng2 * Math.PI / 180;
var R1 = radius(lat1);
var x1 = R1*cos(lat1)*cos(lng1);
var y1 = R1*cos(lat1)*sin(lng1);
var z1 = R1*sin(lat1);
var R2 = radius(lat2);
var x2 = R2*cos(lat2)*cos(lng2);
var y2 = R2*cos(lat2)*sin(lng2);
var z2 = R2*sin(lat2);
return sqr(sq(x1-x2)+sq(y1-y2)+sq(z1-z2));
}
Berikut ini adalah Implementasi SQL untuk menghitung jarak dalam km,
SELECT UserId, ( 3959 * acos( cos( radians( your latitude here ) ) * cos( radians(latitude) ) *
cos( radians(longitude) - radians( your longitude here ) ) + sin( radians( your latitude here ) ) *
sin( radians(latitude) ) ) ) AS distance FROM user HAVING
distance < 5 ORDER BY distance LIMIT 0 , 5;
Untuk rincian lebih lanjut dalam implementasi pemrograman langugage, anda hanya dapat pergi melalui script php yang diberikan di sini
Berikut adalah naskah pelaksanaan Haversine formula
static getDistanceFromLatLonInKm(lat1: number, lon1: number, lat2: number, lon2: number): number {
var deg2Rad = deg => {
return deg * Math.PI / 180;
}
var r = 6371; // Radius of the earth in km
var dLat = deg2Rad(lat2 - lat1);
var dLon = deg2Rad(lon2 - lon1);
var a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(deg2Rad(lat1)) * Math.cos(deg2Rad(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var d = r * c; // Distance in km
return d;
}
Script ini [PHP] menghitung jarak antara dua titik.
public static function getDistanceOfTwoPoints($source, $dest, $unit='K') {
$lat1 = $source[0];
$lon1 = $source[1];
$lat2 = $dest[0];
$lon2 = $dest[1];
$theta = $lon1 - $lon2;
$dist = sin(deg2rad($lat1)) * sin(deg2rad($lat2)) + cos(deg2rad($lat1)) * cos(deg2rad($lat2)) * cos(deg2rad($theta));
$dist = acos($dist);
$dist = rad2deg($dist);
$miles = $dist * 60 * 1.1515;
$unit = strtoupper($unit);
if ($unit == "K") {
return ($miles * 1.609344);
}
else if ($unit == "M")
{
return ($miles * 1.609344 * 1000);
}
else if ($unit == "N") {
return ($miles * 0.8684);
}
else {
return $miles;
}
}
Untuk menghitung jarak antara dua titik pada bidang yang anda butuhkan untuk melakukan Lingkaran Besar perhitungan.
Ada sejumlah C/C++ perpustakaan untuk membantu dengan proyeksi peta di MapTools jika anda perlu untuk mengubah proyeksi jarak untuk permukaan yang datar. Untuk melakukan ini, anda akan perlu proyeksi string dari berbagai sistem koordinat.
Anda juga dapat menemukan MapWindow alat yang berguna untuk memvisualisasikan poin. Juga sebagai open source yang berguna panduan untuk cara menggunakan proj.dll perpustakaan, yang tampaknya menjadi inti open source proyeksi perpustakaan.
Berikut ini's jawaban yang diterima pelaksanaan porting ke Jawa dalam kasus ada yang membutuhkan itu.
package com.project529.garage.util;
/**
* Mean radius.
*/
private static double EARTH_RADIUS = 6371;
/**
* Returns the distance between two sets of latitudes and longitudes in meters.
* <p/>
* Based from the following JavaScript SO answer:
* http://stackoverflow.com/questions/27928/calculate-distance-between-two-latitude-longitude-points-haversine-formula,
* which is based on https://en.wikipedia.org/wiki/Haversine_formula (error rate: ~0.55%).
*/
public double getDistanceBetween(double lat1, double lon1, double lat2, double lon2) {
double dLat = toRadians(lat2 - lat1);
double dLon = toRadians(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = EARTH_RADIUS * c;
return d;
}
public double toRadians(double degrees) {
return degrees * (Math.PI / 180);
}