Space filling with circles of unequal size

后端 未结 3 443
臣服心动
臣服心动 2021-02-05 17:18

Here is my problem:

  • I have a bunch of circles that I need to display inside a canvas.
  • There are an arbitrary number of circles, each with a predefined ra
3条回答
  •  深忆病人
    2021-02-05 18:07

    I would try to insert sphere after sphere (largest first). Each one is added in the largest available space, with some random jitter.

    One relatively easy way to find (more or less) the largest available space, is to imagine a grid of points on your view and store for each grid point (in a 2D array) the closest distance to any item: edge or sphere, whichever is closest. This array is updated as each new sphere is added.

    To add a new sphere, just take the grid point with highest distance and apply some random jitter (you actually know how much you can jitter, because you know the distance to the closest item). (I would randomize not more than (d-r)/2 where d is the distance in the array and r is the radius of the sphere to add.

    Updating this array after adding another circle is no rocket science: you calculate for each grid point the distance to newly added sphere and replace the stored value if that was larger.

    It is possible that your grid is too coarse, and you can't add any more circle (when the 2D array contains no distances larger than the radius of the circle to add). Then you have to increase (e.g. double) the grid resolution before continuing.

    Here are some result of this implementation (it took me about 100 lines of code)

    • 100 Circles of varying size

    100 circles of varying size

    • 500 Circles of varying size

    500 circles of varying size

    • 100 Circles of same size

    enter image description here

    And here is some rough C++ code (just the algorithm, don't expect this to compile)

        // INITIALIZATION
    
        // Dimension of canvas
        float width = 768;
        float height = 1004;
    
        // The algorithm creates a grid on the canvas
        float gridSize=10;
    
        int gridColumns, gridRows;
        float *dist;
    
        void initDistances()
        {
          // Determine grid dimensions and allocate array
          gridColumns = width/gridSize;
          gridRows = height/gridSize;
    
          // We store a 2D array as a 1D array:
          dist = new float[ gridColumns * gridRows ];
    
          // Init dist array with shortest distances to the edges
          float y = gridSize/2.0;
          for (int row=0; rowdistanceFromLeft) dist[i] = distanceFromLeft;
              if (dist[i]>distanceFromRight) dist[i] = distanceFromRight;
            }
            x+=gridSize;
          }
        }
    
        void drawCircles()
        {
          for (int circle = 0; circled) dist[i] = d;
    
                // Optimized implementation (no unnecessary sqrt)
                float prev2 = dist[i]+radius;
                prev2 *= prev2;
                if (prev2 > d2)
                {
                  float d = sqrt(d2) - radius;
                  if (dist[i]>d) dist[i] = d;
                }
    
    
    
                xx += gridSize;
                i++;
              }
              yy += gridSize;
            }
          }
        }
    

提交回复
热议问题