두 서클의 교차점을 계산합니까?


29

중심 위도 / 경도와 각 점의 반지름이 주어지면 지표면에서 두 개의 교차 원의 공통 점을 수학적으로 도출하는 방법을 알아 내려고합니다.

예를 들면 다음과 같습니다.

  • 위도 / 경도 (37.673442, -90.234036) 반경 107.5 NM
  • 위도 / 경도 (36.109997, -90.953669) 반경 145 NM

두 점 중 하나가 (36.948, -088.158) 인 두 개의 교점을 찾아야합니다.

평평한 평면에서 이것을 해결하는 것은 사소한 일이지만, 지표면과 같은 불완전한 구면에서 방정식을 푸는 경험은 없습니다.


1
모든 반지름이이 작은 것 (수 킬로미터 미만)이라면 지구는 기본적으로이 평면에서 평평하며 정확하고 간단한 투영을 선택하고 일반적인 유클리드 계산을 수행 할 수도 있습니다. 소수점 이하 세 자리 이상의 교차점을 계산해야합니다. 소수점 이하 자릿수의 부정확도는 반지름 중 하나만큼 큽니다!
whuber

1
단위를 추가 했어야하는데, 그 반경은 NM에 있으므로 여전히 지표면에 비해 작은 거리이지만 수 km 이상입니다. 이 스케일은 왜곡에 어떤 영향을 줍니까? 1nm 미만의 정확한 솔루션을 찾으려고 노력하고 있으므로 매우 정확할 필요는 없습니다. 감사!

구형의 지구 모델을 사용할 수 있음을 보여주기 때문에 알면 좋습니다. 더 복잡한 타원체 모델은 필요하지 않습니다.
whuber

@whuber이 문제로 재 작성 될 수있는 의미 하는가 : 3 개 분야의 교차점 찾을 구체 중 하나가 지구이고, 다른 두 사람은 각각의 반경 점을 중심으로하는?
Kirk Kuykendall

@Kirk 네, 지구 표면의 구형 모델을 가정하면 그렇게 할 수 있습니다. 예비 계산 후이를 3D의 Trilateration 문제의 특별한 경우로 줄였습니다. (구형 호를 따라 거리를 구 화음을 따라 거리로 변환하려면 계산이 필요합니다. 두 개의 작은 구의 반지름이됩니다.)
whuber

답변:


21

일단 당신이 그것을 인식하면 그것은 비행기보다 구체에서 그리 어렵지 않습니다.

  1. 문제가되는 점은 세 가지 구체 의 상호 교차점입니다 . 주어진 반지름의 위치 x1 (지구 표면) 아래에 중심에있는 구, 주어진 반지름의 위치 x2 (지구 표면) 아래에 중심에있는 구, 지구 자체 주어진 반경의 O = (0,0,0)을 중심으로하는 구입니다.

  2. 처음 두 구체의 지구 표면과의 교차점은 두 평면을 정의하는 원입니다. 그러므로 세 구의 상호 교차점은 두 평면의 교차점 인 입니다.

결과적으로, 문제는 구와 선을 교차시키는 것으로 줄어들 기 때문에 쉽습니다.


자세한 내용은 다음과 같습니다. 입력은 지구 표면의 점 P1 = (lat1, lon1) 및 ​​P2 = (lat2, lon2)이며 구로 간주되며 두 개의 해당 반지름 r1 및 r2입니다.

  1. (lat, lon)을 (x, y, z) 지 중심 좌표로 변환합니다. 평소와 같이 지구의 반지름이 측정 단위를 선택할 수 있기 때문에

    x = cos(lon) cos(lat)
    y = sin(lon) cos(lat)
    z = sin(lat).
    

    예에서, P1 = (-90.234036 Degree, 37.673442 Degree)는 지리 중심 좌표 x1 = (-0.00323306, -0.7915, 0.61116)을 가지며 P2 = (-90.953669 Degree, 36.109997 Degree)는 지리 중심 좌표 x2 = (-0.0134464, -0.807775 0.589337).

  2. 반지름 r1 및 r2 (구를 따라 측정 됨)를 구를 따라 각도로 변환합니다. 정의에 따라 1 해리 (NM)는 1/60도 (pi / 180 * 1/60 = 0.0002908888 라디안)입니다. 따라서 각도로

    r1 = 107.5 / 60 Degree = 0.0312705 radian
    r2 = 145 / 60 Degree = 0.0421788 radian
    
  3. x1 주위의 반지름 r1 의 측지 원은 cos (r1) * x1을 중심으로 하는 유클리드 반지름 sin (r1) 과 지구 표면의 교차점입니다 .

  4. cos (r1) * x1 주위의 반경 sin (r1) 구의 교차점과 지구 표면의 교점에 의해 결정된 평면은 x1에 직각이고 점 cos (r1) x1을 통과 합니다. 방정식은 x.x1 = cos입니다. (r1) ( "."은 일반적인 내적을 나타냄 ); 다른 비행기도 마찬가지입니다. x1과 x2의 선형 조합 인 두 평면의 교차점에 고유 한 점 x0이 있습니다. x0 = a x1 + b * x2라고 쓰면 두 평면 방정식은

    cos(r1) = x.x1 = (a*x1 + b*x2).x1 = a + b*(x2.x1)
    cos(r2) = x.x2 = (a*x1 + b*x2).x2 = a*(x1.x2) + b
    

    q로 쓸 x2.x1 = x1.x2라는 사실을 사용하여 솔루션이 존재한다면 해결책은 다음과 같습니다.

    a = (cos(r1) - cos(r2)*q) / (1 - q^2),
    b = (cos(r2) - cos(r1)*q) / (1 - q^2).
    

    실행 예제에서 a = 0.973503 및 b = 0.0260194를 계산합니다.

    분명히 우리는 q ^ 2! = 1이 필요합니다. 이것은 x1과 x2가 같은 지점도 아니고 대지 점도 될 수 없음을 의미합니다.

  5. 이제 두 평면의 교차 선에있는 다른 모든 점은 두 평면에 서로 수직 인 벡터 n의 배수에 의해 x0과 다릅니다. 크로스 프로덕트

    n = x1~Cross~x2
    

    n이 0이 아닌 경우 작업이 수행됩니까? 다시 한 번 x1과 x2가 일치하거나 정반대가 아닙니다. (x1과 x2가 서로 가까울 때 많은 취소가 포함 된 빼기를 포함하므로 교차 곱을 높은 정밀도로 계산해야합니다.)이 예에서 n = (0.0272194, -0.00631254, -0.00803124) .

  6. 따라서 우리는 지구 표면에있는 x0 + t * n 형식의 두 점, 즉 길이가 1과 같습니다. 마찬가지로, 제곱 길이는 1입니다.

    1 = squared length = (x0 + t*n).(x0 + t*n) = x0.x0 + 2t*x0.n + t^2*n.n = x0.x0 + t^2*n.n
    

    x0 (x1과 x2의 선형 조합 임)이 n에 직각이므로 x0.n을 가진 항은 사라집니다. 두 가지 솔루션은 쉽게

    t = sqrt((1 - x0.x0)/n.n)
    

    그리고 그 부정적인. x1과 x2가 가까울 때 x0.x0이 1에 매우 가깝기 때문에 부동 소수점 정밀도가 약간 손실 되기 때문에 다시 한 번 높은 정밀도가 요구됩니다 . 이 예에서 t = 1.07509 또는 t = -1.07509입니다. 따라서 두 교차점은 동일합니다

    x0 + t*n = (0.0257661, -0.798332, 0.601666)
    x0 - t*n = (-0.0327606, -0.784759, 0.618935)
    
  7. 마지막으로, 지구 중심 (x, y, z)을 지리적 좌표로 변환하여 이러한 솔루션을 (lat, lon)으로 다시 변환 할 수 있습니다.

    lon = ArcTan(x,y)
    lat = ArcTan(Sqrt[x^2+y^2], z)
    

    경도를 들어, 범위가 -180 내지 180 정도의 값을 반환하는 일반화 된 아크 탄젠트를 사용하여 (계산 애플리케이션에서,이 기능은 얻어 모두 인수보다는 비율 Y / (X)로서, x 및 y가, 때때로 "ATAN2"라고 함).

    그림에 노란색 점으로 표시된 두 가지 솔루션 (-88.151426, 36.989311) 및 (-92.390485, 38.238380)을 얻습니다.

3D 그림

축은 지오 중심 (x, y, z) 좌표를 표시합니다. 회색 패치는 지구 표면에서 경도 -95 ~ -87도, 위도 33 ~ 40 도의 부분입니다 (1도 계수 선으로 표시). 지구 표면은 세 구체를 모두 보여주기 위해 부분적으로 투명하게 만들어졌습니다. 계산 된 솔루션의 정확성은 노란색 점이 구의 교차점에 어떻게 위치하는지에 의해 분명합니다.


빌, 대단해 구현하려는 사람을 기준으로 추가 할 수있는 설명이 하나 있습니다. 2 단계에서는도에서 라디안으로의 변환을 명시 적으로 제공하지 않습니다.
Jersey Andy

@ 저지 제안 해 주셔서 감사합니다. 중복을 피하고 수식을 최대한 명확하게 유지하기 위해 조금 변경했습니다. 당신이 언급하고있는 실을 읽은 후에도 내적을 설명하는 링크를 삽입했습니다.
whuber

8

타원형 의 경우 :

이 문제는 "중간 선"으로 정의 된 해양 경계를 찾는 것의 일반화이며이 주제에 대한 광범위한 문헌이 있습니다. 이 문제에 대한 나의 해결책은 등거리 방위각 투영법을 활용하는 것입니다.

  1. 교차점에서 추측
  2. 이 추측 된 교점을 등거리 방위각의 중심으로 사용하여 두 개의 기준점을 투영합니다.
  3. 2D 투영 공간에서 교차 문제를 해결하십시오.
  4. 새 교차점이 이전 교차점과 너무 멀어서 2 단계로 돌아갑니다.

이 알고리즘은 2 차적으로 수렴하고 타원체에 대한 정확한 솔루션을 제공합니다. (해양, 석유 및 광물 권을 결정하기 때문에 해양 경계의 경우 정확도가 필요합니다.)

공식은 타원체 회전에 관한 측지선의 섹션 14에 나와 있습니다. 타원 등거리 방위각 투영법은 GeographicLib 에 의해 제공됩니다 . 타원체에 대한 측지 투영법 에서 MATLAB 버전을 사용할 수 있습니다 .


+1 그것은 놀라운 논문입니다 : 여기서 당신의 겸손한 설명은 공의가 아닙니다.
whuber

측지선 "측지선 알고리즘" dx.doi.org/10.1007/s00190-012-0578-z (무료 다운로드!) 와이 논문에 대한 정오표 및 부록에 대한 내 짧은 논문을 참조하십시오 geographiclib.sf.net/geod-addenda.html
cffk

1

이 작업을 수행하는 R 코드는 다음과 같습니다.

p1 <- cbind(-90.234036, 37.673442) 
p2 <- cbind(-90.953669, 36.109997 )

library(geosphere)
steps <- seq(0, 360, 0.1)
c1 <- destPoint(p1, steps, 107.5 * 1852)
c2 <- destPoint(p2, steps, 145 * 1852)

library(raster)
s1 <- spLines(c1)
s2 <- spLines(c2)

i <- intersect(s1, s2)
coordinates(i)

#        x        y
# -92.38241 38.24267
# -88.15830 36.98740

s <- bind(s1, s2)
crs(s) <- "+proj=longlat +datum=WGS84"
plot(s)
points(i, col='red', pch=20, cex=2)

1

@ whuber의 답변 에서 다음 두 가지 이유로 유용한 Java 코드가 있습니다.

  • ArcTan에 대한 문제를 강조합니다 (Java 및 기타 언어의 경우).
  • @whuber의 답변에 언급되지 않은 사례를 포함하여 가능한 경우를 처리합니다.

최적화되지 않았거나 완전 Point하지는 않지만 ( 와 같은 명백한 클래스를 생략했습니다 ), 트릭을 수행해야합니다.

public static List<Point> intersection(EarthSurfaceCircle c1, EarthSurfaceCircle c2) {

    List<Point> intersections = new ArrayList<Point>();

    // project to (x,y,z) with unit radius
    UnitVector x1 = UnitVector.toPlanar(c1.lat, c1.lon);
    UnitVector x2 = UnitVector.toPlanar(c2.lat, c2.lon);

    // convert radii to radians:
    double r1 = c1.radius / RadiusEarth;
    double r2 = c2.radius / RadiusEarth;

    // compute the unique point x0
    double q = UnitVector.dot(x1, x2);
    double q2 = q * q;
    if (q2 == 1) {
        // no solution: circle centers are either the same or antipodal
        return intersections;
    }
    double a = (Math.cos(r1) - q * Math.cos(r2)) / (1 - q2);
    double b = (Math.cos(r2) - q * Math.cos(r1)) / (1 - q2);
    UnitVector x0 = UnitVector.add(UnitVector.scale(x1, a), UnitVector.scale(x2, b));

    // we only have a solution if x0 is within the sphere - if not,
    // the circles are not touching.
    double x02 = UnitVector.dot(x0, x0);
    if (x02 > 1) {
        // no solution: circles not touching
        return intersections;
    }

    // get the normal vector:
    UnitVector n = UnitVector.cross(x1, x2);
    double n2 = UnitVector.dot(n, n);
    if (n2 == 0) {
        // no solution: circle centers are either the same or antipodal
        return intersections;
    }

    // find intersections:
    double t = Math.sqrt((1 - UnitVector.dot(x0, x0)) / n2);
    intersections.add(UnitVector.toPolar(UnitVector.add(x0, UnitVector.scale(n, t))));
    if (t > 0) {
        // there's only multiple solutions if t > 0
        intersections.add(UnitVector.toPolar(UnitVector.add(x0, UnitVector.scale(n, -t))));
    }
    return intersections;
}

또한 중요한 점은 atan2@ whuber의 답변에서 기대하는 것과 반대입니다 (왜 그런지 모르겠지만 작동합니다).

    public static Point toPolar(UnitVector a) {
        return new Point(
                Math.toDegrees(Math.atan2(a.z, Math.sqrt(a.x * a.x + a.y * a.y))),
                Math.toDegrees(Math.atan2(a.y, a.x)));          
    }

0

@wuhber 답변에 대한 작업 'R'코드.

P1 <- c(37.673442, -90.234036)
P2 <- c(36.109997, -90.953669) 

#1 NM nautical-mile is 1852 meters
R1 <- 107.5
R2 <- 145

x1 <- c(
  cos(deg2rad(P1[2])) * cos(deg2rad(P1[1])),  
  sin(deg2rad(P1[2])) * cos(deg2rad(P1[1])),
  sin(deg2rad(P1[1]))
);

x2 <- c(
  cos(deg2rad(P2[2])) * cos(deg2rad(P2[1])),
  sin(deg2rad(P2[2])) * cos(deg2rad(P2[1])),
  sin(deg2rad(P2[1]))
);

r1 = R1 * (pi/180) * (1/60)
r2 = R2 * (pi/180) * (1/60)

q = dot(x1,x2)
a = (cos(r1) - cos(r2) * q) / (1 - q^2)
b = (cos(r2) - cos(r1) * q)/ (1 - q^2)

n <- cross(x1,x2)

x0 = a*x1 + b*x2


t = sqrt((1 - dot(x0, x0))/dot(n,n))

point1 = x0 + (t * n)
point2 = x0 - (t * n)

lat1 = rad2deg(atan2(point1[2] ,point1[1]))
lon1= rad2deg(asin(point1[3]))
paste(lat1, lon1, sep=",")

lat2 = rad2deg(atan2(point2[2] ,point2[1]))
lon2 = rad2deg(asin(point2[3]))
paste(lat2, lon2, sep=",")

-1

원 중 하나가 Nortstar이면 단위 구를 사용하는 가장 쉬운 방법이 있습니다.

Nortstar로 위도를 측정 할 수 있습니다. 그런 다음이 구체에서 상대 위치를 갖습니다. v1 (0, sin (la), cos (la)) 알 마나 흐에서 다른 별 (star2)의 위치 (각도)를 알고 있습니다. v2 (sin (lo2) * cos (la2), sin (la2), cos (lo2) * cos (la2)) 벡터. 구의 방정식에서.

lo2는 상대 경도입니다. 그 알 수없는 .

당신과 star2 사이의 각도도 측정 할 수 있습니다 (m) 그리고 두 단위 벡터의 내적은 사이의 cos (angle)입니다. cos (m) = dot (v1, v2) u는 이제 상대 경도 (lo2)를 계산할 수 있습니다. lo2 = acos ((cos (m) -sin (la) * sin (la2)) / (cos (la) * cos (la2)))

결국 star2의 실제 경도를 lo2에 추가하십시오. (또는 하위, 서쪽 또는 서쪽의 동쪽에 따라 다릅니다.) 이제 lo2는 경도입니다.

내 영어가 유감이지만, 나는이 언어를 배우지 않습니다.


2 가지 : Northstar는 극 별을 의미합니다.

다른. 각도가 상대적으로 수평으로 측정 되었기 때문에 항상 90도 보정이 필요합니다. m 각도에도 유효합니다.

추신 : 실제 각도 평균 : 별 위치-시간 수정.


이것이 어떻게 질문에 대답하는지는 분명하지 않습니다.
whuber
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.