下の画像の例は、真ん中に白い点の点があり、すべての赤い円がすでに存在する場合に、青い円の最も近い可能な場所(明らかに、それを配置した場所にあります)を見つけたい場合です。 。どうすればその場所を見つけることができますか?
私にとってのパフォーマンスは、このアプリケーションの主要な問題ではありません。
これは一般的な解決策ではありません。それは、白い点までの最短距離で青い円の位置を提供しないといういくつかの状況があるためです。たとえば、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つの解を見つけます。これを行うには、これらの方程式をこの画像と一緒に使用します
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)のようです。
ポイントに最も近い配置は、ポイント上か、円に触れます。
したがって、最初に点を確認してから、既存の各円のエッジを中心に新しい円を回転させ、点からの距離を計算します。移動するときに重なり、最小距離の点を追跡します。すべての円を通過したら停止します。
すなわち。緑の線上のすべての点と白い円をチェックします。ここで、緑の線は、赤と青の半径を持つ円です
これらのEdgeケースをカバーするために、交差点だけでなく緑の線全体をチェックする必要があります。
明らかに、トラバーサルのステップサイズはパフォーマンスの点で重要になります。ただし、パフォーマンスは問題ではないので、出力値の解像度に対応する値を選択してください。すなわち、フロート、ロング?
説明:
私の提案は、eachの周りのすべてのポイントをブルートフォースして、他のすべての各ポイントで円。賢さはありません。
例の写真が円の数と解像度を示している場合、標準的なPCでは問題になりません。
平均半径200の20個の円があるため、約20 * 2π* 200ポイント* 20交差テスト= 4800000回の繰り返し
注意:
このような反復アプローチには、ステップサイズ(この場合は出力の解像度)が結果に大きく影響する可能性があるという欠点があります。
2ピクセル離れた2つの赤い円とそれらの間を絞る1ピクセルの半径の青い円があるとします。明らかに、2つのピクセルのいずれかを青い円の中心として、赤の1つと重なります。しかし、中心が2つのピクセルの間にある場合、明らかに円の余地があります。
したがって、出力の解像度について尋ねる私のコメント。あなたが言ったのは何でもかまいません。
青い円の半径だけ半径が増加する円の各ペアの連立方程式を解くこともできます。
これにより、青い円が両方の赤い円に繰り返しよりも正確に接触するポイントが得られます。
しかしながら。これを行うだけでは間違った結果が返される、または応答がないいくつかの条件があります。すなわち。
サークル1つまたはなし
2つ以上の円ですが、ターゲットポイントが遠く外にあります。
多くの円ですが、ターゲットポイントはサーフェスに近い
このプランク は作業コードを含み、
コンセプト
与えられた円は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++;
}
};
すべての方程式を満たす最初の座標は、青い円の位置です
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つの円の間の距離は無線によって減少します)は、カバレッジと交差点検索の検索スペースを制限するのに役立ちます
これで、可能な解であるポイントのセットが得られ、それらを反復処理して、それぞれについてチェックします。
注意:アルゴリズムの実装が正確に記述されている必要があると言っているのではありません。動的プログラミングを使用してパフォーマンスを改善するか、機能しないことが明らかな場合は可能なソリューションをスキップしてみてください。