Mokabyte

Dal 1996, architetture, metodologie, sviluppo software

  • Argomenti
    • Programmazione & Linguaggi
      • Java
      • DataBase & elaborazione dei dati
      • Frameworks & Tools
      • Processi di sviluppo
    • Architetture dei sistemi
      • Sicurezza informatica
      • DevOps
    • Project Management
      • Organizzazione aziendale
      • HR
      • Soft skills
    • Lean/Agile
      • Scrum
      • Teoria della complessità
      • Apprendimento & Serious Gaming
    • Internet & Digital
      • Cultura & Società
      • Conferenze & Reportage
      • Marketing & eCommerce
    • Hardware & Tecnologia
      • Intelligenza artificiale
      • UX design & Grafica
  • Ultimo numero
  • Archivio
    • Archivio dal 2006 ad oggi
    • Il primo sito web – 1996-2005
  • Chi siamo
  • Ventennale
  • Libri
  • Contatti
Menu
  • Argomenti
    • Programmazione & Linguaggi
      • Java
      • DataBase & elaborazione dei dati
      • Frameworks & Tools
      • Processi di sviluppo
    • Architetture dei sistemi
      • Sicurezza informatica
      • DevOps
    • Project Management
      • Organizzazione aziendale
      • HR
      • Soft skills
    • Lean/Agile
      • Scrum
      • Teoria della complessità
      • Apprendimento & Serious Gaming
    • Internet & Digital
      • Cultura & Società
      • Conferenze & Reportage
      • Marketing & eCommerce
    • Hardware & Tecnologia
      • Intelligenza artificiale
      • UX design & Grafica
  • Ultimo numero
  • Archivio
    • Archivio dal 2006 ad oggi
    • Il primo sito web – 1996-2005
  • Chi siamo
  • Ventennale
  • Libri
  • Contatti
Cerca
Chiudi

Nel numero:

129 maggio
, anno 2008

Processing e visualizzazione

II parte: Le primitive grafiche

Avatar

Simone Chiaretta

Software Architect e sviluppatore, Simone ha esperienza decennale nello sviluppo di appicazioni web based (sette anni con ASP.NET). Vive a Milano dove lavora come "Senior Solution Developer" per Avanade. Ha partecipato a numerosi progetti Open Source, sia Java che .NET, ma attualmente si sta concentrando principalmente su SubText per aiutarlo a fare un salto di qualità.

MokaByte

Processing e visualizzazione

II parte: Le primitive grafiche

Simone Chiaretta

Simone Chiaretta

  • Questo articolo parla di: Programmazione & Linguaggi, UX design & Grafica

Il mese scorso abbiamo introdotto Processing, una libreria per realizzare animazioni e visualizzazioni di dati senza dover andare a usare direttamente le funzionalità grafiche di Java. Questo mese vedremo come disegnare con Processing sia in 2D che in 3D.

Elementi Base

Coordinate

Guardiamo come è organizzato lo spazio in Processing partendo dalle coordinate [1].

Figura 1 – Sistema di coordinate 3D in Processing

 

Processing usa un sistema di coordinate cartesiano con l’origine posizionato in alto a sinistra. Nel caso di immagini 2D viene usato solo il piano X-Y, ipotizzando quindi la coordinata Z sempre pari 0.
La funzione size() definisce, oltre che la dimensione dello sketch, anche il rendering engine da usare per disegnare sullo schermo. Si può scegliere tra:

  • P2D (Processing 2D): Un rendering engine 2D proprietario, veloce che produce immagini di minore qualità (ma non ancora implementato)
  • JAVA2D: Il rendering engine di default, che utilizza le API grafiche Java 2D
  • P3D (Processing 3D): Rendering engine veloce e ottimizzato per le animazioni 3D per il web. Sacrifica la qualità per una maggior velocità e minor utilizzo di risorse macchina
  • OPENGL: Si interfaccia con schede grafiche OpenGL per aumentare la velocità del rendering 3D
//Definisce un schermo di 200x200 con rendering engine 3D
size(200, 200, P3D)

Colori

Prima di parlare delle primitive grafiche, un altro elemento importante da analizzare è il colore.
Processing può utilizzare sia il formato RGB che quello HSB e in entrambi i casi i colori possono essere definiti sia specificando una tripletta di valori che specificando direttamente la stringa col valore esadecimale. È inoltre possibile specificare un valore per la trasparenza (alpha channel).

Figura 2 – Esempio di colori con alpha channel

 

colorMode(RGB);
color c1 = color(70,137,102);
color c2 = color(#FFF0A5);
colorMode(HSB,360,100,100);
color c5 = color(17, 100, 56, 125); // H, S, B, A

Primitive Grafiche

Passiamo ora ad analizzare gli elementi costruttivi base per disegnare con Processing, partendo da quelli a zero dimensioni, ossia i punti.

Punti (0D)

L’elemento grafico indispensabile per disegnare qualsiasi oggetto è il punto.
Per disegnare un punto si usa il metodo point(). Chiamato con due parametri disegna un punto nello spazio 2D; se chiamato con 3 parametri nello spazio 3D.
Come per tutti gli elementi grafici 2D, è possibile impostare lo spessore e il colore della linea con strokeWeight() e stroke().
Ad esempio:

stroke(180,0,0);
strokeWeight(20);
point(60,60);

disegna un punto rosso da 20 px di diametro.

Figura 3 – Punto rosso

 

Primitive lineari (1D)

Linee rette. Con il comando line() è possibile disegnare una linea tra due punti, sia nello spazio 2D che nello spazio 3D. Anche in questo caso, come per il punto, è possibile definire il colore e lo spessore della linea.

line(20, 20, 100, 100); //x1,y1, x2, y2

 

Linee Curve. In Processing è possibile disegnare due tipologie di linee curve: spline di Catmull-Rom e curve di Bezier [3].

In entrambi i casi, le funzioni per disegnarle accettano 4 punti come parametri:

Curve, disegna una spline: il secondo ed il terzo punto sono i punti d’inizio e fine, mentre il primo e l’ultimo sono punti di controllo. La curva passa per tutti e 4 i punti, ma viene disegnata solo tra il secondo ed il terzo.

curve(5, 26, 73, 24, 73, 61, 15, 80);

 

Figura 4 – Spline e i suoi punti di controllo

Bezier, per la curva di bezier, al contrario, il primo e l’ultimo sono l’inizio e la fine della curva mentre, il secondo e il terzo sono punti di controllo, ossia i punti finali delle linee tangenti all’inizio e alla fine della curva.

bezier(85, 20, 10, 10, 90, 90, 15, 80);

 

 Figura 5 – Curva bezier e sue tangenti

In entrambi i casi per avere curve più lunghe e con maggiori punti di controllo bisogna usare una serie di chiamate ai metodi curveVertex() e bezierVertex() racchiuse nel blocco beginShape()/endShape().

beginShape();
curveVertex(5,195);
curveVertex(84,91);
curveVertex(68,19);
curveVertex(21,17);
curveVertex(32,100);
curveVertex(150,100);
endShape();

Primitive 2D

Triangoli. Il triangolo è l’elemento costruttivo base nella grafica 3D e viene usato per simulare le superfici continue (mesh). Per questa ragione in Processing esiste una funzione che permette di disegnare con una sola istruzione un triangolo, senza doverlo costruire come sequenza di linee rette (ovvero come un poligono generico).

triangle(10,10,30,70,80,80); //i tre vertici del triangolo

Quadrilateri. Processing ha due funzioni per disegnare delle figure geometriche a 4 lati:

  • rect() che disegna un quadrilatero regolare accettando come parametri il vertice in alto a sinistra, l’altezza e la larghezza;
  • quad() che invece disegna una quadrilatero irregolare, definendo singolarmente i 4 vertici.

Per lasciare maggiore flessibilità è possibile cambiare il significato dei parametri della funzione rect() con il metodo rectMode().

//comportamento di default
rectMode(CORNER);
//il punto specificato è il centro del rettangolo e non il vertice
rectMode(CENTER);
//altezza e larghezza diventano la posizione del vertice in basso a destra
rectMode(CORNERS);

 

 Figura 6 – Rettangoli disegnati coi vari mode


Poligoni
. Lo abbiamo già visto parlando delle curve: includendo una serie di vertici nel blocco beginShape()/endShape() è possibile fare poligoni di un numero arbitrario di lati.

beginShape(POLYGON);
vertex(30, 20);
vertex(35, 15);
vertex(40, 25);
vertex(35, 30);
vertex(30, 27);
endShape(CLOSE);

 

Figure curve. La funzione per creare cerchi o ellissi è ellipse().

Il suo funzionamento è identico a quello dalla funzione rect(), con la differenza che invece che disegnare un quadrilatero, disegna una ellisse inscritta.
Anche in questo caso è possibile modificare il significato dei parametri della funzione con ellipseMode().

Figura 7 – Ellissi disegnate coi vari mode

 

Primitive 3D

In Processing esistono solo due primitive strettamente 3D: sfere e cubi.
La funzione box() crea un cubo quando invocata con un solo parametro, mentre crea un parallelepipedo quando chiamata con le tre dimensioni.
La funzione sphere() disegna un una sfera del raggio specificato. È possibile modificare la qualità della sfera disegnata cambiando il numero di vertici con il metodo sphereDetail().

Figura 8 – Cubi e sfere

 

Trasformazioni di coordinate

Le trasformazioni di coordinate consentono di spostare l’origine degli assi o di ruotarli.
Abbiamo 3 funzioni per farlo:

  1. rotateX(): ruota la vista corrente attorno all’asse X e intorno all’origine degli assi (lo stesso vale per rotateY() e rotateZ()). In uno scena 2D l’unica rotazione possibile è attorno all’asse Z, ma per evitare confusione esiste la funzione rotate() che funziona solo in 2D. Il parametro è l’angolo di rotazione in radianti.
  2. translate(): trasla gli assi del valore specificato dai parametri (x e y nel 2D, x, y e z nel 3D)
  3. scale(): aumenta o diminusce la dimensione degli oggetti. Per esempio scale(2.0) raddoppia le dimensioni di tutti gli oggetti.

Un comportamento comune a tutte le funzioni di trasformazione è che sono additive, cioè il loro effetto si somma. Ogni chiamata modifica la matrice di trasformazione [4] usata da Processing per calcolare la posizione di tutti i vertici disegnati sulla scena.

translate(50, 20);
translate(20, 20);
//equivale a
translate(70, 40);

Ultimo concetto da comprendere è lo stack delle trasformazioni: come ho detto poche righe fa, ogni volta che è chiamata una funzione di trasformazione la matrice viene cambiata. Come posso fare quindi a ruotare un figura in un verso e un’altra nel verso opposto? Potrei fare due rotazioni opposte, con la seconda di un angolo equivalente alla prima più l’effettiva rotazione del secondo oggetto. Questa soluzione va bene in casi semplici, ma in casi più complessi diventa difficile tenere traccia di tutte le trasformazioni fatte per poi poterle annullare.
Processing ci viene in aiuto con le funzioni pushMatrix() e popMatrix(): queste servono per “salvare” il sistema di coordinate correnti e, in seguito, per recuperarlo.
Usando queste funzioni, per risolvere il problema di prima, basta chiamare la funzione pushMatrix() prima di ruotare il primo oggetto, e poi chiamare la funzione popMatrix() per tornare al sistema di coordinate precedente.

Conclusioni

In questo secondo articolo delle serie “Processing e visualizzazione” abbiamo esaminato nel dettaglio tutti gli elementi base per creare composizioni grafiche.
Il prossimo mese analizzeremo le librerie che estendono Processing e gli permettono di interagire con la rete, con il video, con la webcam e l’audio.

Riferimenti

[1] D. Rocchesso P. Polotti, “Media Representation in Processing”, Connexions, 17 Oct. 2006
http://cnx.org/content/m12983/1.6/

[2] Wikipedia: “Cubic Hermite spline – Catmull-Rom spline”
http://en.wikipedia.org/wiki/Catmull-Rom_spline#Catmull.E2.80.93Rom_spline

[3] Wikipedia: “Curva Bezier”
http://it.wikipedia.org/wiki/Curva_Bezier

[4] Wikipedia: “Matrice di trasformazione”
http://it.wikipedia.org/wiki/Matrice_di_trasformazione

 

Facebook
Twitter
LinkedIn
Avatar

Simone Chiaretta

Software Architect e sviluppatore, Simone ha esperienza decennale nello sviluppo di appicazioni web based (sette anni con ASP.NET). Vive a Milano dove lavora come "Senior Solution Developer" per Avanade. Ha partecipato a numerosi progetti Open Source, sia Java che .NET, ma attualmente si sta concentrando principalmente su SubText per aiutarlo a fare un salto di qualità.

Simone Chiaretta

Simone Chiaretta

Software Architect e sviluppatore, Simone ha esperienza decennale nello sviluppo di appicazioni web based (sette anni con ASP.NET). Vive a Milano dove lavora come "Senior Solution Developer" per Avanade. Ha partecipato a numerosi progetti Open Source, sia Java che .NET, ma attualmente si sta concentrando principalmente su SubText per aiutarlo a fare un salto di qualità.
Tutti gli articoli
Nello stesso numero
Loading...

Stime e pianificazione agile

Il progetto in corso d‘opera

Ruby in azione

III parte: Deployment di applicazioni Rails con JRuby

BPEL: Business Process Execution Language

III parte: Gestione di processi complessi

Programmare con Ajax

IV parte: Ajax e Rails, integrazione e caratteristiche

Nella stessa serie
Loading...

Processing e visualizzazione

IV parte: Visualizzazione

Processing e visualizzazione

III parte: Oltre la grafica - le librerie esterne

Processing e visualizzazione

I parte: Panoramica e introduzione

Mokabyte

MokaByte è una rivista online nata nel 1996, dedicata alla comunità degli sviluppatori java.
La rivista tratta di vari argomenti, tra cui architetture enterprise e integrazione, metodologie di sviluppo lean/agile e aspetti sociali e culturali del web.

Imola Informatica

MokaByte è un marchio registrato da:
Imola Informatica S.P.A.
Via Selice 66/a 40026 Imola (BO)
C.F. e Iscriz. Registro imprese BO 03351570373
P.I. 00614381200
Cap. Soc. euro 100.000,00 i.v.

Privacy | Cookie Policy

Contatti

Contattaci tramite la nostra pagina contatti, oppure scrivendo a redazione@mokabyte.it

Seguici sui social

Facebook Linkedin Rss
Imola Informatica
Mokabyte