문제

이것은 후속 조치입니다 이 질문.

나는 이것에 붙어있는 것 같습니다. 기본적으로 표준 학위 시스템의 좌표를 참조하거나 국제 날짜 라인을 따라 남극에서 북쪽으로 거리를 측정 한 다음 날짜의 해당 지점에서 시작하는 거리를 측정하여 앞뒤로 변환 할 수 있어야합니다. 선. 이 작업을 수행하려면 (보다 일반적인 거리 측정 작업) 두 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을 따라 북쪽으로 거리를보고 그 결과 위도에서 평행을 따라 동쪽 거리를 살펴 봐야합니다. 그리고 특정 평행을 따라 거리를 계산하는 것은 큰 원을 따라 거리를 계산하는 것과는 상당히 다릅니다!

어쨌든, 당신은 그것을 가지고 있습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top