Vous pouvez également le faire en coordonnées sphériques, auquel cas il n'y a pas de rejet. Vous générez d'abord le rayon et les deux angles au hasard, puis vous utilisez la formule de transition pour récupérer , et ( , , ).xyzx=rsinθcosϕy=rsinθsinϕz=rcosθ
Vous générez uniformément entre et . Le rayon et l'inclinaison ne sont cependant pas uniformes. La probabilité qu'un point se trouve à l'intérieur de la boule de rayon est donc la fonction de densité de probabilité de est . Vous pouvez facilement vérifier que la racine cubique d'une variable uniforme a exactement la même distribution, c'est ainsi que vous pouvez générer . La probabilité qu'un point se trouve à l'intérieur d'un cône sphérique défini par l'inclinaison est ou siϕ02πrθrr3r3r2rθ(1−cosθ)/21−(1−cos(−θ))/2θ>π/2 . La densité est donc . Vous pouvez vérifier que moins l'arc cosinus d'une variable uniforme a la bonne densité.θsin(θ)/2
Ou plus simplement, nous pouvons simuler le cosinus de uniformément entre et .θ−11
Dans R, cela ressemblerait à ce qui suit.
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
Au cours de l'écriture et de l'édition de cette réponse, j'ai réalisé que la solution est moins triviale que je ne le pensais.
Je pense que la méthode la plus simple et la plus efficace sur le plan informatique est de suivre la méthode de @ whuber pour générer sur la sphère unitaire comme indiqué dans ce post et les mettre à l'échelle avec .(x,y,z)r
xyz <- matrix(rnorm(3*n), ncol=3)
lambda <- runif(n)^(1/3) / sqrt(rowSums(xyz^2))
xyz <- xyz*lambda