지리 공간 좌표 및 킬로미터의 거리
-
23-08-2019 - |
문제
이것은 후속 조치입니다 이 질문.
나는 이것에 붙어있는 것 같습니다. 기본적으로 표준 학위 시스템의 좌표를 참조하거나 국제 날짜 라인을 따라 남극에서 북쪽으로 거리를 측정 한 다음 날짜의 해당 지점에서 시작하는 거리를 측정하여 앞뒤로 변환 할 수 있어야합니다. 선. 이 작업을 수행하려면 (보다 일반적인 거리 측정 작업) 두 LAT/LON 포인트 사이의 거리를 결정하는 한 가지 방법과 LAT/LON 포인트, 제목 및 거리 및 반품을 취하는 다른 방법이 있습니다. 그 과정의 끝에있는 위도/론 포인트.
내가 정의한 두 가지 정적 방법은 다음과 같습니다.
/* Takes two lon/lat pairs and returns the distance between them in kilometers.
*/
public static double distance (double lat1, double lon1, double lat2, double lon2) {
double theta = toRadians(lon1-lon2);
lat1 = toRadians(lat1);
lon1 = toRadians(lon1);
lat2 = toRadians(lat2);
lon2 = toRadians(lon2);
double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta);
dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;
return dist;
}
/* endOfCourse takes a lat/lon pair, a heading (in degrees clockwise from north), and a distance (in kilometers), and returns
* the lat/lon pair that would be reached by traveling that distance in that direction from the given point.
*/
public static double[] endOfCourse (double lat1, double lon1, double tc, double dist) {
double pi = Math.PI;
lat1 = toRadians(lat1);
lon1 = toRadians(lon1);
tc = toRadians(tc);
double dist_radians = toRadians(dist / (60 * 1.1515 * 1.609344 * 1000));
double lat = asin(sin(lat1) * cos(dist_radians) + cos(lat1) * sin(dist_radians) * cos(tc));
double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
double[] endPoint = new double[2];
endPoint[0] = lat; endPoint[1] = lon;
return endPoint;
}
그리고 여기 테스트하는 데 사용하는 기능이 있습니다.
public static void main(String args[]) throws java.io.IOException, java.io.FileNotFoundException {
double distNorth = distance(0.0, 0.0, 72.0, 0.0);
double distEast = distance(72.0, 0.0, 72.0, 31.5);
double lat1 = endOfCourse(0.0, 0.0, 0.0, distNorth)[0];
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
System.out.println("end at: " + lat1 + " / " + lon1);
return;
}
"종료"값은 AppX 여야합니다. 72.0 / 31.5. 그러나 대신 약 1.25 / 0.021을 받고 있습니다.
나는 어리석은 것을 놓치고있는 것을 놓치고, 어딘가에서 유닛을 변환하는 것을 잊어 버렸다고 생각합니다 ... 어떤 도움이든 큰 감사를드립니다!
UPDATE 1:
나는 미터를 반환하기 위해 거리 기능을 (정확하게) 작성했지만 실수로 킬로미터를 썼습니다. 물론 오늘 다시 돌아 왔을 때 나를 혼란스럽게했습니다. 어쨌든, 이제는 고정되어 고정 과정 방법에서 인수 오류를 수정했으며, 그 방법에서 라디안의 정도로 전환하는 것을 잊었다는 것을 깨달았습니다. 어쨌든 : 이제 올바른 위도 번호 (71.99 ...)를 얻고 있지만 경도 수는 꺼져 있습니다 (11.5 대신 3.54를 얻습니다).
UPDATE 2:아래에서 언급했듯이 테스트에서 오타가있었습니다. 이제 코드에 고정되었습니다. 그러나 경도 수는 여전히 잘못되었습니다. 11.5 대신 -11.34를 받고 있습니다. 나는이 라인에 뭔가 문제가 있어야한다고 생각합니다.
double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
해결책
코드에 마법의 숫자가 심각한 경우가 있습니다. 표현식:
(60 * 1.1515 * 1.609344 * 1000)
두 번 나타나지만 설명은 많지 않습니다. 약간의 도움으로 : 1.609344는 1 마일의 킬로미터 수입니다. 60은 학위의 분 수입니다. 1000은 킬로미터의 미터 수입니다. 1.1515는 해상 마일의 법령 마일 수입니다 (감사합니다, Danm). 1 해리 마일은 적도에서 위도 1 분의 길이입니다.
나는 당신이 구형 지구보다는 구형 지구 모델을 사용하고 있다고 생각합니까? 대수는 구형이 될 정도로 복잡하지 않습니다.
두 위도와 경도 쌍 사이의 전환 - 첫 번째 공식은 홀수입니다. 답을 분류하려면 델타-라트 (Δλ)와 델타 론 (Δφ)이 모두 필요합니다. 또한, 쌍 사이의 거리 :
(60° N, 30° W), (60° N, 60° W)
(60° N, 60° W), (60° N, 90° W)
동일해야하지만 코드가 다른 답변을 생성한다고 확신합니다.
그래서, 나는 당신이 당신의 구형 삼각법 참조 자료로 돌아가서 당신이 무엇을 잘못하고 있는지 확인해야한다고 생각합니다. (주제에 관한 내 책을 찾는 데 시간이 걸릴 것입니다. 상자가있는 상자에서 포장을 풀어야 할 것입니다.)
[... 시간 패스 ... 포장 풀기 ...]
각도가있는 구형 삼각형이 주어졌습니다 ㅏ, 비, 씨 정점과 측면에서 ㅏ, 비, 씨 그 정점 (즉, 측면 ㅏ 출신입니다 비 에게 씨, 등), 코사인 공식은 다음과 같습니다.
cos a = cos b . cos c + sin b . sin c . cos A
문제에 이것에 적용하면 주어진 두 가지 점을 호출 할 수 있습니다. 비 그리고 씨, 그리고 우리는 직각으로 올바른 구형 삼각형을 만듭니다. ㅏ.
최악의 ASCII 예술 :
+ C
/|
/ |
a / | b
/ |
/ |
/ |
B +------+ A
c
측면 씨 경도의 차이와 동일합니다. 측면 비 위도의 차이와 같습니다. 각도 ㅏ 90 °이므로 COS입니다 ㅏ = 0. 그러므로 나는 방정식을 믿는다 ㅏ 이다:
cos a = cos Δλ . cos Δφ + sin Δλ . sin Δφ . cos 90°
a = arccos (cos Δλ . cos Δφ)
각도 ㅏ 그런 다음 라디안에서 지구의 반경을 곱하여 거리로 변환됩니다. 또는 주어진 ㅏ 학위 (및 1 학년의 분수)에서 60 해리 마일에서 1도, 따라서 60 * 1.1515 마일, 60 * 1.1515 * 1.609344 킬로미터에서 1 도가 있습니다. 미터의 거리를 원하지 않는 한, 나는 1000의 계수가 필요하지 않습니다.
폴 톰 블린은 항공 공식 v1.44 방정식의 원천으로서, 그리고 실제로, 그것은 위치의 차이가 작을 때에 대한 더 수치 적으로 안정적인 버전과 함께 있습니다.
기본 삼각법으로 이동하면 다음을 알고 있습니다.
cos (A - B) = cos A . cos B + sin A . sin B
내가 준 방정식에 두 번 적용하면 항공 공식의 공식이 잘 될 수 있습니다.
(내 참조 : "천문학 : 원리와 실습, 제 4 판" Ae Roy와 D Clarke (2003); 내 사본은 1977 년의 첫 번째 판, Adam Hilger, ISBN 0-85274-346-7입니다.)
NB (Google) '정의 : "해상 마일"; 해상 마일은 현재 1852m (1.852km) 인 것으로 보입니다. 승수 1.1515는 해상 마일의 기존 정의에 약 6080 피트를 사용합니다. bc
10의 규모로 다음과 같이받습니다.
(1852/(3*0.3048))/1760
1.1507794480
당신을 위해 어떤 요소가 작동하는지에 따라 다릅니다.
첫 번째 원칙의 두 번째 문제를 살펴보면 약간 다른 설정이 있으며, '다른'구형 삼각법 방정식 인 사인 공식이 필요합니다.
sin A sin B sin C
----- = ----- = -----
sin a sin b sin c
이전 다이어그램 적응 :
+ C
/|
/ |
a / | b
| / |
|X/ |
|/ |
B +------+ A
c
출발점이 주어집니다 비, 각도 엑스 = 90º -B, 길이 (각도) ㅏ, 및 각도 ㅏ = 90 °. 당신이 뒤에있는 것은 비 (위도의 델타) 및 씨 (경도의 델타).
그래서 우리는 다음과 같습니다.
sin a sin b
----- = ----
sin A sin B
또는
sin a . sin B
sin b = -------------
sin A
또는 a = 90 °이므로 sin a = 1, sin b = sin (90 ° -x) = cos x :
sin b = sin a . cos X
그것은 당신이 이동하는 거리를 각도로 변환한다는 것을 의미합니다. ㅏ, 그 사인을 가져 가서 코스 방향의 코사인을 곱하고 결과의 아크 신을 가져 가십시오.
주어진 ㅏ, 비 (방금 계산) 및 ㅏ 그리고 비, 우리는 코사인 공식을 적용하여 얻을 수 있습니다 씨. 우리는 단순히 사인 공식을 다시 적용 할 수 없습니다. 씨 우리는 가치가 없기 때문에 씨 그리고 우리는 구형 삼각법을 가지고 놀기 때문에 c = 90 ° -b (구형 삼각형의 각도의 합이 180 °보다 클 수있는 편리한 규칙은 없습니다. 90 °, 완벽하게 실현 가능).
다른 팁
체크 아웃 http://www.movable-type.co.uk/scripts/latlong.html
이 사이트에는 다양한 공식과 JavaScript 코드가있어 도움이됩니다. 나는 그것을 C#과 SQL Server UDF로 성공적으로 번역했으며 모든 곳에서 사용합니다.
예를 들어 JavaScript가 거리를 계산하려면 다음과 같습니다.
var R = 6371; // km
var φ1 = lat1.toRadians();
var φ2 = lat2.toRadians();
var Δφ = (lat2-lat1).toRadians();
var Δλ = (lon2-lon1).toRadians();
var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
Math.cos(φ1) * Math.cos(φ2) *
Math.sin(Δλ/2) * Math.sin(Δλ/2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
즐기다!
KM과 라디안 사이의 전환이 잘못되었습니다. 해상 마일은 1 학년의 1/60이므로 1.15는 마일에서 해상 마일로 전환하고 1.6은 KM에서 법령 마일로 전환된다고 가정합니다.
nm = km / (1.1515 * 1.609344);
deg = nm / 60;
rad = toRadians(deg);
다시 말해, 나는 당신이 1000의 계수를 벗어난 것 같습니다.
업데이트 된 질문에 관해 : 안됩니다
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[0];
~이다
double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
다른 답변과 업데이트에 언급 된 구현 오류를 제외하고는 이러한 공식의 큰 문제를 알아 냈습니다.
큰 문제는 이것입니다. 거리 방법 (두 점 사이의 거리를 계산하기위한)은 큰 원장을 계산하는 것이 었습니다. 물론 의미가 있습니다. 이것이 두 지점 사이의 가장 짧은 경로입니다. 하지만, 동일한 평행 (위도선)에있는 두 지점 사이의 큰 원 거리는 적도에 있지 않는 한 위도선을 따라 직접 이동할 때 두 지점 사이의 거리와 다릅니다.
따라서 : 기능은 올바르게 작동합니다. 그러나 원래 질문에서 제안한 대체 좌표 시스템은 IDL을 따라 북쪽으로 거리를보고 그 결과 위도에서 평행을 따라 동쪽 거리를 살펴 봐야합니다. 그리고 특정 평행을 따라 거리를 계산하는 것은 큰 원을 따라 거리를 계산하는 것과는 상당히 다릅니다!
어쨌든, 당신은 그것을 가지고 있습니다.