我正在尝试在填充了立方体的球体上生成随机点。 因为我不知道怎么做,所以我从2d开始。 (一个用方形填充的圆圈。)
基本上在蓝色区域。
广场位于(-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))
是正方形边长的一半
在有人要求之前: 我知道我可以重新生成绿色方块内的点,直到我得到一个在外面的点,但我不想这样做。
我感谢任何帮助。谢谢:))
答案 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);
从rmin
到rmax = 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)
所以算法是:
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)的五个值的函数
可以重新排列采样,使r
采样是非线性的,但它表现出同样的问题 - 需要用多项式和三角函数求解非线性方程
更新II
只是为了记录,如果你想首先采样r
,那么必须从非线性方程的解决方案中采样:
r 2 sec -1 (r) - sqrt(r 2 - 1)= U(0,1)*(\ pi / 2 - 1)
解决它并找到采样r
后,\phi
可以在r
允许的时间间隔内均匀采样:[ - cos -1 (1 / r)... + cos -1 (1 / r)]