Andres画的圆不够精准

Lack of precision in Andres drawn circle

我编写了一个小程序,使用 Andres 算法绘制圆形色阶。 这是执行的结果:

如果最终用户以弧度为单位给程序一个偏移,它将使用后者开始以此角度绘制圆。 因此,渐变将从这个角度开始(这就是我想要的)。

例如,您可以看到渐变从圆圈的底部开始,而不是在下图中的左侧。

但是如你所见,出现了两个问题:

  1. 首先,圆圈有些空隙;
  2. 那么,圆的周长就很不精确了。

我觉得是精度的问题。所以我问自己是不是有一些不好的演员表,但事实并非如此。 好吧,我不知道我的圈子如此不精确的原因是什么。你能帮帮我吗?

这里是绘制圆的每个像素的class。它采用指定的偏移,以弧度为单位。

/**
 * 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;
}

现在,绘制圆的代码,使用 Andres 算法和 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;

你不必 'rotate' 像素,你只需要绘制它们

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 提供圆的所有像素,不需要 translate/rotate 它们