위도와 경도로 지정된 두 점 사이의 거리를 어떻게 계산합니까?
명확히하기 위해 거리를 킬로미터 단위로 원합니다. 요점은 WGS84 시스템을 사용하며 사용 가능한 접근 방식의 상대적 정확성을 이해하고 싶습니다.
위도와 경도로 지정된 두 점 사이의 거리를 어떻게 계산합니까?
명확히하기 위해 거리를 킬로미터 단위로 원합니다. 요점은 WGS84 시스템을 사용하며 사용 가능한 접근 방식의 상대적 정확성을 이해하고 싶습니다.
답변:
이 링크 는 거리 계산에 Haversine 공식 사용을 자세히 설명하므로 도움이 될 수 있습니다 .
발췌 :
이 스크립트 [Javascript]는 'Haversine'공식을 사용하여 두 점 사이의 원거리, 즉 지표면에서 가장 짧은 거리를 계산합니다.
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)
}
Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
대신 Math.asin(Math.sqrt(h))
Wikipedia 기사에서 사용하는 수식을 직접 구현하는 대신 사용할 이유 가 있습니까? 더 효율적이고 수치 적으로 안정적입니까?
(sin(x))²
등호(sin(-x))²
프로젝트의 포인트 사이의 거리를 많이 계산해야했기 때문에 코드를 최적화하려고했습니다. 다른 브라우저에서 평균적으로 새로운 구현 은 가장 많이 응답 된 답변보다 2 배 빠르게 실행됩니다 .
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
}
내 jsPerf로 게임을하고 결과를 확인할 수 있습니다 .
최근에는 파이썬에서 동일한 작업을 수행해야 했으므로 다음은 파이썬 구현입니다 .
from math import cos, asin, sqrt, pi
def distance(lat1, lon1, lat2, lon2):
p = 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...
그리고 완전성을 위해 : 위키의 Haversine .
// 2 * R; R = 6371 km
의미 하는가? 현재 방법은 km 또는 마일로 답변을 제공합니까? 더 나은 문서가 필요합니다. 감사합니다
다음은 C # 구현입니다.
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;
}
}
double dlon = Radians(lon2 - lon1);
와double dlat = Radians(lat2 - lat1);
RADIUS
다른 답변에서와 같이 6371을 할 수있는 값이 필요?
Haversine 공식의 Java 구현은 다음과 같습니다.
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));
}
여기서 우리는 답을 가장 가까운 km로 반올림합니다.
6371000
지구의 반지름으로 사용하려면 ? (평균 지구 반경은 6371000 미터) 또는 함수에서 킬로미터를 미터로 변환 하시겠습니까?
0.621371
이 모든 것에 대해 대단히 감사합니다. Objective-C iPhone 앱에서 다음 코드를 사용했습니다.
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;
}
위도와 경도는 10 진수입니다. asin () 호출에 min ()을 사용하지 않았습니다. 사용하는 거리가 너무 작아서 필요하지 않기 때문입니다.
Radians의 값을 전달할 때까지 잘못된 답변을 제공했습니다. 이제 Apple의 Map 앱에서 얻은 값과 거의 동일합니다. :-)
추가 업데이트 :
iOS4 이상을 사용하는 경우 Apple은이를 수행하는 몇 가지 방법을 제공하므로 다음과 같은 기능을 수행 할 수 있습니다.
-(double)kilometresBetweenPlace1:(CLLocationCoordinate2D) place1 andPlace2:(CLLocationCoordinate2D) place2 {
MKMapPoint start, finish;
start = MKMapPointForCoordinate(place1);
finish = MKMapPointForCoordinate(place2);
return MKMetersBetweenMapPoints(start, finish) / 1000;
}
pow(sin(dlat / 2), 2) + cos(convertToRadians(place1.latitude))
가 잘못 되었다고 생각합니다 . 그것들을 제거하면 결과는이 페이지에서 다른 구현을 사용할 때 얻는 것과 일치하거나 Wikipedia 의 Haversine 수식 을 처음부터 구현합니다 .
()
주위에 3869.75가됩니다. 그것들이 없으면 웹 검색이 나타나는 3935.75를 얻습니다.
이것은 매우 합리적인 근사치 (+/- 1 % 오류 한계)를 제공하는 간단한 PHP 함수입니다.
<?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;
}
?>
전에 말했듯이; 지구는 구체가 아닙니다. 그것은 마크 맥 와이어가 연습하기로 결정한 낡고 오래된 야구와 같습니다. 더 간단한 계산 (이와 같이)은 구처럼 취급합니다.
이 불규칙한 난형의 위치와 점이 얼마나 떨어져 있는지에 따라 다른 방법이 다소 정확 할 수 있습니다 (절대 오차 한계가 작을수록). 기대치가 정확할수록 수학은 더 복잡해집니다.
더 많은 정보를 원하시면 : wikipedia geographic distance
나는 여기에 작업 예제를 게시합니다.
MySQL에서 위도 및 경도와 함께 50KM 미만의 지정된 점 사이의 거리를 갖는 테이블의 모든 점을 나열합니다 (임의의 점-위도 : 45.20327, 긴 : 23.7806) (테이블 필드는 coord_lat 및 coord_long).
킬로미터에서 거리가 50 미만인 모든 것을 나열하십시오 (지구 반경 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
위의 예제는 MySQL 5.0.95 및 5.5.16 (Linux)에서 테스트되었습니다.
다른 답변에서 구현 아르 자형 누락.
두 점 사이의 거리를 계산하는 distm
것은 geosphere
패키지 의 기능으로 매우 간단 합니다.
distm(p1, p2, fun = distHaversine)
어디:
p1 = longitude/latitude for point(s)
p2 = longitude/latitude for point(s)
# type of distance calculation
fun = distCosine / distHaversine / distVincentySphere / distVincentyEllipsoid
지구가 완전히 구형이 아니기 때문에 타원체 의 Vincenty 공식 은 아마도 거리를 계산하는 가장 좋은 방법 일 것입니다. 따라서 geosphere
패키지 에서 다음을 사용하십시오.
distm(p1, p2, fun = distVincentyEllipsoid)
물론 geosphere
패키지 를 반드시 사용할 필요는 없으며 R
함수를 사용하여 기본 거리를 계산할 수도 있습니다.
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)
}
haversine은 아마도 대부분의 경우에 좋은 공식입니다. 다른 답변에는 이미 포함되어 있으므로 공간을 차지하지 않을 것입니다. 그러나 어떤 수식을 사용하든 (예 하나가 아니라) 유의해야합니다. 필요한 계산 시간뿐만 아니라 가능한 넓은 범위의 정확도로 인해. 공식을 선택하려면 단순한 무 정답보다 조금 더 많은 생각이 필요합니다.
NASA의 사람이 게시 한이 옵션을 논의 할 때 찾은 최고의 것입니다
http://www.cs.nyu.edu/visual/home/proj/tiger/gisfaq.html
예를 들어 반경 100 마일의 거리를 기준으로 행을 정렬하는 경우가 있습니다. 평평한 지구 공식은 헤르 세인보다 훨씬 빠릅니다.
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;
하나의 코사인과 하나의 제곱근이 있습니다. Haversine 공식에 대한 9 대.
CLLocationDistance에서 빌드를 사용하여이를 계산할 수 있습니다.
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;
}
귀하의 경우 킬로미터를 1000으로 나누려면.
또 다른 답변을 추가하는 것을 좋아하지 않지만 Google Maps API v.3에는 구형 지오메트리가 있습니다. WGS84를 십진수로 변환 한 후 다음을 수행 할 수 있습니다.
<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));
구글의 계산이 얼마나 정확한지, 심지어 어떤 모델이 사용되는지에 대해서는 아무 말도하지 않는다. 모든 사람들이 추정하는 지구 표면.
파이썬 함축 기원은 인접한 미국의 중심입니다.
from haversine import haversine
origin = (39.50, 98.35)
paris = (48.8567, 2.3508)
haversine(origin, paris, miles=True)
킬로미터 단위로 답을 얻으려면 단순히 miles = false를 설정하십시오.
더 간단한 해결책과 더 정확한 방법이있을 수 있습니다. 지구의 둘레는 적도에서 40,000Km이며 그리니치 (또는 경도)주기에서 약 37,000입니다. 그러므로:
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));
};
나는 그것이 타원이라고 말했기 때문에 미세 조정되어야한다는 데 동의하므로 코사인에 곱할 반지름은 다양합니다. 그러나 좀 더 정확합니다. Google지도와 비교하여 오류가 크게 줄었습니다.
위의 모든 대답은 지구가 구체라고 가정합니다. 그러나,보다 정확한 근사치는 편원 구형의 근사치 일 것입니다.
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
다음은 km 단위의 거리를 계산하는 SQL 구현입니다.
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;
langugage를 프로그래밍하여 구현에 대한 자세한 내용을 보려면 여기에 제공된 PHP 스크립트를 사용 하십시오.
Haversine 공식 의 타이프 스크립트 구현은 다음과 같습니다.
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;
}
지적한 바와 같이, 정확한 계산은 지구가 완벽한 구체가 아니라는 점을 고려해야합니다. 여기에 제공된 다양한 알고리즘을 비교 한 것입니다.
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
먼 거리에서 Keerthana의 알고리즘은 Google Maps의 알고리즘과 일치하는 것 같습니다. Google지도는 간단한 알고리즘을 따르지 않는 것 같습니다. 여기에서 가장 정확한 방법 일 수 있습니다.
어쨌든 다음은 Keerthana 알고리즘의 Javascript 구현입니다.
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));
}
이 스크립트 (PHP)는 두 점 사이의 거리를 계산합니다.
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;
}
}
Haversine 공식 에 따른 Java 구현
double calculateDistance(double latPoint1, double lngPoint1,
double latPoint2, double lngPoint2) {
if(latPoint1 == latPoint2 && lngPoint1 == lngPoint2) {
return 0d;
}
final double EARTH_RADIUS = 6371.0; //km value;
//converting to radians
latPoint1 = Math.toRadians(latPoint1);
lngPoint1 = Math.toRadians(lngPoint1);
latPoint2 = Math.toRadians(latPoint2);
lngPoint2 = Math.toRadians(lngPoint2);
double distance = Math.pow(Math.sin((latPoint2 - latPoint1) / 2.0), 2)
+ Math.cos(latPoint1) * Math.cos(latPoint2)
* Math.pow(Math.sin((lngPoint2 - lngPoint1) / 2.0), 2);
distance = 2.0 * EARTH_RADIUS * Math.asin(Math.sqrt(distance));
return distance; //km value
}
구의 두 점 사이의 거리를 계산하려면 Great Circle 계산 을 수행해야합니다 .
거리를 평평한 표면으로 재 투영해야하는 경우 MapTools 에서지도 투영에 도움이되는 여러 C / C ++ 라이브러리가 있습니다. 이렇게하려면 다양한 좌표계의 투영 문자열이 필요합니다.
당신은 또한 찾을 수 있습니다 MapWindow에게 포인트를 시각화하는 유용한 도구. 또한 오픈 소스로서 핵심 오픈 소스 프로젝션 라이브러리로 보이는 proj.dll 라이브러리를 사용하는 방법에 대한 유용한 안내서입니다.
다음은 누구나 필요로하는 경우 Java로 포팅 된 승인 된 응답 구현입니다.
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);
}
다음은 VB.NET 구현입니다.이 구현은 전달한 Enum 값을 기반으로 KM 또는 마일 단위로 결과를 제공합니다.
Public Enum DistanceType
Miles
KiloMeters
End Enum
Public Structure Position
Public Latitude As Double
Public Longitude As Double
End Structure
Public Class Haversine
Public Function Distance(Pos1 As Position,
Pos2 As Position,
DistType As DistanceType) As Double
Dim R As Double = If((DistType = DistanceType.Miles), 3960, 6371)
Dim dLat As Double = Me.toRadian(Pos2.Latitude - Pos1.Latitude)
Dim dLon As Double = Me.toRadian(Pos2.Longitude - Pos1.Longitude)
Dim a As Double = Math.Sin(dLat / 2) * Math.Sin(dLat / 2) + Math.Cos(Me.toRadian(Pos1.Latitude)) * Math.Cos(Me.toRadian(Pos2.Latitude)) * Math.Sin(dLon / 2) * Math.Sin(dLon / 2)
Dim c As Double = 2 * Math.Asin(Math.Min(1, Math.Sqrt(a)))
Dim result As Double = R * c
Return result
End Function
Private Function toRadian(val As Double) As Double
Return (Math.PI / 180) * val
End Function
End Class
수식을 단순화하여 계산을 축소했습니다.
여기 Ruby가 있습니다 :
include Math
earth_radius_mi = 3959
radians = lambda { |deg| deg * PI / 180 }
coord_radians = lambda { |c| { :lat => radians[c[:lat]], :lng => radians[c[:lng]] } }
# from/to = { :lat => (latitude_in_degrees), :lng => (longitude_in_degrees) }
def haversine_distance(from, to)
from, to = coord_radians[from], coord_radians[to]
cosines_product = cos(to[:lat]) * cos(from[:lat]) * cos(from[:lng] - to[:lng])
sines_product = sin(to[:lat]) * sin(from[:lat])
return earth_radius_mi * acos(cosines_product + sines_product)
end
function getDistanceFromLatLonInKm(lat1,lon1,lat2,lon2,units) {
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;
var miles = d / 1.609344;
if ( units == 'km' ) {
return d;
} else {
return miles;
}}
척의 솔루션, 마일에도 유효합니다.
다음은 일부 검색 후 십진도를 통한 계산 거리에 대한 Java 구현입니다. 나는 wikipedia에서 세계의 평균 반경을 km 단위로 사용했습니다. 결과 마일을 원하면 세계 반경을 마일 단위로 사용하십시오.
public static double distanceLatLong2(double lat1, double lng1, double lat2, double lng2)
{
double earthRadius = 6371.0d; // KM: use mile here if you want mile result
double dLat = toRadian(lat2 - lat1);
double dLng = toRadian(lng2 - lng1);
double a = Math.pow(Math.sin(dLat/2), 2) +
Math.cos(toRadian(lat1)) * Math.cos(toRadian(lat2)) *
Math.pow(Math.sin(dLng/2), 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return earthRadius * c; // returns result kilometers
}
public static double toRadian(double degrees)
{
return (degrees * Math.PI) / 180.0d;
}
MySQL에서는 다음 함수를 사용하여 매개 변수를 전달하십시오. POINT(LONG,LAT)
CREATE FUNCTION `distance`(a POINT, b POINT)
RETURNS double
DETERMINISTIC
BEGIN
RETURN
GLength( LineString(( PointFromWKB(a)), (PointFromWKB(b)))) * 100000; -- To Make the distance in meters
END;
function getDistanceFromLatLonInKm(position1, position2) {
"use strict";
var deg2rad = function (deg) { return deg * (Math.PI / 180); },
R = 6371,
dLat = deg2rad(position2.lat - position1.lat),
dLng = deg2rad(position2.lng - position1.lng),
a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(deg2rad(position1.lat))
* Math.cos(deg2rad(position1.lat))
* Math.sin(dLng / 2) * Math.sin(dLng / 2),
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return R * c;
}
console.log(getDistanceFromLatLonInKm(
{lat: 48.7931459, lng: 1.9483572},
{lat: 48.827167, lng: 2.2459745}
));
다음은 postgres sql 의 예입니다 (km 단위의 경우 km 단위로 1.609344를 0.8684 버전으로 대체)
CREATE OR REPLACE FUNCTION public.geodistance(alat float, alng float, blat
float, blng float)
RETURNS float AS
$BODY$
DECLARE
v_distance float;
BEGIN
v_distance = asin( sqrt(
sin(radians(blat-alat)/2)^2
+ (
(sin(radians(blng-alng)/2)^2) *
cos(radians(alat)) *
cos(radians(blat))
)
)
) * cast('7926.3352' as float) * cast('1.609344' as float) ;
RETURN v_distance;
END
$BODY$
language plpgsql VOLATILE SECURITY DEFINER;
alter function geodistance(alat float, alng float, blat float, blng float)
owner to postgres;
다음은 또 다른 Ruby 코드 로 변환 된 것입니다 .
include Math
#Note: from/to = [lat, long]
def get_distance_in_km(from, to)
radians = lambda { |deg| deg * Math.PI / 180 }
radius = 6371 # Radius of the earth in kilometer
dLat = radians[to[0]-from[0]]
dLon = radians[to[1]-from[1]]
cosines_product = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(radians[from[0]]) * Math.cos(radians[to[1]]) * Math.sin(dLon/2) * Math.sin(dLon/2)
c = 2 * Math.atan2(Math.sqrt(cosines_product), Math.sqrt(1-cosines_product))
return radius * c # Distance in kilometer
end
PHP로 거리를 계산하는 좋은 예가 있습니다 http://www.geodatasource.com/developers/php :
function distance($lat1, $lon1, $lat2, $lon2, $unit) {
$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 == "N") {
return ($miles * 0.8684);
} else {
return $miles;
}
}