安德烈斯算法 - 绘制圆形彩色渐变

Andres' algorithm - Draw a circular chromatic gradiation

我写了一个程序,它使用 Andres 算法绘制了一个彩色圆圈,这要归功于色阶。这是执行的结果:

现在我想改变这个层次。例如,我希望红色从圆圈的右侧开始。或者在 70°。等等

所以我有一个弧度偏移。我必须在我的 Andres 算法中使用它。 但我不明白如何。但是,我看到有两种方法可以做到这一点:

  1. 要么我改变了安德烈斯的算法,我的意思是我改变了每个八分圆的每个像素的坐标(=我改变了圆的绘图);
  2. 或者我真的改变了层次而不是绘图。

我更喜欢第一个解决方案。 而且我知道它将利用 三角函数。但是我的技术太差了,我真的需要你的帮助...

这是我的Andres实现的源码。如果你需要的话,我也可以给你看我的gradation-function的代码。提前谢谢你。

注意:最重要的部分就在 while (y >= x) 行下方(id est:八分圆的坐标)。

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]))); // 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])));

        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])));

        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]))); // 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]))); // 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])));

        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])));

        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]))); // 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;

在二维空间中,可以通过以下公式实现旋转:

x' = x cos f - y sin f

y' = y cos f + x sin f


无需在每个像素实例化中重复转换,您可以编写一个帮助程序来创建一个旋转像素并 returns 它。我的意思是:

Pixel rotated_pixel (double x, double y, Pixel rotation_center, Color color, double angle) {
    double x0 = rotation_center.x,
    y0 = rotation_center.y, // Oh god I hope I'm not also wrong about the field names now
    sinw = Math.sin(angle), cosw = Math.cos(angle),
    x_rot = x0 + (x-x0)*cosw - (y-y0)*sinw,
    y_rot = y0 + (y-y0)*cosw + (x-x0)*sinw;
    return new Pixel(x_rot, y_rot, color); // or smth
}

然后就可以像updates.add(rotated_pixel(x,y,whatever));

一样使用了

很抱歉,我无法检查此代码的有效性;我目前无法使用 Java.

的计算机

感谢@kubuzetto,下面的代码允许我绘制一个考虑到偏移的圆,以弧度表示。我的意思是它的绘图从某个角度开始(即偏移)。我还在用安德烈斯

这个解决方案唯一的新问题是当圆旋转时出现间隙(即:当有偏移时)。

确实: http://imgur.com/BcAsP9n

我以为是因为转换会降低坐标的精度,但事实并非如此。

如果有人看到为什么会出现这个问题就好了!

/**
 * 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 算法:

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;