在填充有立方体/正方形的球体/圆上生成均匀随机数

时间:2017-04-06 10:49:16

标签: java math random geometry

我正在尝试在填充了立方体的球体上生成随机点。 因为我不知道怎么做,所以我从2d开始。 (一个用方形填充的圆圈。)

我想做的事情:在外圈内生成随机点,但在绿色方块外。 enter image description here

基本上在蓝色区域。

广场位于(-1|-1),(1|-1),(1|1),(-1|1) 圆的半径为r = sqrt(2),并以(0|0)为中心。

我已经有脚本:

  • 在圆上生成一个随机点(统一):

    float a = 2 * MathUtils.PI * MathUtils.random(1f); // angle between 0 and 2pi
    float r = radius * Math.sqrt(MathUtils.random(0, 1f)
    float x = r * MathUtils.cos(a);
    float y = r * MathUtils.sin(a);
    
  • 计算给定角度的半径以形成正方形:

    float r = (1/Math.sqrt(2)) / MathUtils.cos(((a+45)%90-45)/180*MathUtils.PI);
    

    (1/Math.sqrt(2))是正方形边长的一半

在有人要求之前: 我知道我可以重新生成绿色方块内的点,直到我得到一个在外面的点,但我不想这样做。

我感谢任何帮助。谢谢:))

2 个答案:

答案 0 :(得分:0)

仅在立方体(帽和楔形)之外的球体区域中生成点是相当困难的,因此拒绝方法看起来合理。

但你可以减少无用点的数量,在2D情况下生成点in the ring only,在3D情况下生成球壳。

所以伪代码可能看起来像

 //2d
 SquaredR  = RandomUniformInRange(0.5, 1)
 R = Sqrt(SquaredR)

 //3d
 CubedR  = RandomUniformInRange(Pow(3, -3/2), 1)
 R = Pow(CubedR, 1/3)

 //generate point on the circle or on the sphere with radius R

 if Abs(x) > Sqrt(2)/2 or Sqrt(3)/3  and so on - reject

拥有R,您可以使用here

中的任何方法在球体上生成点

答案 1 :(得分:0)

这是这个想法的粗略草图。您可以选择一个象限进行采样,例如右侧一个。

首先,样本角度从-pi / 4到pi / 4

float a = -MathUtils.PI/4.0f + MathUtils.PI/2.0 * MathUtils.random(0.f,1.f);
float c = MathUtils.cos(a);
float s = MathUtils.sin(a);

其次,找到最小半径。光线从(0,0)以角度a开始将至少与x=1处的象限线相交

float rmin = 1.0f / c;
float rmax = Math.sqrt(2.0f);

rminrmax = sqrt(2)的示例,考虑到对于平面你采样平方半径然后使用sqrt(),对于3d空间你采样立方半径然后使用cbrt()。< / p>

float r2 = rmin*rmin + (rmax*rmax-rmin*rmin)*MathUtils.random(0.f,1.f);
float r  = Math.sqrt(r);

float x = r * c;
float y = r * s;

现在,我们构造(x,y)就是这样一种方式,它保证在圆圈下方的右边象限和x = 1线的右边。

要覆盖所有四个象限,只需采样你将移动点的象限

float q = MathUtils.random(0.f,1.f);
if (q < 0.25f) // top quadrant
    return (y, x);
if (q < 0.5f)  // left quadrant
    return (-x, y);
if (q < 0.75f)  // bottom quadrant
    return (y, -x);
return (x,y); // right quadrant

请耐心等待 - 我的Java非常生疏,我无法测试代码。

在3D情况下,你必须处理两个角度,立方半径,八个八分圆而不是四个象限,但一般逻辑是相同的

更新

我错了,像我建议的抽样会导致点数分布不均匀。

来自PDF:

PDF(phi, r) = S_(-\pi/4)^\phi d\phi S_1/cos(\phi)^\sqrt(2) r dr

我们必须得到\ phi采样不均匀。不幸的是,来自 U(0,1)得到采样\ phi需要求解非线性方程

\pi/2 (0.5*(\phi/\pi/4 + 1) - U(0,1)) = 0.5*(tan(phi) + 1) - U(0,1)

所以算法是:

  • 样本U(0,1)
  • 通过解决上面的等式找到合适的\ phi
  • 查找较低的R边界
  • 样本R

用于绘制此非线性函数的快速代码(在Python中,抱歉)

import numpy as np
import matplotlib.pyplot as plt

def f(phi, ksi):
    c   = 0.5 * np.pi
    c_2 = 0.5 * c

    left = c * (0.5 * (phi/c_2     + 1.0) - ksi)
    rght =     (0.5 * (np.tan(phi) + 1.0) - ksi)

    return left - rght

nof_points = 41
phi   = np.linspace(-0.25*np.pi, 0.25*np.pi, nof_points)
y0_00 = f(phi, 0.00)
y0_25 = f(phi, 0.25)
y0_50 = f(phi, 0.50)
y0_75 = f(phi, 0.75)
y0_99 = f(phi, 1.00)

plt.plot(phi, y0_00, 'ro', phi, y0_25, 'b+', phi, y0_50, 'gx', phi, y0_75, 'm.', phi, y0_99, 'y^')
plt.show()

并绘制了U(0,1)(代码中的ksi)的五个值的函数

enter image description here

可以重新排列采样,使r采样是非线性的,但它表现出同样的问题 - 需要用多项式和三角函数求解非线性方程

更新II

只是为了记录,如果你想首先采样r,那么必须从非线性方程的解决方案中采样: r 2 sec -1 (r) - sqrt(r 2 - 1)= U(0,1)*(\ pi / 2 - 1)

区间[1 ... sqrt(2)]

中的

解决它并找到采样r后,\phi可以在r允许的时间间隔内均匀采样:[ - cos -1 (1 / r)... + cos -1 (1 / r)]