我正在使用 ActionScript 3 和 Flash 10 3D (2.5D) API 创建一个 3D 球体图库。我找到了一种有效但并不理想的方法。我想看看是否有更好的方法。
我的算法是这样的:
Let n = the number of images h = the height of each image w = the width of each image
- 通过假设(错误地)图像的表面积等于我们要创建的球体的表面积来近似圆的半径。
计算r
的半径求解在nwh = 4πr<sup>2</sup>
。这是需要改进的部分。 - 计算行之间的角度。
rowAngle = 2atan(h / 2 / r)
. - 计算行数。
rows = floor(π / rowAngle)
. - 由于第一步是近似值,行数不会完全适合,因此为了演示添加填充 rowAngle。
rowAngle += (π - rowAngle * rows) / rows
. 对于每个
i
在rows
:- 计算该行纬度圆的半径。
latitudeRadius = radius * cos(π / 2 - rowAngle * i
. - 计算柱之间的角度。
columnAngle = atan(w / 2 / latitudeRadius) * 2
. - 计算列数。
columns = floor(2 * π / columnAngle)
- 由于第一步是近似值,因此列数不会完全适合,因此为了演示,请向 columnAngle 添加填充。
columnAngle += (2 * π - columnAngle * column) / column
. - 对于每个
j
在columns
,翻译-radius
沿Z轴,旋转π / 2 + rowAngle * i
绕X轴,旋转columnAngle * j
绕 Y 轴。
- 计算该行纬度圆的半径。
要查看实际效果,click here 。 alternate link 。请注意,使用默认设置时,球体中实际的项目数少了 13。我相信这是我在第一步中的近似引入的错误。
我无法找出一种方法来确定这样一个球体的确切半径应该是多少。我希望学习一种更好的方法、正确的方法,或者我正在尝试做的事情很难或非常难(在这种情况下,我会对我所拥有的感到满意)。
最佳答案
我会把这个问题分成两个相连的问题。
给定半径,如何将东西打包到球体上?
考虑到很多因素,如何找到正确的半径?
如果第一个问题解决了,第二个问题就很容易解决了。这是伪代码。
lowerRadius = somethingTooSmall
fittedItems = itemsForRadius(lowerRadius)
while fittedItems < wantedItems:
lowerRadius *= 2
fittedItems = itemsForRadius(lowerRadius)
upperRadius = 2 * lowerRadius
while threshold < upperRadius - lowerRadius:
middleRadius = (upperRadius + lowerRadius)/2
if itemsForRadius(middleRadius) < wantedItems:
lowerRadius = middleRadius
else:
upperRadius = middleRadius
这将找到最小半径,可以使用您的打包算法打包所需数量的元素。如果您希望可以从一个更好的起点开始 - 您当前的估计非常接近。但我不认为解析公式可以做到这一点。
现在我们来讨论第一个问题。你有一个非常合理的方法。但它确实有一个严重的错误。错误是您的 columnAngle
不应该针对行的中间进行计算。您需要做的是找出您的元素最接近极点的纬度,并将其用于计算。这就是为什么当您尝试装入 10 件元素时,您会发现包装导致角重叠。
如果您想要更密集的包装,您可以尝试将行压向赤道。这有时会导致连续有空间容纳更多元素,这样你就可以在较小的范围内获得更多元素。但从视觉上看,它可能看起来不太好。尝试一下,然后决定您是否喜欢结果。
顺便说一句,我喜欢这个主意。看起来不错。
关于actionscript-3 - 如何更好地为 3D 画廊打包与球体相切的矩形?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5333243/