JarsOfJam-Scheduler
JarsOfJam-Scheduler

Reputation: 3149

Lack of precision in Andres drawn circle

I wrote a little program which draws a circular chromatic gradation using Andres' algorithm. Here is the result of an execution :

enter image description here

If the final-user gives the program a shift, in radians, it will use the latter to begin the drawing of the circle at this angle. Thus, the gradation will begin at this angle (and that's what I want).

For example, you can see that the gradation begins at the bottom of the circle and not at its left in the following image.

enter image description here

But as you can see, two problems appear :

  1. First, there are some gaps in the circle ;
  2. Then, the circumference of the circle is quite imprecise.

I think it's a problem of precision. So I asked myself if there were some bad casts but it's not the case. Well, I don't know what is the reason why my circle is so imprecise. Could you help me please ?

Here is the class that draws each pixel of the circle. It takes on board the specified shift, in radians.

/**
 * Constructs a Pixel taking account of a shift and near the position (x0 ; y0)
 * @param x
 * @param y
 * @param color
 * @param angle
 * @param x0
 * @param y0
 */
Pixel(double x, double y, Color color, double angle, double x0, double y0) {
    this.x = (int) (x0 + (x-x0) * Math.cos(angle) - (y-y0) * Math.sin(angle));
    this.y = (int) (y0 + (y-y0) * Math.cos(angle) + (x-x0) * Math.sin(angle));
    this.color = color;
}

Now, the code that draws the circle, using Andres' algorithm and the Pixel class.

case "Andres' algorithm":
    w = 2 * Math.PI;

    for(double current_thickness = 0; current_thickness < this.thickness; current_thickness++) {
        x = 0;
        y = (int) (radius + current_thickness);
        double d = radius + current_thickness - 1;

        while (y >= x) {
            double octant_1_x = x0 + x, octant_1_y = y0 + y;
            double octant_2_x = x0 + y, octant_2_y = y0 + x;
            double octant_3_x = x0 - x, octant_3_y = y0 + y;
            double octant_4_x = x0 - y, octant_4_y = y0 + x;
            double octant_5_x = x0 + x, octant_5_y = y0 - y;
            double octant_6_x = x0 + y, octant_6_y = y0 - x;
            double octant_7_x = x0 - x, octant_7_y =  y0 - y;
            double octant_8_x = x0 - y, octant_8_y = y0 - x;

            max_counter++;

            double[] rgb_gradation_octant_1 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_1_y - y0, octant_1_x - x0) + Math.PI, w);
            updates.add(new Pixel(octant_1_x, octant_1_y,
                    Color.color(rgb_gradation_octant_1[0], rgb_gradation_octant_1[1], rgb_gradation_octant_1[2]),
                    circle_gradation_beginning, x0, y0)); // octant n°1

            double[] rgb_gradation_octant_2 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_2_y - y0, octant_2_x - x0) + Math.PI, w);
            updates.add(new Pixel(octant_2_x, octant_2_y,
                    Color.color(rgb_gradation_octant_2[0], rgb_gradation_octant_2[1], rgb_gradation_octant_2[2]),
                    circle_gradation_beginning, x0, y0));

            double[] rgb_gradation_octant_3 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_3_y - y0, octant_3_x - x0) + Math.PI, w);
            updates.add(new Pixel(octant_3_x, octant_3_y,
                    Color.color(rgb_gradation_octant_3[0], rgb_gradation_octant_3[1], rgb_gradation_octant_3[2]),
                    circle_gradation_beginning, x0, y0));

            double[] rgb_gradation_octant_4 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_4_y - y0, octant_4_x - x0) + Math.PI, w);
            updates.add(new Pixel(octant_4_x, octant_4_y,
                    Color.color(rgb_gradation_octant_4[0], rgb_gradation_octant_4[1], rgb_gradation_octant_4[2]),
                    circle_gradation_beginning, x0, y0)); // octant n°4

            double[] rgb_gradation_octant_5 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_5_y-y0, octant_5_x-x0) + Math.PI, w);
            updates.add(new Pixel(octant_5_x, octant_5_y,
                    Color.color(rgb_gradation_octant_5[0], rgb_gradation_octant_5[1], rgb_gradation_octant_5[2]),
                    circle_gradation_beginning, x0, y0)); // octant n°5

            double[] rgb_gradation_octant_6 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_6_y-y0, octant_6_x-x0) + Math.PI, w);
            updates.add(new Pixel(octant_6_x, octant_6_y,
                    Color.color(rgb_gradation_octant_6[0], rgb_gradation_octant_6[1], rgb_gradation_octant_6[2]),
                    circle_gradation_beginning, x0, y0));

            double[] rgb_gradation_octant_7 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_7_y-y0, octant_7_x-x0) + Math.PI, w);
            updates.add(new Pixel(octant_7_x, octant_7_y,
                    Color.color(rgb_gradation_octant_7[0], rgb_gradation_octant_7[1], rgb_gradation_octant_7[2]),
                    circle_gradation_beginning, x0, y0));

            double[] rgb_gradation_octant_8 = PhotoRetouchingFormulas.chromatic_gradation(Math.atan2(octant_8_y-y0, octant_8_x-x0) + Math.PI, w);
            updates.add(new Pixel(octant_8_x, octant_8_y,
                    Color.color(rgb_gradation_octant_8[0], rgb_gradation_octant_8[1], rgb_gradation_octant_8[2]),
                    circle_gradation_beginning, x0, y0)); // octant n°8

            if (d >= 2 * x) {
                d -= 2 * x + 1;
                x++;
            } else if (d < 2 * (radius + thickness - y)) {
                d += 2 * y - 1;
                y--;
            } else {
                d += 2 * (y - x - 1);
                y--;
                x++;
            }

        }
    }

    gui.getImageAnimation().setMax(max_counter*8);
    break;

Upvotes: 2

Views: 159

Answers (1)

Martin Frank
Martin Frank

Reputation: 3454

you don't have to 'rotate' the pixel, you just have to draw them

Pixel(double x, double y, Color color, double angle, double x0, double y0) {
    this.x = (int) (x + x0);
    this.y = (int) (y + y0);
    this.color = getColorForAngle(angle);
}

Bresenham / Andres provide all pixels of the circle, no need to translate/rotate them

Upvotes: 1

Related Questions