2012-10-25 8 views
6

Eventuali duplicati:
Create random number within an annulusGenerare un punto uniformemente casuale all'interno di un anello (ring)

Vorrei avere un punto casuale uniforme ottenuta entro un annulus, cioè la area che si trova all'interno di un cerchio di raggio R1, ma all'esterno di un raggio di raggio R2, dove R1 > R2 e entrambi i cerchi sono centrati nello stesso punto. Vorrei evitare di usare il campionamento del rifiuto.

Se possibile, mi piacerebbe che la soluzione fosse simile a this one - utilizzata per calcolare punti casuali all'interno di una cerchia - che trovo estremamente elegante e intuitiva. Cioè, vorrei anche evitare di usare la radice quadrata .

+0

Grazie per la modifica, non conosceva quella zona è stato chiamato un anello. ;-) –

+0

Aggiunti chiarificatori, sottolineando che vorrei evitare la radice quadrata (quindi, non esattamente un duplicato dell'altro). –

+0

Voglio che sia un caso di cambiare '[0, R]' nella tua domanda collegata a '[R1, R2]', ma scommetto che non è così semplice. O è? – AakashM

risposta

2

MODIFICA:Si prega di notare che questa soluzione potrebbe non essere uniforme. Vedi i commenti di Mark Dickinson qui sotto.

Ok, penso di aver capito. Si noti che questa soluzione è fortemente ispirata in this answer e che r1 = R1/R1 e r2 = R2/R1.

pseudo-codice:

t = 2*pi*random() 
u = random()+random() 
r = if u>1 then 2-u else u 
r = if r<r2 then r2+r*((R1-R2)/R2) else r 
[r*cos(t), r*sin(t)] 

Qui è in Mathematica.

f[] := Block[{u, t, r}, u = Random[] + Random[]; 
r1 = 1; r2 = 0.3; 
t = Random[] 2 Pi; 
r = If[u > 1, 2 - u, u]; 
r = If[r < r2, r2 + r*((R1 - R2)/R2), r]; 
{r Cos[t], r Sin[t]}] 

ListPlot[Table[f[], {10000}], AspectRatio -> Automatic] 

Distribution of the simple algorithm

Ciò che non è per riassociare tutti i numeri che cadono all'interno del cerchio interno nell'anello, diffondendo uniformemente. Se qualcuno trova un problema per quanto riguarda l'uniformità di questa soluzione, si prega di commentare.

paragonabile a questo altra soluzione trovata here:

Distribution of the sqrt algorithm

+4

Questo è un risposta ordinata, ma sfortunatamente il risultato non è uniforme. Se provi con ad esempio, 'R2 = 0.95' e' R1 = 1.0', vedrai che i punti più vicini all'esterno dell'anello sono preferiti. Un modo corretto per generare un 'r' appropriato è prendere le variabili casuali' u' e 'v' con' u' scelto uniformemente in '[R2, R1]' e 'v' scelto uniformemente in' [0, R2 + R1 ] ', quindi prendi' r = u' se 'v = u'. –

+0

Mark, grazie per il tuo commento e per la tua alternativa. Sei sicuro che la mia soluzione non sia uniforme? Non riesco a notarlo nemmeno con R2 = 0,95 come suggerito: http://i.imgur.com/wmDEo.png –

+0

Piuttosto sicuro, sì. :-) Ecco un test che puoi fare: prendi 'R2 = 0.5' e' R1 = 1.0' e genera 10.000 campioni (per esempio). Ora dividi il tuo anello in due aggiungendo un cerchio di raggio 0,75 e conta quanti dei campioni generati si trovano nell'anello esterno (0,75 <= raggio <= 1,0) e quanti nell'anello interno (0,5 <= raggio <= 0,75). Se la soluzione è uniforme, dovresti ottenere un rapporto vicino a 7/5 = 1,4 (area dell'anello esterno = 7/16 pi, area dell'anello interno = 5/16 pi). Non ho provato, ma sto prevedendo che la tua soluzione darà un rapporto più vicino a 5/3 = 1.66666 ... –

-1

Il modo più semplice per eseguire questa operazione è utilizzare rejection sampling. Generare un numero elevato di punti in modo uniforme in un quadrato di lunghezza laterale 2 * R2, quindi filtrare quei campioni in quelli all'interno del cerchio esterno e non nel cerchio interno.

Non abbastanza o efficiente, ma nella maggior parte dei casi, sufficiente.

+2

Ha detto che non voleva usare il campionamento del rifiuto. E per il campionamento del rifiuto, almeno si potrebbe iniziare con punti uniformi nel cerchio più grande con il metodo a cui si è collegato. –

1

È molto facile. Usa coordinate polari, cioè generi un valore casuale per il valore angolare theta e uno per la distanza dall'origine. Dato che le tue cerchie hanno entrambe la stessa origine, questo diventa molto facile.

MA ATTENZIONE: è possibile generare il valore theta con una funzione casuale uniforme, che va bene, ma per la distanza non è possibile farlo, poiché i punti si raggrupperanno attorno all'origine. Devi prendere in considerazione che il perimetro di un cerchio cresce in^2 (devi usare l'inverso che è la radice quadrata).

Utilizzando una divisa distribuito funzione random rnd (0..1) sarebbe come questo:

theta = 360 * rnd(); 
dist = sqrt(rnd()*(R1^2-R2^2)+R2^2); 

EDIT: Per la conversione in coordinate cartesion, basta calcolare:

x = dist * cos(theta); 
y = dist * sin(theta); 
+0

Dubito che le funzioni tipiche di 'cos' e' sin' abbiano gradi, più probabilmente radianti. Ma questo è un metodo di lavoro. –

+0

Se possibile, vorrei evitare sqrt() come nella risposta che ho collegato. Neanche io voglio usare il campionamento del rifiuto. –

+0

Depensa la tua funzione. Nel caso in cui non usi gradi ma radianti, basta sostituire il 360 con 2 * PI – flolo