it-swarm.com.de

Einen zufälligen Punkt innerhalb eines Kreises (einheitlich)

Ich muss einen gleichmäßig zufälligen Punkt innerhalb eines Kreises mit dem Radius R erzeugen.

Ich stelle fest, dass ich durch das Wählen eines gleichmäßig zufälligen Winkels im Intervall [0 ... 2π) und eines gleichmäßig zufälligen Radius im Intervall (0 ... R) mit mehr Punkten in Richtung zentrieren, da für zwei gegebene Radien die Punkte im kleineren Radius näher zueinander liegen als für die Punkte im größeren Radius.

Ich habe einen Blogeintrag zu diesem hier gefunden, aber ich verstehe seine Argumentation nicht. Ich vermute, es ist richtig, aber ich würde wirklich gerne verstehen, woher er kommt (2/R2) × r und wie er die endgültige Lösung herleitet.


Update: 7 Jahre nachdem ich diese Frage gestellt hatte, hatte ich immer noch keine befriedigende Antwort auf die eigentliche Frage bezüglich der Mathematik hinter dem Quadratwurzel-Algorithmus erhalten. Also habe ich einen Tag selbst eine Antwort geschrieben. Link zu meiner Antwort .

178
aioobe

So erzeugen Sie einen zufälligen Punkt innerhalb eines Kreises mit dem Radius R:

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

(Angenommen, random() ergibt einen einheitlichen Wert zwischen 0 und 1)

Wenn Sie dies in kartesische Koordinaten umrechnen möchten, können Sie dies tun

x = centerX + r * cos(theta)
y = centerY + r * sin(theta)


Warum sqrt(random())?

Schauen wir uns die Mathematik an, die zu sqrt(random()) führt. Nehmen wir der Einfachheit halber an, dass wir mit dem Einheitskreis arbeiten, d. H. R = 1.

Der durchschnittliche Abstand zwischen den Punkten sollte gleich sein, unabhängig davon, wie weit vom Mittelpunkt entfernt wir aussehen. Dies bedeutet zum Beispiel, dass wir beim Blick auf den Kreisumfang mit dem Umfang 2 doppelt so viele Punkte finden sollten wie die Anzahl der Punkte auf dem Kreisumfang mit dem Umfang 1.




Da der Umfang eines Kreises (2πr) wächst linear mit r, daher sollte die Anzahl der zufälligen Punkte linear mit r wachsen. Mit anderen Worten wächst die gewünschte Wahrscheinlichkeitsdichtefunktion (PDF) linear. Da ein PDF eine Fläche von 1 haben sollte und der maximale Radius 1 ist, haben wir


Wir wissen also, wie die gewünschte Dichte unserer Zufallswerte aussehen sollte ... Jetzt: Wie erzeugen wir einen solchen Zufallswert, wenn wir nur einen einheitlichen Zufallswert zwischen 0 und 1 haben?

Wir verwenden einen Trick namens inverse Transformationsabtastung

  1. Erstellen Sie aus der PDF-Datei die kumulative Verteilungsfunktion (CDF).
  2. Spiegeln Sie dies entlang y = x
  3. Wenden Sie die resultierende Funktion auf einen einheitlichen Wert zwischen 0 und 1 an.

Klingt kompliziert? Lassen Sie mich eine gelbe Box mit einem kleinen Seitenweg einfügen, der die Intuition vermittelt:

Angenommen, wir möchten einen zufälligen Punkt mit der folgenden Verteilung generieren:

Das ist

  • 1/5 der Punkte gleichmäßig zwischen 1 und 2 und
  • 4/5 der Punkte gleichmäßig zwischen 2 und 3.

Die CDF ist, wie der Name schon sagt, die kumulative Version der PDF-Datei. Intuitiv: Während PDF (x) die Anzahl der Zufallswerte at x beschreibt, beschreibt CDF (x) die Anzahl der Zufallswerte kleiner als x.

In diesem Fall würde die CDF folgendermaßen aussehen:

Um zu sehen, wie nützlich dies ist, stellen Sie sich vor, dass wir Kugeln in gleichmäßig verteilten Höhen von links nach rechts schießen. Wenn die Kugeln die Linie treffen, fallen sie zu Boden:

Sehen Sie, wie die Dichte der Geschosse am Boden unserer gewünschten Verteilung entspricht! Wir sind fast da!

Das Problem ist, dass für diese Funktion die Achse y der Ausgang und die Achse x der Eingang ist. Wir können nur "Kugeln direkt vom Boden abschießen"! Wir brauchen die Umkehrfunktion!

Deshalb spiegeln wir das Ganze wider; x wird y und y wird x:

Wir nennen dies CDF-1 . Um Werte entsprechend der gewünschten Verteilung zu erhalten, verwenden wir CDF-1(zufällig()).

… Also zurück zur Erzeugung von zufälligen Radiuswerten, bei denen unser PDF gleich 2 istx.

Schritt 1: CDF erstellen:

Da wir mit reellen arbeiten, wird der CDF als das Integral des PDFs ausgedrückt.

CDF(x) = ∫ 2xx2

Schritt 2: Spiegeln Sie die CDF entlang y = x

Mathematisch geht es darum, x und y zu tauschen und nach y zu suchen:

CDF: Yx2
Swap: xy2
Lösung: y = √x
CDF-1: Y = √x

Schritt 3: Wenden Sie die resultierende Funktion auf einen einheitlichen Wert zwischen 0 und 1 an.

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

Welches ist es, was wir daraus ableiten wollten :-)

57
aioobe

Gehen wir so vor, wie es Archimedes getan hätte.

Wie können wir einen Punkt gleichmäßig in einem Dreieck ABC erzeugen, wobei | AB | = | BC | Lassen Sie uns dies durch die Erweiterung auf ein Parallelogramm-ABCD vereinfachen. In ABCD lassen sich Punkte einheitlich generieren. Wir wählen einheitlich einen zufälligen Punkt X auf AB und Y auf BC und wählen Z so, dass XBYZ ein Parallelogramm ist. Um einen einheitlich gewählten Punkt im ursprünglichen Dreieck zu erhalten, falten wir einfach alle Punkte, die in ADC erscheinen, entlang AC auf ABC herunter.

Betrachten Sie nun einen Kreis. In der Grenze können wir es als unendlich viele Isocelen-Dreiecke ABC mit B am Ursprung und A und C am Umfang verschwindend nahe beieinander betrachten. Wir können eines dieser Dreiecke einfach auswählen, indem wir einen Winkel Theta auswählen. Wir müssen jetzt einen Abstand vom Zentrum erzeugen, indem Sie einen Punkt im ABC-Band auswählen. Verlängern Sie sich wieder auf ABCD, wo D jetzt der doppelte Radius vom Kreismittelpunkt ist.

Das Auswählen eines zufälligen Punktes in ABCD ist mit der obigen Methode einfach. Wählen Sie einen zufälligen Punkt auf AB. Wählen Sie gleichmäßig einen zufälligen Punkt auf BC. Ie. Wählen Sie ein Paar von Zufallszahlen x und y auf [0, R], um die Entfernung vom Mittelpunkt zu bestimmen. Unser Dreieck ist ein dünnes Band, also sind AB und BC im Wesentlichen parallel. Der Punkt Z ist also einfach eine Entfernung x + y vom Ursprung. Wenn x + y> R, klappen wir wieder nach unten.

Hier ist der vollständige Algorithmus für R = 1. Ich hoffe, Sie stimmen zu, dass es ziemlich einfach ist. Es verwendet Trig, aber Sie können eine Garantie dafür geben, wie lange es dauert und wie viele random()-Aufrufe es benötigt, im Gegensatz zur Ablehnungsabtastung.

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

Hier ist es 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]

enter image description here

180
sigfpe

Hier ist eine schnelle und einfache Lösung.

Wählen Sie zwei Zufallszahlen im Bereich (0, 1) aus, nämlich a und b. Wenn b < a, tauschen Sie sie aus. Ihr Punkt ist (b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b)).

Sie können sich diese Lösung wie folgt vorstellen. Wenn Sie den Kreis nehmen, ausschneiden und ausrichten, erhalten Sie ein rechtwinkliges Dreieck. Skalieren Sie dieses Dreieck nach unten, und Sie haben ein Dreieck von (0, 0) zu (1, 0) zu (1, 1) und wieder zu (0, 0). Alle diese Transformationen verändern die Dichte gleichmäßig. Was Sie getan haben, ist gleichmäßig einen zufälligen Punkt im Dreieck auszuwählen und den Vorgang umzukehren, um einen Punkt im Kreis zu erhalten.

26
btilly

Notieren Sie die Punktdichte proportional zum umgekehrten Quadrat des Radius. Wählen Sie daher r aus [0, r_max] aus, und wählen Sie dann [0, r_max^2] aus.

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

Dadurch erhalten Sie eine einheitliche Punktverteilung auf einer Festplatte.

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

18
Libor

Denken Sie so darüber nach. Wenn Sie ein Rechteck mit einer Achse als Radius und einer mit einem Winkel haben, nehmen Sie die Punkte innerhalb dieses Rechtecks, die sich in der Nähe des Radius 0 befinden. Diese Punkte liegen alle sehr nahe am Ursprung (dh dem Kreis nahe beieinander). Wenn sich die Punkte in der Nähe des Radius R befinden, fallen diese alle in die Nähe des Randes des Kreises (dh weit voneinander entfernt). 

Dies kann Ihnen eine Vorstellung davon geben, warum Sie dieses Verhalten erhalten.

Der von diesem Link abgeleitete Faktor gibt an, um wie viel der entsprechende Bereich im Rechteck angepasst werden muss, damit er nicht vom Radius abhängt, wenn er dem Kreis zugeordnet ist.

Edit: Was er also in den Link schreibt, den Sie teilen, ist: "Das ist einfach genug, indem Sie die Umkehrung der kumulativen Verteilung berechnen, und wir erhalten für r:".

Die Grundvoraussetzung ist hier, dass Sie eine Variable mit einer gewünschten Verteilung aus einer Uniform erstellen können, indem Sie die Uniform durch die Umkehrfunktion der kumulativen Verteilungsfunktion der gewünschten Wahrscheinlichkeitsdichtefunktion abbilden. Warum? Nehmen Sie es einfach als selbstverständlich an, aber das ist eine Tatsache.

Hier ist meine intuitive Erklärung der Mathematik. Die Dichtefunktion f(r) in Bezug auf r muss zu r selbst proportional sein. Diese Tatsache zu verstehen, ist Teil eines grundlegenden Kalkülbuches. Siehe Abschnitte zu Polarflächenelementen. Einige andere Poster haben dies erwähnt. 

Wir nennen es also f(r) = C * r; 

Dies stellt sich als die meiste Arbeit heraus. Da f(r) eine Wahrscheinlichkeitsdichte sein sollte, können Sie leicht erkennen, dass durch Integration von f(r) über das Intervall (0, R) C = 2/R ^ 2 entsteht (Dies ist eine Übung für den Leser.) 

Somit ist f(r) = 2 * r/R ^ 2

OK, so bekommen Sie die Formel im Link. 

Der letzte Teil geht von der einheitlichen Zufallsvariablen u in (0,1) aus, die Sie mit der Umkehrfunktion der Summenverteilungsfunktion aus dieser gewünschten Dichte f (r) abbilden müssen. Um zu verstehen, warum dies der Fall ist, müssen Sie wahrscheinlich einen fortgeschrittenen Wahrscheinlichkeitstext wie Papoulis finden (oder ihn selbst ableiten.)

Wenn Sie f(r) integrieren, erhalten Sie F(r) = r ^ 2/R ^ 2

Um die Umkehrfunktion zu finden, setzen Sie u = r ^ 2/R ^ 2 und lösen dann nach r auf, was zu r = R * sqrt (u) führt.

Dies ist auch intuitiv sinnvoll, u = 0 sollte auf r = 0 abgebildet werden. Außerdem sollte u = 1 für r = R stehen. Außerdem wird die Quadratwurzelfunktion verwendet, die Sinn ergibt und mit der Verknüpfung übereinstimmt.

12
Chris A.

Der Grund, warum die naive Lösung nicht funktioniert, ist, dass sie den Punkten, die sich näher am Kreismittelpunkt befinden, eine höhere Wahrscheinlichkeitsdichte verleihen. Mit anderen Worten hat der Kreis mit dem Radius r/2 die Wahrscheinlichkeit r/2, einen Punkt zu erhalten, aber er hat eine Fläche (Anzahl von Punkten) pi * r ^ 2/4.

Daher möchten wir, dass eine Radiuswahrscheinlichkeitsdichte die folgende Eigenschaft hat: 

Die Wahrscheinlichkeit, einen Radius kleiner oder gleich einem gegebenen r zu wählen, muss proportional zur Fläche des Kreises mit dem Radius r sein. (weil wir eine gleichmäßige Verteilung auf die Punkte haben wollen und größere Flächen mehr Punkte bedeuten)

Mit anderen Worten möchten wir, dass die Wahrscheinlichkeit, einen Radius zwischen [0, r] zu wählen, seinem Anteil an der Gesamtfläche des Kreises entspricht. Die Gesamtkreisfläche ist pi * R ^ 2 und die Fläche des Kreises mit dem Radius r ist pi * r ^ 2. Wir möchten daher, dass die Wahrscheinlichkeit, einen Radius zwischen [0, r] zu wählen, (pi * r ^ 2)/(pi * R ^ 2) = r ^ 2/R ^ 2 ist.

Jetzt kommt die Rechnung: 

Die Wahrscheinlichkeit, einen Radius zwischen [0, r] zu wählen, ist das Integral von p(r) dr von 0 bis r (weil wir alle Wahrscheinlichkeiten der kleineren Radien addieren). Wir wollen also das Integral (p (r) dr) = r ^ 2/R ^ 2. Wir können deutlich sehen, dass R ^ 2 eine Konstante ist. Wir müssen also nur herausfinden, welches p (r), wenn es integriert ist, etwas wie r ^ 2 ergibt. Die Antwort ist eindeutig r * konstant. Integral (r * Konstante dr) = r ^ 2/2 * Konstante. Dies muss gleich r ^ 2/R ^ 2 sein, daher konstant = 2/R ^ 2. Damit haben Sie die Wahrscheinlichkeitsverteilung p(r) = r * 2/R ^ 2

Hinweis: Eine weitere intuitive Methode, um über das Problem nachzudenken, besteht darin, sich vorzustellen, dass Sie versuchen, jedem Radius r eine Wahrscheinlichkeitsdichte zu geben, die dem Anteil der Anzahl der Punkte auf seinem Umfang entspricht. Somit hat ein Kreis mit dem Radius r auf seinem Umfang 2 * pi * r "Punkte". Die Gesamtpunktzahl ist pi * R ^ 2. Daher sollten Sie dem Kreis r eine Wahrscheinlichkeit von (2 * pi * r)/(pi * R ^ 2) = 2 * r/R ^ 2 geben. Dies ist viel einfacher zu verstehen und intuitiver, aber es ist nicht ganz so mathematisch richtig.

8
user502248

Es hängt wirklich davon ab, was Sie unter "einheitlich zufällig" verstehen. Dies ist ein subtiler Punkt, und Sie können mehr darüber auf der Wiki-Seite hier lesen: http://en.wikipedia.org/wiki/Bertrand_paradox_%28probability%29 , wo dasselbe Problem besteht, wobei ' einheitlich zufällig 'gibt verschiedene Antworten!

Je nachdem, wie Sie die Punkte auswählen, kann die Verteilung variieren, auch wenn sie im Sinne von einige zufällig sind.

Es scheint, als würde der Blogeintrag versuchen, ihn im folgenden Sinne gleichförmig zufällig zu machen: Wenn Sie einen Teilkreis des Kreises mit demselben Zentrum nehmen, ist die Wahrscheinlichkeit, dass der Punkt in diese Region fällt, proportional zur Fläche von die Region. Ich glaube, dass versucht wird, der jetzt üblichen Interpretation von "einheitlich zufällig" für 2D-Regionen mit definierten Bereichen zu folgen : Die Wahrscheinlichkeit, dass ein Punkt in eine beliebige Region fällt (mit genau definierten Bereichen), ist proportional zur Fläche dieser Region.

7
Aryabhatta

Sei ρ (Radius) und uth (Azimut) zwei Zufallsvariablen, die Polarkoordinaten eines beliebigen Punktes innerhalb des Kreises entsprechen. Wenn die Punkte gleichmäßig verteilt sind, wie lautet dann die Verteilungsfunktion von ρ und φ?

Für jedes r: 0 <r <R ist die Wahrscheinlichkeit, dass die Radiuskoordinate kleiner als r ist

P [ρ <r] = P [Punkt liegt innerhalb eines Kreises mit dem Radius r] = S1/S0 = (r/R)2

Dabei sind S1 und S0 die Flächen des Kreises mit dem Radius r bzw. R. Damit kann die CDF wie folgt angegeben werden:

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

Und PDF:

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

Beachten Sie, dass für R = 1 die Zufallsvariable sqrt (X), bei der X auf [0,1] gleichförmig ist, genau diese CDF hat (weil * 2 für 0 <y <= 1). 

Die Verteilung von φ ist offensichtlich gleichförmig von 0 bis 2 * π. Jetzt können Sie zufällige Polarkoordinaten erstellen und sie mithilfe von trigonometrischen Gleichungen in Kartesisch konvertieren:

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

Kann nicht widerstehen, Python-Code für R = 1 ..__ zu posten.

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)

Sie erhalten

6
Pommy

Hier ist mein Python-Code zum Erzeugen von num zufälligen Punkten aus einem Radiuskreis 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()
5
krishnab

Ich denke, in diesem Fall ist die Verwendung von Polarkoordinaten eine Möglichkeit, das Problem zu komplizieren. Es wäre viel einfacher, zufällige Punkte in ein Quadrat mit Seiten der Länge 2R zu wählen und dann die Punkte (x,y) so auszuwählen, dass x^2+y^2<=R^2.

3
ascanio

Lösung in Java und das Verteilungsbeispiel (2000 Punkte) 

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);
}

 Distribution 2000 points

basierend auf previus solution https://stackoverflow.com/a/5838055/5224246 von @sigfpe

3
bolec_kolec

Zuerst erzeugen wir eine cdf [x], die ist

Die Wahrscheinlichkeit, dass ein Punkt kleiner ist als der Abstand x vom Mittelpunkt des Kreises. Angenommen, der Kreis hat einen Radius von R.

wenn x Null ist, ist cdf [0] = 0

wenn x R ist, ist cdf [R] = 1

offensichtlich, wenn x = r, dann ist die cdf [r] = (Pi r ^ 2)/(Pi R ^ 2)

Dies liegt daran, dass jeder "kleine Bereich" auf dem Kreis die gleiche Wahrscheinlichkeit hat, dass er ausgewählt wird. Die Wahrscheinlichkeit ist also proportional zu dem betreffenden Bereich. Und die Fläche, die einen Abstand x vom Mittelpunkt des Kreises hat, ist Pi r ^ 2

so cdf [x] = x ^ 2/R ^ 2, da sich die Pi gegenseitig aufheben

wir haben cdf [x] = x ^ 2/R ^ 2, wobei x von 0 nach R geht

Also lösen wir nach x

R^2 cdf[x] = x^2

x = R Sqrt[ cdf[x] ]

Wir können jetzt cdf durch eine Zufallszahl von 0 bis 1 ersetzen

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

Endlich

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

wir erhalten die Polarkoordinaten {0,601168 R, 311,915 Grad}

2
Steven Siew

Es gibt eine lineare Beziehung zwischen dem Radius und der Anzahl von Punkten, die sich "nahe" an diesem Radius befinden. Daher muss er eine Radiusverteilung verwenden, bei der die Anzahl der Datenpunkte nahe einem Radius r proportional zu r ist.

1
recursive

Ich habe einmal diese Methode verwendet: Diese Methode ist möglicherweise völlig unoptimiert (dh sie verwendet ein Array von Punkten, daher ist sie für große Kreise unbrauchbar), gibt aber eine zufällige Verteilung aus. Sie können die Erstellung der Matrix überspringen und direkt zeichnen, wenn Sie möchten. Die Methode besteht darin, alle Punkte in einem Rechteck, die in den Kreis fallen, zufällig zu sortieren.

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);
}

enter image description here

1
Marino Šimić

Das Flächenelement in einem Kreis lautet dA = rdr * dphi. Dieser zusätzliche Faktor r zerstörte die Idee, zufällig ein r und einen Phi zu wählen. Während Phi flach verteilt ist, ist r nicht, aber flach in 1/r (d. H. Sie treffen mit größerer Wahrscheinlichkeit die Grenze als "das Bullauge").

Um Punkte zu erzeugen, die gleichmäßig über den Kreis verteilt sind, wählen Sie den Phi aus einer flachen Verteilung und r aus einer 1/r-Verteilung.

Verwenden Sie alternativ die von Mehrdad vorgeschlagene Monte-Carlo-Methode.

EDIT

Um einen zufälligen Wert in 1/r zu wählen, können Sie ein zufälliges x aus dem Intervall [1/R, unendlich] auswählen und r = 1/x berechnen. r wird dann flach in 1/r verteilt.

Um ein zufälliges Phi zu berechnen, wählen Sie ein zufälliges x aus dem Intervall [0, 1] und berechnen Sie phi = 2 * pi * x.

1

Eine Programmiererlösung:

  • Erstellen Sie eine Bitmap (eine Matrix mit booleschen Werten). Es kann so groß sein, wie Sie möchten.
  • Zeichne einen Kreis in dieser Bitmap.
  • Erstellen Sie eine Nachschlagetabelle der Punkte des Kreises.
  • Wählen Sie einen zufälligen Index in dieser Nachschlagetabelle.
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];
} // ()

Die Bitmap ist nur zur Erläuterung der Logik notwendig. Dies ist der Code ohne die 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];
} // ()
0
selalerer

Sie können auch Ihre Intuition verwenden.

Die Fläche eines Kreises ist pi*r^2

Für r=1

Dies gibt uns einen Bereich von pi. Nehmen wir an, dass wir eine Funktion haben, die f die N=10 Punkte innerhalb eines Kreises gleichmäßig zerstören würde. Das Verhältnis hier ist 10 / pi

Jetzt verdoppeln wir die Fläche und die Anzahl der Punkte

Für r=2 und N=20

Dies ergibt einen Bereich von 4pi und das Verhältnis ist jetzt 20/4pi oder 10/2pi. Das Verhältnis wird kleiner und kleiner, je größer der Radius ist, da sein Wachstum quadratisch ist und N linear skaliert.

Um dies zu beheben, können wir nur sagen

x = r^2
sqrt(x) = r

Wenn Sie einen Vektor in Polarkoordinaten wie folgt erzeugen würden

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

Um das Zentrum würden mehr Punkte landen.

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

length ist nicht mehr gleichmäßig verteilt, der Vektor wird jetzt jedoch gleichmäßig verteilt.

0
Maik Klein

Ich bin mir immer noch nicht sicher, was genau '(2/R2) × r' ist, aber es ist offensichtlich, wie viele Punkte in der gegebenen Einheit 'dr' verteilt werden müssen, d. H. Die Erhöhung von r ist proportional zu r2 und nicht zu r. 

check this way ... Anzahl der Punkte in einem bestimmten Winkel zwischen Theta und zwischen r (0,1r bis 0,2r), dh der Bruchteil von r und die Anzahl der Punkte zwischen r (0,6r bis 0,7r) wäre gleich, wenn Sie die Standardgenerierung verwenden. da die Differenz zwischen zwei Intervallen nur 0,1r beträgt. Da jedoch die Fläche zwischen den Punkten (0,6r bis 0,7r) viel größer ist als die Fläche zwischen 0,1r und 0,2r, wird die gleiche Anzahl von Punkten in einem größeren Bereich spärlich beabstandet sein. Ich nehme an, Sie wissen bereits, also die Funktion Die Erzeugung der Zufallspunkte darf nicht linear, sondern quadratisch sein (da die Anzahl der Punkte, die in der gegebenen Einheit 'dr' verteilt werden müssen, dh die Erhöhung von r ist proportional zu r2 und nicht zu r), ist dies in diesem Fall umgekehrt quadratisch, da das Delta (0,1r) in beiden Intervallen quadratisch einer Funktion sein muss, damit es als Startwert für die lineare Erzeugung von Punkten fungieren kann (da diese Nachwörter in Sin- und Cos-Funktion linear verwendet werden), so wir Wissen Sie, dr muss ein quadratischer Wert sein, und um diesen Samen quadratisch zu machen, müssen wir diese Werte von der Quadratwurzel von r und nicht von r selbst ableiten. Ich hoffe, das macht es etwas klarer.

0
cheesefest

Ich weiß nicht, ob diese Frage noch offen ist für eine neue Lösung mit all der bereits gegebenen Antwort, aber ich hatte selbst genau dieselbe Frage. Ich habe versucht, mit mir eine Lösung zu finden, und ich habe eine gefunden. Es mag dasselbe sein, wie einige hier bereits vorgeschlagen haben, aber hier ist es trotzdem: 

damit zwei Elemente der Oberfläche des Kreises gleich groß sind, vorausgesetzt, dass gleich dr ist, müssen wir dtheta1/dtheta2 = r2/r1 haben. Schreibe den Ausdruck der Wahrscheinlichkeit für dieses Element als P (r, theta) = P {r1 <r1 + dr, theta1 <theta <theta + dtheta1} = f (r, theta) · dr * dtheta1 und setze die beiden Wahrscheinlichkeiten (für r1 und r2) gleich, erreichen wir (unter der Annahme, dass r und Theta unabhängig sind) f (r1)/r1 = f (r2)/r2 = konstant, was f(r) = c * r ergibt . Der Rest, der die Konstante c bestimmt, folgt aus der Bedingung, dass f(r) ein PDF ist.

0
arsaKasra

So ein lustiges Problem.
Der Grund für die Wahrscheinlichkeit, dass ein Punkt mit zunehmendem Abstand von der Ursprungsachse abgesenkt wird, wird oben mehrfach erläutert. Wir erklären das, indem wir die Wurzel von U [0,1] ..__ nehmen. Hier eine allgemeine Lösung für ein positives r 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])

 enter image description here

0
AChervony