Genera un punto casuale all’interno di un cerchio (uniformsmente)

Ho bisogno di generare un punto uniformsmente casuale all’interno di un cerchio di raggio R.

Mi rendo conto che selezionando un angolo uniformsmente casuale nell’intervallo [0 … 2π), e uniformsmente il raggio casuale nell’intervallo (0 … R ) finirei con più punti verso il centro, poiché per due dati raggi, i punti nel raggio più piccolo saranno più vicini tra loro che per i punti nel raggio più ampio.

Ho trovato un post sul blog qui ma non capisco il suo ragionamento. Suppongo sia corretto, ma mi piacerebbe davvero capire da dove ottiene (2 / R 2 ) × r e come ottiene la soluzione finale.


Aggiornamento: 7 anni dopo aver postato questa domanda non avevo ancora ricevuto una risposta soddisfacente sulla vera domanda riguardante la matematica dietro l’algoritmo della radice quadrata. Così ho trascorso una giornata scrivendo una risposta da solo. Link alla mia risposta .

Avviciniamoci a questo come avrebbe fatto Archimede.

Come possiamo generare un punto uniformsmente in un triangolo ABC, dove | AB | = | BC |? Rendiamolo più semplice estendendoci a un parallelogramma ABCD. È facile generare punti uniformsmente in ABCD. Selezioniamo uniformsmente un punto casuale X su AB e Y su BC e selezioniamo Z tale che XBYZ sia un parallelogramma. Per ottenere un punto scelto in modo uniforms nel triangolo originale, basta piegare qualsiasi punto che appare in ADC indietro in ABC lungo AC.

Ora considera un cerchio. Nel limite possiamo pensarlo come infinitamente molti triangoli isocelici ABC con B all’origine e A e C sulla circonferenza che si avvicinano in modo quasi invisibile. Possiamo scegliere uno di questi triangoli semplicemente selezionando un angolo theta. Quindi ora dobbiamo generare una distanza dal centro selezionando un punto nel nastro ABC. Ancora una volta, estendersi a ABCD, dove D è ora il doppio del raggio dal centro del cerchio.

Scegliere un punto casuale in ABCD è facile usando il metodo sopra. Scegli un punto casuale su AB. Scegli uniformsmente un punto casuale su BC. Vale a dire. scegli un paio di numeri casuali xey uniformsmente su [0, R] dando distanze dal centro. Il nostro triangolo è un sottile strato così AB e BC sono essenzialmente paralleli. Quindi il punto Z è semplicemente una distanza x + y dall’origine. Se x + y> R torniamo indietro.

Ecco l’algoritmo completo per R = 1. Spero tu sia d’accordo è piuttosto semplice. Usa trig, ma puoi dare una garanzia su quanto tempo ci vorrà e quante chiamate random() ha bisogno, a differenza del campionamento del rifiuto.

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

Eccolo in Mathematica.

 f[] := Block[{u, t, r}, u = Random[] + Random[]; t = Random[] 2 Pi; r = If[u > 1, 2 - u, u]; {r Cos[t], r Sin[t]} ] ListPlot[Table[f[], {10000}], AspectRatio -> Automatic] 

inserisci la descrizione dell'immagine qui

Come generare un punto casuale all’interno di un cerchio di raggio R :

 r = R * sqrt(random()) theta = random() * 2 * PI 

(Supponendo random() fornisce un valore compreso tra 0 e 1 uniformsmente)

Se vuoi convertirlo in coordinate cartesiane, puoi farlo

 x = r * cos(theta) y = r * sin(theta) 

Perché sqrt(random()) ?

Diamo un’occhiata alla matematica che porta a sqrt(random()) . Supponiamo per semplicità che stiamo lavorando con il cerchio unitario, cioè R = 1.

La distanza media tra i punti dovrebbe essere la stessa indipendentemente dalla distanza dal centro che osserviamo. Ciò significa, ad esempio, che guardando il perimetro di un cerchio con la circonferenza 2 dovremmo trovare il doppio dei punti del numero di punti sul perimetro di un cerchio con la circonferenza 1.

Poiché la circonferenza di un cerchio (2π r ) cresce linearmente con r , ne consegue che il numero di punti casuali dovrebbe crescere linearmente con r . In altre parole, la funzione di densità di probabilità desiderata (PDF) cresce linearmente. Dal momento che un PDF dovrebbe avere un’area pari a 1 e il raggio massimo è 1, lo abbiamo

Quindi sappiamo come dovrebbe apparire la densità desiderata dei nostri valori casuali. Ora: come generiamo un tale valore casuale quando tutto ciò che abbiamo è un valore casuale uniforms compreso tra 0 e 1?

Usiamo un trucco chiamato inverse transform sampling

  1. Dal PDF, creare la funzione di distribuzione cumulativa (CDF)
  2. Specchia questo lungo y = x
  3. Applicare la funzione risultante ad un valore uniforms tra 0 e 1.

Sembra complicato? Lasciami inserire una scatola gialla con un piccolo binario che trasmetta l’intuizione:

Supponiamo di voler generare un punto casuale con la seguente distribuzione:

Questo è

  • 1/5 dei punti uniformsmente tra 1 e 2, e
  • 4/5 dei punti uniformsmente tra 2 e 3.

Il CDF è, come suggerisce il nome, la versione cumulativa del PDF. Intuitivamente: mentre PDF ( x ) descrive il numero di valori casuali in x , CDF ( x ) descrive il numero di valori casuali inferiori a x .

In questo caso il CDF dovrebbe essere:

Per vedere come è utile, immagina di sparare proiettili da sinistra a destra in altezze uniformsmente distribuite. Mentre i proiettili colpiscono la linea, cadono a terra:

Guarda come la densità dei proiettili sul terreno corrisponde alla nostra distribuzione desiderata! Ci siamo quasi!

Il problema è che per questa funzione, l’asse y è l’ output e l’asse x è l’ input . Possiamo solo “sparare proiettili da terra”! Abbiamo bisogno della funzione inversa!

Questo è il motivo per cui rispecchiamo l’intera cosa; x diventa yey diventa x :

Chiamiamo questo CDF -1 . Per ottenere i valori in base alla distribuzione desiderata, utilizziamo CDF -1 (random ()).

… quindi, torniamo a generare valori di raggio casuale in cui il nostro PDF equivale a 2 x .

Passaggio 1: creare il CDF:

Poiché stiamo lavorando con real, il CDF è express come integrale del PDF.

CDF ( x ) = ∫ 2 x = x 2

Passaggio 2: Specchia il CDF lungo y = x :

Matematicamente questo si riduce a scambiare x e y e risolvere per y :

CDF : y = x 2
Swap: x = y 2
Risolvi: y = √ x
CDF -1 : y = √ x

Passaggio 3: applicare la funzione risultante a un valore uniforms compreso tra 0 e 1

CDF -1 (random ()) = √random ()

Questo è ciò che abbiamo deciso di derivare 🙂

Ecco una soluzione rapida e semplice.

Scegli due numeri casuali nell’intervallo (0, 1), ovvero a e b . Se b < a , scambiali. Il tuo punto è (b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b)) .

Puoi pensare a questa soluzione come segue. Se prendi il cerchio, lo tagli, poi lo raddrizzi, otterrai un triangolo rettangolo. Ridimensiona quel triangolo e avresti un triangolo da (0, 0) a (1, 0) a (1, 1) e viceversa (0, 0) . Tutte queste trasformazioni cambiano la densità in modo uniforms. Quello che hai fatto è stato scegliere in modo uniforms un punto casuale nel triangolo e invertito il processo per ottenere un punto nel cerchio.

Nota la densità del punto in proporzione al quadrato inverso del raggio, quindi anziché prendere r da [0, r_max] , scegli da [0, r_max^2] , quindi calcola le coordinate come:

 x = sqrt(r) * cos(angle) y = sqrt(r) * sin(angle) 

Questo ti darà una distribuzione uniforms dei punti su un disco.

http://mathworld.wolfram.com/DiskPointPicking.html

Pensaci in questo modo. Se hai un rettangolo in cui un asse è il raggio e uno è l’angolo, e prendi i punti all’interno di questo rettangolo che sono vicini al raggio 0. Questi cadranno tutti molto vicini all’origine (cioè vicini sul cerchio). Tuttavia, i punti vicino al raggio R, questi cadranno tutti vicino al bordo del cerchio (cioè distanti l’uno dall’altro).

Questo potrebbe darti un’idea del perché stai assumendo questo comportamento.

Il fattore derivato da quel collegamento indica quanta area corrispondente nel rettangolo deve essere regolata per non dipendere dal raggio una volta mappata al cerchio.

Modifica: Quindi quello che scrive nel link che condividi è: “È abbastanza facile da fare calcolando l’inverso della distribuzione cumulativa, e otteniamo per r:”.

La premessa di base è qui che è ansible creare una variabile con una distribuzione desiderata da un’uniforms mappando l’uniforms mediante la funzione inversa della funzione di distribuzione cumulativa della funzione di densità di probabilità desiderata. Perché? Lo diamo per scontato per ora, ma questo è un dato di fatto.

Ecco la mia spiegazione intuitiva della matematica. La funzione di densità f (r) rispetto a r deve essere proporzionale a r stesso. Comprendere questo fatto fa parte di qualsiasi libro di base di calcolo. Vedi le sezioni sugli elementi dell’area polare. Alcuni altri poster hanno menzionato questo.

Quindi lo chiameremo f (r) = C * r;

Questa risulta essere la maggior parte del lavoro. Ora, dato che f (r) dovrebbe essere una densità di probabilità, puoi facilmente vedere che integrando f (r) sull’intervallo (0, R) ottieni C = 2 / R ^ 2 (questo è un esercizio per il lettore .)

Quindi, f (r) = 2 * r / R ^ 2

OK, ecco come si ottiene la formula nel link.

Quindi, la parte finale sta passando dalla variabile casuale uniforms u in (0,1) che devi mappare per funzione inversa della funzione di distribuzione cumulativa da questa densità desiderata f (r). Per capire perché questo è il caso, è necessario trovare un testo di probabilità avanzato come Papoulis probabilmente (o derivarlo tu stesso).

Integrando f (r) ottieni F (r) = r ^ 2 / R ^ 2

Per trovare la funzione inversa di questo hai impostato u = r ^ 2 / R ^ 2 e quindi risolvi per r, che ti dà r = R * sqrt (u)

Anche questo ha un senso in modo intuitivo, u = 0 dovrebbe mappare a r = 0. Inoltre, u = 1 shoudl map in r = R. Inoltre, passa alla funzione radice quadrata, che ha senso e corrisponde al collegamento.

Dipende davvero da cosa intendi per “uniformsmente casuale”. Questo è un punto sottile e puoi leggerne di più sulla pagina wiki qui: http://en.wikipedia.org/wiki/Bertrand_paradox_%28probability%29 , dove lo stesso problema, dando diverse interpretazioni a ‘uniformsmente casuale’ dà risposte diverse!

A seconda di come scegli i punti, la distribuzione potrebbe variare, anche se in un certo senso sono casuali in modo uniforms.

Sembra che il blog stia cercando di renderlo uniformsmente casuale nel seguente senso: se prendi un sub-cerchio del cerchio, con lo stesso centro, allora la probabilità che il punto cada in quella regione sia proporzionale all’area di la Regione. Questo, ritengo, sta tentando di seguire l’interpretazione ormai standard di “uniformsmente casuale” per le regioni 2D con aree definite su di esse : la probabilità che un punto cada in qualsiasi regione (con un’area ben definita) è proporzionale all’area di quella regione.

Il motivo per cui la soluzione ingenua non funziona è che dà una densità di probabilità più elevata ai punti più vicini al centro del cerchio. In altre parole il cerchio che ha raggio r / 2 ha probabilità r / 2 di ottenere un punto selezionato in esso, ma ha area (numero di punti) pi * r ^ 2/4.

Pertanto vogliamo che la densità di probabilità del raggio abbia la seguente proprietà:

La probabilità di scegliere un raggio più piccolo o uguale a un dato r deve essere proporzionale all’area del cerchio con raggio r. (perché vogliamo avere una distribuzione uniforms sui punti e aree più grandi significano più punti)

In altre parole, vogliamo che la probabilità di scegliere un raggio tra [0, r] sia uguale alla sua quota dell’area complessiva del cerchio. L’area del cerchio totale è pi * R ^ 2, e l’area del cerchio con raggio r è pi * r ^ 2. Quindi vorremmo che la probabilità di scegliere un raggio tra [0, r] fosse (pi * r ^ 2) / (pi * R ^ 2) = r ^ 2 / R ^ 2.

Ora arriva la matematica:

La probabilità di scegliere un raggio tra [0, r] è l’integrale di p (r) dr da 0 a r (è solo perché aggiungiamo tutte le probabilità dei raggi più piccoli). Quindi vogliamo integrale (p (r) dr) = r ^ 2 / R ^ 2. Possiamo vedere chiaramente che R ^ 2 è una costante, quindi tutto ciò che dobbiamo fare è capire quale p (r), quando integrato, ci darebbe qualcosa come r ^ 2. La risposta è chiaramente r * costante. integrale (r * costante dr) = r ^ 2/2 * costante. Questo deve essere uguale a r ^ 2 / R ^ 2, quindi costante = 2 / R ^ 2. Quindi avete la distribuzione di probabilità p (r) = r * 2 / R ^ 2

Nota: un altro modo più intuitivo di pensare al problema è immaginare che si stia provando a dare a ciascun cerchio di densità di probabilità di raggio uguale alla proporzione del numero di punti che ha sulla sua circonferenza. Quindi un cerchio che ha raggio r avrà 2 * pi * r “punti” sulla sua circonferenza. Il numero totale di punti è pi * R ^ 2. Quindi dovresti dare al cerchio una probabilità pari a (2 * pi * r) / (pi * R ^ 2) = 2 * r / R ^ 2. Questo è molto più facile da capire e più intuitivo, ma non è altrettanto matematicamente valido.

Ecco il mio codice Python per generare num punti casuali da un cerchio di raggio rad :

 import matplotlib.pyplot as plt import numpy as np rad = 10 num = 1000 t = np.random.uniform(0.0, 2.0*np.pi, num) r = rad * np.sqrt(np.random.uniform(0.0, 1.0, num)) x = r * np.cos(t) y = r * np.sin(t) plt.plot(x, y, "ro", ms=1) plt.axis([-15, 15, -15, 15]) plt.show() 

Sia ρ (raggio) e φ (azimuth) siano due variabili casuali corrispondenti alle coordinate polari di un punto arbitrario all’interno del cerchio. Se i punti sono distribuiti uniformsmente, qual è la funzione di disribuzione di ρ e φ?

Per ogni r: 0

P [ρ 2

Dove S1 e S0 sono le aree del cerchio di raggio r e R, rispettivamente. Quindi la CDF può essere data come:

  0 if r<=0 CDF = (r/R)**2 if 0 < r <= R 1 if r > R 

E PDF:

 PDF = d/dr(CDF) = 2 * (r/R**2) (0 < r <= R). 

Si noti che per R = 1 variabile casuale sqrt (X) dove X è uniforms su [0, 1) ha questo esatto CDF (perché P [sqrt (X)

La distribuzione di φ è ovviamente uniforms da 0 a 2 * π. Ora puoi creare coordinate polari casuali e convertirle in cartesiano usando le equazioni trigonometriche:

 x = ρ * cos(φ) y = ρ * sin(φ) 

Non resisto a postare codice python per R = 1.

 from matplotlib import pyplot as plt import numpy as np rho = np.sqrt(np.random.uniform(0, 1, 5000)) phi = np.random.uniform(0, 2*np.pi, 5000) x = rho * np.cos(phi) y = rho * np.sin(phi) plt.scatter(x, y, s = 4) 

Otterrete

Soluzione in Java e l’esempio di distribuzione (2000 punti)

 public void getRandomPointInCircle() { double t = 2 * Math.PI * Math.random(); double r = Math.sqrt(Math.random()); double x = r * Math.cos(t); double y = r * Math.sin(t); System.out.println(x); System.out.println(y); } 

Punti di distribuzione 2000

basato sulla soluzione di previus https://stackoverflow.com/a/5838055/5224246 da @sigfpe

Penso che in questo caso l’uso delle coordinate polari sia un modo per complicare il problema, sarebbe molto più semplice se si selezionassero punti casuali in un quadrato con lati di lunghezza 2R e quindi si selezionassero i punti (x,y) tali che x^2+y^2<=R^2 .

Per prima cosa generiamo un cdf [x] che è

La probabilità che un punto sia inferiore alla distanza x dal centro del cerchio. Supponiamo che il cerchio abbia un raggio di R.

ovviamente se x è zero allora cdf [0] = 0

ovviamente se x è R allora cdf [R] = 1

ovviamente se x = r allora cdf [r] = (Pi r ^ 2) / (Pi R ^ 2)

Questo perché ogni “piccola area” sul cerchio ha la stessa probabilità di essere prelevata, quindi la probabilità è proporzionale all’area in questione. E l’area data una distanza x dal centro del cerchio è Pi r ^ 2

quindi cdf [x] = x ^ 2 / R ^ 2 perché il Pi si annulla a vicenda

abbiamo cdf [x] = x ^ 2 / R ^ 2 dove x va da 0 a R

Quindi risolviamo x

 R^2 cdf[x] = x^2 x = R Sqrt[ cdf[x] ] 

Ora possiamo sostituire cdf con un numero casuale da 0 a 1

 x = R Sqrt[ RandomReal[{0,1}] ] 

Finalmente

 r = R Sqrt[ RandomReal[{0,1}] ]; theta = 360 deg * RandomReal[{0,1}]; {r,theta} 

otteniamo le coordinate polari {0,601168 R, 311,915 gradi}

Esiste una relazione lineare tra il raggio e il numero di punti “vicino” a quel raggio, quindi ha bisogno di usare una distribuzione del raggio che rende anche il numero di punti dati vicino a un raggio r proporzionale a r .

Ho usato una volta questo metodo: Questo può essere totalmente non ottimizzato (cioè usa una matrice di punti quindi è inutilizzabile per i grandi cerchi) ma dà abbastanza distribuzione casuale. Puoi saltare la creazione della matrice e disegnare direttamente se lo desideri. Il metodo consiste nel randomizzare tutti i punti di un rettangolo che cadono all’interno del cerchio.

 bool[,] getMatrix(System.Drawing.Rectangle r) { bool[,] matrix = new bool[r.Width, r.Height]; return matrix; } void fillMatrix(ref bool[,] matrix, Vector center) { double radius = center.X; Random r = new Random(); for (int y = 0; y < matrix.GetLength(0); y++) { for (int x = 0; x < matrix.GetLength(1); x++) { double distance = (center - new Vector(x, y)).Length; if (distance < radius) { matrix[x, y] = r.NextDouble() > 0.5; } } } } private void drawMatrix(Vector centerPoint, double radius, bool[,] matrix) { var g = this.CreateGraphics(); Bitmap pixel = new Bitmap(1,1); pixel.SetPixel(0, 0, Color.Black); for (int y = 0; y < matrix.GetLength(0); y++) { for (int x = 0; x < matrix.GetLength(1); x++) { if (matrix[x, y]) { g.DrawImage(pixel, new PointF((float)(centerPoint.X - radius + x), (float)(centerPoint.Y - radius + y))); } } } g.Dispose(); } private void button1_Click(object sender, EventArgs e) { System.Drawing.Rectangle r = new System.Drawing.Rectangle(100,100,200,200); double radius = r.Width / 2; Vector center = new Vector(r.Left + radius, r.Top + radius); Vector normalizedCenter = new Vector(radius, radius); bool[,] matrix = getMatrix(r); fillMatrix(ref matrix, normalizedCenter); drawMatrix(center, radius, matrix); } 

inserisci la descrizione dell'immagine qui

L’elemento area in un cerchio è dA = rdr * dphi. Quel fattore in più ha distrutto la tua idea di scegliere casualmente ar e phi. Mentre phi è distribuito piatto, r non lo è, ma piatto in 1 / r (cioè è più probabile che si raggiunga il limite rispetto a “l’occhio del toro”).

Quindi, per generare punti distribuiti uniformsmente sul cerchio, selezionare phi da una distribuzione piatta e r da una distribuzione 1 / r.

In alternativa, usa il metodo Monte Carlo proposto da Mehrdad.

MODIFICARE

Per scegliere un r piatto casuale in 1 / r puoi scegliere una x casuale dall’intervallo [1 / R, infinito] e calcolare r = 1 / x. r viene quindi distribuito piatto in 1 / r.

Per calcolare un phi casuale, selezionare una x casuale dall’intervallo [0, 1] e calcolare phi = 2 * pi * x.

Non so se questa domanda è ancora aperta per una nuova soluzione con tutta la risposta già data, ma mi è capitato di avere affrontato esattamente la stessa domanda io stesso. Ho cercato di “ragionare” con me stesso per una soluzione, e l’ho trovato. Potrebbe essere la stessa cosa che alcuni hanno già suggerito qui, ma comunque eccolo qui:

in modo che due elementi della superficie del cerchio siano uguali, supponendo uguali dr, dobbiamo avere dtheta1 / dtheta2 = r2 / r1. Espressione di scrittura della probabilità per quell’elemento come P (r, theta) = P {r1

Una soluzione per il programmatore:

  • Crea una mappa bit (una matrice di valori booleani). Può essere grande quanto vuoi.
  • Disegna un cerchio in quella mappa bit.
  • Crea una tabella di ricerca dei punti del cerchio.
  • Scegli un indice casuale in questa tabella di ricerca.
 const int RADIUS = 64; const int MATRIX_SIZE = RADIUS * 2; bool matrix[MATRIX_SIZE][MATRIX_SIZE] = {0}; struct Point { int x; int y; }; Point lookupTable[MATRIX_SIZE * MATRIX_SIZE]; void init() { int numberOfOnBits = 0; for (int x = 0 ; x < MATRIX_SIZE ; ++x) { for (int y = 0 ; y < MATRIX_SIZE ; ++y) { if (x * x + y * y < RADIUS * RADIUS) { matrix[x][y] = true; loopUpTable[numberOfOnBits].x = x; loopUpTable[numberOfOnBits].y = y; ++numberOfOnBits; } // if } // for } // for } // () Point choose() { int randomIndex = randomInt(numberOfBits); return loopUpTable[randomIndex]; } // () 

La bitmap è necessaria solo per la spiegazione della logica. Questo è il codice senza bitmap:

 const int RADIUS = 64; const int MATRIX_SIZE = RADIUS * 2; struct Point { int x; int y; }; Point lookupTable[MATRIX_SIZE * MATRIX_SIZE]; void init() { int numberOfOnBits = 0; for (int x = 0 ; x < MATRIX_SIZE ; ++x) { for (int y = 0 ; y < MATRIX_SIZE ; ++y) { if (x * x + y * y < RADIUS * RADIUS) { loopUpTable[numberOfOnBits].x = x; loopUpTable[numberOfOnBits].y = y; ++numberOfOnBits; } // if } // for } // for } // () Point choose() { int randomIndex = randomInt(numberOfBits); return loopUpTable[randomIndex]; } // () 

Non sono ancora sicuro dell’esatta ‘(2 / R2) × r’, ma ciò che è evidente è il numero di punti necessari per essere distribuiti in una determinata unità ‘dr’, cioè l’aumento di r sarà proporzionale a r2 e non r.

controlla in questo modo … il numero di punti ad un angolo theta e tra r (0.1r a 0.2r) cioè frazione di r e numero di punti tra r (0.6r a 0.7r) sarebbe uguale se usi la generazione standard, poiché la differenza è di soli 0,1r tra due intervalli. ma dal momento che l’area coperta tra i punti (da 0,6 a 0,7) sarà molto più grande dell’area coperta tra 0,1 e 0,2 r, il numero uguale di punti sarà spaziato in un’area più ampia, presumo che tu sappia già, quindi la funzione per generare i punti casuali non deve essere lineare ma quadratico, (dal momento che il numero di punti necessari per essere distribuiti in una determinata unità ‘dr’ cioè l’aumento di r sarà proporzionale a r2 e non r), quindi in questo caso sarà inverso di quadratico, poiché il delta che abbiamo (0.1r) in entrambi gli intervalli deve essere quadrato di qualche funzione in modo che possa agire come valore di partenza per la generazione lineare di punti (poiché afterwords, questo seme è usato linearmente in funzione sin e cos), quindi so, dr deve essere un valore quadratico e per rendere quadratico questo seme, abbiamo bisogno di originare questi valori dalla radice quadrata di r non r stesso, spero che questo lo renda un po ‘più chiaro.

Un tale divertente problema.
La motivazione della probabilità che un punto venga scelto abbassandosi al crescere della distanza dall’origine dell’asse viene spiegata più volte sopra. Teniamo conto di ciò prendendo la radice di U [0,1]. Ecco una soluzione generale per un r positivo in Python 3.

 import numpy import math import matplotlib.pyplot as plt def sq_point_in_circle(r): """ Generate a random point in an r radius circle centered around the start of the axis """ t = 2*math.pi*numpy.random.uniform() R = (numpy.random.uniform(0,1) ** 0.5) * r return(R*math.cos(t), R*math.sin(t)) R = 200 # Radius N = 1000 # Samples points = numpy.array([sq_point_in_circle(R) for i in range(N)]) plt.scatter(points[:, 0], points[:,1]) 

inserisci la descrizione dell'immagine qui

Puoi anche usare la tua intuizione.

L’area di un cerchio è pi*r^2

Per r=1

Questo ci dà un’area di pi . Supponiamo di avere un qualche tipo di funzione f che distolga uniformsmente N=10 punti all’interno di un cerchio. Il rapporto qui è 10 / pi

Ora raddoppiamo l’area e il numero di punti

Per r=2 e N=20

Questo dà un’area di 4pi e il rapporto ora è 20/4pi o 10/2pi . Il rapporto diventerà sempre più piccolo più grande è il raggio, perché la sua crescita è quadratica e la N scala linearmente.

Per risolvere questo problema possiamo solo dire

 x = r^2 sqrt(x) = r 

Se dovessi generare un vettore con coordinate polari come questo

 length = random_0_1(); angle = random_0_2pi(); 

Più punti sarebbero atterrati intorno al centro.

 length = sqrt(random_0_1()); angle = random_0_2pi(); 

length non è più uniformsmente distribuita, ma il vettore sarà ora uniformsmente distribuito.

1) Scegli una X casuale tra -1 e 1.

 var X:Number = Math.random() * 2 - 1; 

2) Utilizzando la formula del cerchio, calcola i valori massimo e minimo di Y dato che X e un raggio di 1:

 var YMin:Number = -Math.sqrt(1 - X * X); var YMax:Number = Math.sqrt(1 - X * X); 

3) Scegli una Y casuale tra questi estremi:

 var Y:Number = Math.random() * (YMax - YMin) + YMin; 

4) Incorporare i valori di posizione e raggio nel valore finale:

 var finalX:Number = X * radius + pos.x; var finalY:Number = Y * radois + pos.y;