以下は、真ん中に白い点のポイントがあり、すべての赤い円がすでに存在する場合に青い円(明らかにそれを配置した場所にある)に最も近い場所を見つけたい場合の画像例です。 。その場所を見つけるにはどうすればよいですか?
私にとってパフォーマンスは、このアプリケーションにとって大きな関心事ではありません。
以下は、真ん中に白い点のポイントがあり、すべての赤い円がすでに存在する場合に青い円(明らかにそれを配置した場所にある)に最も近い場所を見つけたい場合の画像例です。 。その場所を見つけるにはどうすればよいですか?
私にとってパフォーマンスは、このアプリケーションにとって大きな関心事ではありません。
回答:
これは一般的な解決策ではありません。なぜなら、青い円の位置に白い点までの最短距離が提供されない場合がいくつかあるからです。たとえば、100個の赤いボールがグループ化されており、白いドットがこの赤いボールのグループから遠く離れている場合、白いボールの中心にできる青い円の位置に影響する赤いボールはありません。 。また、すべての計算の詳細も表示されません。とにかく、ソリューションの一部(青の円)が2つの赤の円に接している
場合、1)Rを青の円の半径にする
2)赤の円のすべてのペアでループを作成する、はいこれがO(n2)であることは知っています。
3)それぞれの半径riとrjを中心とする(xi、yi)および(xj、yj)に中心を持つ円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つの円の中心を見つけることができます。青い円の候補ごとに、他のすべての赤い円をループし、重複しないかどうかを確認します。白丸までの距離を確認しない場合、彼らはそれをdisartする場合。距離の短いものを保持する場合、円のペアのリストを走査し終えたときに解決策が得られると思います。アルゴリズムはO(n3)のようです。
ポイントに最も近い配置は、ポイント上にあるか、円に触れます。
したがって、最初にポイントをチェックし、次に既存の各円のエッジの周りに新しい円を転がし、ポイントからの距離を計算し、移動中にオーバーラップする場合は最小距離ポイントを追跡します。すべての円を横断したら停止します。
すなわち。緑の線上のすべての点と白い円を確認してください。ここで、緑の線は赤と青の半径を持つ円です
これらのエッジケースをカバーするには、交差点だけでなく緑の線全体をチェックする必要があります。
明らかに、パフォーマンスの観点から、トラバーサルのステップサイズが重要になります。ただし、パフォーマンスは問題ではないと述べるので、出力値の解像度に対応する値を選択します。すなわち、フロート、長い?
明確化:
私の提案は、各点で他のすべての円との重なりをテストする各円の周りのすべての点をブルートフォースすることです。賢さはありません。
サンプルの写真が円の数と解像度を示している場合、標準の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++;
}
};
すべての方程式を満たすことがわかった最初の座標は、青い円の位置です
拡張円は、半径がrだけ拡張された円の1つです。
Oが円の中心にない場合、いくつかの追加の作業があります。したがって、今はO == C0と仮定します
それぞれの半径とrを使用して、C0とのすべての円のすべての交差を計算します。つまり、拡張C0と拡張円を交差させます。交差点がない場合、探しているポイントはC0の任意の場所にあり、交差点がある場合は、交差点ごとに、別の拡張円内にあるかどうかを確認します(C0との交差点がある円に制限できます)。Pとして別の拡張円にない最初の交差点を取ります。他の交差点がある可能性があります。
拡張円とC0の間に別の拡張円の内側にない交点がない場合は、すべての拡張円の相互の交点を計算します。次に、これらの交差点をOまでの距離の順にチェックします。交差点のいずれかが別の拡張円内にあるかどうかを確認します。
これを想像して、青い円の可能な位置を示すすべての円の周りに線を引くとしたら、すべての拡張円を結合すると、青い円ができない領域がわかります。あなたが探しているポイントは、その組合にない最も近いポイントです。解決策であるそのユニオンにないC0に点がある場合、C0が完全に覆われている場合、Pは2つの他の拡張円の交差点にあり、それによって覆われていない領域になければなりませんこの結合(拡張円ではない)。
これはO(n ^ 2)です。これを改善する方法はいくつかありますが、グリッドを使用してペアワイズ検索の労力を減らすことができます。また、Oに近いことで円をソートすることもできます。ラジオで2つの円を減らす)カバレッジと交差点検索の検索スペースを制限するのに役立ちます
これで、可能な解決策であるポイントのセットがあり、それらを反復処理し、それぞれをチェックします。
NB:アルゴリズムの実装が正確に記述されるべきだと言っているわけではありません。動的プログラミングを使用するか、機能しないことが明らかな場合は可能なソリューションをスキップして、パフォーマンスの改善を試みることができます。