c++geometrygeometric-arcbresenham

c++ Bresenham's line algorithm draw arc and rotate


I'm searching way to make arc with Bresenham's line algorithm. This algoritm draw perfect circle, but what if i need draw arc (from 0 to Pi) and rotate it for 30 degrees (for example)?

void DrawCircle(HDC hdc,int x0, int y0, int radius) 
{
        int x = 0;
        int y = radius;
        int delta = 2 - 2 * radius;
        int error = 0;

        while(y >= 0) {
                //SetPixel(hdc,x0 + x, y0 + y,pencol);
                SetPixel(hdc,x0 + x, y0 - y,pencol);
                //SetPixel(hdc,x0 - x, y0 + y,pencol);
                SetPixel(hdc,x0 - x, y0 - y,pencol);
                error = 2 * (delta + y) - 1;
                if(delta < 0 && error <= 0) {
                        ++x;
                        delta += 2 * x + 1;
                        continue;
                }
                error = 2 * (delta - x) - 1;
                if(delta > 0 && error > 0) {
                        --y;
                        delta += 1 - 2 * y;
                        continue;
                }
                ++x;
                delta += 2 * (x - y);
                --y;
        }
}

Solution

  • To get 1/2 a circle (to pi), only call one of your SetPixel routines. To have your arc rotated 30 degrees requires some trig. You could let the above loop run until your x/y ratio is equal to tan(30 degrees), then start actually drawing until your ratio hits the value at which you want to stop. Not the most efficient way, but it will work. To get it better, you'd need to pre-calculate your starting 4 var values. You could take the values from the above run and plug them in as starting values and that would be very efficient.

    Did you get the above algorithm from Michael Abrash's Black Book stuff? If not, I'd google for that as a second point of reference on fast circle/arc drawing.

    Well, alas, the ellipses that rip chapter wasn't included in there. Here's something I found on the web that claims to be from Abrash:

    
    /* One of Abrash's ellipse algorithms  */
    
    void draw_ellipse(int x, int y, int a, int b, int color)
    {
        int wx, wy;
        int thresh;
        int asq = a * a;
        int bsq = b * b;
        int xa, ya;
    
        draw_pixel(x, y+b, color);
        draw_pixel(x, y-b, color);
    
        wx = 0;
        wy = b;
        xa = 0;
        ya = asq * 2 * b;
        thresh = asq / 4 - asq * b;
    
        for (;;) {
            thresh += xa + bsq;
    
            if (thresh >= 0) {
                ya -= asq * 2;
                thresh -= ya;
                wy--;
            }
    
            xa += bsq * 2;
            wx++;
    
            if (xa >= ya)
              break;
    
    
            draw_pixel(x+wx, y-wy, color);
            draw_pixel(x-wx, y-wy, color);
            draw_pixel(x+wx, y+wy, color);
            draw_pixel(x-wx, y+wy, color);
        }
    
        draw_pixel(x+a, y, color);
        draw_pixel(x-a, y, color);
    
        wx = a;
        wy = 0;
        xa = bsq * 2 * a;
    
        ya = 0;
        thresh = bsq / 4 - bsq * a;
    
        for (;;) {
            thresh += ya + asq;
    
            if (thresh >= 0) {
                xa -= bsq * 2;
                thresh = thresh - xa;
                wx--;
            }
    
            ya += asq * 2;
            wy++;
    
            if (ya > xa)
              break;
    
            draw_pixel(x+wx, y-wy, color);
            draw_pixel(x-wx, y-wy, color);
            draw_pixel(x+wx, y+wy, color);
            draw_pixel(x-wx, y+wy, color);
        }
    }
    

    The idea being you draw an 8th of the circle at a time x4 and then flip to get the other 8ths drawn. Still doesn't directly answer your question though. Working on that...

    Again, your code above should work, you just need to control the starting and ending conditions carefully. The y >= 0 needs to become whatever the y would be upon finishing your 'arc' length and the starting values need to be calculated to be the start of your arc.

    This will not be a straight forward task with things as they are. Might just be easier to use a floating point routine instead. The math is much more straight forward and processors tend to handle them better now than when these integer routines were crafted.