简体   繁体   English

在圆柱/圆锥上均匀生成3D点

[英]uniform generation of 3D points on cylinder/cone

I wish to randomly and uniformly generate points on a cylinder and a cone (separately). 我希望随机均匀地在圆柱体和圆锥体上生成点(单独)。 The cylinder is defined by its center, its radius and height. 圆柱体由其中心,半径和高度限定。 Same specifications for the cone. 锥体的规格相同。 I am able to get the bounding box for each shape so I was thinking of generating points within the bounding box. 我能够得到每个形状的边界框,所以我想在边界框内生成点。 However, I'm not sure how to project them onto the cylinder/cone or if this is the best idea. 但是,我不知道如何将它们投射到圆柱/圆锥上或者这是最好的想法。

Any suggestions? 有什么建议?

Thanks. 谢谢。

The cylinder case is trivial. 气缸壳是微不足道的。 If the cylinder of radius r > 0 and height h > 0 is the image of (x, y, z) = (r cos φ, r sin φ, z) on φ ∈ [0, 2π[ and z ∈ [-h/2, h/2], then simply choose φ and z randomly on these intervals. 如果半径r> 0且高度h> 0的圆柱是φ∈[0,2π[和z∈[-h]上的(x,y,z)=(rcosφ,rsinφ,z)的图像/ 2,h / 2],然后在这些间隔上随机选择φ和z。 Of course one can simply parametrise the cone as well using the standard parametrisation, but then the area element will not be constant on the parameter plane, and so the distribution of points will not be random. 当然,也可以使用标准参数化简单地对锥体进行参数化,但是面积元素在参数平面上不会是恒定的,因此点的分布不是随机的。 Thus you need to find a different parametrisation. 因此,您需要找到不同的参数化。 I have discussed this topic in detail for a sphere at my AlgoSim site . 我已经在AlgoSim网站上详细讨论了这个主题。

It would be simpler to generate the points directly on the cylinder or cone. 直接在圆柱体或圆锥体上生成点会更简单。

It's been a while since I did this, but parametrise the axis of the cylinder and then for each point parametrise the circle at that height. 我做了这个已经有一段时间了,但是参数化圆柱体的轴,然后对于每个点参数化该高度处的圆。 This will create points on the surface. 这将在表面上创建点。 The radius of the circle is the radius of the cylinder. 圆的半径是圆柱的半径。

For the cone you need to reduce the radius of the circle as you move from the base to the apex. 对于锥体,当您从基部移动到顶点时,需要减小圆的半径。

One way to think of this is that both the cylinder and the cone can be unwrapped into flat surfaces - just cut each one with a straight line from top to bottom. 想到这一点的一种方法是圆柱体和圆锥体都可以打开平面 - 只需从顶部到底部用直线切割每一个。

The cylinder unwraps to a rectangle (if you're including the top and bottom, then add a couple of disks). 圆柱体展开为矩形(如果您包括顶部和底部,则添加几个磁盘)。

The cone unwraps to a triangle with a curved bottom that is the arc of a circle (if you're including the base of the cone, then add a disk). 圆锥展开到一个三角形,底部是弧形的圆弧(如果你包括圆锥的底部,那么添加一个圆盘)。

It's easy enough to embed these flat surfaces inside a rectangle R on the xy plane. 将这些平面嵌入xy平面上的矩形R内很容易。 Generate uniformly distributed points in R , and whenever they are inside the flat surfaces, map them back to the original surfaces. R生成均匀分布的点,只要它们位于平面内,就将它们映射回原始曲面。

Watch out for some of the other answers here which try to co-ordinatize a cone in terms of angle and height. 注意这里的一些其他答案,试图在角度和高度方面协调锥形。 Although the points will be uniformly distributed with respect to angle and height, they will not be uniformly distributed wrt area. 尽管这些点在角度和高度方面均匀分布,但它们不会均匀分布在区域内。 They will be more densely distributed at the tip. 它们将在尖端更密集地分布。

Let a point be defined by coordinates r , a , h , where r is the "radius" (distance from the vertical axis passing from the center), a is the angle as in polar coordinates, and h is its height. 设点由坐标rah定义,其中r是“半径”(距离中心的垂直轴的距离), a是极坐标中的角度, h是其高度。

For the cylinder (radius R and height H ): choose independently 对于气缸 (半径R和高度H ):独立选择

  • a uniform in [0, 2pi), [0,2pi]中制服,
  • h uniform in [0, H ], and h均匀[0, H ]和
  • r with a "triangular density": f( r ) = 2 r / R if 0 <= r <= R , 0 otherwise (the density at r should be proportional to the length of the circumference of radius r ). r具有“三角形密度”:f( r )= 2 r / R如果0 <= r <= R ,则0(否则r处的密度应与半径r的圆周长度成比例)。

It should not be difficult to sample from such triangular distribution, since its cumulative distribution (a quadratic monomial) is easily invertible (see this article ). 从这种三角形分布中抽样应该不难,因为它的累积分布(二次单项式)很容易可逆(见本文 )。 Also, this answer is based on intuition, but it should not be difficult to prove that the distribution you obtain on the cylinder is uniform. 此外,这个答案是基于直觉,但是要证明你在气缸上获得的分布是均匀的并不难。

For the cone (radius R and height H ): choose 对于锥体 (半径R和高度H ):选择

  • a uniform in [0, 2pi), [0,2pi]中制服,
  • h with a density made with a segment of parabola: f( h ) = 3 ( H - h )^2 / H ^3 if 0 <= h <= H , 0 otherwise (the density at h should be proportional to the area of the circular section at height h ), h用一段抛物线制成的密度:f( h )= 3( H - h )^ 2 / H ^ 3如果0 <= h <= H ,则0(否则h处的密度应与面积成比例)高度为h )的圆形截面,
  • let r ( h ) = ( H - h ) R / H (the radius of the section at height h ); rh )=( H - hR / H (高度为h的截面半径); then choose r with a "triangular distribution" f( r ) = 2 r / r ( h ) if 0 <= r <= r ( h ), 0 otherwise. 然后选择具有“三角分布” F(R)= 2 R / R(h)如0 <= R <= R(h) ,否则为0

Again, sampling h should be easy, since the cumulative distribution is easily invertible. 同样,采样h应该很容易,因为累积分布很容易反转。

EDIT. 编辑。 If you mean to generate points on the surface of the shapes, then the solution is simpler: 如果您想在形状表面上生成点,则解决方案更简单:

Cylinder : choose 气缸 :选择

  • a uniform in [0, 2pi), [0,2pi]中制服,
  • h uniform in [0, H ], h在[0, H ]中均匀,
  • r = R . r = R.

Cone : choose :选择

  • a uniform in [0, 2pi), [0,2pi]中制服,
  • h with a triangular density: f( h ) = 2 ( H - h ) / H ^2 if 0 <= h <= H , 0 otherwise (the density at h should be proportional to the length of the circumference at height h ). h具有三角形密度:f( h )= 2( H - h )/ H ^ 2如果0 <= h <= H ,则否则为0( h处的密度应与高度h处的圆周长度成比例) 。
  • r = r ( h ) = ( H - h ) R / H = radius at height h . r = rh )=( H - hR / H =高度h处的半径。

Other answers have already covered the cylinder case pretty well. 其他答案已经很好地涵盖了气缸外壳。 For the cone, things are a bit more difficult. 对于锥形,事情有点困难。 To maintain a constant density of points, you need to compensate for the change in radius. 要保持恒定的点密度,您需要补偿半径的变化。

To do that, you can start by picking a distance between the points. 要做到这一点,您可以从点之间选择一个距离开始。 As you move along the axis of the cone, you compute the circumference at that height, then divide the circumference the linear distance between the points to get the number of points. 当您沿着圆锥轴移动时,您可以计算该高度的圆周,然后将圆周除以点之间的直线距离以获得点数。 You then divide 2pi radians (or 360 degrees, or whatever) by the number of points to get the angular distance for that radius. 然后,您将2pi弧度(或360度,或其他)除以点数,以获得该半径的角距离。

Depending on the accuracy you need, you can keep track of the remainder from one circle as you're computing the next circle. 根据您所需的精度,您可以在计算下一个圆时跟踪一个圆的余数。 For example, if you have two circles in a row that work out to needing xxx.4 points, you'd round each down if looked at in isolation -- but looking at them together, you have xxx.8 points, so you should round one down and the other up to keep the overall density as close as possible to the correct value. 例如,如果连续两个圆圈需要xxx.4点,那么如果孤立地查看它们就会向下舍入 - 但是一起看它们,你有xxx.8点,所以你应该这样做第一个向下,另一个向上,以保持整体密度尽可能接近正确的值。

Note that although it's not as obvious, the latter can apply to the cylinder as well -- you'll typically have some rounding in distributing each circle of points. 请注意,虽然它不那么明显,后者也可以应用于圆柱体 - 通常在分布每个圆点时会有一些圆角。

To put those answers in pseudocode: 将这些答案放在伪代码中:

For a cylinder, given cylinderRadius and cylinderHeight: 对于圆柱体,给定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.

For a cone, given coneRadius, coneHeight: 对于锥形,给定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

Each point (x,y,z) will lie on the cylinder/cone. 每个点(x,y,z)将位于圆柱体/圆锥体上。 Generate enough of these points and you can spawn particles on the surface of a cylinder/cone, but it may not make an exactly uniform distribution... 生成足够的这些点,你可以在圆柱/圆锥的表面上产生粒子,但它可能不会产生完全均匀的分布......

For uniform points on a circle or cone of radius R, and height/elevation H: 对于半径为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 )

Note that if you want a base on your cone, you will need to do it separately from the curved shape. 请注意,如果您想在锥体上使用基座,则需要与弯曲形状分开进行。 To make sure the density of points is the same for the different parts, an easy way is to calculate the areas of the parts and generate a proportional number of points for each part. 为了确保不同零件的点密度相同,一种简单的方法是计算零件的面积并为每个零件生成一定比例的点数。

The sqrt(value) is what makes sure the density of your random points is uniform. sqrt(值)是确保随机点密度均匀的原因。 As other questions have mentioned, you want a triangular distribution for this; 正如其他问题所提到的,你想要一个三角形分布 ; taking the sqrt() turns the uniform distribution on [0,1) into a triangular one. 取sqrt()将[0,1]上的均匀分布变为三角形。

For a cylinder you don't want the sqrt(); 对于圆柱体,您不需要sqrt(); the curved part is: 弯曲的部分是:

  cylinder_point= point3d( R*cos(angle), R*sin(angle), H*value )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM