Na última sessão, mais do que um estudante quiseram abordar o desenho do retrato generativo com algoritmo diferente: provocar uma espécie de “raiado” que vai do centro para fora da imagem.
Como o Processing desenha “por cima” o que desenha em último, este raiado tem que ser produzido de fora para dentro. E, como nós estamos a percorrer a imagem pixel-a-pixel e linha-a-linha por ordem as primeiras tentativas de percorrer a imagem geram um artefacto estranho quando se cruza “o meio” da imagem. Fica metade bem, e metade mal.
Assim, quase imediatamente, surgiu a ideia de fazer um algoritmo de espiral. Mas, o problema é como fazer isto com um sistema de regras simples (sem usar matrizes de dados / vetores bidimensionais)?
A solução que surge imediatamente no stackoverflow parece-me muito visual e adequada. Mas, o logo de imediato sugere o conceito de uma matriz de vetores bidimensionais:
A ideia está lá, de forma crua num par de soluções (de python e c++). Agora que as vejo depois de fazer a minha, apercebo-me de quão primitiva é a minha pilha condicional! 🙂
Mas pronto. Arregaçadas as mangas, e passado um pouco, consegui converter a decisão de percorrer uma imagem ou matriz de dados em espiral, de forma a obter uma rotação completa e evitar artefactos de simetria.
Ainda há aspetos a corrigir. Por exemplo, percorrer a imagem sem ser de forma simétrica a partir de qualquer ponto—na realidade era isso que queria, mas a dificuldade de fazer isto sem sem em active mode foi esmagadora da experiência. Por isso, fica aqui esta solução que já resolve (?) e no próximo módulo podemos atacar de novo o problema com matrizes como deve ser 😉
// Square spiral algorithm from Bruno B. (from T2) and… ??? from T1
// FBAUP/LSI/P1 Portrait idea/sketch base code
// PAmado, 2021-03-12
// declare variables
int ts; // tile size
int nh, nv; // number of horz. and vert. tiles
int iph, ipv; // initial positions
int counth, countv; // position counters
float col; // gradient color value
size(1000, 500);
background(255);
ts = 50; // size of tiles
nh = width/ts; // number of tiles on screen
nv = height/ts;
iph = 1; // initial tile position
ipv = 1;
counth = nh - iph; // number of tiles left in the row/column after the chosen position
countv = nv - ipv;
col = 255; // initial color value to draw a trail of tiles
textSize(ts*0.3); // debug tile numbers…
noStroke();
// set the tile board
for (int k = 0; k < nv; k++) {
for (int i = 0; i < nh; i++) {
stroke(0);
line(i*ts+ts, k*ts, i*ts, k*ts+ts);
noStroke();
fill(200);
rect(i*ts + ts*0.1, k*ts + ts*0.1, ts *0.8, ts *0.8);
}
}
noStroke();
// determine the total tiles available on the board
int total = (nv-ipv*2) * (nh-iph*2);
// draw a tile (set x and y of the tile in the initial position) <-- I didn't really have to do this… but it helps me think ;)
int x = iph;
int y = ipv;
// you will be placing the tile somewhere…
// take the initial position out of the counters of the remaining positions!…
counth--;
countv--;
// set an initial direction 1: right, 2: down, 3: left, 4: up…
int dir = 1;
int number = 1; // display a text counter for visual debug
// move it to a specific direction in a loop
// start in the initial position and loop for the rest of the available positions in the board
for (int i = 0; i < total; i++) {
// draw the tile
noStroke();
fill(col, 0, 0);
rect(x*ts + ts*0.2, y*ts + ts*0.2, ts*0.6, ts*0.6);
fill(255);
text(number, x*ts + ts*0.3, y*ts + ts*0.7);
// update the position
// if… go right
if (dir == 1) {
x++;
println("going right");
// check if at the end of horizontal space right
if (x > counth-1) {
dir = 2;
counth--;
println("changing dir down");
}
} else if (dir == 2) {
y++;
println("going down");
// check if at the end of vertical space down
if (y > countv-1) {
dir = 3;
countv--;
println("changing dir left");
}
} else if (dir == 3) {
x--;
println("going left");
// check if at the end of horizontal space left
if (x < nh-counth-1) {
dir = 4;
//counth--; // <-- I haven't checked for alternate starting directions other than right… you might need to do an aditional verification/boolean to make this bullet proof for eery starting direction…
println("changing dir up");
}
} else if (dir == 4) {
y--;
println("going up");
// check if at the end of vertical space up
if (y < nv-countv) {
dir = 1;
// counth--;
println("changing dir right");
}
}
// update the color
col -= 255/float(total) ;
// update the text number counter
number++;
println(number);
}