라디안(Radian)
- 각의 크기를 재는
SI 유도 단위
로 기호는 rad
또는 c
를 사용한다.
1 rad = 180 / π
Haversine 공식
Haversine
공식은, 구형 지구
로 가정하고 주어지는 두 위도, 경도에 따라 거리를 구하는 공식입니다.
- 지구 표면에서 최단거리를 구하는 것으로, 지구는 실제로
타원
모양이기 때문에 최대 0.3%의 오차가 존재한다고 합니다.
a = sin²(Δφ/2) + cos φ 1 ⋅ cos φ 2 ⋅ sin²(Δλ/2)
c = 2 ⋅ atan2( √ a , √ (1−a) )
d = R ⋅ c
// φ는 위도, λ는 경도, R은 지구의 반지름(평균 반지름 = 6,371km)
/** 두 지점 위치의 거리 반환
* @param point1 좌표 1
* @param point2 좌표 2
*/
latLonToKm(point1: [number, number], point2: [number, number]) {
// 두 좌표를 각각 위도와 경도 변수로 저장
const lat1 = point1[1];
const lon1 = point1[0];
const lat2 = point2[1];
const lon2 = point2[0];
const R = 6371; // 지구의 반지름 길이 상수
// 각 위도 및 경도 차이를 라디안 값으로 계산
const dLat = this.toRadians(lat2 - lat1);
const dLon = this.toRadians(lon2 - lon1);
// 각 지점의 위도를 라디안 값으로 변환
const radLat1 = this.toRadians(lat1);
const radLat2 = this.toRadians(lat2);
// Haversine 공식을 사용하여 두 지점 사이의 거리 계산
const a =
Math.sin(dLat / 2) * Math.sin(dLat / 2) + // sin²(Δφ/2)
Math.sin(dLon / 2) * // cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)
Math.sin(dLon / 2) *
Math.cos(radLat1) *
Math.cos(radLat2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 2 ⋅ atan2( √a, √(1−a) )
// 거리 반환 (단위: 킬로미터)
return R * c;
}
/** 각도를 라디안 값으로 반환 */
private toRadians(degrees: number) {
return degrees * (Math.PI / 180);
}
구면 코사인 법칙(Spherical Law of Cosines)
- 대부분의 컴퓨터 언어는
IEEE 754
64비트 부동 소수점 숫자를 사용하기 때문에, 소수점 15자리까지의 정밀도를 제공한다.
구면 코사인 법칙
을 함께 이용해 정밀한 거리 결과
를 가져올 수 있지만, Haversine 공식
보다는 약간 느린 성능을 갖는다고 합니다.
- 또한 짧은 거리의 경우 아래 서술할
정방형 근사
가 더 정확하다고 합니다.
d = acos( sin φ 1 ⋅ sin φ 2 + cos φ 1 ⋅ cos φ 2 ⋅ cos Δλ ) ⋅ R
/** 두 지점 위치의 거리 반환
* @param point1 좌표 1
* @param point2 좌표 2
*/
latLonToKm(point1: [number, number], point2: [number, number]) {
// 두 좌표를 각각 위도와 경도 변수로 저장
const lat1 = point1[1];
const lon1 = point1[0];
const lat2 = point2[1];
const lon2 = point2[0];
const R = 6371; // 지구의 반지름 길이 상수
// 경도 차이를 라디안 값으로 계산
const dLon = this.toRadians(lon2 - lon1);
// 각 지점의 위도를 라디안 값으로 변환
const radLat1 = this.toRadians(lat1);
const radLat2 = this.toRadians(lat2);
// 구면 코사인 법칙을 이용한 거리 반환 (단위: 킬로미터)
return Math.acos(
Math.sin(radLat1) * Math.sin(radLat2) + // sin φ 1 ⋅ sin φ 2
Math.cos(radLat1) * // cos φ 1 ⋅ cos φ 2 ⋅ cos Δλ
Math.cos(radLat2) *
Math.cos(dLon)
) * R;
}
/** 각도를 라디안 값으로 반환 */
private toRadians(degrees: number) {
return degrees * (Math.PI / 180);
}
정방형 근사(Spherical Law of Cosines)
- 정확도보다
성능
이 중요한 상황이라면, 짧은 거리에 한하여 피타고라스 법칙
을 사용한 정방형 근사
를 사용할 수 있습니다.
- 거리가 길어질 수록 오차값이 커집니다.
x = Δλ ⋅ cos φ m
y = Δφ
d = R ⋅ √x² + y²
/** 두 지점 위치의 거리 반환
* @param point1 좌표 1
* @param point2 좌표 2
*/
latLonToKm(point1: [number, number], point2: [number, number]) {
// 두 좌표를 각각 위도와 경도 변수로 저장
const lat1 = point1[1];
const lon1 = point1[0];
const lat2 = point2[1];
const lon2 = point2[0];
const R = 6371; // 지구의 반지름 길이 상수
// 정방형 근사를 이용한 거리 반환 (단위: 킬로미터)
const x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
const y = (lat2 - lat1);
return Math.sqrt(x * x + y * y) * R
}
참고 자료
Ghost