[英]uniform generation of 3D points on cylinder/cone
我希望随机均匀地在圆柱体和圆锥体上生成点(单独)。 圆柱体由其中心,半径和高度限定。 锥体的规格相同。 我能够得到每个形状的边界框,所以我想在边界框内生成点。 但是,我不知道如何将它们投射到圆柱/圆锥上或者这是最好的想法。
有什么建议?
谢谢。
气缸壳是微不足道的。 如果半径r> 0且高度h> 0的圆柱是φ∈[0,2π[和z∈[-h]上的(x,y,z)=(rcosφ,rsinφ,z)的图像/ 2,h / 2],然后在这些间隔上随机选择φ和z。 当然,也可以使用标准参数化简单地对锥体进行参数化,但是面积元素在参数平面上不会是恒定的,因此点的分布不是随机的。 因此,您需要找到不同的参数化。 我已经在AlgoSim网站上详细讨论了这个主题。
直接在圆柱体或圆锥体上生成点会更简单。
我做了这个已经有一段时间了,但是参数化圆柱体的轴,然后对于每个点参数化该高度处的圆。 这将在表面上创建点。 圆的半径是圆柱的半径。
对于锥体,当您从基部移动到顶点时,需要减小圆的半径。
想到这一点的一种方法是圆柱体和圆锥体都可以打开平面 - 只需从顶部到底部用直线切割每一个。
圆柱体展开为矩形(如果您包括顶部和底部,则添加几个磁盘)。
圆锥展开到一个三角形,底部是弧形的圆弧(如果你包括圆锥的底部,那么添加一个圆盘)。
将这些平面嵌入xy平面上的矩形R
内很容易。 在R
生成均匀分布的点,只要它们位于平面内,就将它们映射回原始曲面。
注意这里的一些其他答案,试图在角度和高度方面协调锥形。 尽管这些点在角度和高度方面均匀分布,但它们不会均匀分布在区域内。 它们将在尖端更密集地分布。
设点由坐标r , a , h定义,其中r是“半径”(距离中心的垂直轴的距离), a是极坐标中的角度, h是其高度。
对于气缸 (半径R和高度H ):独立选择
从这种三角形分布中抽样应该不难,因为它的累积分布(二次单项式)很容易可逆(见本文 )。 此外,这个答案是基于直觉,但是要证明你在气缸上获得的分布是均匀的并不难。
对于锥体 (半径R和高度H ):选择
同样,采样h应该很容易,因为累积分布很容易反转。
编辑。 如果您想在形状表面上生成点,则解决方案更简单:
气缸 :选择
锥 :选择
其他答案已经很好地涵盖了气缸外壳。 对于锥形,事情有点困难。 要保持恒定的点密度,您需要补偿半径的变化。
要做到这一点,您可以从点之间选择一个距离开始。 当您沿着圆锥轴移动时,您可以计算该高度的圆周,然后将圆周除以点之间的直线距离以获得点数。 然后,您将2pi弧度(或360度,或其他)除以点数,以获得该半径的角距离。
根据您所需的精度,您可以在计算下一个圆时跟踪一个圆的余数。 例如,如果连续两个圆圈需要xxx.4点,那么如果孤立地查看它们就会向下舍入 - 但是一起看它们,你有xxx.8点,所以你应该这样做第一个向下,另一个向上,以保持整体密度尽可能接近正确的值。
请注意,虽然它不那么明显,后者也可以应用于圆柱体 - 通常在分布每个圆点时会有一些圆角。
将这些答案放在伪代码中:
对于圆柱体,给定cylinderRadius和cylinderHeight:
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)将位于圆柱体/圆锥体上。 生成足够的这些点,你可以在圆柱/圆锥的表面上产生粒子,但它可能不会产生完全均匀的分布......
对于半径为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(值)是确保随机点密度均匀的原因。 正如其他问题所提到的,你想要一个三角形分布 ; 取sqrt()将[0,1]上的均匀分布变为三角形。
对于圆柱体,您不需要sqrt(); 弯曲的部分是:
cylinder_point= point3d( R*cos(angle), R*sin(angle), H*value )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.