在R中特定球坐标内随机生成点

时间:2019-04-07 16:03:44

标签: r function random geometry

我有特定的x,y,z坐标。我想在以x为中心,从另一个数据框以x2作为半径边缘的球体中生成随机点(因此,从x到x2的距离将是球体半径的长度)。

我已经看到了很多关于如何在数学上适当地做到这一点(随机分布点以避免聚类)的讨论,并且能够为示例R代码编译最简单的示例herehere

我还发现了这个[R封装的sphereplot](https://cran.r-project.org/web/packages/sphereplot/sphereplot.pdf)可能更简单,但是却很难理解如何应用它。

这些都是很好的起点,但是使用下面的示例代码,我不确定如何将其应用于特定的起点/球坐标?

set.seed(101)
n <- 50
theta <- runif(n,0,2*pi)
u <- runif(n,-1,1)
x <- sqrt(1-u^2)*cos(theta)
y <- sqrt(1-u^2)*sin(theta)
z <- u

仅使用我数据框中的一组x / y,z坐标:

x = -0.0684486861
y= 0.0125857380
z= 0.0201056441

x2= -0.0684486861
y2 = 0.0125857380
z2= -0.0228805516


我希望x,y,z为球的中心,到x2,y2,z2的距离为球的半径长度/边缘。然后从以x,y,z为中心的球体内生成随机点。

最终,我尝试使用100个球体进行比较,以比较第二组坐标中的所有点在空间中的相似角度/方向是否移动。

感谢指导。

1 个答案:

答案 0 :(得分:1)

好吧,让问题分解成几个子问题。

首先,生成的点均匀地分布在球体上(体积上或表面上),其中心为(0,0,0),并且给定半径。紧跟http://mathworld.wolfram.com/SpherePointPicking.html,并且非常接近您显示的代码

rsphere <- function(n, r = 1.0, surface_only = FALSE) {
    phi       <- runif(n, 0.0, 2.0 * pi)
    cos_theta <- runif(n, -1.0, 1.0)
    sin_theta <- sqrt((1.0-cos_theta)*(1.0+cos_theta))
    radius <- r
    if (surface_only == FALSE) {
        radius <- r * runif(n, 0.0, 1.0)^(1.0/3.0)
    }

    x <- radius * sin_theta * cos(phi)
    y <- radius * sin_theta * sin(phi)
    z <- radius * cos_theta

    cbind(x, y, z)
}

set.seed(312345)
sphere_points <- rsphere(10000)

第二个问题-将这些点移到X点的中心

rsphere <- function(n, r = 1.0, surface_only = FALSE, center=cbind(Xx, Xy, Xz)) {
    ....
    cbind(x+center[1], y+center[2], z+center[3])
}

第三个问题-计算给定中心(Xx,Xy,Xz)和表面点(Yx,Yy,Yz))的半径

radius <- sqrt((Xx-Yx)**2+(Xy-Yy)**2+(Xz-Yz)**2)

将它们组合在一起,以获得完全的满意。好的,既然您已经提供了中心和半径的值,我们就将它们放在一起

rsphere <- function(n, r = 1.0, surface_only = FALSE, center=cbind(0.0, 0.0, 0.0)) {
    phi       <- runif(n, 0.0, 2.0 * pi)
    cos_theta <- runif(n, -1.0, 1.0)
    sin_theta <- sqrt((1.0-cos_theta)*(1.0+cos_theta))
    radius <- r
    if (surface_only == FALSE) {
        radius <- r * runif(n, 0.0, 1.0)^(1.0/3.0)
    }

    x <- radius * sin_theta * cos(phi)
    y <- radius * sin_theta * sin(phi)
    z <- radius * cos_theta

    # if radius is fixed, we could check it
    # rr = sqrt(x^2+y^2+z^2)
    # print(rr)

    cbind(x+center[1], y+center[2], z+center[3])
}

x1 = -0.0684486861
y1 = 0.0125857380
z1 = 0.0201056441

x2 = -0.0684486861
y2 = 0.0125857380
z2 = -0.0228805516

R = sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2)
print(R)

set.seed(32345)
sphere_points <- rsphere(100000, R, FALSE, cbind(x1, y1, z1))

看起来如何?

更新

在表面和体积中分别生成10个点并将其打印出来,radius = 2对我来说没问题

# 10 points uniform on surface, supposed to have fixed radius
sphere_points <- rsphere(10, 2, TRUE, cbind(x1, y1, z1))
for (k in 1:10) {
    rr <- sqrt((sphere_points[k,1]-x1)^2+(sphere_points[k,2]-y1)^2+(sphere_points[k,3]-z1)^2)
    print(rr)
}

# 10 points uniform in the sphere, supposed to have varying radius
sphere_points <- rsphere(10, 2, FALSE, cbind(x1, y1, z1))
for (k in 1:10) {
    rr <- sqrt((sphere_points[k,1]-x1)^2+(sphere_points[k,2]-y1)^2+(sphere_points[k,3]-z1)^2)
    print(rr)
}

得到

[1] 2
[1] 2
[1] 2
[1] 2
[1] 2
[1] 2
[1] 2
[1] 2
[1] 2
[1] 2

[1] 1.32571
[1] 1.505066
[1] 1.255023
[1] 1.82773
[1] 1.219957
[1] 1.641258
[1] 1.881937
[1] 1.083975
[1] 0.4745712
[1] 1.900066

你得到了什么?