在圆柱/圆锥上统一生成 3D 点
Posted
技术标签:
【中文标题】在圆柱/圆锥上统一生成 3D 点【英文标题】:uniform generation of 3D points on cylinder/cone 【发布时间】:2011-02-10 07:59:23 【问题描述】:我希望在圆柱体和圆锥体上随机均匀地生成点(分别)。圆柱体由其中心、半径和高度定义。锥体规格相同。我能够获得每个形状的边界框,所以我正在考虑在边界框中生成点。但是,我不确定如何将它们投影到圆柱体/圆锥体上,或者这是否是最好的主意。
有什么建议吗?
谢谢。
【问题讨论】:
看起来比率从 1.5 变为 0.5。您可能想要 ratio=(max_y-y)/cone->Height() 代替。 另外,为了阻止你的点在顶点周围聚集,你需要 y=(max_y-min_y)*(1-sqrt(RandomNumber()))+min_y 看起来您编辑中的问题已得到解答。你能把它清理干净,或者添加另一个 EDIT 来表明它已经被回答了吗? 【参考方案1】:圆柱壳是微不足道的。如果半径 r > 0 且高度 h > 0 的圆柱体是 (x, y, z) = (r cos φ, r sin φ, z) 在 φ ∈ [0, 2π[ 和 z ∈ [-h /2, h/2],然后简单地在这些区间上随机选择 φ 和 z。当然,也可以使用标准参数化简单地对圆锥进行参数化,但是面积元素在参数平面上不会是恒定的,因此点的分布不会是随机的。因此,您需要找到不同的参数化。我已经在my AlgoSim site 的一个领域详细讨论了这个话题。
【讨论】:
【参考方案2】:对此的一种思考方式是圆柱体和圆锥体都可以展开成平面 - 只需用一条直线从上到下切割每一个。
圆柱体展开成一个矩形(如果包括顶部和底部,则添加几个圆盘)。
圆锥展开成一个三角形,其底部是弧形的圆弧(如果包括圆锥的底部,则添加一个圆盘)。
将这些平面嵌入到 xy 平面上的矩形 R
中非常简单。在R
中生成均匀分布的点,只要它们在平面内,就将它们映射回原始表面。
请注意此处尝试根据角度和高度协调锥体的其他一些答案。尽管这些点在角度和高度方面是均匀分布的,但它们不会在 w.r.t. 方面均匀分布。区域。它们将更密集地分布在尖端。
【讨论】:
【参考方案3】:直接在圆柱或圆锥上生成点会更简单。
自从我这样做以来已经有一段时间了,但是参数化圆柱体的轴,然后为每个点参数化该高度的圆。这将在曲面上创建点。圆的半径就是圆柱的半径。
对于圆锥,当您从底部移动到顶点时,您需要减小圆的半径。
【讨论】:
【参考方案4】:让一个点由坐标r、a、h定义,其中r是“半径"(从中心经过的垂直轴的距离),a 是极坐标中的角度,h 是它的高度。
对于圆柱体(半径R和高度H):独立选择
a [0, 2pi) 中的制服, h 统一在 [0, H] 和 r 具有“三角密度”:f(r) = 2 r / R if 0 r R,否则为0(r处的密度应与半径r的圆周长度成正比>)。从这种三角分布中采样应该不难,因为它的累积分布(二次单项式)很容易可逆(参见this article)。另外,这个答案是基于直觉的,但是证明你在圆柱体上得到的分布是均匀的应该不难。
对于圆锥(半径R和高度H):选择
一个制服在[0, 2pi), h,密度由一段抛物线构成:f(h) = 3 (H - h) ^2 / H^3 如果 0 h H,否则为 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.圆锥:选择
一个制服在[0, 2pi), h 具有三角形密度:f(h) = 2 (H - h) / H ^2 如果 0 h H,否则为 0(h 处的密度应与高度 h 处的周长)。 r = r( h ) = (H - h) R / H = 高度半径h。【讨论】:
糟糕。你是说表面上的? 是的,根据定义,圆柱体(和圆锥体)是空间中的表面,而不是固体物体。而且我认为 OP 确实在使用这个数学定义,因为他使用介词“on”而不是“inside”。 我完全不确定你的定义(en.wikipedia.org/wiki/Cone_%28geometry%29en.wikipedia.org/wiki/Cylinder_%28geometry%29),但是我已经更新了两个形状侧面的点。【参考方案5】:其他答案已经很好地涵盖了圆柱体外壳。对于锥体来说,事情要困难一些。为了保持点的恒定密度,您需要补偿半径的变化。
为此,您可以从选择点之间的距离开始。当您沿着圆锥的轴移动时,您计算该高度处的周长,然后将周长除以点之间的线性距离以获得点数。然后,您将 2pi 弧度(或 360 度,或其他)除以点数以获得该半径的角距离。
根据您需要的精度,您可以在计算下一个圆时跟踪一个圆的余数。例如,如果你有两个连续的圆圈需要 xxx.4 分,如果孤立地看,你会四舍五入——但一起看,你有 xxx.8 分,所以你应该一个向下取整,另一个向上取整,以使整体密度尽可能接近正确值。
请注意,虽然不是那么明显,但后者也可以应用于圆柱体——在分布每个圆点时通常会进行一些舍入。
【讨论】:
【参考方案6】:将这些答案放入伪代码中:
对于圆柱体,给定圆柱半径和圆柱高度:
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.
对于一个圆锥,给定coneRadius,coneHeight:
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) 将位于圆柱体/圆锥体上。生成足够多的这些点,您可以在圆柱体/圆锥体的表面生成粒子,但它可能不会形成完全均匀的分布......
【讨论】:
问题是要找到一个均匀分布,而在你的圆锥代码中不是这种情况。【参考方案7】:对于半径为 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 )
【讨论】:
以上是关于在圆柱/圆锥上统一生成 3D 点的主要内容,如果未能解决你的问题,请参考以下文章