Lern-X Lern-X - 3 months ago 16
Java Question

Andres' algorithm - Draw a circular chromatic gradiation

I wrote a program which draws a circle colored thanks to a chromatic gradation, using the Andres' algorithm. Here is an execution's result :

Chromatic circular gradiation

Now I would want to shift this gradation. For example, I would want the red to begin at the right of the circle. Or at 70°. Etc.

So I have a shift, in radians. And I must use it in my Andres' algorithm.
But I don't understand how. However, I see two ways to do that :


  1. Either I change the Andres' algorithm, I mean I change the coordinates of each pixel of each octant (= I change the circle's drawing) ;

  2. Or I really shift the gradation and not the drawing.



I would prefer the solution number one. And I know it will make use of trigonometry. But my skills are too bad and I really need your help please...

Here is the source of my Andres' implementation. If you need it, I can also show you the code of my gradation-function. Thank you in advance.

NB : the most important part is just below the line
while (y >= x)
(id est : the octants' coordinates).


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;

Answer

In 2 dimensions, you can achieve rotation with the following formulas:

x' = x cos f - y sin f

y' = y cos f + x sin f


Instead of repeating the transformation in every Pixel instantiation, you could write a helper that creates a rotated pixel and returns it. I meant something like:

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
}

Then you can use it like updates.add(rotated_pixel(x,y,whatever));

I'm sorry that I cannot check the validity of this code; I don't currently have access to a computer with Java.