fast algorithm for drawing filled circles?

前端 未结 10 1153
清歌不尽
清歌不尽 2020-12-02 07:28

I am using Bresenham\'s circle algorithm for fast circle drawing. However, I also want to (at the request of the user) draw a filled circle.

Is there a fast and effi

10条回答
  •  借酒劲吻你
    2020-12-02 08:12

    palm3D's brute-force algorithm I found to be a good starting point. This method uses the same premise, however it includes a couple of ways to skip checking most of the pixels.

    First, here's the code:

    int largestX = circle.radius;
    for (int y = 0; y <= radius; ++y) {
        for (int x = largestX; x >= 0; --x) {
            if ((x * x) + (y * y) <= (circle.radius * circle.radius)) {
                drawLine(circle.center.x - x, circle.center.x + x, circle.center.y + y);
                drawLine(circle.center.x - x, circle.center.x + x, circle.center.y - y);
                largestX = x;
                break; // go to next y coordinate
            }
        }
    }
    

    Next, the explanation.

    The first thing to note is that if you find the minimum x coordinate that is within the circle for a given horizontal line, you immediately know the maximum x coordinate. This is due to the symmetry of the circle. If the minimum x coordinate is 10 pixels ahead of the left of the bounding box of the circle, then the maximum x is 10 pixels behind the right of the bounding box of the circle.

    The reason to iterate from high x values to low x values, is that the minimum x value will be found with less iterations. This is because the minimum x value is closer to the left of the bounding box than the centre x coordinate of the circle for most lines, due to the circle being curved outwards, as seen on this image The next thing to note is that since the circle is also symmetric vertically, each line you find gives you a free second line to draw, each time you find a line in the top half of the circle, you get one on the bottom half at the radius-y y coordinate. Therefore, when any line is found, two can be drawn and only the top half of the y values needs to be iterated over.

    The last thing to note is that is that if you start from a y value that is at the centre of the circle and then move towards the top for y, then the minimum x value for each next line must be closer to the centre x coordinate of the circle than the last line. This is also due to the circle curving closer towards the centre x value as you go up the circle. Here is a visual on how that is the case.

    In summary:

    1. If you find the minimum x coordinate of a line, you get the maximum x coordinate for free.
    2. Every line you find to draw on the top half of the circle gives you a line on the bottom half of the circle for free.
    3. Every minimum x coordinate has to be closer to the centre of the circle than the previous x coordinate for each line when iterating from the centre y coordinate to the top.

    You can also store the value of (radius * radius), and also (y * y) instead of calculating them multiple times.

提交回复
热议问题