Summary: Utilizzazione di array mono- e bi-dimensionali nella realizzazione di mappe per il controllo dell'interazione.
int, float,
ecc.). La numerazione, in Processing (e Java), parte da zero. La
dichiarazione e creazione di un array avviene in maniera uguale
a quella di un oggetto istanza di classe.
Ad esempio
float[] vettore = new float[100];
println(vettore);
crea un array di 100 elementi di tipo float e ne stampa il contenuto, che è inizialmente costituito da zeri.
L'array così dichiarato è a tutti gli effetti un oggetto istanza
di classe, e tale classe ha anche una variabile
length, che ne contiene la lunghezza. Quindi, per
inizializzare l'array come una rampa lineare che va da 0 a 1, si
può fare
for (int i = 0; i < vettore.length; i++)
vettore[i] = (float)i/vettore.length;
println(vettore);
(float) e si spieghi perché la rampa non viene più
generata.
int ris = 128;
int[] midimap = new int[128];
void setup() {
size(ris,2*ris);
}
void draw() {
background(255);
if ((mouseX >= 0) && (mouseX < ris))
if (!mousePressed)
background((256 - midimap[mouseX]));
else
midimap[mouseX] = mouseY;
for (int i=0; i<midimap.length; i++) point(i, midimap[i]);
}
Come si possono evitare i "buchi" nella mappa dovuti alla lettura non continua delle posizioni del mouse?
int sup_ris = 256;
int inf_ris = 128;
float[] midimap = new float[sup_ris];
void setup() {
size(inf_ris,inf_ris);
colorMode(RGB, 1.0);
for (int i = 0; i < midimap.length; i++) midimap[i] = sin(PI*(float)i/midimap.length);
}
void draw() {
if ((mouseX >= 0) && (mouseX < inf_ris) && (mousePressed))
{
point(mouseX, inf_ris - inf_ris*midimap[sup_ris/inf_ris*mouseX]);
}
}
int inf_ris = 128;
int sup_ris = 1024;
float[] midimap = new float[inf_ris];
void setup() {
size(sup_ris,32);
colorMode(RGB, 1.0);
for (int i = 0; i < midimap.length; i++) midimap[i] = sin(PI*(float)i/midimap.length);
}
void draw() {
if ((mouseX >= 0) && (mouseX < sup_ris) && (mousePressed))
background(midimap[int(float(mouseX)/sup_ris*inf_ris)]);
}
Come posso accedere alla tabella sfruttando per quanto possibile
l'accuratezza dei 10 bit? Si può fare una
interpolazione lineare. Il beneficio
dell'interpolazione diventa molto evidente nel passaggio da 10 a
3 bit, cioè ponendo inf_ris = 8. Con
l'interpolazione lineare, il metodo draw() va così
riscritto:
void draw() {
if ((mouseX >= 0) && (mouseX < sup_ris) && (mousePressed))
{
int flo = floor(float(mouseX)/sup_ris*inf_ris);
float alpha = float(mouseX)/sup_ris*inf_ris - float(flo);
background((1-alpha)*midimap[flo] + alpha*midimap[(flo+1)%midimap.length]);
}
}
alpha è il resto del troncamento a inf_res elementi. Quale è la funzione
dell'operazione di modulo %midimap.length?
int ris = 128;
float[] midimap = new float[ris];
float[] invmap = new float[ris];
void setup() {
size(ris,ris);
colorMode(RGB, 1.0);
/* inizializza */
for (int i = 0; i < midimap.length; i++) midimap[i] = (ris - 1) * sin(PI/2*(float)i/midimap.length);
/* inverti */
for (int i = 0; i < midimap.length; i++) invmap[round(midimap[i])] = i;
/* disegna */
for (int i = 0; i < midimap.length; i++)
{
point(i, ris - midimap[i]);
point(i, ris - invmap[i]);
}
println(invmap);
}
for (int i = 1; i < invmap.length-1; i++)
if (invmap[i] < 0.0001) // se buco, fai la media degli adiacenti
invmap[i] = (invmap[i-1] + invmap[i+1])/2; /* non funziona se i buchi sono fatti
da più zeri contigui */
println(invmap);
table, alle quale viene passato un nome e una
lunghezza. Tutti gli array sono memorizzati come numeri
floating point. Il contenuto degli array può essere
visualizzato in una finestra facendo "open" sull'oggetto
table. Ad esempio, se creo un oggetto con
table mappa 64, l'interprete costruisce un
subpatch contenente un array, il quale si può visualizzare
cliccando sull'oggetto stesso. Si può
accedere ad ogni singolo elemento dell'array con gli oggetti
tabread mappa e tabwrite mappa,
rispettivamente.
In più, gli array in Pd hanno metodi che supportano varie
operazioni. Ad esempio:
; mappa 4 -3 -2 -1 0 1 2
3;mappa si può rinominare map mediante il messaggio ; mappa rename map;; map bounds 0 -2 10 2; map xticks 0 0.1 5 nonché dei valori di riferimento con ; map xlabel -1.1 0 1 2 3 4 5int, float,
string, ecc.). In particolare, un array può essere
tipo base per un array, in questo modo consentendo di fare array
di array, o array bidimensionali.
Un array bidimensionale si dichiara e si istanzia con int[][] A = new int[ROWS][COLUMNS];dove
ROWS e COLUMNS conterranno i numeri
di righe e colonne che si vogliono riservare per l'array.
Ogni riga è essa stessa un array, al quale si può accedere con
A[i], mentre all'elemento di riga i
e colonna j si accede con A[i][j],
che in questo caso è una variabile di tipo int.
Questa volta A.length restituisce il numero di
righe dell'array, mentre il numero di colonne si può conoscere
con A[0].length.
int[][] A = { { 1, 0, 12, -1 },
{ 7, -3, 2, 5 },
{ -5, -2, 2, -9 }
};
for, così gli array
bidimensionali vengono scanditi con due cicli for
annidati, uno che scandisce le righe e uno che scandisce le
colonne:
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLUMNS; j++) {
A[i][j] = ...
}
}
Ad esempio, nel codice seguente viene inizializzato un array
bidimensionale di colori, e successivamente questa tavolozza
di colori viene visualizzata.
int ROWS = 4;
int COLUMNS = 4;
color[][] grid = new color[ROWS][COLUMNS];
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
grid[row][col] = color(row*60, 0, col*60);
}
}
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
fill(grid[row][col]);
rect(row*25, col*25, 25, 25);
}
}
int ROWS = 4;
int COLUMNS = 4;
color[][] grid = new color[ROWS][COLUMNS];
int step;
void setup(){
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
grid[row][col] = color(row*60, 0, col*60);
}
frameRate(5);
noStroke();
}
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
fill(grid[row][col]);
rect(row*25, col*25, 25, 25);
}
}
}
void draw(){
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLUMNS; col++) {
fill(grid[(row+step)%COLUMNS][col]);
rect(row*25, col*25, 25, 25);
}
}
step = (step+1)%COLUMNS;
}
float o
double sono utilizzati in moltissimi contesti, in
quanto sono di supporto alla Aritmetica delle Matrici. Questa
aritmetica consente di rappresentare ed effettuare in maniera
compatta operazioni su array di numeri. Ad esempio, per
invertire l'ordine dei numeri di un array di 4 elementi è
sufficiente pre-moltiplicarlo per una matrice
int DIM = 4;
float[][] myMatrix = {{0, 1, 0, 0},
{1, 0, 0, 0},
{0, 0, 0, 1},
{0, 0, 1, 0}
};
float[] myVector = {0.1, 0.2, 0.3, 0.4};
float[] newVector = new float[4];
for (int i=0; i<DIM; i++)
for (int j=0; j<DIM; j++)
newVector[i] += myMatrix[i][j] * myVector[j];
println(myVector); println();
println(newVector);
Matrix myMatrix = Matrix(0, 2, 1);Si può predisporre un array bidimensionale di bit 8x8 mediante istanziazione della classe Sprite:
Sprite wave = Sprite(
8, 8,
b10000000,
b10000000,
b01000010,
b01000010,
b00100100,
b00100100,
b00011000,
b00011000,
);
e scrivere una funzione da eseguirsi a clockrate
void loop()
{
myMatrix.write(i, 1, wave); // place sprite on screen (i is an int)
delay(1000); // wait a little bit
myMatrix.clear(); // clear the screen for next animation frame
i = 1 + (i+1)%8; // circular (between 1 and 8) increment of i
}
oppure, alternativamente, procedere direttamente alla scrittura ciclica
void loop()
{
myMatrix.clear(); // clear display
delay(1000);
// turn pixels on (i is an int that is forced to stay between 0 and 7)
// decreasing ramp
myMatrix.write(1, 1+(i)%8, HIGH);
myMatrix.write(2, 1+(i)%8, HIGH);
myMatrix.write(3, 1+(i+1)%8, HIGH);
myMatrix.write(4, 1+(i+1)%8, HIGH);
myMatrix.write(5, 1+(i+2)%8, HIGH);
myMatrix.write(6, 1+(i+2)%8, HIGH);
myMatrix.write(7, 1+(i+3)%8, HIGH);
myMatrix.write(8, 1+(i+3)%8, HIGH);
// increasing ramp
myMatrix.write(3, 1+(i+6)%8, HIGH);
myMatrix.write(4, 1+(i+6)%8, HIGH);
myMatrix.write(5, 1+(i+5)%8, HIGH);
myMatrix.write(6, 1+(i+5)%8, HIGH);
myMatrix.write(7, 1+(i+4)%8, HIGH);
myMatrix.write(8, 1+(i+4)%8, HIGH);
i++;
}
Comments, questions, feedback, criticisms?