Հաշվեք կամ հարցում կատարեք լայնության և երկայնության կետերի միջև մեծ շրջանի հեռավորությունը՝ օգտագործելով Haversine բանաձևը (PHP, JavaScript, Java, Python, MySQL, MSSQL օրինակներ)
Այս ամիս ես ծրագրավորում եմ PHP-ով և MySQL-ով GIS-ի համար: Թեման ուսումնասիրելիս դժվարությամբ էի գտնում աշխարհագրական հաշվարկներ երկու վայրերի միջև հեռավորությունը գտնելու համար, ուստի ես ուզում էի դրանք կիսել այստեղ:
Երկու կետերի միջև հեռավորության հաշվարկման պարզ ձևը Պյութագորասյան բանաձևի օգտագործումն է եռանկյան հիպոթենուսի հաշվարկի համար (A² + B² = C²): Սա հայտնի է որպես Էվկլիդյան հեռավորությունը.
Սա հետաքրքիր սկիզբ է, բայց դա չի վերաբերում աշխարհագրությանը, քանի որ լայնության և երկայնության գծերի միջև հեռավորությունը ոչ հավասար հեռավորություններ միմյանցից. Հասարակածին ավելի մոտենալուն պես լայնության գծերը ավելի են բաժանվում միմյանցից: Եթե դուք օգտագործում եք պարզ եռանկյունավորման հավասարում, այն կարող է ճշգրիտ չափել հեռավորությունը մի վայրում, իսկ մյուսում՝ սխալ՝ Երկրի կորության պատճառով:
Շրջանակի մեծ հեռավորություն
Երթուղիները, որոնք անցել են Երկրի շուրջ երկար տարածություններ, հայտնի են որպես Մեծ շրջանի հեռավորություն: Այսինքն… գնդակի երկու կետերի միջև ամենակարճ հեռավորությունը տարբերվում է հարթ քարտեզի կետերից: Միավորեք դա այն փաստի հետ, որ լայնության և երկայնության գծերը հավասար հեռավորության վրա չեն… և դուք ունեք դժվար հաշվարկ:
Ահա ֆանտաստիկ տեսանյութի բացատրություն, թե ինչպես են աշխատում «Մեծ շրջաններ» -ը:
Haversine բանաձևը
Երկրի կորությունը օգտագործող հեռավորությունը ներառված է Haversine բանաձևում, որն օգտագործում է եռանկյունաչափությունը՝ թույլ տալու համար Երկրի կորությունը: Երբ դուք գտնում եք Երկրի վրա 2 վայրերի միջև հեռավորությունը (քանի որ ագռավը թռչում է), ուղիղ գիծն իրականում աղեղ է:
Սա կիրառելի է օդային թռիչքների ժամանակ. երբևէ նայե՞լ եք թռիչքների իրական քարտեզին և նկատե՞լ եք, որ դրանք կամարակապ են: Դա պայմանավորված է նրանով, որ երկու կետերի միջև ընկած կամարով թռչելը ավելի կարճ է, քան ուղիղ դեպի գտնվելու վայրը:
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));
}
Փոփոխականներն են.
- $Latitude1 – փոփոխական ձեր առաջին գտնվելու վայրի լայնության համար:
- $Երկայնություն1 – փոփոխական ձեր առաջին գտնվելու վայրի երկայնության համար
- $Latitude2 – փոփոխական ձեր երկրորդ տեղանքի լայնության համար:
- $Երկայնություն2 – փոփոխական ձեր երկրորդ տեղանքի երկայնության համար:
- $ միավոր - լռելյայն լինելը մղոն. Սա կարող է թարմացվել կամ փոխանցվել որպես կիլոմետր.
Java. Հաշվեք տարածությունը լայնության և երկայնության 2 կետի միջև
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. Հաշվեք տարածությունը լայնության և երկայնության 2 կետի միջև
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-ի բանաձևը երկու կետերի միջև հեռավորությունը հաշվարկելու համար (մղոնի ընդդեմ կիլոմետրի փոխարկման հետ միասին) կլորացված երկու տասնորդական թվերի: Շնորհավորում եմ իմ որդուն՝ Բիլ Կարին, որը տվյալների գիտնական է OpenINSIGHTS, կոդի համար։
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
օգտագործում է Haversine բանաձևը. Այս մոտարկումը հարմար է շատ գործնական նպատակների համար, բայց կարող է փոքր անճշտություններ առաջացնել շատ մեծ հեռավորությունների համար:
Ահա, թե ինչպես կարող եք հաշվարկել հեռավորությունները երկու կետերի միջև՝ օգտագործելով Տարածական տվյալների տեսակները.
- Ստեղծեք աղյուսակ՝ տարածական տվյալների տեսակովՍկզբում ստեղծեք աղյուսակ a
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 Աշխարհագրական հեռավորություն. STDDistance
Եթե դուք օգտագործում եք Microsoft SQL Server, նրանք առաջարկում են իրենց սեփական գործառույթը, STD հեռավորություն երկու կետերի միջև հեռավորությունը հաշվարկելու համար՝ օգտագործելով Աշխարհագրություն տվյալների տեսակը:
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);
Գլխարկի հուշում Մանաշ Սահուին, հիմնադիր և ավագ ճարտարապետ Իոն երեք.