在圆柱体/锥体上均匀生成三维点

7
我希望能在圆柱体和圆锥体上随机均匀生成点。圆柱体由其中心、半径和高度定义,圆锥体也是如此。我可以获得每个形状的边界框,所以我考虑在边界框内生成点。但是,我不确定如何将它们投影到圆柱体/圆锥体上,或者这是否是最好的想法。
有什么建议吗?
谢谢。

1
看起来比例从1.5变成了0.5。你可能想要使用ratio=(max_y-y)/cone->Height()代替。 - comingstorm
1
此外,为了防止您的点围绕顶点聚集,您需要使用y =(max_y-min_y)*(1-sqrt(RandomNumber()))+min_y。 - comingstorm
你的编辑问题似乎已经得到了回答。你能整理一下它,或者再添加一个编辑说明它已得到解答吗? - brainjam
7个回答

5
圆柱体的情况比较简单。如果半径为r > 0,高度为h > 0的圆柱体是在φ∈[0, 2π[和z∈[-h/2, h/2]上的(x, y, z) = (r cos φ, r sin φ, z)的图像,则只需在这些区间内随机选择φ和z即可。当然,也可以使用标准参数化方法对圆锥体进行简单的参数化,但是这样得到的面积元素在参数平面上不是常数,因此点的分布不会是随机的。因此,您需要找到一种不同的参数化方法。我已经在我的AlgoSim网站上详细讨论了球体的这个问题。 (链接)

3
一种思考方式是将圆柱体和圆锥体都展开成平面表面——只需从顶部到底部用一条直线切割即可。
圆柱体展开成一个矩形(如果包括顶部和底部,则添加两个圆盘)。
圆锥体展开成一个带有曲底的三角形,该曲底为圆弧(如果包括圆锥体的底部,则添加一个圆盘)。
很容易将这些平面表面嵌入到xy平面上的矩形R中。在R中生成均匀分布的点,并且每当它们位于平面表面内时,将它们映射回原始表面。
注意其他答案试图通过角度和高度来协调圆锥体。虽然这些点在角度和高度方面均匀分布,但它们在面积方面不均匀分布。它们在尖端处分布更密集。

2

直接在圆柱体或圆锥体上生成点会更简单。

虽然我已经有一段时间没有这样做了,但是可以将圆柱轴参数化,并对每个点参数化其高度处的圆。这将在表面创建点。圆的半径为圆柱的半径。

对于圆锥体,需要随着从底部到顶部的移动减小圆的半径。


0

定义一个点的坐标为rah,其中r是“半径”(从中心垂直轴线的距离),a是极坐标中的角度,h是其高度。

对于圆柱体(半径R和高度H):独立选择

  • a在[0,2pi)内均匀分布,
  • h在[0,H]内均匀分布,并且
  • r具有“三角形密度”:如果0 <= r <= R,则f(r) = 2 r / R,否则为0(r处的密度应与半径为r的周长长度成比例)。

从这样的三角形分布中进行抽样不应该很困难,因为它的累积分布(一个二次单项式)很容易可逆(参见this article)。此外,这个答案是基于直觉的,但证明你在圆柱体上获得的分布是均匀的也不应该很困难。

对于圆锥(半径R和高度H):选择

  • a 在 [0, 2pi) 范围内均匀分布,
  • h 的密度由抛物线段构成:如果 0 <= h <= H,则 f(h) = 3 (H - h)^2 / H^3;否则为 0(h 处的密度应与高度为 h 的圆截面的面积成比例),
  • r( h ) = (H - h) R / H(高度为 h 的截面半径);然后选择 "三角形分布" 的 r,即 f(r) = 2 r / r( h ),如果 0 <= r <= r( h ),否则为 0。

再次,取样h应该很容易,因为累积分布是容易可逆的。

编辑。 如果您想在形状的表面上生成点,则解决方案更简单:

圆柱体:选择

  • a均匀在[0,2pi),
  • h均匀在[0,H],
  • r = R

锥体:选择

  • a 在 [0, 2pi) 范围内均匀分布,
  • h 的密度为三角形:如果 0 <= h <= H,则 f(h) = 2 (H - h) / H^2,否则为 0(在高度 h 处的密度应与该处圆周长成比例)。
  • r = r( h ) = (H - h) R / H,即高度为 h 处的半径。

哎呀,你是指表面上吗? - Federico A. Ramponi
是的,根据定义,圆柱体(和圆锥体)是空间中的一个表面,而不是实体物体。我认为楼主确实使用了这个数学定义,因为他使用了介词“on”而不是“inside”。 - Andreas Rejbrand
我对你所定义的内容(http://en.wikipedia.org/wiki/Cone_%28geometry%29 http://en.wikipedia.org/wiki/Cylinder_%28geometry%29)一点都不确定,但是我已经在这两个形状的侧面上添加了点。 - Federico A. Ramponi

0

其他答案已经很好地涵盖了圆柱体的情况。对于圆锥体,情况会更加困难。为了保持点的密度恒定,您需要补偿半径的变化。

为此,您可以首先选择点之间的距离。当您沿着圆锥体的轴移动时,计算该高度处的周长,然后将周长除以点之间的线性距离,以获取点数。然后,您将2pi弧度(或360度,或任何角度)除以点数,以获取该半径的角度距离。

根据您需要的精度,您可以在计算下一个圆时跟踪上一个圆的余数。例如,如果您连续有两个圆需要xxx.4个点,如果单独看每个圆,则会将每个圆都舍去小数部分-但是将它们放在一起看,您就有了xxx.8个点,因此您应该将一个圆向下舍入,将另一个圆向上舍入,以使整体密度尽可能接近正确值。

请注意,虽然不太明显,但后者也适用于圆柱体-您通常会在分配每个圆的点时进行四舍五入。


-1

将这些答案用伪代码表示:

对于一个圆柱体,已知圆柱半径和圆柱高度:

angle = random number between 0 & 360

x = cos(pi/180*angle)*cylinderRadius
y = sin(pi/180*angle)*cylinderRadius
z = random number between 0 and cylinderHeight.

对于一个圆锥,已知圆锥半径和圆锥高度:

angle = random number between 0 & 360

z = random number between 0 and coneHeight

thisRadius = coneRadius * (1-(z/coneHeight)); //This gives a decreasing radius as height increases.

x = cos(pi/180*angle)*thisRadius
y = sin(pi/180*angle)*thisRadius

每个点(x,y,z)都将位于圆柱/锥体上。生成足够多的这些点,您就可以在圆柱/锥体表面产生粒子,但可能不会形成完全均匀的分布...

问题在于找到一个均匀分布,而你的代码对于圆锥体来说并不是这种情况。 - Andreas Rejbrand

-1

对于半径为R的圆或锥体上的均匀点,以及高度/仰角H:

generate:
  angle= uniform_random(0,2*pi)
  value= uniform_random(0,1)

in either case, let:
  r= R * sqrt(value)

then (using separate random numbers for each):
  circle_point= point3d( r*cos(angle), r*sin(angle), H )
or:
  cone_point= point3d( r*cos(angle), r*sin(angle), r*H )

请注意,如果您想在圆锥体上设置底部,您需要将其与曲面分开处理。为确保不同部分的点密度相同,一种简单的方法是计算各部分的面积并为每个部分生成成比例的点数。
sqrt(value)可以确保您的随机点密度均匀。正如其他问题所提到的,您需要一个三角形分布;取sqrt()可以将[0,1)上的均匀分布变为三角形分布。
对于圆柱体,您不需要使用sqrt()函数;曲线部分已经是:
  cylinder_point= point3d( R*cos(angle), R*sin(angle), H*value )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接