2つの円の交差を計算しますか?


29

中心の緯度/経度と各点の半径を指定して、地球上の2つの交差する円の共通点を数学的に導き出す方法を見つけようとしています。

たとえば、次の場合:

  • 緯度/経度(37.673442、-90.234036)半径107.5 NM
  • 緯度/経度(36.109997、-90.953669)半径145 NM

2つの交点を見つけて、そのうちの1つ(36.948、-088.158)を見つけます。

これを平面で簡単に解決することは簡単ですが、地球の表面などの不完全な球で方程式を解く経験はありません。


1
すべての半径がこれほど小さい場合(数キロメートル未満)、地球はこのスケールで基本的に平らであり、正確で単純な投影を選択して通常のユークリッド計算を実行することもできます。必ず交差点を小数点以下3桁以上まで計算してください。小数点以下3桁不正確さは、半径のいずれかと同じです。
whuber

1
ユニットを追加する必要があります。半径はNMであるため、地球の表面からの距離はわずかですが、数kmを超えます。そのスケールは歪みにどのように影響しますか?<1nm未満の精度のソリューションを見つけようとしているため、超精密である必要はありません。ありがとう!
ウィル

地球の球体モデルを使用できることを示しているため、これはすべて知っておくと便利です。より複雑な楕円体モデルは不要です。
whuber

@whuberこれは、問題を次のように言い換えることができることを意味します:球の 1つが地球であり、他の2 つがそれぞれの半径の点を中心とする3つの球の交差を見つけますか?
カーククイケンドール

@Kirkはい、それはそれを行う方法です。地球の表面の球体モデルを想定しています。これを3Dの三辺測量問題の特別なケースに減らす予備計算の後。(計算は、球面弧に沿った距離を
球弦に

回答:


21

あなたがそれを認識したら、それは飛行機よりも球体でそれほど難しくありません

  1. 問題のポイントは、3つの球体の相互交差点です。特定の半径の位置x1(地球の表面)の下に中心を置く球、特定の半径の位置x2(地球の表面)の下に中心を置く球、および地球自体、特定の半径のO =(0,0,0)を中心とする球体です。

  2. 最初の2つの球のそれぞれと地球の表面との交点は、2つの平面を定義する円です。:すべての3つの球の相互の交差点は、したがって、これら二つの平面の交点にあるライン

その結果、問題は線と球を交差させることになり、簡単です。


詳細は次のとおりです。入力は、球と見なされる地球の表面上のポイントP1 =(lat1、lon1)およびP2 =(lat2、lon2)、および2つの対応する半径r1およびr2です。

  1. (lat、lon)を(x、y、z)地心座標に変換します。いつものように、地球が単位半径を持つ測定単位を選択する場合があるため、

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

    この例では、P1 =(-90.234036度、37.673442度)は地心座標x1 =(-0.00323306、-0.7915、0.61116)であり、P2 =(-90.953669度、36.109997度)は地心座標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に垂直であり、その方程式はx.x1 = cosであるため、点cos(r1)x1を通過します。 (r1)(「。」は通常の内積を表します); 他の飛行機も同様です。これらの2つの平面の交点には、x1とx2の線形結合である一意のポイントx0があります。x0 = a x1 + b * x2と書くと、2つの平面方程式は

    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
    

    x2.x1 = x1.x2という事実を使用して、これをqと書くと、解(存在する場合)は次のようになります。

    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が同じポイントでも対antiポイントでもないことを意味します。

  5. これで、2つの平面の交線上の他のすべての点は、両方の平面に相互に垂直なベクトルnの倍数だけx0と異なります。クロス積

    n = x1~Cross~x2
    

    nがゼロ以外の場合、ジョブは実行されますか。これも、x1とx2が一致せず、正反対でもないことを意味します。(x1とx2が互いに近い場合、多くのキャンセルを伴う減算を伴うため、外積を高精度で計算するように注意する必要があります。)例では、n =(0.0272194、-0.00631254、-0.00803124) 。

  6. したがって、地球の表面上にあるx0 + t * nの形式の最大2つのポイントを探します。つまり、それらの長さは1に等しくなります。同等に、その長さの2乗は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(nはx1とx2の線形結合である)がnに垂直であるため、x0.nの項は消えます。2つのソリューションは簡単に

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

    そしてその否定。ここでも、x1とx2が近い場合、x0.x0は1 に非常に近いため、浮動小数点の精度がいくらか失われるため、高精度が要求されます。この例では、t = 1.07509またはt = -1.07509です。したがって、2つの交点は等しい

    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の両方を引数として取ります。

    図に黄色の点で示されている2つのソリューション(-88.151426、36.989311)と(-92.390485、38.238380)を取得します。

3Dフィギュア

軸は、地心(x、y、z)座標を表示します。灰色のパッチは、地表面の経度-95〜-87度、緯度33〜40度(1度の経緯線でマークされています)です。地球の表面は、3つすべての球体が見えるように部分的に透明になっています。計算された解の正確さは、黄色の点が球の交点にどのように位置するかによって明らかです。


ビル、これはすごい。実装しようとしている人に基づいて、追加できる説明を1つ。ステップ2では、度からラジアンへの変換を明示的に指定しません。
ジャージーアンディ14年

@Jersey提案された編集をありがとう。冗長性を避け、式をできる限り明確にするために、少し変更しました。参照しているスレッドを読んだ後、ドット積を説明するリンクも挿入しました。
whuber

8

楕円形の場合:

この問題は、「中央線」として定義されている海上境界を見つけることの一般化であり、このトピックに関する広範な文献があります。この問題に対する私の解決策は、等距離の方位角投影を活用することです。

  1. 交差点で推測
  2. この推測された交差点を等距離の方位角投影の中心として使用して、2つの基点を投影します。
  3. 2D投影空間で交差問題を解きます。
  4. 新しい交差点が古い交差点から離れすぎている場合は、手順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の答えに続いて、次の 2つの理由で役立つ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

円の1つがNortstarである場合、単位球を使用した最も簡単な方法があります。

Nortstarで緯度を測定できます。次に、この球体上の相対位置があります。v1(0、sin(la)、cos(la))アルマナッハからの別の星(star2)の位置(角度)を知っています。v2(sin(lo2)* cos(la2)、sin(la2)、cos(lo2)* cos(la2))そのベクトル。球の方程式から。

lo2は相対経度です。その知らない

あなたとstar2の間の角度も測定できます、(m)そして、2つの単位ベクトルの内積はcos(angle)の間です。cos(m)= dot(v1、v2)uは相対経度(lo2)を計算できるようになりました。lo2 = acos((cos(m)-sin(la)* sin(la2))/(cos(la)* cos(la2)))

結局、star2の実際の経度をlo2に追加します。(またはsub、あなたから西側、または東に依存します。)lo2は現在の経度です。

私の英語で申し訳ありませんが、私はこの言語を学ぶことはありません。


2つのこと:ノーススターはポールスターを意味します。

もう一つ。角度は水平線に対して相対的に測定されるため、常に90角度の補正が必要です。m角までも有効です。

ps:実角度平均:星の位置-時間補正。


これがどのように質問に答えるかは明らかではありません。
whuber
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.