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

问题描述 投票:2回答:1

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

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

我也发现这个[R package 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个球体进行比较,如果第二组坐标中的所有点在空间中以相似的角度/方向移动。

感谢您的指导。

r function random geometry
1个回答
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))

看起来怎么样?

UPDATE

在表面和体积中生成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

你得到了什么?

© www.soinside.com 2019 - 2024. All rights reserved.