Salut !
Après le dégradé horizontal que vous m'avez aidé à construire, voici le cercle chromatique !
J'ai utilisé les mêmes équations pour déterminer la couleur, cette fois-ci en me basant sur des angles et non pas sur des abscisses.
Pour l'instant, je peux choisir le rayon du cercle ainsi que sa largeur. Voici par exemple un cercle de rayon 100px et de largeur 50px :
Les contours internes et externes du cercle sont abrupts, et ceci est dû à mon algorithme (pas au screenshot par exemple !).
Alors évidemment si j'ai créé ce topic c'est que j'ai une ou deux questions à vous poser !
Concernant l'algorithme actuel
-
Pour dessiner un cercle de largeur 2px, je dessine deux cercles de largeur 1px dont le rayon est de 1px pour le premier et de 2px pour le second, etc. : est-ce cool ou y a-t-il une manière plus commune et élégante de faire ça ?
-
Plus j'augmente la largeur, plus le rendu prend du temps à être dessiné : est-ce dû au point n°1 ?
Autres petites questions, générales
Comme je l'ai dit, j'utilise les mêmes équations que pour le dégradé horizontal et ça marche. J'en déduis que :
a. Les équations qui permettent d'obtenir un dégradé arc-en-ciel sont indépendantes de la forme de cet arc-en-ciel (ça paraît évident vu que ces équations sont juste ce qui lie deux couleurs entre elles : rouge et jaune sont liés par le fait que R = 255 tout en augmentant progressivement G, ces équations n'expriment rien d'autre).
b. Elles peuvent prendre comme paramètre des angles mais aussi des pixels (les abscisses du dégradé horizontal, c'est-à-dire non pas des angles mais des positions - je ne sais pas trop comment appeler ça). Est-ce exact ?
c. Conséquemment au point n°b, aurais-je pu selon vous dessiner mon cercle en utilisant non pas les angles mais les "positions/abscisses" comme j'ai fait pour le dégradé horizontal (histoire d'harmoniser la création du dégradé horizontal et celle du cercle) ? J'imagine qu'utiliser des angles pour le dégradé horizontal n'a pas de sens puisqu'un rectangle n'a pas d'angle…
d. Petite précision pour le point n°c : mon algo crée tout cercle en tant qu'une succession d'une multitude de points qui, s'ils sont suffisamment nombreux, donnent l'impression que cette forme discontinue est continue et que c'est donc un cercle fait d'une ligne. Donc le nombre de ces points est largement supérieur au périmètre du cercle. Enfin voilà j'ai l'impression que cette précision est pertinente mais peut-être que j'aurais pu ne pas vous le dire !
Amélioration à apporter
- Je souhaiterais pouvoir démarrer le dégradé à l'angle $\frac{3\pi}{2}$ (par exemple). Par définition du cercle chromatique, ce dégradé se finira également à cette angle (enfin à l'angle $\frac{7\pi}{2}$ du coup, puisqu'on fait un tour complet du cercle pour revenir à cet angle - j'ai donc ajouté ${2\pi}$). Pensez-vous que c'est possible sans trop changer mon algo actuel ? Vous auriez une piste ? ^^'
Voilà voilà !
Mon algorithme
Introduction : équation du tracé d'un cercle
J'utilise le plus simple : deux fonctions (une pour les abscisses, une pour les ordonnées) affines faisant usage des fonctions $cos$ et $sin$ appliquées à plein d'angles ($0$, $\frac{\pi}{2}$, $pi$, et plein d'autres) que je multiplie au rayon et que j'ajoute au centre du cercle.
Après avoir apporté l'amélioration dont je vous ai parlé un peu plus haut, je pense que je créerai une nouvelle version de mon algo, cette fois sans utiliser ces équations. A la place j'essaierai de mettre en place Bresenham.
Le source
Et bien sûr voici mon algo (n'hésitez pas à le critiquer !).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | public void displayCircle() { double pi = 3.14159; double ra = 100, x0 = 200, y0 = 300, x, y; double r, g , b; double custom_angle = 0; double w = 2*pi; for(double width = 0; width < 50; width++) { r = 0; g = 0; b = 0; for (double angle = custom_angle; angle <= w; angle += 0.00001) { x = (width + ra) * Math.cos(angle) + x0; y = (width + ra) * Math.sin(angle) + y0; if (angle >= 0 && angle < w / 6) { r = 255; g = 1530 * angle / w; } if (angle >= 0 && angle < 2 * w / 6) { b = 0; } if (angle >= 2 * w / 6 && angle < 3 * w / 6) { b = 1530 * angle / w - 510; } if (angle >= 3 * w / 6 && angle < 5 * w / 6) { b = 255; } if (angle >= 5 * w / 6 && angle <= w) { b = -1530 * angle / w + 1530; } if (angle >= w / 6 && angle < 3 * w / 6) { g = 255; } if (angle >= 3 * w / 6 && angle < 4 * w / 6) { g = -1530 * angle / w + 1020; } if (angle >= 4 * w / 6 && angle <= w) { g = 0; } if (angle >= w / 6 && angle < 2 * w / 6) { r = -1530 * angle / w + 510; } if (angle >= 2 * w / 6 && angle < 4 * w / 6) { r = 0; } if (angle >= 4 * w / 6 && angle < 5 * w / 6) { r = 1530 * angle / w - 1020; } if (angle >= 5 * w / 6 && angle <= w) { r = 255; } this.writable_pixel_writer.setColor((int) x, (int) y, Color.color(r / 255, g / 255, b / 255)); } } } |
Merci d'avance !