最近、4つの円(中間点と半径)があり、これらの円の結合の面積を計算する必要があるという問題に遭遇しました。
サンプル画像:
2つの円の場合、非常に簡単です。
三角形内にない各円の面積の割合を計算してから、三角形の面積を計算できます。
しかし、3つ以上の円があるときに使用できる賢いアルゴリズムはありますか?
外周上のすべての円の交点を見つけます(たとえば、次の図のB、D、F、H)。それらを対応する円の中心と一緒に接続して、多角形を形成します。円の結合の面積は、ポリゴンの面積+連続する交差点とそれらの間の円の中心によって定義される円スライスの面積です。穴も考慮する必要があります。
巧妙なアルゴリズムがあると確信していますが、これを探す手間を省くための愚かなアルゴリズムがあります。
確かにそれは愚かですが、:
前のソリューションとは異なるソリューションの場合、4分木を使用して任意の精度で推定を生成できます。
これは、正方形がシェイプの内側または外側にあるか、シェイプと交差しているかどうかを確認できる場合、すべてのシェイプユニオンでも機能します。
各セルには、空、完全、部分のいずれかの状態があります
このアルゴリズムは、低解像度(たとえば、4つのセルが空としてマークされている)で始まるクアッドツリーの円を「描く」ことで構成されます。各セルは次のいずれかです。
完了したら、面積の推定値を計算できます。フルセルは下限を示し、空のセルは上限を示し、部分セルは最大面積誤差を示します。
エラーが大きすぎる場合は、適切な精度が得られるまで部分セルを調整します。
これは、多くの特殊なケースを処理する必要がある幾何学的手法よりも実装が簡単だと思います。
Ants Aasmaの答えは基本的なアイデアを与えましたが、私はそれをもう少し具体的にしたかったです。以下の5つの円とそれらの分解方法を見てください。
これら3種類のドットの識別は簡単です。次に、ノードが青いドットで、赤いドットが内部の白いドットであるグラフデータ構造を構築します。すべての円について、円の中央(青い点)とその境界の各交点(白い点が付いた赤い点)の間にエッジを配置します。
これにより、サークルユニオンは、元のユニオン(つまりパーティション)をカバーするペアで互いに素であるポリゴン(青の陰影付き)と円形のパイ片(緑の陰影付き)のセットに分解されます。ここの各ピースは面積の計算が簡単なものであるため、ピースの面積を合計することでユニオンの面積を計算できます。
私は2つの交差する円の場合のアプローチが大好きです-より複雑な例のために同じアプローチのわずかなバリエーションを使用する方法は次のとおりです。
多数の半重複円のアルゴリズムを一般化するためのより良い洞察を与えるかもしれません。
ここでの違いは、中心をリンクすることから開始することです(したがって、円が交差する場所の間ではなく、円の中心の間に頂点があります)。
(実際には、おそらくモンテカルロ法は価値があります)
(ソース: secretGeek.net )
(連続ではなく)離散的な回答が必要な場合は、ピクセルペイントアルゴリズムに似た何かをすることができます。
グリッド上に円を描画し、グリッド内の各セルの大部分が円周内に含まれている場合(つまり、面積の少なくとも50%が円の1つ内にある場合)に色を付けます。これをグリッド全体(グリッドが円で覆われたすべての領域にまたがる場所)に対して行い、グリッド内の色付きセルの数を数えます。
うーん、非常に興味深い問題。私のアプローチは、おそらく次のようなものです。
(これは、円やその他の形状に当てはまります)
_area(A∪B) = area(A) + area(B) - area(A∩B)
_
ここで、_A ∪ B
_はAユニオンBを意味し、_A ∩ B
_はAインターセクトBを意味します(これは最初のステップから解決できます。
(これは、A
が_A∪B
_に置き換えられた上記と同じです)
_area((A∪B)∪C) = area(A∪B) + area(C) - area((A∪B)∩C)
_
ここでarea(A∪B)
が解決され、area((A∪B)∩C)
が見つかりました:
_area((A∪B)nC) = area((A∩C)∪(B∩C)) = area(A∩C) + area(A∩B) - area((A∩C)∩(B∩C)) = area(A∩C) + area(A∩B) - area(A∩B∩C)
_
ここでも、上からエリア(A∩B∩C)を見つけることができます。
トリッキーなビットが最後のステップです-より多くのサークルが追加されると、より複雑になります。私は、有限結合との交差点の領域を解決するための拡張があると信じています。あるいは、再帰的に解決することができるかもしれません。
また、モンテカルロを使用して反復区間の面積を近似することに関して、任意の数の円の交差を、正確に計算できる4つの円の交差に減らすことができると考えています(これを行う方法はわかりません)しかしながら)。
おそらくこれを行うためのより良い方法があります-追加された余分な円ごとに複雑さが大幅に増加します(おそらく指数関数的になりますが、確かではありません)。
私は、重なった星のフィールドをシミュレートする問題に取り組んでおり、大きな明るい星が暗い星を隠すことができる密なフィールドの実際のディスク領域から真の星の数を推定しようと試みました。私も厳密な形式的分析によってこれを行うことができることを望んでいましたが、タスクのアルゴリズムを見つけることができませんでした。青色の背景に緑色の円盤としてスターフィールドを生成し、その直径を確率アルゴリズムによって決定することで解決しました。単純なルーチンでそれらをペアにして、オーバーラップがあるかどうかを確認できます(スターペアが黄色になります)。次に、色のピクセルカウントによって観測領域が生成され、理論上の領域と比較されます。これにより、真のカウントの確率曲線が生成されます。おそらくブルートフォースですが、うまくいくようです。
(ソース: 2from.com )
電力線図と呼ばれるものを使用して、この問題に対する効率的な解決策があります。しかし、これは本当に重い数学であり、私がオフハンドで取り組むことを望むものではありません。 「簡単な」ソリューションについては、ラインスイープアルゴリズムを調べてください。ここでの基本原則は、図をストリップに分割することです。各ストリップの面積の計算は比較的簡単です。
そのため、擦り切れていないすべての円を含む図に、円の上部、円の下部、または2つの円の交点のいずれかである水平線を各位置に描画します。これらのストリップ内では、計算する必要があるすべての領域が同じように見えることに注意してください。円形のセグメントで置き換えられた2つの側面を持つ「台形」。したがって、そのような形状を計算する方法を考え出すことができれば、すべての個々の形状に対してそれを行い、それらを一緒に追加します。この単純なアプローチの複雑さはO(N ^ 3)です。ここで、Nは図の円の数です。巧妙なデータ構造を使用すると、このラインスイープメソッドをO(N ^ 2 * log(N))に改善できますが、本当に必要な場合を除き、おそらく面倒な価値はありません。
役に立つかもしれないこのリンクを見つけました。しかし、決定的な答えはないようです。 Googleアンサー 。 3つの円の別の参照は、 ハルキの定理 です。そこにも論文があります。
以下は、実際に実装しやすく、任意の小さなエラーを生成するように調整できるアルゴリズムです。
手順2および3は、計算幾何学から標準の見つけやすいアルゴリズムを使用して実行できます。
明らかに、各近似ポリゴンに使用する辺が多ければ多いほど、答えはより正確になります。内接および外接ポリゴンを使用して近似し、正確な答えの範囲を取得できます。
解決しようとしている問題によっては、上限と下限を取得するのに十分な場合があります。上限は簡単で、すべての円の合計だけです。下限については、円が重ならないように単一の半径を選択できます。さらに良くするには、各円の最大半径(実際の半径まで)を見つけて、重ならないようにします。完全に重なった円を削除することも非常に簡単です(このような円はすべて| P_a-P_b | <= r_aを満たします)。P_aは円Aの中心、P_bは円Bの中心、r_aはAの半径です)そして、これは上限と下限の両方を改善します。また、すべての円の合計ではなく、任意のペアでペアの式を使用すると、より良い上限を得ることができます。 「最適な」ペア(合計面積が最小になるペア)を選択する良い方法があるかもしれません。
上限と下限を考えると、モンテカルロアプローチをよりうまく調整できるかもしれませんが、具体的なことは何も思い浮かびません。もう1つのオプション(これもアプリケーションによって異なります)は、円をラスタライズしてピクセルをカウントすることです。基本的には、固定分布のモンテカルロアプローチです。
これは、n = 2log(n)の複雑さでGreenの定理を使用して解決できます。 グリーンの定理に詳しくなく、さらに知りたい場合は、 video と notes カーンアカデミーから。しかし、私たちの問題のために、私の説明で十分だと思います。
画像を投稿できないため、写真へのリンクで申し訳ありません。(評判ポイントが足りません)
[〜#〜] l [〜#〜]および[〜#〜] m [〜#〜]そのような
rHSは単に領域の領域[〜#〜] r [〜#〜]であり、閉じた積分またはLHSを解くことで取得できます。するつもりです。
すべての結合は、交差するこのような互いに素な円のセットに分割できます
したがって、パスに沿って反時計回りに積分すると、領域のAreaが得られ、時計回りに積分すると、エリア。そう
AreaOfUnion=(反時計回りの赤い弧に沿った積分+時計回りの青い弧に沿った積分)
しかし、クールなトリックは、各円について、他の円の内側にない円弧を統合する場合、必要な領域を取得する場合、つまり、すべての赤い円弧に沿って反時計回りに統合し、時計回りに沿ってすべての青い円弧に沿って統合する場合です。 ジョブ完了!!!
円が他の円と交差しない場合でも処理されます。
ここに私の C++コード へのGitHubリンクがあります