【问题标题】:randomly generate points within specific sphere coordinates in R在R中的特定球体坐标内随机生成点
【发布时间】:2019-08-28 20:50:21
【问题描述】:

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

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

我还发现了这个 [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 个球体来比较第二组坐标中的所有点是否在空间中以相似的角度/方向移动。

感谢您的指导。

【问题讨论】:

  • 我无法理解您的问题。球体存在于三个维度中。一个圆圈存在于两个中。您打算如何使用单个 x 坐标作为“圆心”或球心?前者取两个坐标值,后者取三个坐标值。
  • 嗯,我确实有每个点的 x,y,z 坐标 - 我刚刚添加了(我应该提到这些是从排序生成的)但是你不能只使用半径吗?类似于根据半径计算球体的体积?
  • 不,你不能只使用半径,因为半径定义了一个相对于一个点的圆或球体,而在 2 空间或 3 空间中定义一个点需要两个或三个坐标, 分别。有无数个具有相同半径和 x 坐标的圆或球体。
  • 感谢 @pjs 帮助我改进这一点。我想错了。我做了一些更正,希望能澄清我正在尝试做的事情。
  • 您是否希望点均匀分布在球体中,即给定体积中的预期点数与体积成正比?

标签: r function random geometry


【解决方案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

你得到了什么?

【讨论】:

  • 谢谢。我仍然不确定如何将其应用于我的特定 x,y,z 坐标而不是 0,0,0?实际上,我无法遵循第 2 部分或第 3 部分中的任何代码。虽然这可能只是因为我学习 R 真的很慢......
  • @KNN 我已经更新了代码以及您提供的所有数据,请查看
  • 很高兴看到您在半径上使用立方根来统一缩放结果!
  • 在球体表面生成点的另一种方法是生成一个由三个独立的 N(0,1) 组成的向量,然后通过向量的长度(即然后可以进一步缩放以分布到球体内部)。这种方法可以推广到任意维度的超球体,而三角函数的版本很快就会变得非常丑陋。
  • 另一个变种类似于Marsaglia's polar method:生成三个U(-1,1)坐标的向量,当范数> 1时拒绝。然后按向量的范数缩放以放置球体表面上的坐标。在二维或三维中,这可能比生成法线更快(这就是 Marsaglia 这样做的原因),但向量的接受概率随着维度的增加而降低,因此高斯方法更通用。
猜你喜欢
  • 2015-09-20
  • 2018-03-31
  • 2020-12-09
  • 1970-01-01
  • 2023-01-07
  • 2019-06-29
  • 2014-05-20
  • 1970-01-01
  • 2021-10-03
相关资源
最近更新 更多