SlideShare ist ein Scribd-Unternehmen logo
1 von 179
Downloaden Sie, um offline zu lesen
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
ii
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
iv
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.
vi
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
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
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
x INDICE
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
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
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.
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 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
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
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
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
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]).
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
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
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
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.
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
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
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
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.
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.
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
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.
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 ]
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)
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


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
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
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.
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:
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.
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
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:
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.
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)
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)
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:
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.
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)
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
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
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;
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
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:
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
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’:
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:
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
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.
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
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
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
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.
3.6. LIBRERIE UTILIZZATE 51
(a) Wireframe
(b) Surface
Figura 3.2: Plot della funzione z = x2−y2, in wireframe e superfice completa
52 CAPITOLO 3. CENNI DI PYTHON
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
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
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):
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.]])
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.
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
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

Weitere ähnliche Inhalte

Was ist angesagt?

24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
maaske
 
Inoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxInoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linux
Ce.Se.N.A. Security
 
Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...
Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...
Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...
lucafiore1
 
tesi_dottorato_marco_tannino_2015
tesi_dottorato_marco_tannino_2015tesi_dottorato_marco_tannino_2015
tesi_dottorato_marco_tannino_2015
Marco Tannino
 
GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007
GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007
GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007
Gabriele Filosofi
 
Il mio libro - My book (intro)
Il mio libro - My book (intro)Il mio libro - My book (intro)
Il mio libro - My book (intro)
pls3d
 
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Francesco De Giorgi
 
Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...
Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...
Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...
Simone Fini
 
GaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in LinuxGaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in Linux
AmmLibera AL
 

Was ist angesagt? (20)

24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
24546913 progettazione-e-implementazione-del-sistema-di-controllo-per-un-pend...
 
Modellazione della dinamica di un liquido bifase mediante GPU CUDA
Modellazione della dinamica di un liquido bifase mediante GPU CUDAModellazione della dinamica di un liquido bifase mediante GPU CUDA
Modellazione della dinamica di un liquido bifase mediante GPU CUDA
 
Il Linux OpenSound System
Il Linux OpenSound SystemIl Linux OpenSound System
Il Linux OpenSound System
 
Andrea_Gangemi_tesi
Andrea_Gangemi_tesiAndrea_Gangemi_tesi
Andrea_Gangemi_tesi
 
Inoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linuxInoltro di pacchetti ip in sistemi linux
Inoltro di pacchetti ip in sistemi linux
 
Monitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di MarkovMonitoraggio di applicazioni software mediante modelli di Markov
Monitoraggio di applicazioni software mediante modelli di Markov
 
Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...
Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...
Libro "La valutazione dei rischi di incendio" L. Fiorentini (TECSA S.p.A.), L...
 
Profilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzatiProfilazione utente in ambienti virtualizzati
Profilazione utente in ambienti virtualizzati
 
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientaleInterfaccia utente basata su eye-tracking per sistemi di controllo ambientale
Interfaccia utente basata su eye-tracking per sistemi di controllo ambientale
 
Realizzazione di un modello di router ottico in ambiente open source.
Realizzazione di un modello di router ottico in ambiente open source.Realizzazione di un modello di router ottico in ambiente open source.
Realizzazione di un modello di router ottico in ambiente open source.
 
tesi_dottorato_marco_tannino_2015
tesi_dottorato_marco_tannino_2015tesi_dottorato_marco_tannino_2015
tesi_dottorato_marco_tannino_2015
 
Tesi Laurea Sergio Taddia
Tesi Laurea Sergio TaddiaTesi Laurea Sergio Taddia
Tesi Laurea Sergio Taddia
 
GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007
GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007
GFilosofi_brain-mind-and-behavior_a-neuroscientific-approach_2007
 
Il mio libro - My book (intro)
Il mio libro - My book (intro)Il mio libro - My book (intro)
Il mio libro - My book (intro)
 
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
Valutazione sperimentale di tecnologie per la gestione dei dati per workflow ...
 
Pagine da calcio preparazione a inseguimento
Pagine da calcio preparazione a inseguimentoPagine da calcio preparazione a inseguimento
Pagine da calcio preparazione a inseguimento
 
Promuovere e misurare la biodiversità nei soft robot modulari evolvendo corpo...
Promuovere e misurare la biodiversità nei soft robot modulari evolvendo corpo...Promuovere e misurare la biodiversità nei soft robot modulari evolvendo corpo...
Promuovere e misurare la biodiversità nei soft robot modulari evolvendo corpo...
 
Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...
Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...
Costruzione e Sviluppo in ambiente STNucleo di un Quadricottero con Stabilizz...
 
CurvED
CurvEDCurvED
CurvED
 
GaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in LinuxGaPiL - Guida alla Programmazione in Linux
GaPiL - Guida alla Programmazione in Linux
 

Andere mochten auch

Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - TesiIl Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Francesco Magagnino
 
Tecnologie di libertà
Tecnologie di libertà Tecnologie di libertà
Tecnologie di libertà
Giovanni Ferretti
 
Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...
Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...
Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...
Davide Trebbi
 
Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...
Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...
Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...
Andrea Marchetti
 

Andere mochten auch (20)

Ringraziamenti
RingraziamentiRingraziamenti
Ringraziamenti
 
Strumenti e modelli per la gestione dei servizi idrici
Strumenti e modelli per la gestione dei servizi idriciStrumenti e modelli per la gestione dei servizi idrici
Strumenti e modelli per la gestione dei servizi idrici
 
Conettività cnipa
Conettività cnipaConettività cnipa
Conettività cnipa
 
Il Mobbing Secondario e gli effetti sulla prole in età evolutiva - Tesi di La...
Il Mobbing Secondario e gli effetti sulla prole in età evolutiva - Tesi di La...Il Mobbing Secondario e gli effetti sulla prole in età evolutiva - Tesi di La...
Il Mobbing Secondario e gli effetti sulla prole in età evolutiva - Tesi di La...
 
Progettazione e realizzazione di un sistema DRM utilizzando SSL e GStreamer
Progettazione e realizzazione di un sistema DRM utilizzando SSL e GStreamerProgettazione e realizzazione di un sistema DRM utilizzando SSL e GStreamer
Progettazione e realizzazione di un sistema DRM utilizzando SSL e GStreamer
 
Mini tesi "lo stile costa crociere"
Mini tesi "lo stile costa crociere" Mini tesi "lo stile costa crociere"
Mini tesi "lo stile costa crociere"
 
Tesi
TesiTesi
Tesi
 
Tesi peiretti
Tesi peirettiTesi peiretti
Tesi peiretti
 
Realizzazione di un servizio di conferenza telefonica/VoIP multiutente median...
Realizzazione di un servizio di conferenza telefonica/VoIP multiutente median...Realizzazione di un servizio di conferenza telefonica/VoIP multiutente median...
Realizzazione di un servizio di conferenza telefonica/VoIP multiutente median...
 
Giochi di coordinamento su grafi
Giochi di coordinamento su grafiGiochi di coordinamento su grafi
Giochi di coordinamento su grafi
 
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - TesiIl Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
Il Modello Pragmatico Elementare per lo sviluppo di Sistemi Adattivi - Tesi
 
Cloud Computing: Una Soluzione "Private" Basata Su Software IBM (Tesi di laur...
Cloud Computing: Una Soluzione "Private" Basata Su Software IBM (Tesi di laur...Cloud Computing: Una Soluzione "Private" Basata Su Software IBM (Tesi di laur...
Cloud Computing: Una Soluzione "Private" Basata Su Software IBM (Tesi di laur...
 
Tesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGPTesi Triennale - X509 e PGP
Tesi Triennale - X509 e PGP
 
Tecnologie di libertà
Tecnologie di libertà Tecnologie di libertà
Tecnologie di libertà
 
Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...
Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...
Tesi di laurea - L'industria culturale in Italia - il caffé letterario - Davi...
 
Il Business Model di Grom S.r.l. - tesi di laurea
Il Business Model di Grom S.r.l. - tesi di laureaIl Business Model di Grom S.r.l. - tesi di laurea
Il Business Model di Grom S.r.l. - tesi di laurea
 
Corso di stampa 3D - parte 1
Corso di stampa 3D - parte 1Corso di stampa 3D - parte 1
Corso di stampa 3D - parte 1
 
Geometric model & curve
Geometric model & curveGeometric model & curve
Geometric model & curve
 
A.Dionisi Thesis
A.Dionisi ThesisA.Dionisi Thesis
A.Dionisi Thesis
 
Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...
Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...
Valutazione delle prestazioni di un protocollo di routing (Surge) per reti di...
 

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

Il tutorial di Python
Il tutorial di PythonIl tutorial di Python
Il tutorial di Python
AmmLibera AL
 
Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...
Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...
Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...
GabrieleGandossi
 
Reti di partecipazione fra società di capitale in Italia: presenza di topolog...
Reti di partecipazione fra società di capitale in Italia: presenza di topolog...Reti di partecipazione fra società di capitale in Italia: presenza di topolog...
Reti di partecipazione fra società di capitale in Italia: presenza di topolog...
Andrea Cavicchini
 

Ähnlich wie Sviluppo di una libreria orientata agli oggetti per il calcolo di NURBS con applicazioni alla grafica 2D e 3D (20)

Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
Reti neurali di convoluzione per la visione artificiale - Tesi di Laurea Magi...
 
[Thesis] IBSS: Intelligent Brake Support System
[Thesis] IBSS: Intelligent Brake Support System [Thesis] IBSS: Intelligent Brake Support System
[Thesis] IBSS: Intelligent Brake Support System
 
Tesi Nicola Pretto
Tesi Nicola PrettoTesi Nicola Pretto
Tesi Nicola Pretto
 
Tesi Specialistica - Weka SMP
Tesi Specialistica - Weka SMPTesi Specialistica - Weka SMP
Tesi Specialistica - Weka SMP
 
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
Implementazione di un sistema di misura di tipo quantitativo per sensori a na...
 
Apprendimento di movimenti della testa tramite Hidden Markov Model
Apprendimento di movimenti della testa tramite Hidden Markov ModelApprendimento di movimenti della testa tramite Hidden Markov Model
Apprendimento di movimenti della testa tramite Hidden Markov Model
 
Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques Anomaly detection in network traffic flows with big data analysis techniques
Anomaly detection in network traffic flows with big data analysis techniques
 
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)Caratterizzazione di un rivelatore a piatti resistivi (RPC)
Caratterizzazione di un rivelatore a piatti resistivi (RPC)
 
Il tutorial di Python
Il tutorial di PythonIl tutorial di Python
Il tutorial di Python
 
Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...
Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...
Telecontrollo di un sistema cartesiano a 2 g.d.l. mediante interfaccia aptica...
 
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
Implementazione di protocolli e simulatori MATLAB per lo sviluppo del livello...
 
Pattern Recognition Lecture Notes
Pattern Recognition Lecture NotesPattern Recognition Lecture Notes
Pattern Recognition Lecture Notes
 
Learning of non-homogeneous Continuous Times Bayesian Networks Thesis
Learning of non-homogeneous Continuous Times Bayesian Networks ThesisLearning of non-homogeneous Continuous Times Bayesian Networks Thesis
Learning of non-homogeneous Continuous Times Bayesian Networks Thesis
 
Reti di partecipazione fra società di capitale in Italia: presenza di topolog...
Reti di partecipazione fra società di capitale in Italia: presenza di topolog...Reti di partecipazione fra società di capitale in Italia: presenza di topolog...
Reti di partecipazione fra società di capitale in Italia: presenza di topolog...
 
Publish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based RoutingPublish/Subscribe EDI with Content-Based Routing
Publish/Subscribe EDI with Content-Based Routing
 
Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilità
Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilitàTesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilità
Tesi di Laurea sulla Sicurezza delle Reti Informatiche: Le vulnerabilità
 
Esperimenti_laboratorio di fisica per la scuola superiore
Esperimenti_laboratorio di fisica per la scuola superioreEsperimenti_laboratorio di fisica per la scuola superiore
Esperimenti_laboratorio di fisica per la scuola superiore
 
Banovaz Diego - Tesi
Banovaz Diego - TesiBanovaz Diego - Tesi
Banovaz Diego - Tesi
 
Controllo di un braccio robotico mediante i movimenti della mano
Controllo di un braccio robotico mediante i movimenti della manoControllo di un braccio robotico mediante i movimenti della mano
Controllo di un braccio robotico mediante i movimenti della mano
 
Guida C# By Megahao
Guida C# By MegahaoGuida C# By Megahao
Guida C# By Megahao
 

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

  • 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. ii
  • 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. iv
  • 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. vi
  • 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. 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. 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
  • 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. 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. 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. 4 CAPITOLO 1. INTRODUZIONE
  • 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 3.6. LIBRERIE UTILIZZATE 51 (a) Wireframe (b) Surface Figura 3.2: Plot della funzione z = x2−y2, in wireframe e superfice completa
  • 62. 52 CAPITOLO 3. CENNI DI PYTHON
  • 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. 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. 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. 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. 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. 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