Universit`a degli Studi di Salerno
Facolt`a di Scienze Matematiche Fisiche e Naturali
Tesi di Laurea di I livello in
Infor...
ii
Ringraziamenti
Ai miei genitori, che mi hanno dato fiducia e mi hanno concesso la possibilit`a
di raggiungere questo obiett...
iv
v
Sommario
Le NURBS (Non Uniform Rational B-Splines) sono lo standard attuale per
quanto riguarda la grafica 2D e 3D e rapp...
vi
Indice
1 Introduzione 1
2 Spline, B-Spline e NURBS 5
2.1 Le basi . . . . . . . . . . . . . . . . . . . . . . . . . . . . ....
viii INDICE
3.6.1 Numpy . . . . . . . . . . . . . . . . . . . . . . . . . . 46
3.6.2 Matplotlib . . . . . . . . . . . . . ...
INDICE ix
5.3 Possibili applicazioni . . . . . . . . . . . . . . . . . . . . . . . 110
5.3.1 Scanner 3D . . . . . . . . . ...
x INDICE
Capitolo 1
Introduzione
Scienza `e tutto ci`o che comprendiamo abbastaza
bene da spiegarlo ad un computer, tutto il resto ...
2 CAPITOLO 1. INTRODUZIONE
Figura 1.1: La creazione di una superfice NURBS all’interno del software di
modellazione 3D Blen...
3
classe) sia i dati che i metodi che lavorano su di essi e di definire relazioni fra
le entit`a stesse. Utilizzando questo...
4 CAPITOLO 1. INTRODUZIONE
Capitolo 2
Spline, B-Spline e NURBS
Se le persone non credono che la matematica sia
semplice, `e solo perch´e non hanno an...
6 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Figura 2.1: Una spirale `e una curva polidroma
Questo tipo di rappresentazione, che...
2.1. LE BASI 7
La terza rappresentazione, ovvero quella in forma parametrica, `e la
pi`u flessibile. L’idea consiste nell’e...
8 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
all’interno dell’intervallo [0, 1], in modo che f(0) identifichi l’inizio della
curv...
2.1. LE BASI 9
all’infinito, la curva pu`o essere riprodotta esattamente. Un vantaggio sicuro
della rappresentazione a trat...
10 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Figura 2.2: Differenze fra diverse condizioni di continuit`a [12]
Questo tipo di co...
2.1. LE BASI 11
pi`u generale. Infatti, tramite il polinomio in u `e possibile rappresentare una
generica curva di grado n...
12 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
denoteremo con B, `e denominata matrice di base. La matrice fa da ponte
tra i punt...
2.1. LE BASI 13
La matrice costante che se ne ricava `e:
C =


1 .5 .25
1 1 1
0 0 2


e la matrice di base `e:
B = C−1...
14 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Spline cubica naturale
La spline cubica naturale si ottiene specificando posizione,...
2.1. LE BASI 15
Figura 2.3: Funzioni di base della spline cubica naturale
La matrice costante `e:
C =




1 0 0 0
0 1 ...
16 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Figura 2.4: Funzioni di base della spline cubica di Hermite
la curva deve essere t...
2.2. CURVE 17
Figura 2.5: Spline cardinale con diversi valori del parametro di tensione
(Immagini ottenuta tramite la libr...
18 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Le curve di B´ezier utilizzano come funzioni di base i polinomi di Bernstein:
Jn,i...
2.2. CURVE 19
Figura 2.6: Funzioni di base per una curva di B´ezier con 5 punti di controllo
2.2.2 Curve B-Spline
Le curve...
20 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
dove Bi rappresenta l’i-esimo punto di controllo, Ni,k(t) `e la funzione di base.
...
2.2. CURVE 21
Il vettore dei nodi
Dall’equazione (2.6) appare evidente che la scelta del vettore dei nodi
influisce sulle f...
22 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
(a)
(b)
Figura 2.7: Due B-spline dello stesso ordine calcolate a partire dagli ste...
2.2. CURVE 23
Un vettore non uniforme `e un vettore in cui l’unico vincolo `e quello
standard: xi ≤ xi+1. Possono esserci ...
24 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
In modo simile `e possibile passare dalle funzioni di base alla notazione
matricia...
2.2. CURVE 25
Dove 2 ≤ k ≤ n + 1 ≤ j. Questo sistema di equazioni pu`o essere scritto in
modo pi`u compatto con la notazio...
26 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
di invertire:
[ D ] = [ N ][ B ]
[ N ]T
[ D ] = [ N ]T
[ N ][ B ]
[ B ] = [[ N ]T
...
2.2. CURVE 27
Qui con Bi si indicano i punti di controllo tridimensionali della B-spline
razionale e le
Ri,k(t) =
hiNi,k(t...
28 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
ˆ Ogni funzione di base razionale `e maggiore o uguale a 0 per ogni valore
del par...
2.3. SUPERFICI 29
funzioni parametriche:
x = x(u, w)
y = y(u, w)
z = z(u, w)
Specificando un parametro e lasciando variare ...
30 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Figura 2.9: Esempio di superficie di B´ezier (Immagine ottenute tramite la libreria...
2.3. SUPERFICI 31
ˆ L’ordine massimo della superficie lungo le due direzioni u e w `e pari
al numero di punti di controllo ...
32 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
(a) (b)
(c) (d)
Figura 2.10: Effetto dell’uso di diversi tipi di vettori dei nodi s...
2.3. SUPERFICI 33
2.3.3 Interpolazione 3D tramite B-Splines
Come nel caso delle curve mostrato nella sezione 2.2.3, anche ...
34 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
Lo stesso discorso vale per il parametro w:
w1 = 0
wq
wmax
=
q
g=2
|Dp,g − Dp,g−1|...
2.3. SUPERFICI 35
ˆ La somma delle funzioni di base Si,j(u, w) `e pari a uno per ogni valore
dei parametri u e w;
ˆ L’ordi...
36 CAPITOLO 2. SPLINE, B-SPLINE E NURBS
(a) h2,3 = 0 (b) h2,3 = 1
(c) h2,3 = 5 (d) h2,3 = 10
Figura 2.11: Effetto della var...
Capitolo 3
Cenni di Python
Ed ora passiamo a qualcosa di completamente
diverso.
Monthy Python
In questo capitolo verranno ...
38 CAPITOLO 3. CENNI DI PYTHON
per chi vuole imparare Python. La pagina [10] presenta, oltre ad una breve
guida di stile, ...
3.2. LE LISTE 39
3.2 Le liste
Uno dei punti di forza del Python risiede nelle strutture che offre. Una di
queste strutture ...
40 CAPITOLO 3. CENNI DI PYTHON
6 }
In Python:
1 >>> p = [i**2 for i in range(10)]
2 >>> p
3 [0, 1, 4, 9, 16, 25, 36, 49, 6...
3.3. I DIZIONARI 41
13 [2, 5, 8]
Un’altra funzione che ho usato spesso durante il mio lavoro `e stata la
funzione enumerat...
42 CAPITOLO 3. CENNI DI PYTHON
1 >>> rubrica.keys()
2 [’bianchi’, ’rossi’, ’verdi’]
3 >>> rubrica.values()
4 [99654321, 10...
3.4. PROGRAMMAZIONE ORIENTATA AGLI OGGETTI 43
una convenzione di nomenclatura, che consiste nell’anteporre un doppio un-
d...
44 CAPITOLO 3. CENNI DI PYTHON
7 print "Impossibile modificare l’attributo voto"
8 else:
9 self.__dict__[nome] = valore
Pe...
3.5. LE ECCEZIONI 45
1 try:
2 # codice che potrebbe generare l’errore
3 except TipoEccezione:
4 # codice da esegure se si ...
46 CAPITOLO 3. CENNI DI PYTHON
3.6 Librerie utilizzate
Nello scrivere la libreria per il calcolo delle nurbs, ho utilizzat...
3.6. LIBRERIE UTILIZZATE 47
Un esempio:
1 >>> import numpy as np
2 >>> a = np.arange(5)
3 >>> b = np.arange(6,10)
4 >>> a
...
48 CAPITOLO 3. CENNI DI PYTHON
4 >>> a = np.array([[1,2,3],[4,5,6]])
5 >>> print a
6 [[1 2 3]
7 [4 5 6]]
8 >>> print a.ndi...
3.6. LIBRERIE UTILIZZATE 49
Figura 3.1: Esempio di plot della funzione sin(x) con matplotlib
3 # genera un insieme di valo...
50 CAPITOLO 3. CENNI DI PYTHON
17 # A scelta si utilizza una delle due
18 ax.plot_wireframe(X, Y, Z, cstride = 1, rstride ...
3.6. LIBRERIE UTILIZZATE 51
(a) Wireframe
(b) Surface
Figura 3.2: Plot della funzione z = x2−y2, in wireframe e superfice c...
52 CAPITOLO 3. CENNI DI PYTHON
Capitolo 4
Descrizione delle classi ed algoritmi
implementati
Se, fra dieci anni, mentre state facendo qualcosa
in modo ve...
54 CAPITOLO 4. CLASSI ED ALGORITMI
oppure si pu`o importare l’intero file:
1 import Curve
2 c = Curve.Nurbs(...)
e anche ut...
4.2. LA CLASSE POINTS 55
init . Utilizzando questo metodo, che ha come primo parametro la classe
stessa, `e possibile agir...
56 CAPITOLO 4. CLASSI ED ALGORITMI
2 return sum([self[k].distance(self[k+1]) for k in xrange(len(
self[i:j])-1)])
xrange `...
4.3. LA CLASSE CURVE 57
24 # calcolo la somma delle di stanze fra tutti i punti presenti nell’
array
25 >>> punti.chordLen...
58 CAPITOLO 4. CLASSI ED ALGORITMI
1 def calculate(self):
2 pass
L’istruzione pass permette di dichiarare un metodo lascia...
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D
Upcoming SlideShare
Loading in …5
×

Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D

2,936 views

Published on

Tesi di laurea triennale in cui si discute l\'implementazione di una libreria orientata agli oggetti in Python per il calcolo di curve e superfici parametriche, in particolare NURBS, che trova applicazioni nell\'ambito della grafica 2D e 3D.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
2,936
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
58
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D

  1. 1. Universit`a degli Studi di Salerno Facolt`a di Scienze Matematiche Fisiche e Naturali Tesi di Laurea di I livello in Informatica Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D Relatore Candidato Dott. Mario Annunziato Antonio Sanfelice Matricola 05102/00997 Anno Accademico 2009 - 2010
  2. 2. ii
  3. 3. Ringraziamenti Ai miei genitori, che mi hanno dato fiducia e mi hanno concesso la possibilit`a di raggiungere questo obiettivo. A Mariapia, che ha condiviso le mie gioie e i miei dolori. A Demia, Pasquale, Stefania, Enzo, Gianni e a tutti coloro che hanno reso questi quattro anni i pi`u divertenti e spensierati della mia vita nonostante il carico di lavoro che ho dovuto affrontare. A Tonino, i cui cornetti e caff`e, mi hanno tenuto in piedi in questi anni. A tutti coloro che si chiedono come mai, in una facolt`a il cui nome `e “Scienze Matematiche, Fisiche e Naturali”, vengono torturati con sommato- rie, derivate ed integrali, e che non importa come glielo si spieghi, continuano a porsi bizzarri interrogativi. Ai Dream Theater, agli Iron Maiden, ai Within Temptation, ai Night- wish, agli AC/DC, ai Gotthard, ai Guns ’n Roses, ai Three Doors Down, ai Black Sabbath, ai Metallica, ai Testament, ai Children Of Bodom, agli Edguy, ai Blind Guardian, ai Sonata Artica, ai Dire Straits, ai Queen, agli X-Japan, a Joe Satriani, ad Eric Clapton, ad Eric Johnson, agli Alter Brid- ge, agli Europe, ai Firewind, a Mozart, a Beethoven, a Bach, che da una vita mi danno l’adrenalina necessaria ad affrontare i momenti belli e meno belli. Alla birra che, ne dicano quel che vogliono, mi ha aiutato a risolvere alcuni dei peggiori rompicapo che ho incontrato durante lo studio. A Leonardo Da Vinci, da cui ho imparato che al mondo ci sono troppe cose interessanti per dedicare la vita ad una sola di esse. A tutti voi, Grazie iii
  4. 4. iv
  5. 5. v Sommario Le NURBS (Non Uniform Rational B-Splines) sono lo standard attuale per quanto riguarda la grafica 2D e 3D e rappresentano il modo pi`u generale di rappresentare una curva o una superficie. Sebbene esistano diverse librerie e software gratuiti che consentono di calcolare questo tipo di curve e superfici, alcune di esse sono state abbandonate (come ad esempio la libreria nurbs++ [13]), sono poco documentate o eccessivamente complesse ( come la libreria openNURBS [5]), altre invece sono progettate per il calcolo numerico (esem- pio modulo NURBS per octave [15]). L’obiettivo di questa tesi `e lo sviluppo di una libreria orientata agli oggetti portabile, semplice da usare e che possa essere utilizzata in diversi ambiti. La suddetta libreria `e stata sviluppata in Python, in quanto `e presente per tutte i principali sistemi operativi, `e sup- portato da un gran numero di librerie e consente di risolvere con poche righe di codice problemi complessi. Nella tesi vengono riassunte le conoscenze ne- cessarie per lavorare con curve e superfici parametriche, in particolare con le NURBS e viene illustrata la libreria da me sviluppata che oltre a permettere di calcolare diversi tipi di curve e superfici utilizando una rappresentazione polinomiale a tratti (curve di B´ezier, B-Spline, NURBS), offre strumenti per risolvere il problema dell’approssimazione di un insieme di punti, sia in due che in tre dimensioni, utilizzando le B-Spline. Quest’ultima caratteristica si rivela di particolare interesse e trova applicazioni anche al di fuori della grafica, permettendo ad esempio di calcolare traiettorie per robot mobili, o di approssimare (o ricostruire) segnali audio precedentemente campionati, inoltre versioni pi`u complesse di B-Spline e NURBS trovano applicazione in analisi nuemerica e in altri campi di ricerca avanzati come strumenti di approssimazione di funzioni.
  6. 6. vi
  7. 7. Indice 1 Introduzione 1 2 Spline, B-Spline e NURBS 5 2.1 Le basi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.1 Rappresentazione di curve . . . . . . . . . . . . . . . . 5 2.1.2 Tipi di parametrizzazione . . . . . . . . . . . . . . . . 7 2.1.3 Rappresentazione a tratti . . . . . . . . . . . . . . . . 8 2.1.4 Propriet`a delle curve . . . . . . . . . . . . . . . . . . . 9 2.1.5 Continuit`a . . . . . . . . . . . . . . . . . . . . . . . . 9 2.1.6 Rappresentazione Matriciale di Polinomi . . . . . . . . 10 2.1.7 Funzioni di base . . . . . . . . . . . . . . . . . . . . . 13 2.1.8 Spline cubiche di uso comune . . . . . . . . . . . . . . 13 2.2 Curve . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.2.1 Curve di B´ezier . . . . . . . . . . . . . . . . . . . . . . 17 2.2.2 Curve B-Spline . . . . . . . . . . . . . . . . . . . . . . 19 2.2.3 Interpolazione 2D tramite B-Spline . . . . . . . . . . . 24 2.2.4 Curve NURBS . . . . . . . . . . . . . . . . . . . . . . 26 2.3 Superfici . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28 2.3.1 Superfici di B´ezier . . . . . . . . . . . . . . . . . . . . 29 2.3.2 Superfici B-Spline . . . . . . . . . . . . . . . . . . . . 30 2.3.3 Interpolazione 3D tramite B-Splines . . . . . . . . . . 33 2.3.4 Superfici NURBS . . . . . . . . . . . . . . . . . . . . . 34 3 Cenni di Python 37 3.1 Caratteristiche basilari . . . . . . . . . . . . . . . . . . . . . . 38 3.2 Le liste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39 3.3 I dizionari . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41 3.4 Programmazione orientata agli oggetti . . . . . . . . . . . . . 42 3.5 Le eccezioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44 3.6 Librerie utilizzate . . . . . . . . . . . . . . . . . . . . . . . . . 46 vii
  8. 8. viii INDICE 3.6.1 Numpy . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3.6.2 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . 48 4 Classi ed Algoritmi 53 4.1 La struttura delle classi . . . . . . . . . . . . . . . . . . . . . 54 4.2 La classe Points . . . . . . . . . . . . . . . . . . . . . . . . . 54 4.3 La classe Curve . . . . . . . . . . . . . . . . . . . . . . . . . . 57 4.4 La classe Bezier . . . . . . . . . . . . . . . . . . . . . . . . . 60 4.4.1 Calcolo tramite definizione . . . . . . . . . . . . . . . 60 4.4.2 L’algoritmo di De Casteljau . . . . . . . . . . . . . . . 61 4.5 La classe Spline . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.6 Esempi di estensione di Spline . . . . . . . . . . . . . . . . . . 66 4.6.1 Spline cubica naturale . . . . . . . . . . . . . . . . . . 66 4.6.2 Spline di Hermite . . . . . . . . . . . . . . . . . . . . . 67 4.6.3 Spline cardinale . . . . . . . . . . . . . . . . . . . . . . 67 4.7 La classe BSpline . . . . . . . . . . . . . . . . . . . . . . . . 68 4.7.1 Calcolo da definizione . . . . . . . . . . . . . . . . . . 68 4.7.2 Calcolo con notazione matriciale . . . . . . . . . . . . 71 4.8 La classe Nurbs . . . . . . . . . . . . . . . . . . . . . . . . . . 74 4.9 La classe CurveFit . . . . . . . . . . . . . . . . . . . . . . . . 76 4.10 La classe Surface . . . . . . . . . . . . . . . . . . . . . . . . 79 4.11 La classe BezSurf . . . . . . . . . . . . . . . . . . . . . . . . 80 4.12 La classe BSplineSurf . . . . . . . . . . . . . . . . . . . . . . 82 4.12.1 Calcolo tramite definizione . . . . . . . . . . . . . . . 82 4.12.2 Calcolo con notazione matriciale . . . . . . . . . . . . 83 4.13 La classe NurbsSurf . . . . . . . . . . . . . . . . . . . . . . . 86 4.13.1 Algoritmo naive . . . . . . . . . . . . . . . . . . . . . 86 4.13.2 Algoritmo efficiente . . . . . . . . . . . . . . . . . . . 87 4.13.3 L’implementazione . . . . . . . . . . . . . . . . . . . . 88 4.14 La classe SurfaceFit . . . . . . . . . . . . . . . . . . . . . . 92 5 Esempi di utilizzo e applicazioni 97 5.1 Esempi di utilizzo . . . . . . . . . . . . . . . . . . . . . . . . . 97 5.1.1 Curve di B´ezier . . . . . . . . . . . . . . . . . . . . . . 98 5.1.2 Curve B-Spline . . . . . . . . . . . . . . . . . . . . . . 100 5.1.3 Curve Nurbs . . . . . . . . . . . . . . . . . . . . . . . 102 5.1.4 Approssimazione di curve tramite B-Spline . . . . . . 103 5.1.5 Superfici di B´ezier . . . . . . . . . . . . . . . . . . . . 103 5.1.6 Superfici B-Spline . . . . . . . . . . . . . . . . . . . . 105 5.1.7 Superfici NURBS . . . . . . . . . . . . . . . . . . . . . 106 5.1.8 Approssimazione di superfici tramite B-Spline . . . . . 107 5.2 Confronto con altre librerie . . . . . . . . . . . . . . . . . . . 109 5.2.1 Nurbs++ . . . . . . . . . . . . . . . . . . . . . . . . . 110 5.2.2 openNURBS . . . . . . . . . . . . . . . . . . . . . . . 110
  9. 9. INDICE ix 5.3 Possibili applicazioni . . . . . . . . . . . . . . . . . . . . . . . 110 5.3.1 Scanner 3D . . . . . . . . . . . . . . . . . . . . . . . . 111 5.3.2 Ricostruzione paesaggi . . . . . . . . . . . . . . . . . . 111 5.3.3 Applicazioni mediche . . . . . . . . . . . . . . . . . . . 112 5.4 Conclusioni . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 Appendici 117 A Casi d’uso e Class Diagrams 117 A.1 Casi d’uso . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 A.1.1 Curve . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 A.1.2 Superfici . . . . . . . . . . . . . . . . . . . . . . . . . . 118 A.2 Class Diagram . . . . . . . . . . . . . . . . . . . . . . . . . . 119 B Codice 121 B.1 Curve.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 B.2 Surface.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 B.3 Util.py . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
  10. 10. x INDICE
  11. 11. Capitolo 1 Introduzione Scienza `e tutto ci`o che comprendiamo abbastaza bene da spiegarlo ad un computer, tutto il resto `e arte. Donald E. Knuth Le NURBS (Non Uniform Rational B-Spline) rappresentano lo standard attuale per la rappresentazione di curve e superfici in computer grafica. La loro capacit`a di rappresentare con accuratezza anche le forme pi`u complesse, le rende uno strumento particolarmente utile qualora si abbia la necessit`a di disegnare modelli 2D e 3D, come nelle applicazioni di prototipazione ra- pida: applicazioni volte alla creazione automatica di prototipi solitamente utilizzate in ambito industriale. Il loro sviluppo inizi`o negli anni ’50 con lo scopo di creare un modello matematico in grado di descrivere con precisione superfici a forma libera, da poter utilizzare ad esempio per modellare chiglie di navi, ali di aerei, carrozzerie di automobili. Pionieri nello sviluppo di queste tecniche di approssimazione di curve e superfici furono Pierre B´ezier e Paul de Casteljau, i quali lavorarono praticamente in parallelo entrambi all’oscuro del lavoro dell’altro [25]. Sebbene siano nate come strumento di modellazione CAD e rappresentino tutt’oggi uno degli strumenti fondamen- tali nella grafica 2D e 3D, le B-Spline e le NURBS trovano applicazione anche in campi diversi dalla grafica. Esse infatti trovano applicazione in analisi numerica e in altri ambiti di ricerca avanzata come strumento per approssimare funzioni. Esistono diverse librerie gratuite che permettono il calcolo di curve e superfici NURBS, tutta via alcune di esse presentano alcu- ni problemi: alcune librerie non vengono aggiornate da anni, altre sono poco (o per niente) documentate, rendendo difficile qualsiasi tipo di intervento su di esse o semplicemente mancano le funzionalit`a di cui si aveva bisogno. In questo lavoro ci proponiamo di sviluppare una libreria orientata agli oggetti per il calcolo di NURBS e di altri tipi di curve e superfici parametriche, 1
  12. 12. 2 CAPITOLO 1. INTRODUZIONE Figura 1.1: La creazione di una superfice NURBS all’interno del software di modellazione 3D Blender [1] che consenta inoltre di risolvere il problema dell’approssimazione di punti, sia sul piano che nello spazio. Quest’ultima caratteristica `e di particolare interesse. Sebbene siano nate come strumento per la grafica, le B-Spline, le NURBS e versioni pi`u complesse di entrambe trovano diverse applicazioni anche in ambiti molto diversi, ad esempio in analisi numerica ed altri campi di ricerca avanzati. Basti pensare che esse vengono utilizzate per: ˆ calcolare la traiettoria da far seguire ad un robot per fargli raggiungere una data destinazione [21, 22]; ˆ approssimare (o nel caso migliore ricostruire) un segnale audio o video campionato in precedenza [23]; ˆ controllare le funzioni di densit`a di probabilit`a output di sistemi lineari stocastici [26]. Nella tesi verranno illustrati diversi approcci per il calcolo delle principali curve e superfici parametriche, mettendo a confronto tecniche di calcolo naive con tecniche pi`u complesse. Saranno infine proposti alcuni esempi di utilizzo della libreria sviluppata in campi d’applicazione molto diversi fra loro, per sottolineare l’ampio bacino di applicazioni che le NURBS che possono trovare. Il paradigma Le curve e le superfici trattate, oltre ad essere in numero discreto, presentano attributi e schemi comuni: per questi motivi abbiamo optato per il paradig- ma di programmazione orientata agli oggetti. Questo paradigma, rispetto a quello procedurale, consente di racchiudere in un’unica entit`a (denominata
  13. 13. 3 classe) sia i dati che i metodi che lavorano su di essi e di definire relazioni fra le entit`a stesse. Utilizzando questo paradigma e modellando quindi classi rappresentanti i vari tipi di curve e superfici si ottiene un codice dall’elevata modularit`a, il che facilita eventuali interventi di manutenzione, inoltre `e pi`u semplice per chi conosce il contesto districarsi all’interno del codice stesso. Il linguaggio Per l’implementazione abbiamo scelto il Python: linguaggio versatile che permette di sviluppare seguendo i paradigmi ad oggetti, procedurale e fun- zionale. Questo linguaggio ha guadagnato negli anni un gran numero di consensi, in quanto offre un ottimo compromesso fra velocit`a e semplicit`a. Il Python `e utilizzato negli ambiti pi`u disparati, dallo sviluppo web allo sviluppo di videogiochi, dallo sviluppo di software di computer grafica al calcolo scientifico. Si pensi che Google e la NASA fanno un forte uso di Py- thon nei loro rispettivi ambiti (per ulteriori dettagli vedere le sezioni “suc- cess stories” e “quotes”su [6]). Essendo Python un linguaggio interpretato, i software scritti in questo linguaggio possono essere eseguiti su qualsiasi piattaforma abbia un interprete installato, facendo s`ı che chi sviluppa non debba preoccuparsi del discorso portabilit`a. Sommario dei capitoli Per facilitare la consultazione della tesi, vengono di seguito riassunti i con- tenuti dei singoli capitoli. Il Capitolo 2 copre l’aspetto matematico del lavoro svolto, introducendo le notazioni e le definizioni utilizzate per sviluppare la libreria oggetto di questa tesi. Il Capitolo 3 riassume i concetti base del linguaggio Python, illustrando alcuni particolari della sintassi in modo da rendere pi`u semplice la comprensione delle implementazioni. Il Capitolo 4 illustra una ad una le classi che compongono la libreria, mostrando gli algoritmi utilizzati e la loro implementazione. Il Capitolo 5 mostra alcuni esempi di utilizzo e fornisce alcuni misurazioni del tempo di esecuzione. Inoltre vengono illustrati alcuni esempi di applicazione della libreria. In Appendice A `e presente la documentazione della libreria, corredata di diagrammi UML dei casi d’uso e delle classi. In Appendice B `e possibile consultare il codice sorgente della libreria nella sua interezza.
  14. 14. 4 CAPITOLO 1. INTRODUZIONE
  15. 15. Capitolo 2 Spline, B-Spline e NURBS Se le persone non credono che la matematica sia semplice, `e solo perch´e non hanno ancora realizzato quanto `e complicata la vita. John von Neumann In questo capitolo vengono presentate i vari tipi di curve e superfici oggetto di questo lavoro, partendo da alcune definizioni di base fino ad ar- rivare al metodo pi`u generale per la rappresentazione di curve e superfici: le NURBS. Oltre a [12, 19], materiale di riferimento per questo capitolo, `e possibile visitare [11] per un tutorial interattivo su curve e superfici parame- triche, mentre il materiale pubblicato dal progetto MIT OpenCourseWare ([16]) contiene maggiori dettagli, dal punto di vista analitico, sulle propriet`a delle curve e delle superfici qui presentate. 2.1 Le basi In questo paragrafo verranno illustrati i concetti di base riguardanti la pa- rametrizzazione delle curve, la loro rappresentazione a tratti, i tipi di conti- nuit`a e altri argomenti necessari a comprendere successivamente il compor- tamento di curve di B´ezier, B-Spline e Nurbs, fino ad arrivare alle superfici. 2.1.1 Rappresentazione di curve Una curva `e una successione continua di punti. Esistono tre modi principali per rappresentare una curva. La prima, pi`u nota ed utilizzata nei primi corsi di matematica, `e la rappresentazione esplicita. La rappresentazione in forma esplicita `e una rappresentazione del tipo: y = f(x) 5
  16. 16. 6 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Figura 2.1: Una spirale `e una curva polidroma Questo tipo di rappresentazione, che mette in evidenza la dipendenza della variabile y dalla variabile x ha le seguenti caratteristiche: ˆ Permette di disegnare facilmente la curva; ˆ Permette di verificare facilmente se un punto appartiene la curva; ˆ Non permette di rappresentare facilmente curve polidrome1; ˆ `E dipendente dagli assi, `e quindi difficile trasportare la curva in un altro sistema di riferimento. Proprio quest’ultima caratteristica `e uno svantaggio pesante. Infatti con questo tipo di rappresentazione `e possibile rappresentare solo curve che han- no associato ad ogni valore della variabile x un unico valore della variabile y. `E quindi difficile rappresentare curve come quella mostrata in figura 2.1 Per ovviare a questo problema si pu`o utilizzare la rappresentazione in forma implicita: f(x, y) = 0 Questo tipo di rappresentazione ˆ Permette di rappresentare curve polidrome; ˆ Permette di verificare facilmente se un punto appartiene o meno alla curva; ˆ Rende difficile disegnare la curva; ˆ `E dipendente dagli assi, quindi `e difficile trasportare la curva in un altro sistema di riferimento. 1 Una funzione polidroma `e una funzione f : X → P(Y) (dove P(Y) rappresenta l’insie- me delle parti di Y) che ad un dato valore della variabile x associa uno o pi`u valori della variabile y
  17. 17. 2.1. LE BASI 7 La terza rappresentazione, ovvero quella in forma parametrica, `e la pi`u flessibile. L’idea consiste nell’esprimere sia la variabile x che la variabile y come funzioni di un parametro esterno, che chiameremo t. Otteniamo quindi una rappresentazione del tipo: x = f1(t) y = f2(t) Il motivo per cui la rappresentazione in forma parametrica `e la pi`u flessibile, diventa ovvio con un piccolo esempio. Supponiamo di voler disegnare una circonferenza di raggio r con centro nell’origine: y = ± r2 − x2 L’equazione in forma esplicita costringe a disegnare due semicirconferenze, la prima y = + √ r2 − x2, e la seconda y = − √ r2 − x2. Passando alla forma implicita, diventa comodo generalizzare e considerare una circonferenza di centro (x0, y0): (y − y0)2 + (x − x0)2 = r2 y2 + y2 0 − 2yy0 + x2 + x2 0 − 2xx0 = r2 y2 + y2 0 − 2yy0 + x2 + x2 0 − 2xx0 − r2 = 0 Salta all’occhio che disegnare la circonferenza utilizzando la notazione im- plicita `e tutt’altro che semplice. L’equazione in forma parametrica per una circonferenza di raggio r e centro (x0, y0) invece `e la seguente: C = x(u) = x0 + r · cos(t) t ∈ [0, 2π] y(u) = y0 + r · sin(t) La forma parametrica `e visibilmente pi`u semplice `e consente di calcolare di- rettamente un qualsiasi punto della circonferenza, cosa che non era possibile n´e con la notazione esplicita n´e con quella implicita. Propio per l’estrema flessibilit`a e per la possibilit`a di poter definire for- me molto particolari in modo relativamente semplice, la rappresentazione parametrica `e molto utilizzata in computer grafica. 2.1.2 Tipi di parametrizzazione Rappresentare una curva nel piano in forma parametrica significa creare una applicazione f : R → R2 che ad ogni valore del parametro associa una coordinata (x, y) sul piano. Una delle comodit`a nell’usare questo tipo di rappresentazione `e che il parametro pu`o rappresentare qualsiasi cosa: pu`o essere il tempo, un angolo, una frequenza, qualsiasi cosa si ritiene debba influire sulla forma della curva. Di solito si utilizza un parametro che spazi
  18. 18. 8 CAPITOLO 2. SPLINE, B-SPLINE E NURBS all’interno dell’intervallo [0, 1], in modo che f(0) identifichi l’inizio della curva e f(1) ne identifichi la fine, questo tipo di parametro viene usualmente identificato con u. L’affermazione precedente potrebbe portare erronamente a pensare che f(0.5) identifichi la met`a della curva, ma non `e cos`ı. Il fatto che u = 0.5 identifichi o meno la met`a della curva dipende dal tipo di parametrizzazione che stiamo usando: Naturale: In questo tipo di parametrizzazione, u non `e legato alla curva in se, ma allo spazio all’interno del quale la curva `e definita. Quindi se u = 0.5, f(u) indica il punto della curva al centro dello spazio di definizione. Lunghezza d’arco: In questo tipo di parametrizzazione u segue l’anda- mento della curva, quindi se u = 0.5, f(u) identifica il punto centrale della curva. Avendo una parametrizzazione naturale con parametro u, per conoscere il parametro s che rappresenta la lunghezza dell’arco dal punto f(0) al punto f(u). s = u 0 |f (u)|2 du (2.1) Per poter utilizzare la rappresentazione a lunghezza d’arco, bisogna es- sere in grado di risolvere l’equazione (2.1) rispetto ad u dato s, il ch´e non `e sempre possibile o comunque semplice. 2.1.3 Rappresentazione a tratti Spesso pu`o risultare difficile trovare una funzione parametrica capace di descrivere una curva nella sua interezza. In questi casi pu`o risultare utile un approccio tipo divide et impera, ovvero dividere la curva in tratti la cui descrizione tramite funzione parametrica sia pi`u semplice. Se ad esempio volessimo dividere un ipotetica curva in due tratti, la sua descrizione sarebbe qualcosa di simile a: f(u) = f1(2 · u) se u ≤ 0.5 f2(2 · u − 1) se u > 0.5 Dove f1 `e la funzione parametrica che rappresenta il primo tratto e f2 `e quella che rappresenta il secondo, entrambe sono definite per u ∈ [0, 1]. Nel definire le funzioni f1 e f2 bisogna assicurarsi che i due tratti combacino. Se f1(1) = f2(0) i due tratti non formano un unica curva continua. Un altro problema che riguarda la rappresentazione a tratti riguarda il tipo ed il numero di tratti da usare. Sicuramente, per una questione di semplicit`a, conviene utilizzare tratti dello stesso tipo (ad esempio solo polinomi cubici). La scelta del numero di tratti da usare permette di decidere con che approssimazione ricreare la curva. Col tendere del numero di tratti
  19. 19. 2.1. LE BASI 9 all’infinito, la curva pu`o essere riprodotta esattamente. Un vantaggio sicuro della rappresentazione a tratti `e che permette di decidere, a seconda delle applicazioni, se si vuole una rappresentazione pi`u semplice o pi`u precisa. Si possono utilizzare pochi tratti pi`u complessi, oppure molti tratti semplici ( ad esempio polinomi di primo grado) ed ottenere comunque una buona approssimazione della curva originale. 2.1.4 Propriet`a delle curve Nel descrivere una curva, abbiamo bisogno di conoscere alcune sue caratte- ristiche. Per le curve pi`u comuni, queste caratteristiche sono specifiche per il tipo di curva. Ad esempio, per un cerchio basta specificare il raggio e la posizione del centro. Per curve a forma libera per`o, c’`e bisogno di conoscere diverse caratteristiche. Alcune caratteristiche sono generali, ad esempio se la curva `e chiusa o meno, se passa per un dato punto o se assume una certa direzione almeno una volta. Propriet`a pi`u interessanti per`o, specialmente se la curva viene rappresentata a tratti, sono le propriet`a locali. Le propriet`a locali includono: ˆ Continuit`a; ˆ Posizione di un determinato punto della curva; ˆ Direzione ad un determinato punto della curva (derivata prima); ˆ Curvatura (derivata seconda) e altre derivate; 2.1.5 Continuit`a Il discorso inerente la continuit`a assume una certa importanza quando si tenta di rappresentare una curva a tratti. Come detto nel paragrafo 2.1.3, siano fk e fk+1 le funzioni parametriche descriventi il tratto k-esimo e k + 1-esimo della curva, se fk(1) = fk+1(0) la curva risulta spezzata. Oltre alla posizione, si potrebbe verificare che anche le derivate prime dei due tratti nei punti in cui esse vanno a congiungersi siano uguali. Questo perch´e se fk (1) = fk+1 (0), la curva potrebbe presentare un cambio di di- rezione troppo repentino, che visivamente potrebbe tradursi, ad esempio, in uno spigolo. In generale, si dice che una curva ha una continuit`a di tipo Cn se tutte le derivate fino all’n-esima combaciano fra un tratto e l’altro della curva. Fino a che derivata imporre la continuit`a `e una scelta che dipende dalle applicazioni: se la curva descrive una traiettoria, una discontinuit`a sulla derivata 2° significherebbe un brusco cambio di accelerazione, quindi in questo caso potrebbe essere utile una continuit`a di tipo C3, mentre se la curva rappresenta il profilo di un oggetto che deve attraversare un fluido (lo scafo di una barca, o l’ala di un aereo), allora una discontinuit`a nella 4° o 5° derivata potrebbe causare problemi (vedere [12]).
  20. 20. 10 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Figura 2.2: Differenze fra diverse condizioni di continuit`a [12] Questo tipo di continuit`a `e per`o un p`o restrittiva, e non permette di modellare alcuni tipi di curve. Per questo si introduce una continuit`a pi`u “debole”, denominata continuit`a geometrica. Con questo tipo di conti- nuit`a si impone che la derivata nel punto finale di un tratto abbia solo la direzione in comune con la derivata del punto iniziale del tratto successivo, mentre il modulo pu`o essere diverso. Ci`o significa che laddove una continuit`a di tipo C1 richiede che fk (1) = fk+1 (0) una continuit`a di tipo G1 richiede che fk (1) = c · fk+1 (0) per qualche valore c. Ovviamente, una curva che `e Cn continua `e necessa- riamente anche Gn continua, ma non viceversa. 2.1.6 Rappresentazione Matriciale di Polinomi Supponiamo di voler scrivere l’equazione parametrica di una linea che collega due punti, p0 e p1. Si pu`o utilizzare la formula per la combinazione convessa dei due punti: f(u) = (1 − u)p0 + up1 Tuttavia un modo pi`u semplice per rappresentare la linea pu`o essere quello di scrivere il polinomio di primo grado in u: f(u) = a0 + ua1 Specificare la linea tramite i suoi punti estremi `e sicuramente pi`u semplice, ma la rappresentazione tramite i coefficienti a0 e a1 ha il vantaggio di essere
  21. 21. 2.1. LE BASI 11 pi`u generale. Infatti, tramite il polinomio in u `e possibile rappresentare una generica curva di grado n-esimo nel seguente modo: f(u) = n i=0 ui ai Questa forma `e detta forma canonica. Il precedente polinomio pu`o esse- re facilmente rappresentato in forma vettoriale definendo un vettore delle potenze di u: u = 1 u u2 u3 . . . un T ottenendo quindi: f(u) = uT a Sebbene la forma canonica abbia i suoi vantaggi, pu`o non essere la scelta pi`u comoda per rappresentare una curva. Per la linea ad esempio, la strada pi`u comoda rimane quella di specificare i punti estremi, e quindi imporre che p0 sia il punto dove la linea si trova quando u = 0 e p1 sia il punto dove la linea si trova quando u = 1. Per passare da una rappresentazione all’altra possiamo scrivere: p0 = f(0) = [1 0] [a0 a1]T p1 = f(1) = [1 1] [a0 a1]T Risolvendo rispetto ad a0 ed a1 otteniamo: a0 = p0 a1 = p1 − p0 Il tutto pu`o essere reso pi`u compatto racchiudendo in singoli vettori i punti ed i coefficienti del polinomio: p0 p1 = 1 0 1 1 a0 a1 oppure, se definiamo con p il vettore dei punti, con C la matrice con i valori di u e con a il vettore dei coefficienti: p = C a (2.2) p `e denominato vettore dei punti di controllo2, ed ogni suo elemento `e definito punto di controllo. C `e la matrice costante. Si pu`o risolvere l’equazione 2.2 rispetto ad a trovando l’inversa di C. Questa matrice, che 2 Si noti che dato che un punto pi `e un vettore del tipo [pix piy], p `e in realt`a una matrice 2xn, dove n `e il numero di punti di controllo specificati. Di conseguenza, anche il relativo coefficiente ai `e un vettore, il che `e ovvio se si ricorda che con la notazione parametrica si scrive un polinomio per ogni variabile posizionale, quindi ci sar`a un coefficiente aix per la variabile x ed un coefficiente aiy per la variabile y
  22. 22. 12 CAPITOLO 2. SPLINE, B-SPLINE E NURBS denoteremo con B, `e denominata matrice di base. La matrice fa da ponte tra i punti di controllo e i coefficienti della forma canonica, fornendo quindi un modo pi`u comodo per rappresentare una curva: f(u) = u B p Supponiamo ora di voler parametrizzare una curva di 2° grado, specifi- cando il punto iniziale, il punto centrale e il punto finale. In questo caso scriviamo: p0 = f(0) = a0 + 01 a1 + 02 a2 p1 = f(0.5) = a0 + 0.51 a1 + 0.52 a2 p2 = f(1) = a0 + 11 a1 + 12 a2 La matrice costante `e quindi: C =   1 0 0 1 .5 .25 1 1 1   da cui otteniamo la matrice di base: B = C−1 =   1 0 0 −3 4 −1 2 −4 2   Imporre solo condizioni posizionali per`o non basta. Per avere pi`u con- trollo sull’andamento della curva `e utile introdurre delle condizioni sulle derivate. Imporre tali condizioni `e semplice, basta derivare la forma canonica rispetto ad u, quindi per una curva di secondo grado: f(u) = a0 + a1 u + a2 u2 La derivata prima `e pari a: f (u) = df du = a1 + 2 a2 u Mentre la derivata seconda `e: f (u) = d2f du = 2 a2 Volendo parametrizzare quindi una curva di secondo grado, specificando posizione, derivata prima e derivata seconda del suo punto centrale (u = 0.5): p0 = f(0.5) = a0 + 0.51 a1 + 0.52 a2 p1 = f (0.5) = a1 + 2 (0.5) a2 p2 = f (0.5) = 2 a2
  23. 23. 2.1. LE BASI 13 La matrice costante che se ne ricava `e: C =   1 .5 .25 1 1 1 0 0 2   e la matrice di base `e: B = C−1 =   1 −.5 .125 0 1 −.5 0 0 .5   2.1.7 Funzioni di base Se la matrice di base B `e nota, la si pu`o moltiplicare per il vettore delle potenze del parametro u ottenendo un vettore di funzioni: b(u) = u B Le funzioni che compongono questo vettore sono denominate funzioni di base. Grazie a queste funzioni, `e possibile rappresentare una curva come combinazione lineare dei suoi punti di controllo: f(u) = n i=0 bi(u) pi Una volta nota la matrice di base quindi, ci sono due strade per calcolare la curva: ˆ moltiplicare la matrice di base per i punti di controllo, ottenendo i coefficienti della forma canonica. ˆ moltiplicare la matrice di base per il vettore delle potenze del parame- tro u, ottenendo le funzioni di base. 2.1.8 Spline cubiche di uso comune In questa sezione esamineremo alcune spline di uso comune, utili anche per capire in quanti modi diversi si pu`o parametrizzare una curva. Le spline cubiche (che utilizzano quindi polinomi di 3° grado) sono molto utilizzate nell’ambito della grafica vettoriale. Questo perch´e i polinomi di terzo grado offrono un ottimo compromesso fra versatilit`a e semplicit`a. Nell’interpolare un insieme di punti un polinomio di terzo grado disegna la curva con la minima curvatura, il che vuol dire che la curva ottenuta “oscilla” di meno rispetto a quella ottenuta tramite un polinomio di grado pi`u alto.
  24. 24. 14 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Spline cubica naturale La spline cubica naturale si ottiene specificando posizione, derivata prima, derivata seconda per il punto iniziale di ogni tratto. Questo tipo di spline ha una continuit`a di tipo C2. Per un singolo tratto bisogna specificare anche la posizione del punto finale. Imponendo questi vincoli otteniamo: p0 = f(0) = a0 + 01 a1 + 02 a2 + 03 a3 p1 = f (0) = a1 + 2 01 a2 + 3 02 a3 p2 = f (0) = 2 a2 + 6 01 a3 p3 = f(1) = a0 + 11 a1 + 12 a2 + 13 a3 Quindi la matrice costante `e: C =     1 0 0 0 0 1 0 0 0 0 2 0 1 1 1 1     e la matrice di base `e: B = C−1 =     1 0 0 0 0 1 0 0 0 0 .5 0 −1 −1 −.5 1     La figura 2.1.8 mostra il grafico delle funzioni di base per questa spline. Lo svantaggio principale della spline cubica naturale, `e che c’`e poco controllo sulla parte finale della curva. Mentre per il punto iniziale viene specificata la posizione, la derivata prima e la derivata seconda, per il punto finale viene specificata solo la posizione, il che rende difficile modificare l’andamento della curva a proprio piacimento. Spline di Hermite Le spline cubiche di Hermite si ottengono specificando posizione e derivata prima per entrambi i punti estremi. Diversi tratti di una spline di Hermi- te possono essere concatenati formando una curva con continuit`a C1. Un vantaggio delle spline di Hermite consiste nel fatto che modificando uno dei punti di controllo, solo l’intorno di quel punto viene modificato e non l’intera curva. Questa propriet`a `e nota come controllo locale. Inoltre, le spline di Hermite interpolano tutti i punti di controllo relativi alla posizione. Imponendo quindi le condizioni dette precedentemente otteniamo: p0 = f(0) = a0 + 01 a1 + 02 a2 + 03 a3 p1 = f (0) = a1 + 2 01 a2 + 3 02 a3 p2 = f(1) = a0 + 11 a1 + 12 a2 + 13 a3 p3 = f (1) = a1 + 2 11 a2 + 3 12 a3
  25. 25. 2.1. LE BASI 15 Figura 2.3: Funzioni di base della spline cubica naturale La matrice costante `e: C =     1 0 0 0 0 1 0 0 1 1 1 1 0 1 2 3     e la matrice di base risulta: B = C−1 =     1 0 0 0 0 1 0 0 −3 −2 3 −1 2 1 −2 1     La figura 2.4 mostra le funzioni di base per la spline cubica di Hermite. Spline cardinale Una spline cardinale cubica `e una spline interpolante con continuit`a di tipo C1. Questo tipo di spline intepola tutti i suoi punti di controllo ad ecce- zione del primo e dell’ultimo. Ci`o che contraddistingue la spline cardinale `e l’utilizzo di un parametro di tensione3 t. Questo parametro indica quanto 3 Si pensi alla tensione nel senso meccanico del termine, ad esempio quella di una corda soggetta a trazione
  26. 26. 16 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Figura 2.4: Funzioni di base della spline cubica di Hermite la curva deve essere tesa fra un punto di controllo e l’altro, effettuando una scalatura delle derivate nei punti di controllo. La derivata di un punto di controllo pi viene calcolata a partire dalla posizione dei punti di controllo adiacenti pi−1 e pi+1: la direzione `e parallela alla retta che connette pi−1 e pi+1, mentre il modulo `e pari alla loro distanza. Il parametro di tensione t agisce scalando la derivata di un fattore 1 2(1 − t). I vincoli per una spline cardinale quindi sono: f(0) = p1 f(1) = p2 f (0) = 1 2(1 − t)(p2 − p1) f (1) = 1 2(1 − t)(p3 − p1) Risolvendo rispetto ai punti di controllo e ponendo s = 1−t 2 otteniamo: p0 = f(1) − 2 1−tf (0) = a0 + (1 − 1 s )a1 + a2 + a3 p1 = f(0) = a0 p2 = f(1) = a0 + a1 + a2 + a3 p3 = f(0) + 1 s f (1) = a0 + 1 s a1 + 21 s a2 + 31 s a3
  27. 27. 2.2. CURVE 17 Figura 2.5: Spline cardinale con diversi valori del parametro di tensione (Immagini ottenuta tramite la libreria da me sviluppata) Ci`o porta alla matrice di base: B = C−1 =     0 1 0 0 −s 0 s 0 2s s − 3 3 − 2s −s −s 2 − s s − 2 s     Le spline cardinali sono comode in quanto rappresentano uno dei me- todi pi`u semplici per interpolare un insieme di punti ottenendo una curva con continuit`a C1 con in pi`u la propriet`a del controllo locale (vedere [12]). La figura 2.5 mostra l’interpolazione di un insieme di punti tramite spline cardinale con diversi valori per il parametro di tensione. 2.2 Curve In questa sezione verranno mostrate le tecniche di approssimazione di curve che hanno portato negli anni allo sviluppo delle NURBS. 2.2.1 Curve di B´ezier Le curve di B´ezier sono un tipo di curve la cui forma `e influenzata dal poligono formato dai punti di controllo, denominato poligono di controllo.
  28. 28. 18 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Le curve di B´ezier utilizzano come funzioni di base i polinomi di Bernstein: Jn,i(t) = n i ti (1 − t)n−i (0)0 ≡ 1 (2.3) Dove con n su k si intende il coefficiente binomiale: n k = n! k!(n − k)! 0! ≡ 1 La figura 2.6 mostra le funzioni di base per n = 4. Una curva con n + 1 punti di controllo, numerati da 0 a n, viene cos`ı rappresentata: P(t) = n i=0 Bi Jn,i(t) 0 ≤ t ≤ 1 (2.4) ove Bi indica l’i-esimo punto di controllo. Dato che utilizzano come funzioni di base i polinomi di Bernstein, alcune propriet`a delle curve di B´ezier sono note. ˆ Le funzioni di base sono reali; ˆ Il grado del polinomio `e pari a n (numero di punti di controllo meno uno); ˆ La curva solitamente segue la forma del poligono di controllo; ˆ Il primo e l’ultimo punto della curva coincidono con il primo e l’ultimo punto del poligono di controllo; ˆ La curva `e invariante rispetto a trasformazioni affini4; ˆ I vettori tangenti al primo e all’ultimo punto di controllo hanno la stessa direzione del primo e dell’ultimo lato del poligono di controllo. ˆ La curva rimane all’interno del pi`u grande poligono convesso formato dai punti di controllo, questa proprit`a va sotto il nome di propriet`a dell’involucro convesso; ˆ Si supponga di tracciare una retta in modo che essa “attraversi“ il poligono di controllo e di conseguenza la curva di B´ezier ad esso asso- ciata: il numero di intersezioni fra la retta e la curva non `e superiore al numero di intersezioni fra la retta e il poligono. Questa propriet`a va sotto il nome di variation-diminishing. 4 Una trasformazione affine `e una trasformazione x → Ax + b, ovvero la composizione di una trasformazione lineare determinata dalla matrice A e di una traslazione identificata dal vettore b. Una rotazione `e un esempio di trasformazione affine.
  29. 29. 2.2. CURVE 19 Figura 2.6: Funzioni di base per una curva di B´ezier con 5 punti di controllo 2.2.2 Curve B-Spline Le curve di B´ezier presentano due grossi limiti. Il primo `e rappresentato dalla relazione fra il numero di punti di controllo e il grado della curva ottenuta. Per cinque punti di controllo, si otterr`a sempre e comunque una curva di 4° grado. L’unico modo per variare il grado della curva `e di aumentare o diminuire il numero di punti di controllo. Il secondo problema riguarda una caratteristica dei polinomi di Bernstein: osservando la figura 2.6 si nota che ogni funzione Jn,i(u) copre l’intero spazio del parametro; ci`o significa che se si modifica un singolo punto di controllo, l’intera curva viene influenzata. Esiste un altro tipo di funzioni di base, le basi B-spline ( da basis spline ) di cui i polinomi di Bernstein sono un caso particolare. Queste funzioni di base permettono di decidere il grado della curva indipendentemente dal numero di punti di controllo e permettono inoltre di avere un controllo locale sulla curva. Definizione Sia P(t) il vettore posizione della curva espresso come funzione del parametro t. Una curva B-spline `e data da 5: P(t) = n+1 i=1 BiNi,k(t) tmin ≤ t < tmax, 2 ≤ k ≤ n + 1 (2.5) 5 Si noti che i punti di controllo sono numerati da 1 a n + 1, e non da 0 a n
  30. 30. 20 CAPITOLO 2. SPLINE, B-SPLINE E NURBS dove Bi rappresenta l’i-esimo punto di controllo, Ni,k(t) `e la funzione di base. La funzione di base Ni,k(t) di ordine k (grado k − 1) pu`o essere calcolata tramite la relazione di ricorrenza di Cox-de Boor: Ni,1(t) = 1 se xi ≤ t < xi+1 0 altrimenti Ni,k(t) = (t − xi)Ni,k−1(t) xi+k−1 − xi + (xi+k − t)Ni+1,k−1(t) xi+k − xi+1 (2.6) I valori xi sono componenti di un vettore, denominato vettore dei nodi, con la propriet`a che xi ≤ xi+1. Una propriet`a di queste funzioni di base `e che per un dato ordine k, la funzione di base Ni,k(t) `e diversa da 0 per xi ≤ t < xi+k. Quindi ogni punto di controllo influenza solo una zona limitata della curva, al contrario di ci`o che accade cone le curve di B´ezier. Una B-spline `e definita come uana spline polinomiale di ordine k in quanto soddisfa le segueti propriet`a: ˆ P(t) `e un polinomio di grado k − 1 per ogni intervallo xi ≤ t < xi+1; ˆ P(t) e le relative derivate di ordine 1, 2, . . . , k − 2 sono continue lungo l’intera curva. Una B-spline inoltre, possiede le seguenti propriet`a: ˆ La somma delle funzioni di base per ogni dato valore del parametro t `e pari a 1: n+1 i=1 Ni,k(t) ≡ 1 ˆ Ni,k(t) ≥ 0 per ogni valore del parametro t; ˆ La curva pu`o essere al massimo di ordine pari al numero di punti di controllo n + 1, quindi pu`o essere al massimo di grado n. ˆ La curva possiede la propriet`a variation-diminishing; ˆ La curva solitamente segue la forma del poligono di controllo; ˆ Qualsiasi trasformazione affine viene applicata alla curva applicandola al suo poligono di controllo; ˆ La curva risiede sempre all’interno dei poligoni convessi creati dai punti di controllo presi a gruppi di k.
  31. 31. 2.2. CURVE 21 Il vettore dei nodi Dall’equazione (2.6) appare evidente che la scelta del vettore dei nodi influisce sulle funzioni di base e di conseguenza sulla forma della curva. Sebbene l’unico requisito per un vettore di nodi sia che valga la relazione xi ≤ xi+1, di solito vengono utilizzate due categorie principali di vettori dei nodi, periodici e aperti, entrambi in versione uniforme o non-uniforme. Un vettore dei nodi uniforme, `e un vettore i cui elementi sono equispa- ziati, il che significa che xi+1 − xi = c con c costante arbitraria. Alcuni esempi sono 0 1 2 3 4 −0.2 −0.1 0.0 0.1 0.2 I vettori uniformi in genere iniziano da zero con incrementi unitari fino ad arrivare a qualche valore massimo, oppure vengono normalizzati all’interno dell’intervallo [0, 1]. Ad esempio: [ 0 0.25 0.5 0.75 1 ] Un vettore dei nodi uniforme periodico, per un dato ordine k porta a delle funzioni di base con la seguente propriet`a: Ni,k(t) = Ni−1,k(t − 1) = Ni+1,k(t + 1) Ogni funzione di base quindi altro non `e che la traslazione dell’altra. Un vettore dei nodi uniforme aperto ha ai suoi estremi dei valori di nodi ripetuti un numero di volte pari all’ordine k della B-Spline. I valori interni sono equispaziati. Alcuni esempi: k = 2 [ 0 0 1 2 3 4 4 ] k = 3 [ 0 0 0 1 2 3 3 3 ] k = 4 [ 0 0 0 0 1 2 2 2 2 ] Un vettore uniforme aperto `e cos`ı definito: xi = 0 1 ≤ i ≤ k xi = i − k k + 1 ≤ i ≤ n + 1 xi = n − k + 2 n + 2 ≤ i ≤ n + k + 1 La figura 2.7 mostra la differenza fra l’uso di un vettore dei nodi aperto e di un vettore dei nodi periodico, entrambi uniformi. Quando si utilizza un vettore uniforme aperto e il numero di punti di controllo `e pari all’ordine della curva, la base delle B-spline si riduce al polinomio di bernstein. Quindi la curva B-spline ottenuta `e in realt`a una curva di B´ezier. Il vettore dei nodi ottenuto in questo caso consiste di k zeri seguiti da k uno. [ 0 0 0 0 1 1 1 1 ]
  32. 32. 22 CAPITOLO 2. SPLINE, B-SPLINE E NURBS (a) (b) Figura 2.7: Due B-spline dello stesso ordine calcolate a partire dagli stessi punti di controllo: 2.7(a) con un vettore dei nodi uniforme aperto, 2.7(b) con un vettore nodi uniforme periodico (Immagini ottenute tramite la libreria da me sviluppata)
  33. 33. 2.2. CURVE 23 Un vettore non uniforme `e un vettore in cui l’unico vincolo `e quello standard: xi ≤ xi+1. Possono esserci valori ripetuti e possono essere equi- spaziati o meno. Esistono vettori dei nodi non uniformi aperti e non uniformi periodici, ecco alcuni esempi: [ 0 0 0 1 1 2 2 2 ] aperto [ 0 1 2 2 3 4 ] periodico [ 0 0.28 0.5 0.72 1 ] periodico Rappresentazione matriciale delle B-Spline L’equazione (2.5) pu`o essere espressa in notazione matriciale (come illustrato nella sezione 2.1.6). Questa “traduzione” `e particolarmente semplice se si assume l’utilizzo di un vettore dei nodi uniforme periodico. Con questo tipo di vettore infatti, ogni funzione di base `e traslazione dell’altra ed ognuna di esse ha influenza su esattamente k intervalli. Ci`o significa che tutte le funzioni di base per 0 ≤ t∗ < 1 hanno la stessa forma, quindi pu`o essere utile riparametrizzare le funzioni di base all’interno di questo intervallo. Un punto della B-spline riparametrizzata si ottiene dunque nel seguente modo: Pj(t∗ ) = k i=0 N∗ i+1,k(t∗ )Bj+i 1 ≤ j ≤ n − k + i, 0 ≤ t∗ < 1 (2.7) Dove j indica il tratto della curva. Supponiamo ora di lavorare con una B-spline di ordine k = 3, le funzioni di base riparametrizzate con t∗ ∈ [0, 1] sono: N∗ 1,3(t∗) = (1−t∗)2 2 N∗ 2,3(t∗) = −2t∗2+2t∗+1 2 N∗ 3,3(t∗) = t∗2 2 L’equazione (2.7) diventa quindi: 2Pj(t∗ ) = (1 − 2t∗ + t∗2 )Bj + (−2t∗2 + 2t∗ + 1)Bj+1 + t∗2 Bj+2 = t∗2 (Bj − 2Bj+1 + Bj+2) + t∗ (−2Bj + 2Bj+1 + 0Bj+2)+ + (Bj + Bj+1 + 0Bj+2) Passando in notazione matriciale si ottiene: Pj(t∗ ) = [T∗ ] [N∗ ] [B] = 1 2 t∗2 t∗ 1   1 −2 1 −2 2 0 1 1 0     Bj Bj+1 Bj+2  
  34. 34. 24 CAPITOLO 2. SPLINE, B-SPLINE E NURBS In modo simile `e possibile passare dalle funzioni di base alla notazione matriciale per k = 4, in questo caso le funzioni di base sono: N∗ 1,4(t∗) = −t∗3+3t∗2−3t∗+1 6 N∗ 2,4(t∗) = 3t∗3+6t∗2+4 6 N∗ 3,4(t∗) = −t∗3+3t∗2+3t∗+1 6 N∗ 4,4(t∗) = t∗3 6 e quindi la forma matriciale `e: Pj(t∗ ) = [T∗ ] [N∗ ] [B] = 1 2 t∗3 t∗2 t∗ 1     −1 3 −3 1 3 −6 3 0 −3 0 3 0 1 4 1 0         Bj Bj+1 Bj+2 Bj+3     Per un generico ordine k, il vettore [ T∗ ] ha la forma: t∗k−1 t∗k−2 . . . t∗ 1 mentre il generico ingresso della matrice [ N∗ ] = [ N∗ i+1,j+1 ] `e dato dalla seguente equazione: N∗ i+1,j+1 = 1 (k − 1)! k − 1 i k−1 l=j (k − (l + 1))i (−1)l−j k l − j 0 ≤ i, j ≤ k − 1 (2.8) 2.2.3 Interpolazione 2D tramite B-Spline Supponiamo di voler interpolare un insieme di punti utilizzando una B- spline. Il problema `e trovare dei punti di controllo tali da generare una curva che passi per i punti desiderati. Indichiamo con D il vettore dei punti della curva noti. Ogni punto Dj corrisponder`a ad un determinato valore del parametro t, che indicheremo con tj. Per appartenere alla B-spline, i punti devono soddifare l’equazione (2.5): D1(t1) = N1,k(t1)B1 + N2,k(t1)B2 + · · · + Nn+1,k(t1)Bn+1 D2(t2) = N1,k(t2)B1 + N2,k(t2)B2 + · · · + Nn+1,k(t2)Bn+1 ... Dj(tj) = N1,k(tj)B1 + N2,k(tj)B2 + · · · + Nn+1,k(tj)Bn+1
  35. 35. 2.2. CURVE 25 Dove 2 ≤ k ≤ n + 1 ≤ j. Questo sistema di equazioni pu`o essere scritto in modo pi`u compatto con la notazione matriciale: [ D ] = [ N ] [ B ] (2.9) Dove [ D ]T = D1(t1) D2(t2) . . . Dj(tj) [ B ]T = B1 B2 . . . Bn+1 [ N ] =       N1,k(t1) . . . . . . Nn+1,k(t1) ... ... ... ... ... ... N1,k(tj) . . . . . . Nn+1,k(tj)       Il valore del parametro tj associato ad ogni punto `e una misura della distanza tra i punti Di lungo la curva B-spline. Un utile approssimazione di questi valori utilizza la somma delle distanze euclidee fra ogni coppia di punti. Nello specifico, per j punti dati, il valore del parametro t associato all’l-esimo punto `e cos`ı calcolato: t1 = 0 tl tmax = l s=2 |Ds − Ds−1| j s=2 |Ds − Ds−1| l ≥ 2 (2.10) Dove |Di − Di−1| indica la distanza euclidea6 fra il punto i-esimo e il precedente. Una volta fissati il numero di punti di controllo, l’ordine e il vettore di nodi che si desidera utilizzare, si pu`o utilizzare l’equazione (2.6) per calcolare gli elementi della matrice [ N ]. Se si sceglie un numero di punti di controllo pari al numero di punti appartenenti alla curva (ovvero n + 1 = j), allora la matrice [ N ] `e quadrata, e i punti di controllo possono essere ottenuti dall’equazione (2.9) calcolando l’inversa della matrice [ N ]. [ B ] = [ N ]−1 [ D ] 2 ≤ k ≤ n + 1 = j (2.11) In questo caso, la B-spline ottenuta interpola tutti i punti specificati. Se invece di un interpolazione si desidera una approssimazione dei punti, basta scegliere un numero di punti di controllo inferiore al numero di punti della curva forniti (n + 1 < j). Cos`ı facendo la matrice [ N ] non `e pi`u quadrata e il sistema di equazioni (2.9) `e sovraspecificato (alcune equazioni non sono necessarie). Per risolvere il sistema moltiplichiamo entrambi i membri della (2.9) per [ N ]T , ottenendo cos`ı una matrice quadrata7 che possiamo tentare 6 La distanza euclidea fra due punti a e b `e pari a (ax − bx)2 + (ay − by)2 7 Data una matrice A rettangolare, il prodotto di A per la sua trasposta AT A `e una matrice quadrata
  36. 36. 26 CAPITOLO 2. SPLINE, B-SPLINE E NURBS di invertire: [ D ] = [ N ][ B ] [ N ]T [ D ] = [ N ]T [ N ][ B ] [ B ] = [[ N ]T [ N ]]−1 [ D ] (2.12) Il tipo di curva ottenuto quindi dipende esclusivamente dalla scelta dei valori di n+1, k e del tipo di vettore dei nodi. Ad esempio, se si sceglie un vettore dei nodi aperto con k = n + 1, la curva ottenuta `e una curva di B´ezier. 2.2.4 Curve NURBS NURBS sta per Non Uniform Rational B-Spline, ovvero B-Spline razionali non uniformi. Si tratta quindi, di B-Spline che utilizzano funzioni di base razionali ed un vettore dei nodi non uniforme, aperto o periodico che sia. Ci sono quindi anche B-Spline razionali uniformi aperte e uniformi periodiche. Dato che i vettori dei nodi sono stati mostrati nella sezione 2.2.2, qui mi limiter`o a definire in generale le B-Spline razionali. Definizione Una B-Spline razionale `e la proiezione di una B-Spline polinomiale definita in uno spazio quadridimensionale con coordinate omogenee all’interno di uno spazio tridimensionale8 (Vedere [19]). Ovvero: P(t) = n+1 i=1 Bh i Ni,k(t) (2.13) Dove con Bh i si indicano i punti di controllo omogenei nello spazio quadridi- mensionale. Ni,k(t) `e l’i-esima funzione di base polinomiale cos`ı come `e stata descritta dall’equazione (2.6). Per effettuare la proiezione, dividiamo il se- condo membro dell’equazione (2.13) per le coordinate omogenee, ottenendo cos`ı la B-spline razionale: P(t) = n+1 i=1 BihiNi,k(t) n+1 i=1 hiNi,k(t) = n+1 i=1 BiRi,k(t) (2.14) 8 Si assume che la curva sia definita nello spazio 3D invece che sul piano, il discorso `e comunque valido anche per il 2D: l’unica differenza, `e che i punti Bi sono identificati da due coordinate invece di tre.
  37. 37. 2.2. CURVE 27 Qui con Bi si indicano i punti di controllo tridimensionali della B-spline razionale e le Ri,k(t) = hiNi,k(t) n+1 i=1 hiNi,k(t) (2.15) sono le basi razionali. Le B-spline razionali contengono le B-spline come caso particolare: se hi = 1 ∀i, allora la curva ottenuta `e una B-spline non razionale. Le coordinate omogenee hi sono anche denominate pesi, in quan- to permettono di decidere quanta influenza deve avere un singolo punto di controllo sulla curva. La figura 2.2.4 mostra l’effetto che ha il cambio di un peso su una curva NURBS. Figura 2.8: Effetto del cambio di un peso su una curva nurbs. Tutte le curve sono state calcolate con lo stesso vettore dei nodi e gli stessi punti di controllo, ma `e stato variato il peso del terzo punto: dall’alto verso il basso, i valori di h3 sono rispettivamente 2, 1.5, 1, 0.75, 0.5, 0.25 e 0.(Immagini ottenute tramite la libreria da me sviluppata) Propriet`a In quanto generalizzazione delle B-Spline non razionali, le B-Spline razionli condividono con esse alcune propriet`a. Ad esempio:
  38. 38. 28 CAPITOLO 2. SPLINE, B-SPLINE E NURBS ˆ Ogni funzione di base razionale `e maggiore o uguale a 0 per ogni valore del parametro t, ovvero: Ri,k(t) ≥ 0 ∀t ∈ [tmin, tmax] ˆ La somma di tutte le funzioni di base per un dato valore del parametro t `e pari a 1: n+1 i=1 Ri,k(t) ≡ 1 ˆ Una B-spline razionale di ordine k ha ovunque una continuit`a di tipo Ck−2; ˆ Il massimo ordine che una B-Spline razionale pu`o assumere `e pari al numero di punti di controllo; ˆ Le B-spline razionali possiedono la propriet`a variation-diminishing; ˆ Se tutti i pesi hi sono positivi, la B-spline razionale rimane all’interno dell’unione degli involucri convessi formati da gruppi di k punti di controllo. ˆ Qualsiasi trasformazione proiettiva `e applicata alla B-spline razionale applicandola ai vertici del poligono di controllo; La curva `e invariante alle trasformazioni proiettive9. Si noti che questa condizione `e pi`u forte rispetto a quella espressa per le B-spline non razionali, che sono invarianti rispetto alle trasformazioni affini. 2.3 Superfici Rappresentare una superficie in forma parametrica non `e molto diverso dal rappresentare una curva. La differenza principale `e che sono necessari due parametri invece di uno: c1 ≤ u ≤ c2 c3 ≤ w ≤ c4 Una volta fissato l’intervallo di definizione dei due parametri tramite le co- stanti c1, c2, c3 e c4 10, bisogna esprimere le coordinate dei punti come 9 Una trasformazione proiettiva descrive cosa accade alla posizione percepita di un oggetto osservato quando il punto di vista dell’osservatore cambia. 10 cos`ı definiti i parametri u e w identificano una forma rettangolare nel piano para- metrico: sebbene si possa utilizzare una qualsiasi forma nello spazio parametrico per poi mapparla all’interno dello spazio 3D, continuer`o ad utilizzare per semplicit`a quella rettangolare.
  39. 39. 2.3. SUPERFICI 29 funzioni parametriche: x = x(u, w) y = y(u, w) z = z(u, w) Specificando un parametro e lasciando variare l’altro si ottiene quella che viene definita una linea parametrica. Specificando il valore di entrambi i parametri si ottiene un determinato punto della superficie. Un’ulteriore differenza `e che ora abbiamo una matrice m×n 11di punti di controllo e non un vettore. Essi sono numerati nel modo seguente:       B0,m B1,m . . . Bn,m ... ... ... ... ... ... B0,0 B1,0 . . . Bn,0       Dove m e n sono rispettivamente il numero di punti di controllo lungo la direzione w e u. 2.3.1 Superfici di B´ezier Definizione e Propriet`a Una superficie di B´ezier per un poliedro di controllo con n + 1 punti lungo la direzione u e m + 1 punti lungo la direzione w `e data dalla seguente equazione: Q(u , w) = n i=0 m j=0 Bi,jJn,i(u)Km,j(w) (2.16) Dove Jn,i(u) e Km,j(w) sono le funzioni di base di Bernstein cos`ı come descritte dall’equazione (2.3). Dato che vengono utilizzate le funzioni di base di Bernstein, le superfici di B´ezier ereditano da esse alcune propriet`a: ˆ Il grado della superficie in ogni direzione parametrica `e pari al numero di punti di controllo in quella direzione meno 1; ˆ La superficie in genere segue la forma del poliedro di controllo; ˆ La superficie possiede lungo le direzioni u e w rispettivamente una continuit`a di tipo Cn−1 e Cm−1; 11 In realt`a dato che ogni elemento della matrice contiene le coordinate di un punto, la matrice `e di dimensioni m × n × 3
  40. 40. 30 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Figura 2.9: Esempio di superficie di B´ezier (Immagine ottenute tramite la libreria da me sviluppata) ˆ La superficie `e contenuta nell’involucro convesso creato dal poligono di controllo; ˆ La superficie `e invariante rispetto alle trasformazioni affini; ˆ La superficie non mostra di avere la prorpriet`a variation-diminishing, essa `e al contempo non definita e non conosciuta. 2.3.2 Superfici B-Spline Definizione e propriet`a Una superficie B-spline per un poliedro di controllo con n + 1 punti lungo la direzione u e m + 1 punti lungo la direzione w `e data dalla seguente equazione: Q(u, w) = n+1 i=1 m+1 j=1 Bi,jNi,k(u)Mj,l(w) (2.17) Dove Ni,k(u)e Mj,l(w) sono le funzioni di base b-spline cos`ı come descritte dall’equazione (2.6). Come per le curve, la scelta dei vettori dei nodi [X] e [Y ] (relativi rispettivamente alle direzioni u e w) influisce sulla forma della curva. Sebbene di solito si utilizzi lo stesso tipo di vettore per entrambe le direzioni, `e possibile scegliere tipi diversi. La figura 2.10 a pagina 32 mostra delle superfici B-Spline che utilizzano diverse combinazioni dei vettori dei nodi. Dato che vengono utilizzate le funzioni di base B-spline, le superfici B-Spline ereditano da esse alcune propriet`a, ad esempio:
  41. 41. 2.3. SUPERFICI 31 ˆ L’ordine massimo della superficie lungo le due direzioni u e w `e pari al numero di punti di controllo lungo quella direzione meno uno. ˆ La continuit`a della superficie `e di tipo Ck−2 lungo la direzione u e Cl−2 lungo la direzione w. ˆ La superficie `e invariante rispetto alle trasformazioni affini: una tra- sformazione affine `e applicata alla superficie applicandola invece al poliedro di controllo. ˆ La propriet`a variation-diminishing non `e nota per le superfici B-Spline. ˆ Se l’ordine della B-spline `e pari al numero di punti di controllo in entrambe le direzioni parametriche e si utilizzano dei vettori dei nodi di tipo uniforme aperto, la superficie B-spline si riduce ad una superficie di B´ezier. ˆ La regione di influenza di un singolo punto di controllo `e limitata a ±k 2 tratti lungo la direzione u e ± l 2 tratti lungo la direzione w. ˆ La superficie risiede all’interno degli involucri convessi formati pren- dendo k, l punti di controllo adiacenti. Rappresentazione matriciale Una rappresentazione matriciale per una superficie B-spline periodica `e del tipo: Qs,t = [ U∗ ][ N∗ ][ B∗ s,t ][ M∗ ]T [ W∗ ]T (2.18) Dove [ U∗ ] = [ u∗k−1 u∗k−2 . . . u∗ 1 ] [ W∗ ] = [ w∗l−1 w∗l−2 . . . w∗ 1 ] con u∗ e w∗ ad indicare i parametri scalati nell’intervallo [0 , 1]. Le matrici [ N∗ ] e [ M∗ ] sono date dall’equazione (2.8). La matrice [ Bs,t ] rappresenta una “finestra scorrevole” che consente di calcolare delle sotto-superfici a partire da un sottoinsieme di k × l punti di controllo. Per superfici B-spline periodiche calcolate a partire da un poliedro di punti di controllo aperto: [ B∗ s,t ] = [ Bi,j ] (2.19) Dove 1 ≤ s ≤ n − k + 2 s ≤ i ≤ s + k − 1 1 ≤ t ≤ m − l + 2 t ≤ j ≤ t + l − 1 (2.20) Bi,j rappresenta un elemento della matrice dei punti di controllo.
  42. 42. 32 CAPITOLO 2. SPLINE, B-SPLINE E NURBS (a) (b) (c) (d) Figura 2.10: Effetto dell’uso di diversi tipi di vettori dei nodi su una su- perficie B-Spline: 2.10(a) il poliedro di controllo; 2.10(b) entrambi i vettori di tipo uniforme aperto; 2.10(c) [X] di tipo uniforme periodico e [Y ] di ti- po uniforme aperto; 2.10(d) entrambi i vettori di tipo periodico. (Immagini ottenute tramite la libreria da me sviluppata)
  43. 43. 2.3. SUPERFICI 33 2.3.3 Interpolazione 3D tramite B-Splines Come nel caso delle curve mostrato nella sezione 2.2.3, anche le superfici B- spline possono essere utilizzate per interpolare (o approssimare) un insieme di punti nello spazio. Organizziamo idealmente i punti da interpolare in una maglia rettangolare r × s e indichiamo con D la matrice r ∗ s × 3 che li contiene, con 2 ≤ k ≤ n + 1 ≤ r e 2 ≤ l ≤ m + 1 ≤ s. Il generico elemento della matrice Di,j sar`a associato a due valori dei parametri, ui e wj. Per appartenere alla superficie, un punto deve soddisfare l’equazione (2.17). Ad esempio il punto D1,1 otteniamo: D1,1(u1, w1) = N1,k(u1)[M1,l(w1)B1,1 + M2,l(w1)B1,2 + · · · + Mm+1,l(w1)B1,m+1]+ ... Nn+1,k(u1)[M1,l(w1)Bn+1,1 + M2,l(w1)Bn+1,2 + · · · + Mm+1,l(w1)Bn+1,m+1] Scrivendo quest’equazione per ognuno dei punti da interpolare, si forma un sistema di equazioni che pu`o essere riscritto in forma matriciale nel seguente modo: [ D ] = [ C ][ B ] (2.21) dove Ci,j = Ni,kMj,l. Come gi`a detto, [ D ] `e una matrice r ∗ s×3, [ C ] `e una matrice r ∗ s×n ∗ m contenente i prodotti delle funzioni di base, e [ B ] `e una matrice n ∗ m × 3 delle coordinate dei punti di controllo , rappresentante l’incognita del problema. Se [ C ] `e quadrata, il problema pu`o essere risolto direttamente calcolandone l’inversa: [ B ] = [ C ]−1 [ D ] (2.22) In questo caso la superficie ottenuta passa per tutti i punti dati. Se in- vece [ C ] non `e quadrata, il problema `e sovraspecificato, e pu`o essere solo approssimato: [ B ] = [[ C ]T [ C ]]−1 [ D ] (2.23) I valori dei parametri ui e wj possono essere ricavati in modo simile a quello descritto dall’equazione (2.10): u1 = 0 uq umax = q g=2 |Dg,p − Dg−1,p| r g=2 |Dg,p − Dg−1,p| 1 ≤ p ≤ s 1 ≤ q ≤ r (2.24)
  44. 44. 34 CAPITOLO 2. SPLINE, B-SPLINE E NURBS Lo stesso discorso vale per il parametro w: w1 = 0 wq wmax = q g=2 |Dp,g − Dp,g−1| s g=2 |Dp,g − Dp,g−1| 1 ≤ p ≤ r 1 ≤ q ≤ s (2.25) dove umax e wmax sono, rispettivamente, i valori massimi dei vettori dei nodi [X] e [Y ]. 2.3.4 Superfici NURBS Definizione e propriet`a Una superficie B-Spline razionale con coordinate omogenee quadridimensio- nale si ottiene dalla seguente equazione: Q(u, w) = n+1 i=1 m+1 j=1 Bh i,jNi,k(u)Mj,l(w) (2.26) Dove con Bh i,j si indicano i punti di controllo omogenei, e con Ni,k(u)Mj,l(w) le funzioni di base b-spline cos`ı come definite dall’equazione (2.6). La pro- iezione della B-spline non razionale definita nello spazio omogeneo quadri- dimensionale all’interno dello spazio tridimensionale si ottiene tramite la seguente equazione: Q(u, w) = n+1 i=1 m+1 j=1 hi,jBi,jNi,k(u)Mj,l(w) n+1 i=1 m+1 j=1 hi,jNi,k(u)Mj,l(w) = n+1 i=1 m+1 j=1 Bi,jSi,j(u, w) (2.27) dove Bi,j indica il punto di controllo tridimensionale di posizione (i, j), e Si,j(u, w) `e la funzione di base della superficie B-spline razionale: Si,j(u, w) = hi,jNi,k(u)Mj,l(w) n+1 i1=1 m+1 j1=1 hi1,j1Ni1,k(u)Mj1,l(w) = hi,jNi,k(u)Mj,l(w) Somma(u, w) (2.28) con Somma(u, w) = n+1 i1=1 m+1 j1=1 hi1,j1Ni1,k(u)Mj1,l(w) `E comodo, sebbene non necessario, assumere hi,j ≥ 0 ∀i, j. Essendo co- struite a partire dalle funzioni di base B-spline, le superfici B-spline razionali ereditano da esse alcune caratteristiche, ad esempio:
  45. 45. 2.3. SUPERFICI 35 ˆ La somma delle funzioni di base Si,j(u, w) `e pari a uno per ogni valore dei parametri u e w; ˆ L’ordine massimo della superficie lungo le due direzioni u e w `e pari al numero di punti di controllo lungo quella direzione meno uno; ˆ La continuit`a della superficie `e di tipo Ck−2 lungo la direzione u e Cl−2 lungo la direzione w. ˆ La superficie `e invariante rispetto alle trasformazioni proiettive: una trasformazione proiettiva `e applicata alla superficie applicandola inve- ce al poliedro di controllo; ˆ La propriet`a variation-diminishing non `e nota per le superfici B-Spline razionali. ˆ Se hi,j = 1 ∀i, j, la superficie B-spline razionale si riduce alla contro- parte non razionale. Se inoltre k = n+1, l = m+1 e i vettori dei nodi utilizzati sono di tipo uniforme aperto, la superficie B-spline razionale si riduce ad una superficie di B´ezier non razionale. ˆ La regione di influenza di un singolo punto di controllo `e limitata a ±k 2 tratti lungo la direzione u e ± l 2 tratti lungo la direzione w. ˆ Se hi,j ≥ 0 ∀i, j, la superficie risiede all’interno degli involucri con- vessi formati prendendo k, l punti di controllo adiacenti. Una superficie B-spline razionale che utilizza dei vettori dei nodi di tipo non-uniforme, `e la forma pi`u generale di rappresentazione di una superficie. La possibilit`a di utilizzare dei pesi (sia positivi che negativi) per i punti di controllo, permette di disegnare superfici che non possono essere disegnate con delle superfici b-spline non-razionali. La figura 2.11 mostra gli effetti della variazione di un peso su una superficie B-spline razionale.
  46. 46. 36 CAPITOLO 2. SPLINE, B-SPLINE E NURBS (a) h2,3 = 0 (b) h2,3 = 1 (c) h2,3 = 5 (d) h2,3 = 10 Figura 2.11: Effetto della variazione di un peso su una superficie B-spline razionale. Il valore di h2,3 (il punto di controllo pi`u alto) `e stato variato mentre tutti gli altri sono pari a uno. Nella figura 2.11(a) il punto viene completamente ignorato, mentre nella figura 2.11(b) la superficie ottenuta `e una B-spline non razionale. (Immagini ottenute tramite la libreria da me sviluppata)
  47. 47. Capitolo 3 Cenni di Python Ed ora passiamo a qualcosa di completamente diverso. Monthy Python In questo capitolo verranno illustrate alcune peculiarit`a del linguaggio Python. La scelta di questo linguaggio `e dovuta a diversi fattori: innan- zitutto, il Python, per essere un linguaggio interpretato, `e molto veloce, `e multi-piattaforma e permette di risolvere problemi complessi con poche ri- ghe di codice. Questo linguaggio `e corredato da un vasto insieme di librerie, come ad esempio NumPy (vedi [4]), che offre funzioni per il calcolo scientifi- co e l’algebra lineare.L’uso di Python permette l’uso della libreria in diversi ambiti. Software di modellazione 3D come Blender (vedi [1]) permettono di includere script in Python, rendendo gli utenti di Blender potenziali uten- ti della libreria. La versione di Python utilizzata `e la 2.6.5. Sul Python ci sarebbe da scrivere davvero, davvero molto. Questo linguaggio, creato da Guido Van Rossum nei tardi anni ’80 con l’intento di correggere buona parte dei difetti a suo dire presenti negli altri linguaggi di programmazione, `e diventato ad oggi uno dei linguaggi pi`u apprezzati, trovando applicazio- ni ovunque. Python `e un linguaggio molto versatile, si possono scrivere programmi utilizzando il paradigma di programmazione procedurale, quello orientato agli oggetti, il paradigma funzionale, ed `e anche possibile scrivere semplici script. Dato che una presentazione approfondita delle funzionalit`a del Python va oltre gli obiettivi di questo lavoro, di seguito saranno elencate solo alcune caratteristiche, funzioni ed esempi di sintassi necessari a com- prendere al meglio il lavoro svolto. Per approfondimenti `e disponibile sotto licenza GPL 1 il libro [18] che rappresenta l’attuale punto di riferimento 1 Gnu General Public License, http://www.gnu.org/licenses/gpl.html 37
  48. 48. 38 CAPITOLO 3. CENNI DI PYTHON per chi vuole imparare Python. La pagina [10] presenta, oltre ad una breve guida di stile, alcune tecniche e caratteristiche proprie del linguaggio. 3.1 Caratteristiche basilari Una delle peculiarit`a del Python `e che esso non utilizza caratteri speciali per individuare blocchi di codice, ma utilizza il livello di indentazione. Un codice male indentato non viene interpretato da python. Il linguaggio quin- di `e pensato in modo da costringere il programmatore a scrivere codice ordinato. Il Python inoltre utilizza la tipizzazione dinamica, caratteristica propria di diversi linguaggi di alto livello come Matlab e Ruby. Ci`o vuol dire che non c’`e vincolo di tipo per una data variabile. Ad esempio2: 1 >>> a = 5 2 >>> print a 3 5 4 # type restituisce il tipo della variabile fornita come parametro 5 >>> type(a) 6 <type ’int’> 7 >>> a = ’Hello World!’ 8 >>> print a 9 Hello World! 10 >>> type(a) 11 <type ’str’> 12 >>> a = range(5) 13 >>> print a 14 [0, 1, 2, 3, 4] 15 >>> type(a) 16 <type ’list’> Ci`o `e reso possibile trattando le variabili in un modo fondamentalmente diverso da quello utilizzato dai linguaggi di livello pi`u basso. Quando, ad esempio in C, si dichiarano tre variabili a1, a2, a3, viene riservato in me- moria dello spazio, la cui quantit`a dipende dal tipo di variabili. Questo spazio viene riservato anche se le variabili sono tutte e tre dello stesso tipo e contengono tutte lo stesso valore. Quindi se le tre variabili sono di tipo intero e hanno tutte valore 10, in memoria vengono riservati 3 × 4 = 12 bytes. Se sono 1’000’000, vengono conservati 4’000’000 di bytes. Python memorizza il valore una volta, ed assegna a quella zona di memoria tante “etichette” quante sono le variabili che hanno quel valore. Quindi in python ad ogni variabile non corrisponde una zona di memoria, una variabile `e un etichetta che viene assegnata alla zona di memoria che contiene il valore attuale della variabile. 2 ’>>>’ rappresenta il prompt dell’ interprete python
  49. 49. 3.2. LE LISTE 39 3.2 Le liste Uno dei punti di forza del Python risiede nelle strutture che offre. Una di queste strutture `e la lista. La lista, in Python, `e l’alternativa ai vettori. Mentre un vettore `e una collezione di oggetti omogenei, ovvero tutti dello stesso tipo, ed `e di taglia fissata, una lista in Python pu`o contenere oggetti eterogenei e la sua taglia `e dinamica. Gli elementi di una lista con n elementi sono numerati da 0 a n − 1. Qualche esempio: 1 >>> l = [] # inizializzo l come lista 2 >>> l.append(4) # aggiungo alla lista il numero 4 3 >>> l 4 [4] 5 >>> l.append(’Hello World!’) # aggiungo la stringa "Hello World!" 6 >>> l 7 [4, ’Hello World!’] 8 >>> l.append(5.9) # aggiungo alla lista il numero 5.9 9 >>> l 10 [4, ’Hello World!’, 5.9000000000000004] 11 >>> l[2] # accedo all’elemento di indice 2 12 5.9000000000000004 13 >>> l[-1] # accedo all’ultimo elemento della lista 14 5.9000000000000004 15 >>> l[-2] # accedo al penultimo elemento della lista 16 ’Hello World!’ 17 >>> l[1] # che l’elemento di indice 1 18 ’Hello World!’ 19 >>> for item in l: # per ogni elemento della lista 20 ... type(item) # controllo il tipo dell’elemento 21 ... 22 <type ’int’> 23 <type ’str’> 24 <type ’float’> I comandi dell’esempio precedente mostrano come la lista venga estesa man mano aggiungendo oggetti. Si noti che una lista `e un oggetto iterabile, infatti nel ciclo presente alla fine del listato si chiede di verificare il tipo di ogni elemento della lista, che contiene alla fine un intero, una stringa ed un numero in virgola mobile. L’indicizzazione degli elementi `e di tipo circolare. Infatti se si chiede di accedere all’elemento di indice −1 Python restituisce l’ultimo elemento della lista. Supponiamo ora di voler costruire un vettore di potenze, tale che p[i] = i2 ∀i ∈ [0, 9]. In linguaggio C la cosa pu`o essere risolta nel seguente modo: 1 int p[10]; 2 int i; 3 4 for( i=0; i < 10; i++){ 5 p[i] = i*i;
  50. 50. 40 CAPITOLO 3. CENNI DI PYTHON 6 } In Python: 1 >>> p = [i**2 for i in range(10)] 2 >>> p 3 [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] in una sola riga di codice, dove range(n) `e una funzione che genera una lista contenente i valori dell’intervallo [0, n − 1] e ** `e l’operatore di elevamento a potenza. In generale per costruire una lista fatta di oggetti determinati ( o selezionati) da una funzione f(n) a partire la una lista di elementi, in python si pu`o scrivere: 1 risultato = [f(elemento) for elemento in lista] `E anche possibile introdurre delle condizioni in questa notazione. Ad esem- pio, supponendo che si voglia inserire nella lista l’ipotetica funzione f se elemento `e compreso fra 0 e k, 0 altrimenti: 1 risultato = [f(elemento) if elemento >= 0 and elemento < k else 0 for elemento in lista] Questa notazione pu`o essere annidata in modo da creare liste di liste. Ad esempio se volessi creare una lista, il cui i-esimo elemento `e una lista delle potenze ij, con i ∈ [0, 5], j ∈ [0, 9] , posso scrivere: 1 >>> potenze = [[ i**j for j in range(10)] for i in range(6) ] 2 >>> potenze 3 [[1, 0, 0, 0, 0, 0, 0, 0, 0, 0], 4 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 5 [1, 2, 4, 8, 16, 32, 64, 128, 256, 512], 6 [1, 3, 9, 27, 81, 243, 729, 2187, 6561, 19683], 7 [1, 4, 16, 64, 256, 1024, 4096, 16384, 65536, 262144], 8 [1, 5, 25, 125, 625, 3125, 15625, 78125, 390625, 1953125]] Un’altra comodit`a `e il sistema di slicing, ovvero la possibilit`a di accedere a “fette” della lista. Alcuni esempi: 1 >>> lista = range(10) 2 >>> lista 3 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 4 >>> lista[2:6] # prendo gli elementi dal 2 al 5 5 [2, 3, 4, 5] 6 >>> lista[-3:] # solo gli ultimi 3 7 [7, 8, 9] 8 >>> lista[:3] # solo i primi 3 9 [0, 1, 2] 10 >>> lista[::2] # un elemento ogni due 11 [0, 2, 4, 6, 8] 12 >>> lista[2:9:3] # un elemento ogni tre dal 2 all’8
  51. 51. 3.3. I DIZIONARI 41 13 [2, 5, 8] Un’altra funzione che ho usato spesso durante il mio lavoro `e stata la funzione enumerate. Questa funzione `e utile quando nell’iterare una lista, si vuole utilizzare anche l’indice di posizione degli elementi. Normalmente una soluzione sarebbe 1 >>> for i in range(len(lista)): 2 ... print i, lista[i] che utilizza la funzione len, la quale restituisce il numero di elementi con- tenuti in una collezione. Utilizzando enumerate 1 >>> for i, elemento in enumerate(lista): 2 ... print i, elemento si ottiene un codice pi`u elegante e facile da comprendere, ed anche pi`u veloce. Da ricordare inoltre `e l’operatore in, che permette di verificare se un oggetto si trova all’interno di una collezione: 1 >>> lista = range(10) 2 >>> tupla = (’Python’,’C’,’C++’) 3 >>> 5 in lista 4 True 5 >>> 50 in lista 6 False 7 >>> ’Python’ in tupla 8 True 9 >>> ’Java’ in tupla 10 False 3.3 I dizionari Un dizionario `e un array associativo, ovvero un array all’interno del quale ad ogni elemento `e associata una chiave che lo identifica. L’implementazione che Python offre di questa struttura dati di alto livello `e tanto comoda quanto semplice da utilizzare. Un classico esempio `e quello della rubrica: 1 >>> rubrica = dict() 2 >>> rubrica[’bianchi’] = 99654321 3 >>> rubrica[’verdi’] = 11123456 4 >>> rubrica[’rossi’] = 10123456 5 >>> rubrica 6 {’bianchi’: 99654321, ’rossi’: 10123456, ’verdi’: 11123456} Dal dizionario `e possibile ottenere liste iterabili delle chiavi e dei valori memorizzati:
  52. 52. 42 CAPITOLO 3. CENNI DI PYTHON 1 >>> rubrica.keys() 2 [’bianchi’, ’rossi’, ’verdi’] 3 >>> rubrica.values() 4 [99654321, 10123456, 11123456] e controllare se esiste una determinata chiave: 1 >>> rubrica.has_key(’rossi’) 2 True 3 >>> rubrica.has_key(’python’) 4 False `e possibile creare un dizionario prendendo chiavi e valori da due liste separate nel seguente modo: 1 >>> nomi = [’nome1’,’nome2’,’nome3’] 2 >>> valori = [ 5, 10, 15 ] 3 >>> dizionario = dict(zip(nomi,valori)) 4 >>> dizionario 5 {’nome1’: 5, ’nome2’: 10, ’nome3’: 15} zip `e una funzione che a partire da un insieme di liste, restituisce una lista di tuple, ovvero delle ennuple non modificabili: 1 >>> zip(nomi,valori) 2 [(’nome1’, 5), (’nome2’, 10), (’nome3’, 15)] 3.4 Programmazione orientata agli oggetti Una classe in python `e definita nel seguente modo: 1 class NomeClasse: 2 def __init__(self, attributo1, attributo2, ..., attributoN): 3 self.attributo1 = attributo1 4 self.attributo2 = attributo2 5 ... 6 def metodo1(self,parametro1, parametro2, ..., parametroN): 7 # corpo del metodo1 8 ... 9 10 oggetto = NomeClasse(valore1, valore2, ..., valoreN) init `e il metodo costruttore. Il primo parametro che viene passato ad ogni metodo della classe `e self, che `e un riferimento all’oggetto stesso (come this in Java). Da notare che non c’`e nessun tipo di riferimento ai modificatori di accesso per attributi e metodi; questo perch´e python non prevede alcun tipo di modificatore di accesso, ergo non esistono attributi o metodi privati. Per indicare che un attributo o un metodo `e privato esiste
  53. 53. 3.4. PROGRAMMAZIONE ORIENTATA AGLI OGGETTI 43 una convenzione di nomenclatura, che consiste nell’anteporre un doppio un- derscore (il carattere ’ ’) al nome dell’attributo o del metodo in questione. Un piccolo esempio: 1 >>> class Prova: 2 ... def __init__(self,valore): 3 ... self.__attributo = valore 4 ... 5 >>> p = Prova(’ciao’) 6 >>> p.attributo 7 Traceback (most recent call last): 8 File "<stdin>", line 1, in <module> 9 AttributeError: Prova instance has no attribute ’attributo’ 10 >>> p.__attributo 11 Traceback (most recent call last): 12 File "<stdin>", line 1, in <module> 13 AttributeError: Prova instance has no attribute ’__attributo’ 14 >>> dir(p) 15 [’_Prova__attributo’, ’__doc__’, ’__init__’, ’__module__’] 16 >>> p._Prova__attributo 17 ’ciao’ L’attributo non `e a tutti gli effetti privato, utilizzando la convenzio- ne di nomenclatura, python cambia il nome dell’attributo / metodo in NomeClasse NomeAttributo. Questo `e probabilmente uno dei pochi di- fetti di python, anche se gli utenti di questo linguaggio spiegano la cosa con un secco “We are all consenting adults here”, ovvero “Siamo tutti adulti consenzienti”, ad indicare che non dovrebbe essere il linguaggio ad impedire l’accesso ad un attributo o ad un metodo, ma il buon senso di chi utilizza la classe. Che si sia d’accordo o meno con questa filosofia, esiste un piccolo truc- co per proteggere almeno gli attributi. Tra i vari metodi standard che fanno parte di una classe python, compare il metodo set attribute . Il corpo di questo metodo contiene il codice da esegure quando si tenta di assegnare un valore ad un attributo con oggetto.attributo = valore. Il problema `e che anche self.attributo = valore `e una assegnazione diretta, quindi dopo aver sovrascritto set attribute anche all’interno della classe stes- sa non possono assegnare direttamente dei valori agli attributi. Bisogna, invece, agire direttamente sul dizionario interno alla classe che conserva le associazioni nome / valore degli attributi. Se ad esempio volessi impedi- re che l’attributo ’voto’ di un ipotetica classe ’Esame’ venga modificato, la suddetta classe dovrebbe essere scritta all’incirca nel seguente modo: 1 class Esame: 2 def __init__(self,voto): 3 self.__dict__[’voto’] = voto 4 ... 5 def __set_attribute__(self,nome,valore): 6 if nome == ’voto’:
  54. 54. 44 CAPITOLO 3. CENNI DI PYTHON 7 print "Impossibile modificare l’attributo voto" 8 else: 9 self.__dict__[nome] = valore Per quanto riguarda l’ereditariet`a, Python offre sia l’ereditariet`a singola che quella multipla. Non tutti i linguaggi possiedono questa caratteristica: in Java, ad esempio, per ottenere qualcosa di simile bisogna utilizzare il mec- canismo delle interfacce. Un interfaccia Java per`o contiene solo la firma dei metodi, non la loro implementazione, quindi ogni volta che si ereditano dei metodi da un interfaccia essi vanno implementati anche se l’implementazio- ne `e gi`a disponibile in un’altra classe, il che comporta ridondanza di codice. Per far ereditare attributi e metodi in Python, la sintassi `e la seguente 1 class ClasseDerivata(Classe1, Classe2, ..., ClasseN): 2 ... Se un metodo, che per esempio chiameremo metodo1, `e presente in pi`u di una classe genitore, per decidere quale versione di metodo1 richiamare bisogna sovrascrivere il metodo nella classe figlia, per poi richiamare espli- citamente l’implementazione che vogliamo. Supponendo di voler utilizzare l’implementazione offerta da Classe2: 1 class ClasseDerivata(Classe1, Classe2, ..., ClasseN): 2 ... 3 def metodo1(self, parametro 1, ..., parametroN): 4 Classe2.metodo1(self, parametro 1, ..., parametroN) Per controllare se un oggetto `e istanza di una classe (o se una variabile ha un valore di un dato tipo) si pu`o utilizzare l’istruzione isistance, che prende come parametro l’oggetto da verificare e la classe. La caratteristica comoda di questa istruzione `e che pu`o essere utilizzata per verificare pi`u classi alla volta passando come secondo parametro una collezione di classi (una lista o una tupla). Ad esempio: 1 >>> a = 5 2 >>> isinstance(a,(int,list,dict)) 3 True 4 >>> a = ’HelloWorld!’ 5 >>> isinstance(a,(int,list,dict)) 6 False 7 >>> a = [1,2,3] 8 >>> isinstance(a,(int,list,dict)) 9 True 3.5 Le eccezioni Il modo in cui Python gestisce le eccezioni `e simile a quello utilizzato da altri linguaggi orientati agli oggetti come C++ e Java. La sintassi `e la seguente:
  55. 55. 3.5. LE ECCEZIONI 45 1 try: 2 # codice che potrebbe generare l’errore 3 except TipoEccezione: 4 # codice da esegure se si solleva l’eccezione 5 else: 6 # codice da esegure solo se non stata sollevata 7 # NESSUNA eccezione 8 finally: 9 # codice da eseguire in ogni caso Ci sono diverse eccezioni standard disponibili con Python, ad esempio: IOError Eccezione che si solleva in caso di errore di I/O; TypeError Eccezione che si solleva quando si tenta di applicare un opera- zione o una funzione ad una variabile del tipo sbagliato (ad esempio invocare len su una variabile che contiene un intero); ImportError Eccezione sollevata quando si tenta di importare un modulo non installato; ValueError Eccezione sollevata quando si passa ad una funzione un pa- rametro del tipo giusto ma con un valore inaspettato (ad esempio si riceve un valore negativo quando ci si aspettava un valore maggiore di 0); IndexError Eccezione sollevata quando si tenta di accedere ad un indice fuori limite in una lista. `E possibile creare eccezioni personalizzate estendendo la classe Exception: 1 class MiaEccezione(Exception): 2 def __init__(self, descrizione): 3 self.descrizione = descrizione 4 def __str__(self): 5 print descrizione str `e l’equivalente del metodo toString di Java. L’eccezione pu`o essere sollevata tramite l’istruzione raise: 1 if valore < 0: 2 raise ValueError(’Il valore deve essere > 0’) Per accedere alla descrizione di una eccezione si pu`o utilizzare l’operatore di ridenominazione as: 1 try: 2 # codice che potrebbe sollevare l’errore 3 except IOError as descrizione: 4 print "Errore: ", descrizione
  56. 56. 46 CAPITOLO 3. CENNI DI PYTHON 3.6 Librerie utilizzate Nello scrivere la libreria per il calcolo delle nurbs, ho utilizzato principal- mente due librerie: NumPy Principalmente per le classi e i metodi per l’algebra lineare ed altre funzioni di comodo; Matplotlib Per il plot 2D e 3D. Le versioni utilizzate sono numpy-1.3.0 e matplotlib-0.99.1.1. Per importare un modulo in python si utilizza l’istruzione import. `E possibile anche im- portare singole componenti di un modulo, invece di del modulo intero, ed eventualmente rinominarle utilizzando l’operatore di rideominazione as. Ad esempio: 1 # senza utilizzare as 2 import modulo1.classe1 3 4 modulo1.classe1.metodo() 5 6 # utilizzando as 7 8 import modulo1.classe1 as cl 9 10 cl.metodo() 11 12 # posso importo direttamente la classe 13 from modulo1 import classe1 14 15 # oppure posso importare una singola classe e ridenominarla 16 from modulo1 import classe1 as cl 3.6.1 Numpy Numpy fornisce classi e metodi utili per l’algebra lineare oltre a funzioni che rendono meno traumatico il passaggio da matlab (come ad esempio linspace). La classe principale di questa libreria `e ndarray, la quale modella un array n-dimensionale. Gli attributi pi`u importanti della classe ndarray sono: ndim numero di dimensioni dell’array shape La “forma” dell’array: per una matrice con n righe ed m colonne, il valore di shape `e (n,m). size Il numero di elementi dell’array; dtype Oggetto che descrive il tipo di dati contenuti dall’array.
  57. 57. 3.6. LIBRERIE UTILIZZATE 47 Un esempio: 1 >>> import numpy as np 2 >>> a = np.arange(5) 3 >>> b = np.arange(6,10) 4 >>> a 5 array([0, 1, 2, 3, 4]) 6 >>> b 7 array([6, 7, 8, 9]) 8 >>> import numpy as np 9 >>> a = np.arange(5) 10 >>> b = np.arange(5,10) 11 >>> print a 12 [0 1 2 3 4] 13 >>> print b 14 [5 6 7 8 9] 15 >>> c = np.append(a,b) 16 >>> print c 17 [0 1 2 3 4 5 6 7 8 9] 18 >>> a = np.array([[1,2,3],[4,5,6]]) 19 >>> print a 20 [[1 2 3] 21 [4 5 6]] 22 >>> b = np.array([7,8,9]) 23 >>> print b 24 [7 8 9] 25 >>> print np.append(a,b) 26 [1 2 3 4 5 6 7 8 9] 27 >>> c = np.append(a,b,axis=0) 28 Traceback (most recent call last): 29 File "<stdin>", line 1, in <module> 30 File "/usr/lib/python2.6/dist-packages/numpy/lib/function_base.py" , line 3234, in append 31 return concatenate((arr, values), axis=axis) 32 ValueError: arrays must have same number of dimensions 33 # i valori di ndim devono essere uguali per entrambi gli array, per risolvere basta scrivere 34 # fra parentesi quadre il secondo vettore 35 >>> print np.append(a,[b],0) 36 [[1 2 3] 37 [4 5 6] 38 [7 8 9]] Un’utile funzione `e append che permette di concatenare due array, permet- tendo di specficare lungo quale “asse” effettuare l’operazione. Un esempio pu`o chiarire meglio questa funzionalit`a: 1 # arange funziona come range, ma restituisce 2 # un’istanza di ndarray 3 >>> import numpy as np
  58. 58. 48 CAPITOLO 3. CENNI DI PYTHON 4 >>> a = np.array([[1,2,3],[4,5,6]]) 5 >>> print a 6 [[1 2 3] 7 [4 5 6]] 8 >>> print a.ndim 9 2 10 >>> print a.shape 11 (2, 3) 12 >>> print a.dtype 13 int32 14 >>> a = np.array([5,7,9],np.double) 15 >>> print a 16 [ 5. 7. 9.] 17 >>> print a.ndim 18 1 19 >>> print a.shape 20 (3,) 21 >>> print a.dtype 22 float64 `E possibile effettuare il prodotto vettoriale fra due vettri a e b tramite la funzione dot: 1 >>> a = np.arange(5) 2 >>> b = np.arange(10,15) 3 >>> print a 4 [0 1 2 3 4] 5 >>> print b 6 [10 11 12 13 14] 7 >>> print np.dot(a,b) 8 130 9 >>> a = np.array([[1,2,3],[4,5,6],[7,8,9]]) 10 >>> print a 11 [[1 2 3] 12 [4 5 6] 13 [7 8 9]] 14 >>> b = np.array([0,1,2]) 15 >>> print b 16 [0 1 2] 17 >>> print np.dot(a,b) 18 [ 8 17 26] 3.6.2 Matplotlib Matplotlib `e una libreria che fornisce funzioni necessarie per eseguire plot 2D e 3D. L’utilizzo `e molto semplice, per il caso 2D: 1 >>> import numpy as np 2 >>> import pylab as pl
  59. 59. 3.6. LIBRERIE UTILIZZATE 49 Figura 3.1: Esempio di plot della funzione sin(x) con matplotlib 3 # genera un insieme di valori compresi fra 0 e 2 * pigreco 4 >>> x = np.linspace(0,2 * np.pi) 5 >>> y = np.sin(x) 6 >>> pl.plot(x,y) 7 [<matplotlib.lines.Line2D object at 0xa7c11cc>] 8 >>> pl.show() L’immagine 3.1 a mostra l’output del codice precedente. Per quanto riguarda il plot di grafici 3D matplotlib, offre diversi me- todi tra cui plot wireframe che visualizza solo i lati della figura che si vuole visualizzare e plot surface che visualizza la superfice completa. Un esempio: 1 import numpy as np 2 from mpl_toolkits.mplot3d.axes3d import Axes3D 3 import pylab as pl 4 5 X = np.linspace(-10,10) 6 Y = np.linspace(-10,10) 7 8 # Ottengo la griglia di punti 9 X,Y = np.meshgrid(X,Y) 10 11 # Inizializzo l’oggetto immagine che conterr il plot 12 fig = pl.figure(1,dpi=100) 13 ax = Axes3D(fig) 14 15 Z = X**2 - Y**2 16
  60. 60. 50 CAPITOLO 3. CENNI DI PYTHON 17 # A scelta si utilizza una delle due 18 ax.plot_wireframe(X, Y, Z, cstride = 1, rstride = 1) 19 ax.plot_surface(X, Y, Z, cstride = 1, rstride = 1) 20 21 pl.show() cstride e rstride permettono di scegliere la precisione del plot. La figura 3.2 mostra la differenza fra i due tipi di plot.
  61. 61. 3.6. LIBRERIE UTILIZZATE 51 (a) Wireframe (b) Surface Figura 3.2: Plot della funzione z = x2−y2, in wireframe e superfice completa
  62. 62. 52 CAPITOLO 3. CENNI DI PYTHON
  63. 63. Capitolo 4 Descrizione delle classi ed algoritmi implementati Se, fra dieci anni, mentre state facendo qualcosa in modo veloce e sporco, improvvisamente mi immaginerete dietro le vostre spalle mentre vi dico:“A Dijkstra questo non sarebbe piaciuto”, quella sar`a l’immortalit`a che mi basta. Edsger W. Dijkstra In questo capitolo saranno illustrate le classi che compongono la libreria che ho sviluppato e gli algoritmi utilizzati. Si noti che la libreria numpy `e stata importata utilizzando una ridenominazione: 1 import numpy as np quindi nei fammenti di codice che seguiranno ogni riferimento a np `e un rife- rimento alla libreria numpy. Buona parte degli algoritmi sono stati adattati dal testo [19]. Dico “adattati” in quanto gli algoritmi illustrati sul testo, ol- tre ad essere scritti in uno pseudocodice eccessivamente vicino al linguaggio C, a volte presentano degli errori e delle incongruenze, probabilmente dovuti alla loro funzione di linea guida. I codici esposti in questo capitolo non sono completi, viene mostrato solo ci`o che `e di interesse per la discussione. Per consultare il codice nella sua interezza fare riferimento all’appendice B. Ho diviso le classi componenti la libreria in due files: Curve.py e Surface.py. In Python ogni file `e un modulo, ovvero ogni file pu`o essere incluso come se si trattasse di una libreria. Volendo, ad esempio, includere nel proprio codice la classe Nurbs dal file Curve.py, si pu`o scrivere: 1 from Curve import Nurbs 2 c = Nurbs(...) 53
  64. 64. 54 CAPITOLO 4. CLASSI ED ALGORITMI oppure si pu`o importare l’intero file: 1 import Curve 2 c = Curve.Nurbs(...) e anche utilizzare ridenominazioni 1 import Curve as crv 2 c = crv.Nurbs(...) 4.1 La struttura delle classi Proseguendo nella lettura si pu`o notare che la gerarchia delle classi non rispecchia le relazioni presenti tra le curve e le superfici illustrate nel ca- pitolo 2. Questo perch´e nel decidere la gerarchia delle classi ho cercato di massimizzare il riutilizzo di codice. Infatti si pu`o notare che metodi che avrebbero potuto lavorare direttamente sugli attributi della classe utilizzano invece dei parametri passati in input. Ad esempio, il calcolo delle funzioni di base b-spline `e lo stesso sia che si tratti di curve che di superfici, quindi il metodo computeBasis della classe BSpline viene utilizzato nella classe BSplineSurf, il che rende BSplineSurf classe figlia della classe BSpline. Sebbene le B-Spline contengano le curve di B´ezier come caso particolare, nel- l’implementazione di questa libreria non vi `e alcuna relazione di ereditariet`a fra di esse, in quanto non condividono metodi. 4.2 La classe Points Sebbene la classe ndarray fornita da numpy basti per modellare un punto, essa non contiene alcune funzioni necessarie come il calcolo della distanza euclidea. Ho quindi esteso la classe ndarray definendo la classe Points, all’interno della quale ho aggiunto i metodi che ho ritenuto pi`u opportuni. Si noti che dal punto di vista semantico la funzione della classe Points `e ambigua, in quanto essa `e utilizzata per rappresentare sia un singolo punto di uno spazio n-dimensionale sia un array di punti. Creare due classi distin- te sarebbe s`ı stato pi`u corretto, ma una classe rappresentante un array di punti sarebbe stata composta da un singolo metodo (metodo chordLength descritto pi`u avanti), un p`o poco per complicare, anche se di poco, la ge- rarchia delle classi. Ho quindi trovato pi`u vantaggioso modellare la classe Points in modo che potesse essere utilizzata sia per modellare un singolo punto che un array di punti. Costruttore Il costruttore di questa classe `e diverso da quello illustrato nella sezione 3.4. Il metodo new `e un metodo che, se presente, viene chiamato prima di
  65. 65. 4.2. LA CLASSE POINTS 55 init . Utilizzando questo metodo, che ha come primo parametro la classe stessa, `e possibile agire direttamente sull’oggetto, piuttosto che assegnare solo degli attributi. 1 class Points(np.ndarray): 2 def __new__(subclass,data,dtype = np.double): 3 obj = np.asarray(data,dtype).view(subclass) 4 return obj Il metodo non fa altro che creare un oggetto obj come ndarray. Il metodo view di ndarray permette di trasformare un’istanza di ndarray in un istanza di una qualsiasi sottoclasse di ndarray, in questo caso particolare trasforma obj da istanza di ndarray ad istanza di Points. Per ulteriori dettagli vedere la documentazione di numpy [4]. Metodo distance Questo metodo calcola la distanza Euclidea fra il punto rappresentato dalla classe e un punto p passato per parametro. Ricordiamo che la distanza Eu- clidea fra due punti n-dimensionali a = (a1, a2, . . . , an) e b = (b1, b2, . . . , bn) `e: n i=1 (bi − ai)2 1 def distance(self,p): 2 return np.sqrt(sum(pow(p-self,2))) L’implementazione del metodo segue pari passo la definizione, ndarray so- vrascrive gli operatori aritmetici, quindi p-self restituisce un vettore il cui i-esimo elemento `e pari alla differenza dell’i-esimo elemento di p con l’i-esimo elemento di self. pow(x,y) `e una funzione di Python che restituisce xy, ed sqrt `e la funzione offerta da numpy per il calcolo della radice quadrata. A questo punto abbiamo un vettore il cui elemento i-esimo `e (pi − selfi)2. La funzione sum calcola la somma degli elementi del vettore passato per parametro. Metodo chordLength Nei problemi di interpolazione descritti nelle sezioni 2.2.3 e 2.3.3, per stimare il valore del parametro si `e usata l’equazione (2.10). Il numeratore di quella equazione rappresenta la somma delle distanze fra ogni coppia di punti. Il metodo chordLengt calcola la somma delle distanze dal punto di indice i al punto di indice j. Se non si passano parametri, il metodo calcola la somma delle distanze di tutti i punti presenti nel vettore. 1 def chordLength(self,i=0,j=None):
  66. 66. 56 CAPITOLO 4. CLASSI ED ALGORITMI 2 return sum([self[k].distance(self[k+1]) for k in xrange(len( self[i:j])-1)]) xrange `e simile a range, solo pi`u efficiente nel caso di intervalli molto ampi. L’argomento di sum `e una lista creata con la sintassi mostrata nella sezione 3.2, la lista creata `e una lista il cui elemento k-esimo `e la distanza fra il punto k e il punto k+1, con k che va da 0 fino alla lunghezza della sottolista contenente gli elementi dall’i-esimo al j-esimo. Metodo convexComb Questo metodo molto semplice restituisce la combinazione convessa in u con un punto p passato per parametro. Nel caso il valore di u ecceda i limiti dell’intervallo [0, 1]. 1 def convexComb(self,p,u): 2 if u < 0 or u > 1: 3 raise ValueError("il parametro u deve essere compreso fra 0 e 1") 4 return (1-u)*self + u*p Esempio d’uso Seguono alcuni esempi basilari d’uso della classe Points. 1 >>> import numpy as np 2 >>> from Curve import Points 3 # creazione di un punto di coordinate (3, 5) 4 >>> a = Points([3,5],np.double) 5 >>> a 6 Points([ 3., 5.]) 7 # creazione di un punto di coordinate (9, 4) 8 >>> b = Points([9,4],np.double) 9 >>> b 10 Points([ 9., 4.]) 11 # calcolo della distanza fra a e b 12 >>> a.distance(b) 13 6.0827625302982193 14 # combinazione convessa tra a e b con u = 0.5 15 >>> a.convexComb(b,0.5) 16 Points([ 6. , 4.5]) 17 # creo un vettore di punti che contiene a, b e altri due punti specificati manualmente 18 >>> punti = Points([a,b,(12,5),(15,9)],np.double) 19 >>> punti 20 Points([[ 3., 5.], 21 [ 9., 4.], 22 [ 12., 5.], 23 [ 15., 9.]])
  67. 67. 4.3. LA CLASSE CURVE 57 24 # calcolo la somma delle di stanze fra tutti i punti presenti nell’ array 25 >>> punti.chordLength() 26 14.245040190466598 4.3 La classe Curve Questa classe contiene attributi e metodi principali comuni a tutti i tipi di curve implementati in questa libreria. Costruttore I principali attributi di una curva sono i punti di controllo necessari per calcolarla, identificati dal parametro cntrl e il numero di punti della curva da calcolare, attributo identificato dal parametro npts. 1 class Curve: 2 def __init__(self,cntrl,npts): 3 4 if isinstance(cntrl,str): 5 self.loadFromFile(cntrl) 6 else: 7 try: 8 self.__dict__[’cntrl’] = Points(cntrl) 9 except Exception as detail: 10 raise PyNurbsError("Errore formato punti di controllo :{0}".format(detail)) 11 12 self.__dict__[’npts’] = npts 13 14 self.__dict__[’points’] = np.zeros((self.npts, 2)).view( Points) nel costruttore controllo se cntrl `e una stringa tramite l’istruzione isinstance (vedere la sezione 3.4). In caso positivo, il valore di cntrl viene inteso come nome del file contenente i punti di controllo, viene invocato quindi il me- todo loadFromFile per caricare da file i suddetti punti. In caso contrario, cntrl `e una lista contenente i punti di controllo della curva. Nel blocco try/except tento di assegnare all’attributo della classe un oggetto di tipo Points costruito a partire dai punti di controllo passati come parametro. Metodo calculate Il metodo calculate `e il metodo che ogni classe dovr`a implementare per calcolare la curva.
  68. 68. 58 CAPITOLO 4. CLASSI ED ALGORITMI 1 def calculate(self): 2 pass L’istruzione pass permette di dichiarare un metodo lasciando il corpo vuoto. Metodo plot Questo metodo consente di effettuare il plot della curva, utilizzando i metodi della libreria matplotlib. Di default, insieme alla curva, viene visualizzato il poligono di controllo da cui la curva stessa `e stata generata. Nel caso si volesse visualizzare solo la curva basta settare il parametro cpgrid a False. 1 def plot(self, cpgrid = True): 2 3 pl.plot(self.points[:, 0], self.points[:, 1]) 4 5 if cpgrid: 6 pl.plot(self.cntrl[:, 0],self.cntrl[:, 1],’ro’) 7 pl.plot(self.cntrl[:, 0], self.cntrl[:, 1],’r--’) 8 9 return Sovrascrittura operatore somma La sovrascrittura dell’operatore somma consente di concatenare due curve. Sebbene il metodo sia molto semplice, i miei sforzi si sono concentrati sul riuscire a rendere questo metodo generico in modo da non doverlo riscrivere per ogni curva. L’idea di base `e quella di “avvicinare” la seconda curva alla prima intervenendo sul vettore dei punti di controllo, per poi creare una nuova curva utilizzando i punti di controllo di entrambe. 1 def __add__(self, c): 2 if not(isinstance(c,type(self))): 3 raise TypeError("Il secondo operando deve essere un istanza di {0}".format(type(self))) 4 5 other_curve = c.cntrl.copy() 6 7 # calcolo la differenza di posizione fra l’ultimo punto della prima curva e il primo della seconda 8 diff = self.cntrl[-1] - other_curve[0] 9 10 # traslo i singoli punti della seconda curva 11 for pt in other_curve: 12 pt += diff 13 14 # creo un nuovo insieme di punti di controllo unendo i punti di controllo delle due curve

×