Un array è una lista numerata di valori,
tutti dello stesso tipo (int, double,
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
double[] vettore = new double[100];
print(vettore);
double 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] = (double)i/vettore.length;
print(vettore);
Nota:
(double) e si spieghi perché la rampa non viene più
generata.Esempio 1: 1-to-1 mapping
Un MIDI controller continuo, come uno slider, può inviare valori tra 0 e 127, che possono essere usati come indici per leggere i valori di una certa proprietà. Un array può servire a mappare un controllo in un valore di proprietà. La relazione tra controllo (indice) e proprietà è una mappa uno a uno. Nel codice che segue, la mappa è costruita muovendo sopra alla finestra il mouse con tasto premuto. Invece, se il mouse viene spostato senza essere premuto, la posizione orizzontale del puntatore (tra 0 e 127) viene interpretata come indice della mappa, che restituisce il valore della proprietà di brillantezza dello sfondo.
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]);
}
Estensione di risoluzione
Ho un controllore MIDI (a 128 valori) e voglio scandire una tabella di 256 valori. Si può iterare la lettura avanzando il punto di lettura con passo 2.
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 < 128) && (mousePressed))
{
point(mouseX, inf_ris - inf_ris*midimap[sup_ris/inf_ris*mouseX]);
}
}
Riduzione di risoluzione
Ho un controllore a 10 bit (1024 valori) e devo mapparlo in una proprietà secondo una tabella di 128 valori che descrivono un semiperiodo di seno.
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)]);
}
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?
Inversione di una mappa
Ha senso costruire una mappa inversa, ad esempio per ritrovare l'indice a partire da un valore di proprietà, solo se la mappa di partenza è monotona, crescente o decrescente, in modo da stabilire una corrispondenza biunivoca tra indice e valore. Ad esempio, pre-caricando un array con un quarto di seno campionato in 128 punti, come costruisco un array che contiene la mappa inversa, cioè l'arcoseno?
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]);
}
print(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 */
print(invmap);
Mappe lineari
In molti casi i
sensori si comportano linearmente e ciò che serve è una mappa
lineare. In tal caso, non è necessario scomodare un array per
realizzarla. Ad esempio, si supponga che un sensore di
distanza restituisca un valore in metri che corrisponde alla
quantizzazione della distanza massima di 10 metri in 1024
valori (10 bit). Se con tale sensore vogliamo mappare diverse
posizioni da 1 a 3 metri in indici di pixel da 0 a 127, si può
semplicemente notare che la distanza di 1 metro produce il valore 102, mentre la distanza di 3 metri produce il valore 307. Detto
Istogrammi
Le operazioni che si basano sul conteggio di elementi vengono supportate bene da rappresentazioni mediante array. E' questo il caso della produzione dell'istogramma. In elaborazione di immagini questa è una operazione che si fa assai di frequente in quanto supporta diverse elaborazioni efficaci dei colori.
Lettura
Si legga il capitolo 10 di How to Think Like a Computer Scientist




