Paola Magillo, Univestita' di Genova, Corso di Interfacce Utente per Informatica, a.a. 2007-2008.

LABORATORIO - INTEGRAZIONE E AGGIUNTA ALL'ESERCIZIO SUL GRAFO

Integrazione: Zoom e traslazione del grafo

Nell'integrazione precedente abbiamo visto come trasportare il dominio del grafo nella finestra di visualizzazione (con alcune varianti).
Secondo la variante scelta, siano

le equazioni di questra trasformazione (dove x,y sono le coordinate di un nodo nel dominio e x_device,y_device le coordinate dello stesso nodo in pixel).

Zoom

Il testo chiede inoltre di eseguire lo zoom (scalatura) del grafo tenendo fermo il baricentro del grafo.
Se dovessimo eseguire solo questa trasformazione (dimenticando che dobbiamo anche trasportare in pixel), le equazioni sarebbero:

dove xC = x0+0.5*deltaX e yC = y0+0.5*deltaY sono le coordinate del baricentro del dominio e zoom e' il fattore di zoom corrente.

Dobbiamo combinare le due trasformazioni:

  1. prima eseguire lo zoom
  2. poi portare tutto in pixel
Percio' Si consiglia di organizzare il codice in maniera modulare con due funzioni distinte, corrispondenti ai due passaggi qui descritti.

Traslazione

La traslazione invece sposta l'immagine disegnata di un certo numero di pixel nella direzione prescelta.
Va fatta per ultima, sulle coordinate del nodo gia' tradotte in pixel, cioe'

Aggiunta: archi con spessore

L'obiettivo e' modificare l'esercizio sul grafo disegnando gli archi come linee o come poligoni con spessore, a seconda dello zoom.

Procederemo a tappe.

Tappa 1: leggere e memorizzare gli spessori

Nel nostro grafo ora ogni arco ha uno spessore. Lo spessore e' un numero intero che si suppone espresso nell'unita' di misura dello stesso sistema di riferimento del dominio del grafo.
Questo significa che lo spessore e' compatibile con le posizioni dei nodi e le lunghezze degli archi, non succedera' mai che due archi spessi si intersechino, se non nei pressi dell'eventuale estremo in comune.

Figura: grafo e lo stesso grafo dove gli archi sono disegnati con spessore. Gli archi verde e magenta hanno un tipo di intersezione non permessa nei nostri grafi.

Questo significa che:

  1. nel file di input oltre agli indici dei due estremi dell'arco c'e' un numero double che rappresenta lo spessore.
  2. nella vostra struttura dati dovete aggiungere un array per gli spessori degli archi
  3. nel disegnare, dovete tener conto dello spessore, lo faremo nella prossima tappa...

Esempi di grafi (gli stessi che nel testo originale) con spessore:

Tappa 2: disegnare con spessore

Un arco di estremi p1, p2 con spessore e' disegnato come un quadrilatero avente:

Per poter disegnare questo quadrilatero, dobbiamo calcolare le coordinate dei suoi 4 vertici.

I due vertici del segmento corto tangente a p1 [p2] sono dati da p1 [p2] traslato di piu o meno meta' spessore nella direzione della normale al segmento p1-p2.

La normale n = (nx,ny) al segmento p1-p2 si trova secondo la formula geometrtica:

Percio' i 4 vertici del quadrilatero sono:

Note utili

Il quadrilatero cosi' ottenuto (ovvero i suoi 4 vertici) e' espresso nel sistema di riferimento del dominio e dovra' essere poi trasformato nel sistema di riferimento della finestra grafica.

Il quadrilatero non ha i lati paralleti agli assi coordinati per cui non si puo' disegnare usando funzioni come drawRect.
Se fate le trasformazioni a mano, dopo aver ottenute le coordinate intere finali potete usare la funzione drawPolygon di Graphics
Se usate le trasformazioni affini di Graphics2D, dovete creare con i 4 punti un oggetto di classe GeneralPath (che implementa Shape) e poi disegnarlo con la funzione draw. Un general path gp funziona come una penna scrivente che si muove con comandi: muove la penna nel primo punto gp.lineto(x1,y1); traccia linea ai 3 punti seguenti gp.lineto(x2,y2); gp.lineto(x3,y3); gp.lineto(x4,y4); infine chiude ricollegando line al primo punto gp.closePath().

Tappa 2: adattare il disegno allo zoom corrente

Quando il grafo e' disegnato con un fattore di zoom molto piccolo, gli archi disegnati spessi possono intersecarsi in modo anomalo o comunque risultare troppo fitti e impedire di leggere il disegno.

Quando il fattore di zoom e' troppo piccolo, non disegnamo l'arco con spessore (quadrilatero) ma disegnamo l'arco senza spessore (segmento di retta).

Come decidere quando lo zoom e' troppo piccolo?
Un possibile modo e' questo.

  1. Calcolare i due estremi a,b di uno dei lati corti del quatrilatero
  2. Tradurre a,b in coordinate della finestra (che sono espresse in pixel)
  3. Guardare quanto sono distanti fra loro a,b in pixel
  4. Se sono piu' distanti di una soglia (es. 3 pixel) allora disegnare l'arco come quadrilatero, altrimenti disegnarlo come segmento di retta

Aggiornamento del disegno

Il disegno deve cambiare, per esempio, quando faccio zoom o traslazione. Intervengono due funzioni:

  1. la funzione di disegno paint / paintComponent del pannello che ospita il grafo
  2. la funzione del listener associato al dispositivo che esegue l'operazione di zoom / traslazione

La regola generale e':