這個月,我一直在使用 PHP 和 MySQL 進行 GIS 程式設計。 在研究該主題時,我很難找到 地理計算 找到兩個位置之間的距離,所以我想在這里分享它們。
計算兩點之間的距離的簡單方法是使用勾股定律公式來計算三角形的斜邊(A²+B²=C²)。 這被稱為 歐氏距離.
這是一個有趣的開始,但它不適用於地理,因為緯度線和經度線之間的距離是 間隔距離不相等。 當你越接近赤道時,緯線就會變得越遠。 如果您使用簡單的三角測量方程,由於地球的曲率,它可能會在一個位置準確地測量距離,而在另一個位置測量錯誤。
大圓距離
繞地球運行很長距離的路線被稱為大圓距離。 那就是……球體上兩點之間的最短距離不同於平面地圖上的點。 將其與緯度和經度線不等距的事實結合起來......你的計算很困難。
這是有關Great Circles工作原理的精彩視頻說明。
Haversine公式
使用地球曲率的距離包含在 Haversine 公式中,該公式使用三角學來考慮地球的曲率。 當您計算地球上兩個地點之間的距離時(如烏鴉所言),一條直線實際上是一條弧線。
這適用於空中飛行——你有沒有看過實際的航班地圖並註意到它們是拱形的? 那是因為在兩點之間的拱形飛行比直接飛到該位置要短。
PHP:計算2個緯度和經度之間的距離
這是計算兩點之間距離的 PHP 公式(以及英里與公里的轉換),四捨五入到小數點後兩位。
function getDistanceBetweenPointsNew($latitude1, $longitude1, $latitude2, $longitude2, $unit = 'miles') {
$theta = $longitude1 - $longitude2;
$distance = (sin(deg2rad($latitude1)) * sin(deg2rad($latitude2))) + (cos(deg2rad($latitude1)) * cos(deg2rad($latitude2)) * cos(deg2rad($theta)));
$distance = acos($distance);
$distance = rad2deg($distance);
$distance = $distance * 60 * 1.1515;
switch($unit) {
case 'miles':
break;
case 'kilometers' :
$distance = $distance * 1.609344;
}
return (round($distance,2));
}
變量是:
- $緯度1 – 您的第一個位置的緯度變量。
- $經度1 – 您的第一個位置的經度變量
- $緯度2 – 第二個位置緯度的變量。
- $經度2 – 第二個位置的經度變量。
- $單位 – 默認是 英里. 這可以更新或傳遞為 公里.
Java:計算經緯度兩點之間的距離
public static double getDistanceBetweenPointsNew(double latitude1, double longitude1, double latitude2, double longitude2, String unit) {
double theta = longitude1 - longitude2;
double distance = 60 * 1.1515 * (180/Math.PI) * Math.acos(
Math.sin(latitude1 * (Math.PI/180)) * Math.sin(latitude2 * (Math.PI/180)) +
Math.cos(latitude1 * (Math.PI/180)) * Math.cos(latitude2 * (Math.PI/180)) * Math.cos(theta * (Math.PI/180))
);
if (unit.equals("miles")) {
return Math.round(distance, 2);
} else if (unit.equals("kilometers")) {
return Math.round(distance * 1.609344, 2);
} else {
return 0;
}
}
變量是:
- 緯度1 – 您的第一個位置的緯度變量。
- 經度1 – 您的第一個位置的經度變量
- 緯度2 – 第二個位置緯度的變量。
- 經度2 – 第二個位置的經度變量。
- 單位 – 默認是 英里. 這可以更新或傳遞為 公里.
JavaScript:計算兩點緯度和經度之間的距離
function getDistanceBetweenPoints(latitude1, longitude1, latitude2, longitude2, unit = 'miles') {
let theta = longitude1 - longitude2;
let distance = 60 * 1.1515 * (180/Math.PI) * Math.acos(
Math.sin(latitude1 * (Math.PI/180)) * Math.sin(latitude2 * (Math.PI/180)) +
Math.cos(latitude1 * (Math.PI/180)) * Math.cos(latitude2 * (Math.PI/180)) * Math.cos(theta * (Math.PI/180))
);
if (unit == 'miles') {
return Math.round(distance, 2);
} else if (unit == 'kilometers') {
return Math.round(distance * 1.609344, 2);
}
}
變量是:
- 緯度1 – 您的第一個位置的緯度變量。
- 經度1 – 您的第一個位置的經度變量
- 緯度2 – 第二個位置緯度的變量。
- 經度2 – 第二個位置的經度變量。
- 單位 – 默認是 英里. 這可以更新或傳遞為 公里.
Python:計算2個緯度和經度點之間的距離
以下是計算兩點之間距離(以及英里與公里轉換)的 Python 公式,四捨五入到小數點後兩位。 感謝我的兒子 Bill Karr,他是一名數據科學家 開放洞察, 對於代碼。
from numpy import sin, cos, arccos, pi, round
def rad2deg(radians):
degrees = radians * 180 / pi
return degrees
def deg2rad(degrees):
radians = degrees * pi / 180
return radians
def getDistanceBetweenPointsNew(latitude1, longitude1, latitude2, longitude2, unit = 'miles'):
theta = longitude1 - longitude2
distance = 60 * 1.1515 * rad2deg(
arccos(
(sin(deg2rad(latitude1)) * sin(deg2rad(latitude2))) +
(cos(deg2rad(latitude1)) * cos(deg2rad(latitude2)) * cos(deg2rad(theta)))
)
)
if unit == 'miles':
return round(distance, 2)
if unit == 'kilometers':
return round(distance * 1.609344, 2)
變量是:
- 緯度1 – 您的第一個位置的變量 緯度.
- 經度1 – 您的第一個位置的變量 經度
- 緯度2 – 您的第二個位置的變量 緯度.
- 經度2 – 您的第二個位置的變量 經度.
- 單位 – 默認是 英里. 這可以更新或傳遞為 公里.
MySQL:通過使用緯度和經度以英里為單位計算距離來檢索範圍內的所有記錄
在 MySQL 中使用空間數據類型是處理地理數據(包括計算點之間的距離)的一種更高效、更方便的方法。 MySQL 支持空間數據類型,例如 POINT
, LINESTRING
和 POLYGON
,以及空間函數,例如 ST_Distance
.
當您使用 ST_Distance
MySQL 中的函數,地理數據表示為 POINT
坐標,它考慮了地球表面的曲率。 使用的球形模型 ST_Distance
採用半正矢公式。 這種近似適用於大多數實際目的,但對於很長的距離可能會產生輕微的誤差。
以下是如何使用空間數據類型計算兩點之間的距離:
- 創建具有空間數據類型的表:首先創建一個表
POINT
存儲地理點的列。 例如:
CREATE TABLE locations (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255),
coordinates POINT
);
使用以下命令將您的地理點插入此表中 POINT
構造函數:
INSERT INTO locations (name, coordinates)
VALUES
('Point A', POINT(40.7128, -74.0060)), -- New York City
('Point B', POINT(34.0522, -118.2437)); -- Los Angeles
- 使用 ST_Distance 計算距離:您可以使用以下方法計算兩點之間的距離
ST_Distance
功能。 以下是計算兩點之間距離的示例查詢:
SELECT
id1,
id2,
(ST_Distance(coordinates1, coordinates2) / 1609.344) AS distance_in_miles
FROM (
SELECT
l1.id AS id1,
l2.id AS id2,
l1.coordinates AS coordinates1,
l2.coordinates AS coordinates2
FROM
locations l1,
locations l2
WHERE
l1.id = 1 AND l2.id = 2
) AS distances;
更換 1
和 2
以及要計算其間距離的兩點的 ID。
- 結果:查詢將返回兩點之間的距離,單位為英里。
使用空間數據類型和 ST_Distance
函數提供了一種更高效、更準確的方式來處理 MySQL 中的地理數據。 它還簡化了點之間距離的計算,使管理和查詢數據變得更加容易。
MySQL:通過使用緯度和經度以公里為單位計算距離來檢索範圍內的所有記錄
默認情況下 ST_Distance
返回以米為單位的距離,因此您只需更新公里查詢:
SELECT
id1,
id2,
(ST_Distance(coordinates1, coordinates2) / 1000) AS distance_in_kilometers
FROM (
SELECT
l1.id AS id1,
l2.id AS id2,
l1.coordinates AS coordinates1,
l2.coordinates AS coordinates2
FROM
locations l1,
locations l2
WHERE
l1.id = 1 AND l2.id = 2
) AS distances;
Microsoft SQL Server 地理距離:STDistance
如果您使用 Microsoft SQL Server,它們會提供自己的功能, 標準距離 用於使用 Geography 數據類型計算兩點之間的距離。
DECLARE @g geography;
DECLARE @h geography;
SET @g = geography::STGeomFromText('LINESTRING(-122.360 47.656, -122.343 47.656)', 4326);
SET @h = geography::STGeomFromText('POINT(-122.34900 47.65100)', 4326);
SELECT @g.STDistance(@h);
向 Manash Sahoo 致敬,創辦人兼高級架構師 離子三號.