Archivi tag: 2D Array

Array di pixel: loadPixels() e updatePixels()

Avevo parlato di pixel in uno dei primissimi post su Processing in questo blog. Grazie alle competenze che abbiamo acquisito nelle ultime settimane, possiamo fare un ulteriore passo in avanti.

Le funzioni che abbiamo usato fino a oggi ci hanno permesso di disegnare linee e forme sullo schermo o, come visto di recente, di mostrare un’immagine. Queste funzioni che, all’apparenza, sembrano eseguire operazioni molto semplici, in realtà nascondono un principio molto complesso: stabilire se ciascun pixel sullo schermo deve essere accesso o spento e, se acceso, il colore che deve rappresentare.

Array di pixel

Siamo abituati a pensare ai pixel come ad una griglia sullo schermo; quindi ad un array bidimensionale.

In Processing, però, il valore di ciascuno di essi viene salvato in un classico array monodimensionale.

È possibile accedere a queste informazioni e modificarle a nostro piacimento? Ovviamente si, utilizzando le funzioni loadPixels()updatePixels().

loadPixels() e updatePixels()

Con la prima funzione stiamo dicendo a Processing che intendiamo lavorare sull’array di pixel e che, quindi, deve caricarlo in una variabile. updatePixels(), invece, la usiamo quando abbiamo apportato tutte le modifiche e vogliamo che il programma aggiorni le informazioni sullo schermo.

Facciamo un esempio pratico:

/*
 * Array di pixel: loadPixels() e updatePixels()
 * Federico Pepe, 26.03.2017
 * http://blog.federicopepe.com/processing
 */

void setup() {
  size(500, 500);
  loadPixels();  
 
  for (int i = 0; i < pixels.length; i++) {
    float rand = random(255);
    color c = color(0, 0, rand);
    pixels[i] = c;
  }
  
  updatePixels();
}

In questo programma carichiamo tutti i valori di una finestra di 500x500 pixel. Con il ciclo for partiamo dal primo valore presente nel nostro array e arriviamo fino all'ultimo, identificato, per comodità, dalla funzione pixel.length e assegniamo a ciascuno un colore casuale float rand = random(255); nella scala dei blu color c = color(0, 0, rand);.

Assegniamo il nuovo colore al pixel pixels[i] = c; e, una volta usciti dal loop, chiediamo a Processing di aggiornare e mostrare tutte le modifiche che abbiamo effettuato updatePixels();.

Il risultato sarà il seguente:

Pixel Array Blu

Modificare un pixel conoscendone la posizione x e y

A questo punto, immagino, potrà esservi sorta spontaneamente una domanda: è possibile accedere a un determinato pixel conoscendone la posizione x e y all'interno della finestra come siamo stati abituati a fare fino a ora?

Riprendendo l'immagine della griglia più sopra, proviamo a capire come accedere al pixel 19: la sua posizione è x = 5, y = 2. A questo punto è importante ricordare che, per questi valori, partiamo a contare da 0 mentre, per la larghezza della finestra, da 1.

Ora dobbiamo sommare il valore di x al valore di y moltiplicato alla larghezza.

La formula è, dunque: x + (y * width)

5 + (2 * 7) = 19

I conti tornano!

Proviamo a modificare il codice di prima come segue:

/*
 * Array di pixel: loadPixels() e updatePixels()
 * Federico Pepe, 26.03.2017
 * http://blog.federicopepe.com/processing
 */

void setup() {
  size(500, 500);
  loadPixels();  
  color c;
  for (int x = 0; x < width; x++) {
    for (int y = 0; y < height; y++) {
      float rand = random(255);
      int pos = x + y * width;
      if(x % 2 == 0) {
        c = color(0, 0, rand);
      } else {
        c = color(rand, 0, 0);
      }
      pixels[pos] = c;
    }
  }
  
  updatePixels();
}

Zoomando l'immagine noterete che una riga è rossa e una riga è, invece, blu. Il prossimo passo sarà applicare quello che abbiamo appena imparato su un'immagine. Provate a pensare a tutte le operazioni che potremmo compiere andando a modificare individualmente ogni singolo pixel.

Array bidimensionali: esercizio alta difficoltà (soluzione)

Ecco la soluzione all’esercizio di difficoltà media proposto nell’articolo Array bidimensionali.

Esercizio

Partendo dalla soluzione all’esercizio di difficoltà media, sareste in grado di modificarlo ulteriormente per fare in modo che la griglia non sia necessariamente 8×8?

Continua la lettura di Array bidimensionali: esercizio alta difficoltà (soluzione)

Array bidimensionali: esercizio media difficoltà (soluzione)

Ecco la soluzione all’esercizio di difficoltà media proposto nell’articolo Array bidimensionali.

Esercizio:

Siete in grado di modificare lo script affinché, ad esempio, modificando i valori all’interno di size() mi venga disegnata sempre una scacchiera di 8×8 che occupi l’intera grandezza della finestra (anche quando non è quadrata)?

Continua la lettura di Array bidimensionali: esercizio media difficoltà (soluzione)

Array bidimensionali in Processing

In programmazione gli Array sono utili per archiviare in modo ordinato una serie di informazioni. Per chi avesse bisogno di un recap, questo è l’articolo in cui ho introdotto il concetto di array e il loro utilizzo in Processing.

A volte può capitare di avere a che fare con informazioni che non possono essere rappresentate in un’unica dimensione. Per questo motivo abbiamo bisogno di una struttura di dati multidimensionale: un array bidimensionale, ovvero un array di array, ci permette di lavorare con facilità su dati di questo tipo.

Per fare un esempio, proviamo a pensare di rappresentare i quadrati neri e bianchi di una scacchiera utilizzando il valore 0 per i primi e 1 per i secondi.

Partiamo da un array monodimensionale:

int[] scacchiera = { 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 };

Con questo array ho rappresentato tutti e 64 i tasselli ma non è chiara la struttura a righe e colonne tipica della scacchiera. Ecco che, invece, inserendo ciascuna riga in un array separato le cose migliorano sensibilmente:

int[][] scacchiera = { 
 {1, 0, 1, 0, 1, 0, 1, 0},
 {0, 1, 0, 1, 0, 1, 0, 1},
 {1, 0, 1, 0, 1, 0, 1, 0},
 {0, 1, 0, 1, 0, 1, 0, 1},
 {1, 0, 1, 0, 1, 0, 1, 0},
 {0, 1, 0, 1, 0, 1, 0, 1},
 {1, 0, 1, 0, 1, 0, 1, 0},
 {0, 1, 0, 1, 0, 1, 0, 1} };

Abbiamo costruito il nostro primo array bidimensionale.

Dichiarazione e inizializzazione

Le regole da rispettare in merito alla dichiarazione e inizializzazione dell’array bidimensionale rimangono identiche rispetto a quanto già visto in passato: è necessario indicare il tipo di dato, il nome dell’array ed è fondamentale stabilire una grandezza iniziale.

Sempre prendendo come riferimento l’esempio della scacchiera, inizializziamo l’array bidimensionale con 8 valori per le righe e 8 per le colonne:

int[][] scacchiera = new int[8][8];

Array bidimensionali e nested loop

I loop annidati sono il modo migliore per accedere a tutti i dati presenti in un array bidimensionale. Proviamo a disegnare la nostra scacchiera:

/*
 * Array bidimensionali e scacchi
 * Federico Pepe, 19.02.2017
 * http://blog.federicopepe.com/processing
*/

int[][] scacchiera = { 
  {1, 0, 1, 0, 1, 0, 1, 0}, 
  {0, 1, 0, 1, 0, 1, 0, 1}, 
  {1, 0, 1, 0, 1, 0, 1, 0}, 
  {0, 1, 0, 1, 0, 1, 0, 1}, 
  {1, 0, 1, 0, 1, 0, 1, 0}, 
  {0, 1, 0, 1, 0, 1, 0, 1}, 
  {1, 0, 1, 0, 1, 0, 1, 0}, 
  {0, 1, 0, 1, 0, 1, 0, 1} };

void setup() {
  size(480, 480);
  
  int rows = 8;
  int cols = 8;
  
  for (int i = 0; i < rows; i++) {
    for(int j = 0; j < cols; j++) {
      if(scacchiera[i][j] == 0) {
        fill(0);
      } else {
        fill(255);
      }
      rect(i*60, j*60, 60, 60);
    }
  }
}

void draw() {
}

All'inizio del programma troviamo l'array bidimensionale che contiene i valori su cui dobbiamo lavorare. All'interno della funzione setup() abbiamo impostato la grandezza della finestra e abbiamo creato due variabili per avere il numero di righe (rows) e il numero di colonne (cols).

Utilizzando due loop andiamo a vedere tutti i valori presenti all'interno dell'array: se il valore trovato è uguale a 0 la casella sarà nera, altrimenti bianca. Completiamo il programma andando effettivamente a disegnare la singola casella.

Esercizio di difficoltà media

In questo script ci sono diversi parametri "hard-coded". Siete in grado di modificare lo script affinché, ad esempio, modificando i valori all'interno di size() mi venga disegnata sempre una scacchiera di 8x8 che occupi l'intera grandezza della finestra (anche quando non è quadrata)?

Esercizio di difficoltà alta

Partendo dalla soluzione all'esercizio di difficoltà media, sareste in grado di modificarlo ulteriormente per fare in modo che la griglia non sia necessariamente 8x8?