Introduzione | Cap.1 | Cap.2 | Cap.3 | Cap.4 | Cap.5 | Appendice | Bibliografia
Per verificare la possibilita' di implementare in parallelo gli algoritmi per il tracciamento di linee di livello e studiarne le prestazioni e' stato realizzato dall' autore un programma che implementa le idee esposte nei paragrafi precedenti. Piu' precisamente il programma implementa un algoritmo cellulare, per dati distribuiti ai nodi di una matrice rettangolare, usando come funzioni locali piani che approssimano il comportamento della superficie. L' equazione analitica di questi ultimi non viene determinata dal momento che sono necessarie soltanto le posizioni dei punti in cui questi intesecano le linee di livello sui lati del rettangolo. E' sufficiente quindi determinare l'equazione della retta che passa per gli estremi di ciascun lato e da questa stimare la posizione in cui la linea di livello interseca il lato.
Segue il listato commentato del programma.
dichiarazione dei sottoprogrammi (Sub) e delle funzione (Function) utlizzate.
DECLARE SUB legenda (n%, c!())
DECLARE SUB lato (i%, j%, m%, n%, c!, x!, y!, flag%)
DECLARE SUB rettangolo (i%, j%, c(), col%(), numlin%)
DECLARE FUNCTION funz! (x!, y!)
DECLARE FUNCTION interp (x1, z1, x2, z2, c)
dimensionamento delle matrici e dei vettori.
grid e' la matrice bidimensionale che contiene i dati della superficie da interpolare
xdim,ydim indicano il numero di righe e colonne della matrice grid.
col il vettore che rappresenta i colori da assegnare alle linee di livello.Esso viene condiviso (Shared) dalla routine principale e dalla sub Legenda.
c e' il vettore che contiene le linee di livello.
DIM grid(100, 100), xdim AS INTEGER, ydim AS INTEGER
DIM xdim1 AS INTEGER, ydim1 AS INTEGER
DIM SHARED col(1 TO 15) AS INTEGER, c(1 TO 14)
Sezione di input.Viene chiesto all' utente il dominio su cui campionare
la funzione, il numero delle linee di livello ed i loro valori.
Viene eseguito un controllo sui dati immessi per evitare errori.
CLS
PRINT "dominio in cui campionare la funzione:"
INPUT "intervallo delle ascisse (a,b) "; xx, xx1
INPUT "intervallo delle ordinate (c,d)"; yy1, yy
IF xx >= xx1 OR yy1 >= yy THEN RUN
INPUT "num. punti sulle x"; xdim
INPUT "num.punti sulle y"; ydim
INPUT "numero di linee di livello (max 14)"; numlin%
PRINT "vettore delle linee di livello"
FOR i% = 1 TO numlin%
INPUT c(i%)
NEXT i%
SCREEN 12
hx e hy contengono le misure dei lati dei rettangoli della reticolazione
hx = (xx1 - xx) / (xdim - 1)
hy = (yy1 - yy) / (ydim - 1)
gridcol% = 15
definizione delle variabili per l'ingrandimento opportuno del
grafico e per la sua centratura sullo schermo
zoomx = 300 / ABS(xx1 - xx)
zoomy = 300 / ABS(yy1 - yy)
specular = 240 + (yy - (ABS(yy1 - yy) / 2)) * zoomy
specularx = 320 - (xx + (ABS(xx1 - xx) / 2)) * zoomx
definizione di un vettore per i colori delle linee di livello
e costruzione della legenda
CALL legenda(numlin%, c())
costruisce una reticolazione del dominio in base ai dati forniti.
I valori ai nodi della griglia sono forniti dalla funzione FUNZ
ydim1 = ydim - 1
xdim1 = xdim - 1
FOR j% = 0 TO ydim1
y = yy + hy * j%
FOR i% = 0 TO xdim1
x = xx + hx * i%
grid(j%, i%) = funz(x, y)
NEXT i%
NEXT j%
traccia il bordo del grafico
LINE (xx * zoomx + specularx, specular - yy * zoomy)-((xx + (xdim
- 1) * hx) * zoomx + specularx, speculaar - ((yy + (xdim - 1) *
hy) * zoomy)), gridcol%, B
GOTO 20 ' togli questa riga se vuoi anche la griglia
disegna la griglia sullo schermo:
assi orizzontali
FOR j% = 0 TO ydim - 1
LINE (xx * zoomx + specularx, specular - ((yy + j% * hy) * zoomy))-(xx1 * zoomx +specularx, specular - ((yy + j% * hy) * zoomy)), gridcol%, , 4681
NEXT j%
e verticali
FOR i% = 0 TO xdim - 1
LINE ((xx + i% * hx) * zoomx + specularx, specular - yy * zoomy)-((xx + i% * hx) * zoomx + specularx, specular - (yy1 * zoomy)), gridcol%, , 4681
NEXT i%
20
e finalmente si processano uno alla volta tutti i rettangolini
che formano la griglia
FOR i% = 0 TO ydim - 2
FOR j% = 0 TO xdim - 2
CALL rettangolo((i%), (j%), c(), col%(), numlin%)
NEXT j%
NEXT i%
END
questa e' la definizione della funzione utilizzata per la costruzione
della griglia. Sono comprese come commenti alcune funzioni da
utilizzare per il test del programma.
FUNCTION funz (x, y)
' funz = x + y
' funz = 3 / 2 * (COS(3 / 5 * (y - 1)) + 5 / 4) / (1 + ((x - 4) / 3) ^ 2)
' funz = ABS(x + y)
funz = SIN(x ^ 2) + COS(y ^ 2) + SIN(x)
' funz = TAN(y - x) + 1
' funz = 8 / 3.14 * EXP(-8 * (x * x + y * y))
' funz = 9 * (3 / 4 * EXP(-(x - 3) ^ 2 - (y - 3) ^ 2) / 4) + EXP(-(x / 7) ^ 2 - (y / 10) - 1 / 5 * EXP(-(x - 5) ^ 2 - (y - 8) ^ 2) + 1 / 2 *
EXP((-(x - 8) ^ 2 - (y - 4) ^ 2) / 4))
END FUNCTION
questa function calcola per interpolazione lineare l'ascissa
del punto di ordinata c (linea di livello). I parametri di input
sono le ascisse dei punti (x1 e x2) ,le loro ordinate (z1 e z2)
e la quota della linea di livello. L' output e' la posizione del
punto rispetto ad un sistema di riferimento con origine in x1
in cui ,secondo l'interpolazione lineare, la linea interseca il
lato.
FUNCTION interp (x1, z1, x2, z2, c)
IF (z2 - z1) = 0 THEN
interp = 0
ELSE
interp = (c - z1) * (x2 - x1) / (z2 - z1)
END IF
END FUNCTION
questa sub determina se la linea di livello specificata interseca
questo lato e la posizione del punto relativamente al sistema
di riferimento del grafico.
SUB lato (i%, j%, m%, n%, c, x, y, flag%)
SHARED hx, hy, grid()
IF (grid(i%, j%) <= c AND c <= grid(m%, n%)) OR (grid(m%, n%) <= c AND c <= grid(i%, j%)) THEN
x = j% * hx + interp(j% * hx, grid(i%, j%), n% * hx, grid(m%, n%), c)
y = i% * hy + interp(i% * hy, grid(i%, j%), m% * hy, grid(m%, n%), c)
flag% = 1
END IF
END SUB
Questa sub definisce il vettore dei colori da assegnare alle linee
di livello e costruisce la legenda.
SUB legenda (n%, c())
SHARED col() AS INTEGER
col(1) = 8: col(2) = 7: col(3) = 3: col(4) = 11: col(5) = 2: col(6) = 10
col(7) = 14: col(8) = 13: col(9) = 5: col(10) = 4: col(11) = 9
col(12) = 1: col(13) = 6: col(14) = 15: col(15) = 12
SCREEN 12
a = 0
FOR i% = 1 TO n%
LINE (10, a + i% * 16)-(23, a + 16 + 16 * i%), col(i%), BF
LOCATE 2 * i%, 4
PRINT c(i%)
a = a + 16
NEXT i%
END SUB
Questa sub processa il rettangolino della griglia individuato
dagli indici i e j.
SUB rettangolo (i%, j%, c(), col%(), numlin%)
SHARED xx, yy, specular, specularx, zoomx, zoomy
DIM x(1 TO 4), y(1 TO 4), flag%(1 TO 4)
FOR k% = 1 TO numlin%
CALL lato(i%, j%, i%, j% + 1, c(k%), x(1), y(1), flag%(1))
CALL lato(i%, j%, i% + 1, j%, c(k%), x(2), y(2), flag%(2))
CALL lato(i% + 1, j%, i% + 1, j% + 1, c(k%), x(3), y(3), flag%(3))
CALL lato(i% + 1, j% + 1, i%, j% + 1, c(k%), x(4), y(4), flag%(4))
FOR ii% = 1 TO 4
IF flag%(ii%) = 1 THEN
x1 = x(ii%)
y1 = y(ii%)
FOR jj% = ii% + 1 TO 4
IF flag%(jj%) = 1 THEN
x2 = x(jj%)
y2 = y(jj%)
END IF
NEXT jj%
LINE ((xx + x1) * zoomx + specularx, specular - (yy + y1) * zoomy)-((xx + x2) * zoomx + specularx, specular - (yy + y2) * zoomy), col%(k%)
END IF
NEXT ii%
10
flag%(1) = 0: flag%(2) = 0: flag%(3) = 0: flag%(4) = 0
NEXT k%
END SUB
NOTA. Il programma presentato e' stato realizzato in Basic. Comunque la sua traduzione in altri linguaggi non dovrebbe comportare particolari problemi dal momento che sono stati usati costrutti presenti in tutti i linguaggi di programmazione.
Diagramma di flusso programma CONTOUR
Le pagine che seguono mostrano alcuni
esempi di output ottenuti con il programma Contour, per un dominio
sempre piu' fitto di punti. La superficie utilizzata per il test
del programma e' visibile in fig.3.1, mentre, in fig.3.2 e' riportato
il risultato "esatto" per le linee di livello.
Introduzione | Cap.1 | Cap.2 | Cap.3 | Cap.4 | Cap.5 | Appendice | Bibliografia