Generate a random point within a circle (uniformly)

前端 未结 21 2319
逝去的感伤
逝去的感伤 2020-11-22 15:45

I need to generate a uniformly random point within a circle of radius R.

I realize that by just picking a uniformly random angle in the interval [0 ... 2π),

相关标签:
21条回答
  • 2020-11-22 16:25

    A programmer solution:

    • Create a bit map (a matrix of boolean values). It can be as large as you want.
    • Draw a circle in that bit map.
    • Create a lookup table of the circle's points.
    • Choose a random index in this lookup table.
    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];
    } // ()
    

    The bitmap is only necessary for the explanation of the logic. This is the code without the 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 讨论(0)
  • 2020-11-22 16:28

    I think that in this case using polar coordinates is a way of complicate the problem, it would be much easier if you pick random points into a square with sides of length 2R and then select the points (x,y) such that x^2+y^2<=R^2.

    0 讨论(0)
  • 2020-11-22 16:28

    1) Choose a random X between -1 and 1.

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

    2) Using the circle formula, calculate the maximum and minimum values of Y given that X and a radius of 1:

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

    3) Choose a random Y between those extremes:

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

    4) Incorporate your location and radius values in the final value:

    var finalX:Number = X * radius + pos.x;
    var finalY:Number = Y * radois + pos.y;
    
    0 讨论(0)
  • 2020-11-22 16:31

    Solution in Java and the distribution example (2000 points)

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

    based on previus solution https://stackoverflow.com/a/5838055/5224246 from @sigfpe

    0 讨论(0)
  • 2020-11-22 16:31

    First we generate a cdf[x] which is

    The probability that a point is less than distance x from the centre of the circle. Assume the circle has a radius of R.

    obviously if x is zero then cdf[0] = 0

    obviously if x is R then the cdf[R] = 1

    obviously if x = r then the cdf[r] = (Pi r^2)/(Pi R^2)

    This is because each "small area" on the circle has the same probability of being picked, So the probability is proportionally to the area in question. And the area given a distance x from the centre of the circle is Pi r^2

    so cdf[x] = x^2/R^2 because the Pi cancel each other out

    we have cdf[x]=x^2/R^2 where x goes from 0 to R

    So we solve for x

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

    We can now replace cdf with a random number from 0 to 1

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

    Finally

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

    we get the polar coordinates {0.601168 R, 311.915 deg}

    0 讨论(0)
  • 2020-11-22 16:33

    Here is a fast and simple solution.

    Pick two random numbers in the range (0, 1), namely a and b. If b < a, swap them. Your point is (b*R*cos(2*pi*a/b), b*R*sin(2*pi*a/b)).

    You can think about this solution as follows. If you took the circle, cut it, then straightened it out, you'd get a right-angled triangle. Scale that triangle down, and you'd have a triangle from (0, 0) to (1, 0) to (1, 1) and back again to (0, 0). All of these transformations change the density uniformly. What you've done is uniformly picked a random point in the triangle and reversed the process to get a point in the circle.

    0 讨论(0)
提交回复
热议问题