web-dev-qa-db-ja.com

円に最も近い最適なものを見つける

下の画像の例は、真ん中に白い点の点があり、すべての赤い円がすでに存在する場合に、青い円の最も近い可能な場所(明らかに、それを配置した場所にあります)を見つけたい場合です。 。どうすればその場所を見つけることができますか?

私にとってのパフォーマンスは、このアプリケーションの主要な問題ではありません。

enter image description here

12
Botanic

これは一般的な解決策ではありません。それは、白い点までの最短距離で青い円の位置を提供しないといういくつかの状況があるためです。たとえば、100個の赤いボールがグループ化されていて、白い点がこの赤いボールのグループから遠く離れている場合、どの赤いボールも、白い点を中心にできる青い円の位置に影響を与えません。 。また、すべての計算の詳細も表示されません。とにかく、構成のサブセットでは、ソリューション(青い円)が2つの赤い円に接している場合、次のように機能します。
1)Rを青い円の半径とする
2)赤い円のペアすべてにループを作成します。はい、これはO(n2)です。
3)(xi、yi)と(xj、yj)に中心があり、それぞれの半径がriとrjの円のペアi、jごとに、円のペア間の距離の2乗を計算します

d_ij^2=(xi-xj)^2+(yi-yj)^2  

4)円のペアをすべて入れます

dij^2<R^2

リストに。

5)リストを走査して、両方の円iとjに接する半径Rの円の2つの解を見つけます。これを行うには、これらの方程式をこの画像と一緒に使用します two blue circle canditates for a pair of red circles

a = R+ri  
b = R+rj  
c = dij  
α = arccos((b^2+c^2-a^2)/(2bc)  

上記の情報で、(X1ij、Y1ij)および(X2ij、Y2ij)は、円iおよびjに接する2つの円の中心を見つけることができます。候補のそれぞれについて、青色の円が他のすべての赤色の円の上にループし、重複しないかどうかを確認します。彼らがそれを捨てるならば、そうでなければ白い円までの距離をチェックしてください。距離の短い方を維持する場合、円のペアのリストのトラバースを終了すると、解決策があると思います。アルゴリズムはO(n3)のようです。

4
Mandrill

ポイントに最も近い配置は、ポイント上か、円に触れます。

したがって、最初に点を確認してから、既存の各円のエッジを中心に新しい円を回転させ、点からの距離を計算します。移動するときに重なり、最小距離の点を追跡します。すべての円を通過したら停止します。

すなわち。緑の線上のすべての点と白い円をチェックします。ここで、緑の線は、赤と青の半径を持つ円です

possible center points

これらのEdgeケースをカバーするために、交差点だけでなく緑の線全体をチェックする必要があります。

single circle cases

明らかに、トラバーサルのステップサイズはパフォーマンスの点で重要になります。ただし、パフォーマンスは問題ではないので、出力値の解像度に対応する値を選択してください。すなわち、フロート、ロング?

説明:

私の提案は、eachの周りのすべてのポイントをブルートフォースして、他のすべての各ポイントで円。賢さはありません。

例の写真が円の数と解像度を示している場合、標準的なPCでは問題になりません。

平均半径200の20個の円があるため、約20 * 2π* 200ポイント* 20交差テスト= 4800000回の繰り返し

注意:

このような反復アプローチには、ステップサイズ(この場合は出力の解像度)が結果に大きく影響する可能性があるという欠点があります。

2ピクセル離れた2つの赤い円とそれらの間を絞る1ピクセルの半径の青い円があるとします。明らかに、2つのピクセルのいずれかを青い円の中心として、赤の1つと重なります。しかし、中心が2つのピクセルの間にある場合、明らかに円の余地があります。

したがって、出力の解像度について尋ねる私のコメント。あなたが言ったのは何でもかまいません。

青い円の半径だけ半径が増加する円の各ペアの連立方程式を解くこともできます。

これにより、青い円が両方の赤い円に繰り返しよりも正確に接触するポイントが得られます。

しかしながら。これを行うだけでは間違った結果が返される、または応答がないいくつかの条件があります。すなわち。

サークル1つまたはなし

2つ以上の円ですが、ターゲットポイントが遠く外にあります。

多くの円ですが、ターゲットポイントはサーフェスに近い

2
Ewan

このプランク は作業コードを含み、

コンセプト

与えられた円はC1、C2 ...です。Cn

円の座標CnはCnx、Cny、半径はCr

必要な円の半径はRです

青い円がX、Yの位置にあり、他の円と競合しない場合は、次の方程式が当てはまります。

(C1x - X)^2 + (C1y - Y)^2 > (C1r + R)^2
(C2x - X)^2 + (C2y - Y)^2 > (C2r + R)^2
....
(Cnx - X)^2 + (Cny - Y)^2 > (Cnr + R)^2

最初の方程式を変更し、

C1x^2 - 2C1x*X + X^2 + C1y^2 - 2C1y*Y + Y^2 > C1r^2 + 2C1r*R + R^2
X^2 + Y^2 - 2C1x*X - 2C1y*Y > C1r^2 + 2C1r*R + R^2 - C1x^2 - C1y^2

方程式は次のように書き直すことができます。

X^2 + Y^2 - 2C1x*X - 2C1y*Y > C1r^2 + 2C1r*R + R^2 - C1x^2 - C1y^2
X^2 + Y^2 - 2C2x*X - 2C2y*Y > C2r^2 + 2C2r*R + R^2 - C2x^2 - C2y^2
....
X^2 + Y^2 - 2Cnx*X - 2Cny*Y > Cnr^2 + 2Cnr*R + R^2 - Cnx^2 - Cny^2

実装

白い点の座標(Xw、Yw)から開始し、

    var isValidLocation = function(x,y,r){
       var valid = true;
       for (var i = 0; i< circles.length; i++){
          var circle = circles[i];
          valid = valid && ((x*x + y*y - 2*circle.x*x - 2*circle.y*y) > (circle.radius*circle.radius + 2*circle.radius*r + r*r - circle.x*circle.x - circle.y*circle.y));
       }
       return valid;
      };

      var find = function(Xw,Yw,Rw){
        var radius = 0;
        while(true){
          for (var x=-1 * radius ;x <= radius; x++) {
            for (var y=-1 * radius;y <= radius; y++) {
               if (isValidLocation(Xw + x,Yw + y, Rw)){
                 drawCircle(Xw + x,Yw + y,Rw,"#0000FF");
                 return;
               }
            }   
          } 
          radius++;
        }
     }; 

すべての方程式を満たす最初の座標は、青い円の位置です

1
  • [〜#〜] o [〜#〜]は、近づこうとしているポイントです
  • [〜#〜] p [〜#〜]は、探している点(青い円の中心)です
  • rは青い円の半径です
  • C0 .. Cnは、上の青の配置を制限するすべての円の中心です
  • extended circleis one of the circles it its radius expanded byr

    [〜#〜] o [〜#〜]が円の中心にない場合は、追加の作業が必要です。したがって、今はO == C0と仮定します

それぞれの半径とrを使用して、C0のすべての円のすべての intersections を計算します。つまり、拡張円と交差します。拡張C0を使用します。交点がない場合、探している点はC0上の任意の場所です。交点がある場合は、交点ごとに、それが別の拡張円の内側にあるかどうかを確認します(C0との交点があった円に制限できます)。別の拡張円にない最初の交差点をPとすると、他の交差点が存在する可能性があります。

拡張円とC0の間に別の拡張円の内側にない交点がない場合は、すべての拡張円の相互の交点を計算します。次に、これらの交点をOまでの距離の順にチェックします。ここでも、交点のいずれかが別の拡張された円内にあるかどうかを確認します。

これを想像して、すべての円の周りに線を描いて、青い円の可能性がある場所を示した場合、すべての拡張された円の結合をとると、青い円ができない領域を示しますあります。あなたが探している点は、その結合にない最も近い点です。解であるその和集合にないC0上の任意の点がある場合、C0が完全に覆われている場合、Pは他の2つの拡張された円の間の交点上になければならず、それによって覆われていない領域にある必要があります。この結合(つまり、拡張円の中にない)。

これはO(n ^ 2)ですが、これを改善する方法はいくつかあります- grid を使用してペアワイズ検索の労力を減らすことができます。また、 O、(2つの円の間の距離は無線によって減少します)は、カバレッジと交差点検索の検索スペースを制限するのに役立ちます

0

可能な解決策ルックアップ

  1. ホワイトポイントがそれ自体で解決策であるかどうかを確認します。赤い円が0の場合と、赤い円が白色点から遠く離れている場合の自明な場合が含まれます。
  2. 赤い丸が1つ。
    1. 白い点は円の中心です。 可能な解は、中心が白い点にあり、半径が青い円の半径と赤い円の直径の合計である円上の点の無限数です。それを緑色の円と呼びましょう。
    2. ホワイトポイントはどこかにあります。白い点と赤い円の中心を結ぶ線上に可能な解が1つだけあり、それは点から離れた青い円の半径です赤い円が白い点に向かって線と交差する場所。
  3. 2つ以上の赤い丸。
    1. 赤い円を1つずつ取り、ポイント2(1つの円)に従ってそれらのそれぞれについて個別に可能な解決策を探します。
    2. 赤い円のペアごとに、両方の赤い円に触れる青い円を描画できるかどうかを確認しましょう。つまりそれらの中心間の距離が、半径と青い円の直径の合計以下である場合。できれば、2つ(または赤い円がちょうど1つの青い円の直径から離れている場合は1つ)可能な解決策があります。

可能なソリューション間の実際のソリューション検索

これで、可能な解であるポイントのセットが得られ、それらを反復処理して、それぞれについてチェックします。

  1. ポイントが実際に解決策である場合。赤い円の中心が半径よりもこの点に近くないようにしてください。
  2. 以前に見つかったソリューションよりも白色点に近い場合。
  3. もしあなたが緑の円を持っているなら(ポイント2.1)
    • 個々の点の中に緑の円に属する解がない場合、緑の円が答えです。
    • 緑の円に個別の解決策があり、解決策が必要な場合は、そのうちの1つを選択してください。
    • 緑の円に個別のソリューションがあり、無制限の数のソリューションがすべて必要な場合は、別の問題を解決する必要があります。緑の円から、各赤の円の個別のソリューションのペアで定義されたすべての円弧を切り取る必要があります。

注意:アルゴリズムの実装が正確に記述されている必要があると言っているのではありません。動的プログラミングを使用してパフォーマンスを改善するか、機能しないことが明らかな場合は可能なソリューションをスキップしてみてください。

0
Vlad