Versione 8 gennaio 2004 (sono state aggiunte le parti in rosso)
Versione 4 febbraio 2004 (e' stata aggiunta la parte in viola)
|
Implementare una triangolazione piana con le operazioni di interrogazione (estrazione delle relazioni topologiche) e di modifica, utilizzando la struttura dati indicizzata con adiacenze vista a lezione.
Il codice dovra' essere scritto in C o C++ e progettato come una libreria che possa essere utilizzata da altri programmi. Per questo sono date precise specifiche riguardo alla sintassi delle funzioni da rendere disponibili.
Un primo esempio di programma che utilizza la libreria e' il programma grafico che vi forniamo per poter visualizzare e controllare se l'implementazione funziona correttamente.
La struttura dati indicizzata con adiacenze e' stata spiegata a lezione.
Internamente, la vostra implementazione puo' fare uso di tipi definiti a vostro piacere (array, puntatori, strutture, classi...). Esternamente pero'deve permettere di accedere alla triangolazione riferendosi ai vertici e ai triangoli semplicemente mediante indici costituiti da numeri interi.
Per avere "gratis" l'accesso ai vertici / triangoli tramite indici,
consigliamo di tenere sia i vertici che i triangoli in array.
Gli array per comodita' possono essere statici, dimensionati ad
un numero di posizioni prefissato e ragionevolmente grande
(es. dell'ordine del centinaio,
e ricordate che i triangoli sono circa il doppio dei vertici).
Poiche' il numero di vertici e triangoli puo' aumentare /
diminuire (con le operazioni di raffinamento / semplificazione)
bisogna prevedere un meccanismo di riuso e ricompattamento
delle posizioni dell'array:
Poiche' la struttura dati vista a lezione memorizza triangoli,
e' necessario tenere traccia separatamente della faccia esterna
o faccia infinita
(ovvero del contorno della triangolazione) che in generale non
e' un triangolo.
Per questo si puo' tenere per esempio una lista di vertici.
Anche qui si consiglia
usare puntatori ai vertici, non i loro indici nell'array.
Devono essere fornite le seguenti funzioni (con la sintassi
specificata).
Cio' non impedisce di implementare anche altre funzioni,
incluse funzioni che assolvano al medesimo compito di queste,
utilizzando i tipi da voi definiti.
int VertexNum() ritorna il numero totale di vertici
int TriangleNum() ritorna il numero totale di triangoli
Nel seguito della specifica si assume che:
float VertexX(int v) ritorna la coordinata x del vertice v
float VertexY(int v) ritorna la coordinata y del vertice v
int getPartialVT(int v) ritorna l'indice del triangolo memorizzato in relazione VT parziale per il vertice v
int getVT(int v, int * arr) copia nell'array arr (che deve essere gia' allocato e di dimensione sufficiente) gli indici dei triangoli in relazione VT (totale) con il vertice v, ritorna il numero di tali triangoli
int getVV(int v, int * arr) copia nell'array arr (che deve essere gia' allocato e di dimensione sufficiente) gli indici dei vertici in relazione VV con il vertice v, ritorna il numero di tali vertici
int getTV(int t, int * arr) copia nell'array arr (che deve essere gia' allocato e di dimensione almeno 3) gli indici dei 3 vertici in relazione TV con il triangolo t, ritorna il numero di tali vertici (cioe' 3)
int getTT(int t, int * arr) copia nell'array arr (che deve essere gia' allocato e di dimensione almeno 3) gli indici dei 3 triangoli in relazione TT con il triangolo t, se qualcuno di essi non esiste (perche' t confina con la faccia esterna), l'indice corrispondente e' -1. Ritorna il numero di triangoli in relazione TT (cioe' 3 meno il numero di spigoli di t che confinano con la faccia esterna)
int getExternalFace(int * arr) copia nell'array arr (che deve essere gia' allocato e di dimensione sufficiente) gli indici dei vertici della faccia esterna infinita, ritorna il numero di tali vertici
int getET(int v1, int v2, int * arr)
Copia nell'array arr
(che deve essere gia' allocato e di dimensione almeno 2)
gli indici dei triangoli in relazione ET con lo spigolo v1,v2,
se lo spigolo e' di bordo uno dei due adiacenti e' la faccia infinita
e l'indice corrispondente e' -1.
Ritorna il numero di triangoli in relazione ET (cioe' 2
se spigolo interno e 1 se di bordo)
int getEE(int v1, int v2, int * arr)
-- Figure 1 e 2
Sia e lo spigolo v1,v2 e sia EE(e) = e1, e2, e3, e4.
Copia nell'array arr
(che deve essere gia' allocato e di dimensione almeno 4)
quattro vertici w1, w2, w3, w4 che sono nell'ordine
gli estremi, diversi da v1, degli spigoli e1, e2,
e gli estremi, diversi da v2, degli spigoli e3, e4.
Ritorna il numero di vertici copiati (cioe' 4).
Figure esplicative per l'estrazione della relazione EE:
|
|
Ogni operazione di modifica viene eseguita solo se sono vere certe condizioni, altrimenti non viene eseguita. Ogni operazione ha un valore di ritorno intero che deve essere 1 se l'operazione e' stata eseguita con successo, 0 altrimenti.
Le operazioni sono state spiegate a lezione, qui le riprendiamo solo brevemente.
int TriangleSplit(int t, float x, float y)
- Figura 3.
Inserisce il punto (x,y) come nuovo vertice della triangolazione
dividendo il triangolo t in tre triangoli.
L'operazione viene eseguita solo se le coordinate x,y cadono all'interno
di t.
int AddEar(int v1, int v2, float x, float y)
- Figura 4.
Implementa il caso particolare dell'operazione precedente in cui
il punto cade fuori dal dominio.
Inserisce il punto (x,y) come nuovo vertice della triangolazione
congiungendolo con gli estremi dello spigolo v1,v2 e
creando cosi' un nuovo triangolo.
L'operazione viene eseguita solo se le coordinate x,y cadono fuori
dal dominio, se v1,v2 sono gli estremi di uno spigolo di bordo
(ovvero sono due vertici consecutivi sul perimetro della faccia esterna)
e se v1 e v2 sono entrambi visibili da (x,y).
Due punti si dicono visibili se il segmento che li unisce
giace all'esterno del dominio (e' sufficiente controllare che non vi siano
intersezioni col contorno della faccia esterna).
int EdgeSplit(int v1, int v2, float x, float y)
- Figure 5 e 6.
Inserisce il punto (x,y) come nuovo vertice
della triangolazione dividendo in due lo spigolo di
estremi v1,v2, e dividendo
in due ciascun triangolo incidente su tale spigolo.
L'operazione viene eseguita solo se le coordinate x,y cadono all'interno
dello spigolo.
Se lo spigolo e' interno alla triangolazione, vi sono due triangoli
da dividere; se invece e' sul bordo, c'e' un solo triangolo da dividere.
int VertexSplit(int v, int v1, int v2, float x1, float y1,
float x2, float y2) - Figure 7 e 8.
Espande il vertice v in un nuovo spigolo con estremi nei punti
(x1,y1) e (x2,y2) ed espande in triangoli gli spigoli v,v1 e v,v2.
I triangoli prima incidenti in v e situati a sinistra
della catena v1-v-v2 vanno ad essere incidenti in (x1,y1),
quelli situati a destra vanno ad essere incidenti in (x2,y2).
L'operazione viene eseguita solo se
int EdgeSwap(int v1, int v2) - Figura 9.
Scambia lo spigolo v1,v2 con l'altra diagonale
del quadrilatero formato dai due triangoli incidenti sullo spigolo.
L'operazione viene eseguita solo se lo spigolo
ha due triangoli incidenti (cioe' non e' sul bordo della triangolazione)
e se il quadrilatero formato da questi e' strettamente convesso.
Nota: il quadrilatero e' strettamente convesso sse
le sue due diagonali si intersecano.
int VertexDelete(int v) - Figure 3 e 4.
Cancella il vertice v fondendo tra loro i triangoli
che incidevano in esso.
L'operazione viene eseguita solo se
int EdgeMerge(int v1, int v2, int v3)
- Figure 10 e 11.
Fonde gli spigoli v1,v2 e v2,v3 in un solo spigolo
di estremi v1,v3 ed elimina tutti gli altri spigoli incidenti
in v2 fondendo i triangoli che vi incidevano.
L'operazione viene eseguita solo se
int EdgeCollapse(int v1, int v2, float x, float y)
- Figure 7 e 8.
Collassa lo spigolo di estremi v1,v2 in un vertice di coordinate
(x,y), eliminando i triangoli che incidevano su v1,v2.
L'operazione viene eseguita solo se
Figure esplicative delle operazioni di modifica (con i casi particolari):
|
|
|
|
|
|
|
|
|
|
Si assume che una triangolazione sia scritta su file in formato indicizzato (senza adiacenze) con la seguente sintassi:
Sono dati alcuni file di esempio: es1.txt, es2.txt
int ReadTriangulation(FILE * fd) legge da file una triangolazione e la memorizza nella struttura dati dopo aver ricostruito le informazioni non contenute nel file (relazioni VT parziale e TT, contorno della faccia esterna infinita)
int WriteTriangulation(FILE * fd) scrive su file la triangolazione
Viene fornito un programma grafico che, compilato assieme alla vostra implementazione, permettera' di visualizzare i risultati e controllare che siano corretti.
Il programma fa uso delle librerie grafiche OpenGL e Glut ed e' fornito con il supporto necessario per utilizzarlo sotto Linux nei laboratori sw1 e sw2. E' altresi' possibile eseguirlo in ambiente Windows ma per questo non viene dato supporto tecnico.
Il programma fa affidamento sul fatto che sia rispettata esattamente la sintassi specifica per le operazioni.
Sono dati i file:
Si compila con make trigraph e si esegue con ./trigraph
Poi dovrete editare il makefile sostituendo a tridummy
il nome del file contenente la vostra implementazione.
Potete usare tridummy come base di partenza per la vostra
implementazione, completando a poco a poco le varie funzioni.
Presenta un'unica finestra nella quale avviene il disegno della triangolazione e su cui e' attivo un menu' pop-up. Sono attivi anche alcuni tasti della tastiera.
Tasti attivi:
Il menu' contiene le voci:
La modalita' corrente come anche altri messaggi (sull'esito con successo o errore dell'operazione, ecc.) sono mostrati in sovra-impressione alla finestra.
In condizioni normali la triangolazione e' mostrata su sfondo bianco con triangoli riempiti in giallino chiaro, spigoli in rosso e vertici in nero.
Nel visualizzare le relazioni topologiche, il vertice o triangolo del quale si visualizzano le relazioni e' evidenziato in verde mentre i vertici / triangoli in relazione con esso sono evidenziati in toni di colore sfumati da rosso chiaro (il primo nella relazione) a blu chiaro (l'ultimo della relazione) passando attraverso i toni del grigio-violetto.
Consegnare per posta elettronica all'indirizzo magillo@disi.unige.it un unico file compresso in formato .tgz oppure .zip contenente:
La scadenza per la consegna e': 20 febbraio 2004.
ATTENZIONE: la scadenza e' stata prorogata al 30 giugno (vedere comunicato del 27 febbraio 2004) |