给定边长 l 的 n 正方形,如何确定圆的最小半径 r ,以便我可以分配所有正方形均匀地沿着圆周边而没有重叠? (约束:第一个方格将始终位于12点。)
后续问题:如何放置高度为 h 和宽度 w 的 n 相同的矩形?
答案 0 :(得分:12)
可能有一种数学上聪明的方法来做到这一点,但我不知道。
我觉得有点复杂,因为每个不同数量的正方形的几何形状都不同;对于4它是菱形,对于5它是五边形,依此类推。
我要做的是将这些方块放在1个单位的圆上(太小,我知道,忍受我),平均分布在它上面。这很容易,只需将你的360度对等(划分)为正方形。然后测试你所有的方块与他们的邻居重叠;如果它们重叠,则增加半径。
通过使用智能算法接近正确的大小,您可以使此过程不那么愚蠢。我正在考虑像牛顿算法这样的东西:给定两个连续的猜测,其中一个太小而一个太大,你的下一个猜测需要是这两个的平均值。
您可以迭代到您喜欢的任何精度。每当猜测之间的距离小于某个任意小的误差范围时停止。
编辑我有更好的解决方案:
如果你问“我怎么知道方块是否重叠?”我正在考虑告诉你什么。这让我对如何准确地计算圆周大小有了一个想法:
将你的方块放在一个太小的圆圈上。您知道如何:计算360 / n角与其相交的圆上的点,并将正方形的中心放在那里。实际上,您还不需要放置方块,接下来的步骤只需要中点。
计算方形与其邻域的最小距离:计算X的差异和中点的Y差异,并取最小值。 X和Y实际上只是圆圈上的余弦和正弦。
您希望任何方格的最小值与其邻居相比(顺时针方向,比如说)。因此,您需要绕着圆圈找到最小的圆圈。
方块之间的最小(X或Y)距离需要变为1.0。因此,只需取最小距离的倒数并乘以圆的大小即可。 Presto,你的圈子大小合适。
修改强>
在不失一般性的情况下,我认为可以将我的解决方案略微下调,以便接近编码。这是一个改进:
摆脱角落案件:
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
开头,对于任意数量的正方形而言,这肯定太小了&gt; 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
用于调整框的大小...懒惰但工作正常。 .5适用于中心的两侧,因此盒子的大小正好是1.0。
唉,我的算法不起作用。它使得半径太大,因此将盒子放置得比必要的远得多。即使按比例缩小2倍(在某些地方使用0.5可能是错误的)也无济于事。
抱歉,我放弃了。也许我的方法可以被挽救,但它不会像我那样工作。 :(
修改强>
我讨厌放弃。当我想到一种方法来挽救我的算法时,我正要离开我的电脑:
该算法将X或Y距离的较小调整为至少为1.很容易证明这只是愚蠢的。当你有很多盒子然后在圆圈的东边和西边时,你的盒子几乎直接堆叠在一起,它们的X彼此非常接近,但是它们之间只有足够的Y距离就可以保存它们。它们。
所以......为了使这个工作,你必须将dx和dy的最大缩放到(对于所有情况)至少半径(或者它是半径的两倍?)。 / p>
更正后的代码位于: http://ideone.com/EQ03g http://ideone.com/VRyyo
再次在GnuPlot中测试,它会产生漂亮的小圆圈,有时只有1或2个盒子正在接触。 问题解决了!:)
(这些图像比它们高很宽,因为GnuPlot不知道我想要比例布局。想象一下整个作品被挤成方形:))
答案 1 :(得分:4)
我会计算最小半径的上限,方法是使用包围正方形的圆圈而不是正方形本身。
我的计算结果为:
Rmin&lt; = X /(sqrt(2)* sin(180 / N))
其中: X是方形边长,N是所需的平方数。
我认为圆圈的位置使得它们的中心位于大圆周上。
- 编辑 -
在下面的评论中使用Dave的想法,我们也可以通过考虑圆形在正方形内(因此具有半径X / 2)来计算一个漂亮的下界。这个界限是:
Rmin> = X /(2 * sin(180 / N))
答案 2 :(得分:1)
如已经指出的那样,将圆形圆周等间隔的n个点定位的问题是微不足道的。问题的(非常非常)困难的部分是找出给出方形的令人愉悦的布局所需的圆的半径。我建议你按照其他一个答案进行思考,然后把方块想象成一个圆形的“缓冲区”,大小足以容纳正方形和足够的空间以满足你的审美要求。然后检查相邻正方形中心之间chord length的公式。现在你有一个角度,在圆心,由方形中心之间的和弦对齐,可以很容易地从三角形的三角学计算圆的半径。
并且,关于你的后续问题:我建议你解决圆周边长min(h,w)
的正方形的问题,然后将正方形转换为矩形,将圆转换为具有偏心率的椭圆h / w(或w / h)。
答案 3 :(得分:0)
从一个任意圆开始(例如,直径为(* n l)
)并将方块均匀地放在圆周上。然后你通过每对相邻的广场和:
计算此线与插入的方形边的交点(M1和M2是中点,S1和S2是与方边相对应的交点:
S2 S1
M1--------------*----------*---------------M2
------------------------
| |
| |
| |
| |
| M1 |
| \ |
| \ |
| -------*------- +--------
| | \ | |
| | \ | |
-------+---------*------ |
| \ |
| M2 |
| |
| |
| |
| |
-------------------------
计算使S1和S2合在一起所需的比例因子(简单地说是M1-S1和S2-M2之和与M1-M2之比),
最后通过找到的比例因子的最大值来缩放圆圈。
编辑:这是确切的解决方案。但是,有一点想法可以进一步优化速度:
答案 4 :(得分:0)
我会这样解决:
要找到半径r和长度l之间的关系,让我们分析无量纲表示
这是最佳解决方案,可以用r = f(l)来解决。 通过调整xLR [i]和yUL [i + 1]的公式,可以使解决方案适应矩形。
会尝试给出一些伪代码。
编辑:
程序中存在一个错误,右下角和左上角不是两个相邻正方形/矩形的必要最近点。
答案 5 :(得分:0)
我们假设你解决了3或4个方格的问题。
如果你有 n &gt; = 5个方格,并且在圆的顶部放置一个方格,你将有另一个方形落入与你的圆同心的笛卡尔平面的第一个象限
问题是找到圆的半径 r ,使得圆圈的左侧与顶部圆圈相邻,而顶部圆圈的右侧不会“交叉”其他
顶部圆圈右侧的 x 坐标是 x1 = L / 2,其中 L 是正方形的一面。顶部旁边的圆圈左侧的 x 坐标为 x2 = r cos a - L / 2,其中 r 是半径, a 是每对方形中心之间的角度( a = 360 / n 度)。
所以我们需要解决 x1 &lt; = x2 ,这会导致
r &gt; = L / cos a 。
L 和 a 已知,所以我们完成了: - )