[英]How to generate an elliptical cylinder, populate it with randomly distributed points, and measure instances of overlap between those points in R
我想確定隨機分布的 A 型 object 占據或接觸(重疊)與填充在橢圓柱內的任何隨機分布的 B 型 object 相同的空間的概率。 然后我想多次循環此模擬以生成更可靠的概率值。
我可以使用形狀 package 繪制橢圓柱:
library(shape)
emptyplot(c(-5, 5), c(-15, 15), main = "filled elliptic cylinder")
filledcylinder(rx = 9, ry = 5, len= 2, angle = 00, col = "white",
lcol = "black", lcolint = "grey")
我不知道如何向該圖中添加點(即對象 A 和 B)。 但是,我懷疑圖形表達不是完成此任務的 go 的方式(盡管我發現可視化很有幫助)。 我懷疑更好的方法是創建一個 function 來描述橢圓柱,類似於以下示例中的圓錐體,並在沒有圖形 output 的情況下運行模擬:
# Create a function to describe a cone
cone <- function(x, y){
sqrt(x ^ 2 + y ^ 2)
}
# prepare variables.
x <- y <- seq(-1, 1, length = 30)
z <- outer(x, y, cone)
# plot as a 3D surface for visual reference (even though I actually want a volume)
persp(x, y, z,
main="Perspective Plot of a Cone",
zlab = "Height",
theta = 30, phi = 15,
col = "orange", shade = 0.4)
可悲的是,我不知道如何為我的橢圓柱做這個。 我從以下來源知道用於描述橢圓柱的參數:
https://mathworld.wolfram.com/EllipticCylinder.html
不幸的是,我不太了解它。 我希望我的填充圓筒中給出的尺寸可以作為指導。 最終維度值並不重要,重要的是可以輸入值的代碼結構。
至於對象:
假設有 50 個 A 類對象和 50 個 B 類對象,其大小為 x=0.4、y=0.4、z=0.4(與我的圖形橢圓柱示例中的單位相同)。
所有物體都將隨機分布在橢圓柱的體積內,除了類型 A 的物體不能與另一個類型 A object 重疊,類型 B 的物體不能與其他類型 B 的物體重疊。類型 A 物體可能與 B 類對象重疊。
我想要 output 在給定體積中與任何 B 型 object 重疊的 A 型對象的數量,這個數字占 A 型對象總數的百分比,以及每次模擬運行的所有對象總數的百分比。
我什至不知道如何開始這樣做。
如果你能幫忙,恐怕需要向(不是特別聰明的)孩子解釋統計、幾何和非基礎 R 表達式。
非常感謝您的寶貴時間!
帶有大量注釋代碼的實現以進行解釋。 這假定 A 型和 B 型對象必須完全位於橢圓柱內。
library(data.table)
rObj <- function(rx, ry, h, n, dims, eps = 2) {
# Function to create a random sample (by rejection) of non-overlapping
# rectangular prism objects inside an elliptical cylinder whose ellipse is
# centered at x = 0, y = 0 and whose height ranges from -dims[3]/2 to h -
# dims[3]/2. The objects have dimensions (x, y, z) = dims, and all edges are
# parallel or orthogonal to each of the x, y, or z axes.
# INPUTS:
# rx: length of the ellipse
# ry: width of the ellipse
# h: height of the elliptical cylinder
# n: number of non-overlapping objects to return
# dims: dimensions of the rectangular prism objects (vector of length 3)
# eps: oversampling factor
# OUTPUT: a data.table with 3 columns and n rows. Each row gives the
# coordinates of the centroid of a sampled object
dt <- data.table()
while(nrow(dt) < n) {
# increase oversampling if it is not the first pass
if (nrow(dt)) eps <- eps*2
rho <- sqrt(runif(eps*n))
phi <- runif(eps*n, 0, 2*pi)
dt <- data.table(
# sample object centroids
# see https://stackoverflow.com/questions/5529148/algorithm-calculate-pseudo-random-point-inside-an-ellipse
# First, uniformly sample on an ellipse centered on x = 0, y = 0,
# with xlength = rx - dims[1] and ylength = ry - dims[2]
# (any object with a centroid outside of this ellipse will stick out of
# the elliptical cylinder, although some with a centroid within the
# smaller ellipse will still stick out of the elliptical cylinder).
x = (rx - dims[1])/2*rho*cos(phi),
y = (ry - dims[2])/2*rho*sin(phi),
# uniformly sample centroid heights
z = runif(eps*n, 0, h - dims[3])
)[
# remove objects that stick out of bounds
# The ellipse satisfies (x/(rx/2))^2 + (y/(ry/2))^2 = 1, which is the
# same as (x/rx)^2 + (y/ry)^2 = 0.25. Taking advantage of symmetry, add
# half of the x and y dimensions of the objects to the absolute value of
# x and y (the object corner furthest from the foci of the ellipse) and
# check if the result satisfies the standard equation.
((abs(x) + dims[1]/2)/rx)^2 + ((abs(y) + dims[2]/2)/ry)^2 < 0.25
][
# remove objects that overlap a previously placed object
# Since each rectangular prism object is oriented with the x, y, z axes,
# two objects overlap if they are closer than their lengths in each
# dimension.
tabulate(
sequence((.N - 1L):1, 2:.N)[ # row numbers (always keep the first row)
(dist(x) < dims[1]) & (dist(y) < dims[2]) & (dist(z) < dims[3])
],
.N
) == 0L
]
}
dt[1:n] # keep the first n objects
}
# function to get pairwise distances between two vectors
dist2 <- function(x, y) abs(outer(x, y, "-"))
fsim <- function(rx, ry, h, nA, nB, dimA, dimB, nreps, eps = 2) {
# function to simulate placement of A and B rectangular prism objects inside
# an elliptical cylinder and count the number of A-type objects that
# intersect at least one B-type object. All object edges are parallel or
# orthogonal to each of the x, y, or z axes.
# INPUTS:
# rx: length of the ellipse
# ry: width of the ellipses
# h: height of the elliptical cylinder
# nA: number of non-overlapping A-type objects to return
# nB: number of non-overlapping B-type objects to return
# dimX: dimensions of the rectangular prism objects (vector of length 3)
# nreps: the number of replications to simulate
# eps: oversampling factor when randomly sampling non-overlapping objects
# by rejection
# OUTPUT: vector of length "nreps" giving the number of A-type objects that
# intersect at least one B-type object for each replication
dims <- rowMeans(cbind(dimA, dimB)) # average dimensions of the A and B objects
out <- integer(nreps) # initialize the output vector
# repeat the simulation "nreps" times
for (i in 1:nreps) {
# get the coordinates of the A- and B-type objects' centroids
A <- rObj(rx, ry, h, nA, dimA, eps)
B <- rObj(rx, ry, h, nB, dimB, eps)
# count the number of A-type objects that intersect at least one B-type
# object
out[i] <- sum(rowSums((dist2(A$x, B$x) < dims[1])*(dist2(A$y, B$y) < dims[2])*(dist2(A$z, B$z) < dims[3])) != 0L)
}
out
}
時間 10K 模擬復制:
system.time(overlaps <- fsim(9, 5, 2, 50L, 50L, rep(0.4, 3), rep(0.4, 3), 1e4L))
#> user system elapsed
#> 27.19 0.25 27.67
mean(overlaps)
#> [1] 18.7408
獲得此問題的近似答案的一種方法是將事物離散化。 將體積設置為零的 3 維數組,然后一次隨機生成一個形狀的參數。
對於每個生成的形狀,找到該形狀內的所有數組元素。 如果任何位置在圓柱體之外或與相同類型的形狀重疊,請重試。 一旦你有一個合法的形狀,標記那些數組條目(例如 1 代表類型 A,2 代表類型 B)。 首先做所有類型 A,然后所有類型 B,並記錄形狀 B 占據先前標記為形狀 A 的空間的次數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.