How to randomly but evenly distribute nodes on a plane

后端 未结 4 1660
闹比i
闹比i 2021-01-04 10:42

I need to place 1 to 100 nodes (actually 25px dots) on a html5 canvas. I need to make them look randomly distributed so using some kind of grid is out. I also need to ensure

相关标签:
4条回答
  • 2021-01-04 11:18

    What you are looking for is called a Poisson-disc distribution. It occurs in nature in the distribution of photoreceptor cells on your retina. There is a great article about this by Mike Bostock (StackOverflow profile) called Visualizing Algorithms. It has JavaScript demos and a lot of code to look at.

    In the interest of doing more then dropping a link into the answer, I will try to give a brief summary of the article:

    Mitchell's best-candidate algorithm

    A simple approximation known as Mitchell’s best-candidate algorithm. It is easy to implement both crowds some spaces and leaves gaps in other. The algorithm adds new points one at a time. For each new sample, the best-candidate algorithm generates a fixed number of candidates, say 10. The point furthest from any other point is added to the set and the process is repeated until the desired density is achieved.

    Bridson's Algorithm

    Bridson’s algorithm for Poisson-disc sampling (original paper pdf) scales linearly and is easy to implement as well. This algorithm grows from an initial point and (IMHO) is quite fun to watch (again see Mike Bostock's article). All points in the set are either active or inactive. all points are added as active. One point is chosen from the active set and some number of candidate points are generated in the annulus (a.k.a ring) that extends from the sample with the inner circle having a radius r and the outer circle having a radius 2r. Candidate sample less then r distance away from any point in the FinalSet are rejected. Once a sample is found that is not rejected it is added the the FinalSet. If all the candidate sample are rejected the original point is marked as inactive on the assumption that is has so many neighboring points that no more can be added around it. When all samples are inactive the algorithm terminates.

    A grid of size r/√2 can be used to greatly increase the speed of checking candidate points. Only one point may ever be in a grid square and only a limite number of adjsent squares need to be checked.

    0 讨论(0)
  • 2021-01-04 11:40

    I don't know if this is a named algorithm, but it sounds like you could assign each node a position on a “grid”, then pick a random offset. That would give the appearance of some chaos while still guaranteeing that there are no big empty spaces.

    For example:

    node.x = node.number / width + (Math.random() - 0.5) * SOME_SCALE;
    node.y = node.number % height + (Math.random() - 0.5) * SOME_SCALE;
    
    0 讨论(0)
  • 2021-01-04 11:40

    Maybe you could use a grid of circles and place one 25px-dot in every circle? Wouldn't really be random, but look good. Or you could place dots randomly and then make empty areas attract dots and give dots a limited-range-repulsion, but that is maybe too complicated and takes too much CPU time for this simple task.

    0 讨论(0)
  • 2021-01-04 11:43

    The easiest way would be to just generate random (x, y) coordinates for each one, repeating if they are touching or overlapping.

    Pseudocode:

    do N times
    {
    start:
      x = rand(0, width)
      y = rand(0, height)
      for each other point, p
        if distance(p.x, p.y, x, y) < radius * 2
          goto start
      add_point(x, y);
    }
    

    This is O(n^2), but if n is only going to be 100 then that's fine.

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