18


4

最小直径の円上の正方形の配置

エッジ長_l_の_n_正方形が与えられた場合、円の最小半径_r_を決定して、すべての正方形を円の周囲に沿って均等に分配し、それらが重ならないようにするにはどうすればよいですか? (制約:最初の正方形は常に12時に配置されます。)

追加の質問:高さ_h_および幅_w_の_n_同一の長方形を配置するにはどうすればよいですか?

6 Answer


12


これを行うには数学的に賢い方法があるかもしれませんが、私は知りません。 ジオメトリが正方形の数ごとに異なるという事実によって、少し複雑になると思います。 4の場合は菱形、5の場合は五角形などです。

私がしたいのは、それらの正方形を1単位の円の上に配置することです(非常に小さすぎます。 それは十分簡単で、360度を正方形の数で分割(分割)するだけです。 次に、すべての正方形を隣接するものと重複してテストします。それらが重なる場合、半径を大きくします。

インテリジェントなアルゴリズムを使用して適切なサイズに近づけることで、この手順を愚かではないようにできます。 私はニュートンのアルゴリズムのようなものを考えています:2つの連続した推測があり、そのうちの1つが小さすぎ、もう1つが大きすぎる場合、次の推測はそれら2つの平均である必要があります。

あなたが好きな精度に反復することができます。 推測間の距離が任意の小さな誤差範囲よりも小さい場合はいつでも停止します。

*編集*より良い解決策があります:

「正方形が重なり合っているかどうかをどうやって知るのか」と尋ねた場合、何を伝えるべきか考えていました。これにより、円のサイズを1ステップで正確に計算する方法がわかりました。

あまりにも小さな円に正方形を配置します。 知っている方法:360 / nの角度が交差する円上の点を計算し、正方形の中心をそこに置きます。 実際には、まだ正方形を配置する必要はありません。次のステップでは中間点のみが必要です。

正方形からその近傍までの最小距離を計算するには:中間点のXの差とYの差を計算し、それらの最小値を取ります。 XとYは実際には円上の余弦と正弦です。

隣人に対して最小の_any_正方形が必要です(たとえば時計回り)。 そのため、非常に小さい円を見つけるには、円を周回する必要があります。

正方形間の最小(XまたはY)距離は1.0になる必要があります。 したがって、最小距離の逆数を取り、円のサイズにそれを掛けます。 プレスト、あなたのサークルは正しいサイズです。

編集

一般性を失うことなく、コーディングに近いように私のソリューションを少し絞り込むことができると思います。 改良点は次のとおりです。

  • 正方形のサイズは1、つまり 各辺の長さは1ユニットです。 最終的に、ボックスは確実に1ピクセルより大きくなりますが、それは単にスケーリングの問題です。

  • 角のケースを取り除く:

    if (n < 2) throw new IllegalArgumentException();
    if (n == 2) return 0.5; // 2 squares will fit exactly on a circle of radius 0.5
  • 0.5の円サイズ `r`から始めます。 任意の数の正方形に対して> 2。

r = 0.5;
dmin = 1.0; // start assuming minimum distance is fine
a = 2 * PI / n;
for (p1 = 0.0; p1 <= PI; p1+=a) { // starting with angle 0, try all points till halfway around
   // (yeah, we're starting east, not north. doesn't matter)
   p2 = p1 + a; // next point on the circle
   dx = abs(r * cos(p2) - r * cos(p1))
   dy = abs(r * sin(p2) - r * sin(p1))
   dmin = min(dmin, dx, dy)
}

r = r / dmin;

'' '' '

編集

これを実際のJavaコードに変換し、これに非常に似たものを実行しました。 コードと結果はこちら:http://ideone.com/r9aiu

GnuPlotを使用してグラフィカルな出力を作成しました。 出力からポイントセットを切り取ってデータファイルに貼り付けてから実行することで、円形に配置されたボックスの簡単な図を作成できました

plot '5.dat' with boxxyerrorbars

ファイル内の `.5`はボックスのサイズを調整するのに役立ちます…​ 怠butだが動作するソリューション。 .5は中央の両側に適用されるため、ボックスのサイズは正確に1.0になります。

悲しいかな、私のアルゴリズムは動作しません。 半径が大きくなりすぎて、ボックスが必要以上に離れてしまいます。 2倍に縮小しても(一部の場所で0.5を使用するのは間違いだったかもしれません)、助けにはなりませんでした。

Sorry, I give up. Maybe my approach can be salvaged, but それは私が持っていた方法では機能しません。 :(

'' '' '

編集

あきらめるのが嫌いです。 私のアルゴリズムを救う方法を考えたとき、私は私のPCを離れようとしていました。

アルゴリズムは、XまたはY距離の_smaller_を少なくとも1に調整していました。 それは簡単なことであると簡単に説明できます。 多数のボックスがある場合、円の東と西の端にボックスがほぼ直接重なり合っており、それらのXは互いに非常に近くなっていますが、Yそれら。

そう…​ これを機能させるには、dxとdyの* maximum *を(すべての場合で)少なくとも半径になるように(または半径の2倍に)スケーリングする必要があります。

修正されたコードはこちらです:[ラインスルー] * http://ideone.com/EQ03g* http://ideone.com/VRyyo

GnuPlotで再度テストされ、1つまたは2つのボックスだけが正確に触れているボックスの美しい小さな円を生成します。 問題が解決しました! :)

image:https://imgur.com/gTCRU.gif [image、title = "imgur.comでホスト"] image:https://imgur.com/NQJ5z.gif [image、title = "imgur.comでホスト"]

(これらの画像は、GnuPlotが私が比例レイアウトを望んでいることを知らなかったため、高さよりも広くなっています。 作品全体が正方形に絞られていることを想像してください:))


4


正方形自体ではなく、正方形を囲む円を使用して、最小半径の上限を計算します。

私の計算結果:

Rmin ⇐ X /(sqrt(2)* sin(180 / N))

ここで、Xは正方形の辺の長さ、Nは必要な正方形の数です。

円は、中心が大きな円の円周上にくるように配置されていると思います。

  • EDIT — 

以下のコメントでデイブのアイデアを使用して、円を正方形の内側にあると考えることにより、素敵な下限を計算することもできます(したがって、半径X / 2を持ちます)。 この境界は次のとおりです。

Rmin> = X /(2 * sin(180 / N))


1


すでに述べたように、円の円周上に等間隔でnポイントを配置する問題は簡単です。 問題の(それほどではないが)難しい部分は、正方形のレイアウトを快適にするために必要な円の半径を把握することです。 他の答えのいずれかに従って、正方形を収容するのに十分な大きさの円形の「バッファー」内に正方形があり、美的要件を満たすのに十分なスペースがあることをお勧めします。 次に、隣接する正方形の中心間のhttp://mathworld.wolfram.com/CircularSegment.html [コード長]の式を確認します。 これで、正方形の中心間の弦によって範囲が定められた角度が円の中心にあり、三角形の三角法から円の半径を簡単に計算できます。

そして、あなたのフォローアップの質問に関して:円上の辺の長さ `min(h、w)`の正方形の問題を解決し、正方形を長方形に、円を偏心h /の楕円に変換することをお勧めしますw(またはw / h)。


0


任意の円(たとえば、直径が (* n l))で開始し、正方形を円周上に均等に配置します。 次に、隣接する正方形の各ペアを通過し、以下を実行します。

  • 中間点を結ぶ直線を計算し、

  • この線と介在する正方形の交点を計算します 辺(M1とM2は中間点、S1とS2は正方形の辺との対応する交点です:+

                S2         S1
M1--------------*----------*---------------M2

------------------------
|                      |
|                      |
|                      |
|                      |
|          M1          |
|           \          |
|            \         |
|      -------*------- +--------
|      |       \       |       |
|      |        \      |       |
-------+---------*------       |
       |          \            |
       |           M2          |
       |                       |
       |                       |
       |                       |
       |                       |
       -------------------------
  • S1とS2をフォールさせるために必要なスケール係数を計算します 一緒に(単にM1-S1とS2-M2の合計とM1-M2の比率)、そして

最後に、見つかったスケールファクターの最大値で円をスケーリングします。

_編集:_これは正確な解決策です。 しかし、少し考えて速度をさらに最適化できます。

  • 45°に最も近い正方形に対してのみこれを行う必要があります(_n_が 偶数) 45°および135°(_n_が奇数の場合、実際には、これらのうち1つだけが必要であることが証明されるかもしれません)。

  • 大きい_n_の場合、円上の正方形の最適な間隔は すぐに正方形の対角線の長さに近づきます。 したがって、いくつかの小さな_n_(最大で数十個程度)のスケーリング係数を事前計算して、対角線で十分に近似することができます。


0


私はこれを次のように解決します。

半径rと長さlの関係を見つけるために、無次元表現を分析しましょう

  • 円の中心(x1、y1)..(xn、yn)を取得します

  • 各中心からi番目の正方形の右下隅と上部を取得します i + 1番目の正方形の左隅

  • 2つのポイントは、xが等しいかyが等しいか、どちらかになる必要があります 小さいl

  • 手順は、各センターおよび次のセンターに対して繰り返す必要があります 最小のlが最終解です。

これは最適なソリューションであり、r = f(l)の項で解決できます。 xLR [i]およびyUL [i + 1]の式を調整することにより、ソリューションを長方形に適合させることができます。

いくつかの擬似コードを与えようとします。

編集:+手順にバグがあります。右下と左上は、2つの隣接する正方形/長方形の最も近いポイントではありません。


0


3または4つの正方形の問題を解決したと仮定しましょう。

n> = 5個の正方形があり、1つの正方形を円の上部に配置すると、円と同心のデカルト平面の最初の象限に別の正方形が落ちます。

問題は、円の半径_r_を見つけて、一番上の円の左側の円と、一番上の円の右側が互いに「交差」しないようにすることです。

上の円の右側の_x_座標は_x1_ = L / 2です。ここで、L_は正方形の辺です。 上の左側の円の左側の_x_座標は、_x2 = r cos a-L / 2です。ここで、r_は半径であり、_a_は正方形の中心の各ペア間の角度です(_a = 360 / _n_度) 。

したがって、x1 ⇐ _x2_を解く必要があります。

  • r> = L / cos _a _。*

_L_と_a_は既知なので、完了です:-)