Puoi anche farlo in coordinate sferiche, nel qual caso non c'è rifiuto. Prima generi il raggio e i due angoli a caso, quindi usi la formula di transizione per recuperare , e ( , , ).y z x = r sin θ cos ϕ y = r sin θ sin ϕ z = r cos θxyzx=rsinθcosϕy=rsinθsinϕz=rcosθ
Si genera unifomly tra e . Il raggio e l'inclinazione non sono però uniformi. La probabilità che un punto sia all'interno della sfera del raggio è quindi la funzione di densità di probabilità di è . Puoi facilmente verificare che la radice cubica di una variabile uniforme abbia esattamente la stessa distribuzione, quindi è così che puoi generare . La probabilità che un punto si trovi all'interno di un cono sferico definito dall'inclinazione è o se0ϕ02πrθrr3r3r2rθ(1−cosθ)/21−(1−cos(−θ))/2θ>π/2 . Quindi la densità è . Puoi verificare che meno l'arccosina di una variabile uniforme abbia la densità corretta.θsin(θ)/2
O più semplicemente, possiamo simulare il coseno di uniformemente tra e .θ−11
In R questo sembrerebbe come mostrato sotto.
n <- 10000 # For example n = 10,000.
phi <- runif(n, max=2*pi)
r <- runif(n)^(1/3)
cos_theta <- runif(n, min=-1, max=1)
x <- r * sqrt(1-cos_theta^2) * cos(phi)
y <- r * sqrt(1-cos_theta^2) * sin(phi)
z <- r * cos_theta
Nel corso della stesura e della modifica di questa risposta, mi sono reso conto che la soluzione è meno banale di quanto pensassi.
Penso che il metodo più semplice e più efficiente dal punto di vista computazionale sia seguire il metodo di @ whuber per generare sulla sfera unitaria come mostrato in questo post e ridimensionarli con .r(x,y,z)r
xyz <- matrix(rnorm(3*n), ncol=3)
lambda <- runif(n)^(1/3) / sqrt(rowSums(xyz^2))
xyz <- xyz*lambda