Gua pernah disuruh ngerjain aplikasi absensi, dan di situ gua diminta ngedeteksi apakah orangnya masih di dalam radius yang ditentukan, alias masih di area kantor. Posisi orang itu dan titik kantor sama-sama cuma berupa dua angka: lintang (latitude) dan bujur (longitude). Dari situ jaraknya harus keluar, terus dibandingin sama radiusnya. Di langkah hitung jarak itulah haversine kepake.
Kenapa bukan Pythagoras?
Godaan pertama: anggap lintang dan bujur itu x dan y, terus akar dari Δx² + Δy². Enggak jalan. Keduanya sudut di permukaan bola, dan panjang satu derajat bujur tergantung lintangnya. Kelihatan di rumus haversine di bawah: selisih bujurnya dikali cos lintang.
Pythagoras baru masuk akal buat jarak kecil, itu pun kalau selisih bujurnya dikoreksi dulu. Movable Type nyebutnya pendekatan equirectangular: x = Δλ · cos φm, y = Δφ, d = R · √(x² + y²), dan φm itu lintang rata-rata kedua titik. Kata halaman itu, ini buat kasus yang performanya lebih penting daripada akurasinya. Kalau butuh yang lebih akurat, atau jaraknya jauh, pakai haversine.
Great-circle distance
Haversine ngitung great-circle distance: jarak dua titik di bola, diukur sepanjang busur great circle di antara keduanya (Wikipedia, Great-circle distance). Gampangnya, potong bola rata lewat pusatnya dan dua titik itu, lalu ukur sepanjang lengkung irisannya. Garis lurus yang nembus bola enggak dihitung.
Asumsinya Bumi itu bola. Aslinya oblate spheroid, alias agak pepat (Wikipedia, Vincenty’s formulae).
Rumusnya
Misalnya ada dua titik (φ1, λ1) dan (φ2, λ2), lintang dan bujurnya udah dalam radian, dan jari-jari bolanya R:
Δφ = φ2 - φ1
Δλ = λ2 - λ1
a = sin²(Δφ/2) + cos(φ1) · cos(φ2) · sin²(Δλ/2)
c = 2 · atan2(√a, √(1-a))
d = R · c
- φ = lintang, λ = bujur. Satuannya radian, jadi derajat diubah dulu.
- R = jari-jari rata-rata Bumi, 6371 km (Movable Type Scripts).
- d = jarak antara dua titik, satuannya ngikutin R.
Suku sin²(θ/2) itu yang disebut haversine: hav θ = sin²(θ/2) (Wikipedia, Great-circle distance). Kelebihannya, hasilnya tetap stabil secara numerik bahkan di jarak kecil, beda sama rumus spherical law of cosines (Movable Type Scripts).
Kodenya
Argumennya derajat, urutannya lintang dulu baru bujur. Konversi ke radian dikerjain di dalam fungsi.
Python
import math
def haversine(lat1: float, lon1: float, lat2: float, lon2: float, radius_km: float = 6371.0) -> float:
"""Hitung jarak great-circle antara dua titik lintang/bujur, defaultnya dalam km."""
phi1, phi2 = math.radians(lat1), math.radians(lat2)
d_phi = math.radians(lat2 - lat1)
d_lambda = math.radians(lon2 - lon1)
a = math.sin(d_phi / 2) ** 2 + math.cos(phi1) * math.cos(phi2) * math.sin(d_lambda / 2) ** 2
c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
return radius_km * c
# Jakarta (-6.2088, 106.8456) ke Bandung (-6.9175, 107.6191)
print(haversine(-6.2088, 106.8456, -6.9175, 107.6191)) # ~116 km
TypeScript
function haversine(lat1: number, lon1: number, lat2: number, lon2: number, radiusKm = 6371): number {
const toRad = (deg: number) => (deg * Math.PI) / 180;
const dPhi = toRad(lat2 - lat1);
const dLambda = toRad(lon2 - lon1);
const phi1 = toRad(lat1);
const phi2 = toRad(lat2);
const a = Math.sin(dPhi / 2) ** 2 + Math.cos(phi1) * Math.cos(phi2) * Math.sin(dLambda / 2) ** 2;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return radiusKm * c;
}
// Jakarta ke Bandung
console.log(haversine(-6.2088, 106.8456, -6.9175, 107.6191)); // ~116 km
Seberapa meleset
Selama Bumi dianggap bola, rumus jarak apa pun cuma dijamin benar dalam kisaran 0,5% (Wikipedia, Great-circle distance). Movable Type nyebut errornya biasanya sampai 0,3%, dan bisa 0,55% kalau garisnya nyebrang khatulistiwa. Angkanya beda dikit antar sumber, jadi anggap ini kisaran kasar.
Errornya ikut persentase jarak. Kalau errornya 0,3% dan radius absensinya misalnya 100 meter, melesetnya sekitar 30 cm. Jakarta ke Bandung yang 116 km meleset sekitar 350 meter. Buat cek radius kantor, selisih segitu enggak bakal kerasa.
Kalau presisi segitu kurang, ada rumus Vincenty. Rumus ini nganggep Bumi oblate spheroid, akurat sampai 0,5 mm di elipsoid Bumi, dan dipake luas di geodesi (Wikipedia, Vincenty’s formulae). Bedanya dari haversine, rumus ini iteratif dan bisa gagal konvergen kalau dua titiknya hampir berseberangan di Bumi.
Sumber: