• Non ci sono risultati.

Capitolo 4: IMPLEMENTAZIONE

N/A
N/A
Protected

Academic year: 2021

Condividi "Capitolo 4: IMPLEMENTAZIONE"

Copied!
18
0
0

Testo completo

(1)

Capitolo 4: IMPLEMENTAZIONE

L’applicazione per la generazione di ambienti urbani è stata realizzata in C++, utilizzando come piattaforma di sviluppo Microsoft Visual Studio .NET 2002, in particolare l’ambiente

Visual C++.

Le librerie grafiche utilizzate per visualizzare i dati in output sono le OpenGL.

Per le operazioni di creazione e gestione delle immagini associate ai modelli generati è stata utilizzata la libreria DevIL.

Sono state inoltre ampiamente utilizzati le strutture dati e gli algoritmi messi a disposizione dalla libreria STL (Standard Template Library) del linguaggio C++.

Per il salvataggio di alcuni dati inerenti il CityGraph si è scelto un formato ASCII essenziale, che verrà descritto in seguito.

Nel seguito del capitolo verrà fornita una descrizione della semplice interfaccia messa a disposizione dall’applicazione per l’editing e la visualizzazione dell’ambiente virtuale urbano sfruttando XVR: tool di sviluppo per le applicazioni di realtà virtuale, messo a disposizione dal Laboratorio PERCRO della Scuola Superiore S. Anna.

4.1. Implementazione del sistema

L’applicazione è articolata in tre fasi distinte: una fase di inizializzazione e semplificazione della mappa necessaria a rendere la mappa più facilmente interpretabile, una fase di riconoscimento delle entità urbane, di calcolo e analisi dei dati per la generazione del modello

(2)

tridimensionale, e una fase di editing e modifica parziale dei dati acquisiti automaticamente (questa fase in realtà non è totalmente distinta e successiva alla precedente ma interviene nel corso della precedente elaborazione dei dati)

Nella prima fase vengono svolte le seguenti operazioni:

Eventuale cleaning della mappa raster in input.

Skeletonizzazione della mappa al fine di riconoscere le varie entità urbane.

Nel secondo (ed eventualmente nel terzo) stadio di elaborazione della mappa, precedentemente modificata, si distinguono le seguenti fasi:

• Riconoscimento e tipizzazione di incroci, strade, piazze, e isolati.

• Eventuale editing e modifica degli elementi riconosciuti

• Creazione del modello 3D

4.2. Classi e strutture dati

Le principali classi utilizzate dall’applicazione possono essere suddivise in due gruppi a seconda delle loro funzionalità:

• Le classi che rappresentano i dati elementari con cui è rappresentato un CityGraph e la classe che rappresenta il CityGraph stesso.

• Le classi utilizzate a supporto delle precedenti, sia per la rappresentazione di semplici entità geometriche, sia per la rappresentazione dell’immagine raster e degli altri dati in input.

In [figura 4.1] è presentato uno schema riassuntivo e semplificato dell’organizzazione in classi del programma, nel quale vengono evidenziate le relazioni tra i vari elementi che compongono il CityGraph. In azzurro sono colorate le classi che rappresentano le entità principali di un ambiente urbano (CityGraph compreso). In giallo le classi di supporto usate

(3)

per rappresentare l’immagine raster e il file TFW per la conversione in coordinate reali. Nello schema mancano le classi minimali che servono a rappresentare i punti nello spazio con coordinate sia float che intere e quella che serve a rappresentare un pixel nello spazio di colori

RGB.

Ogni singola classe che rappresenta le entità urbane, contiene attributi e metodi sia per il riconoscimento e la localizzazione all’interno della mappa, sia per la conversione in coordinate 3D e successiva visualizzazione:

(4)

A differenza dell’immagine raster e del world file, i file di input riguardanti i DTM (sia terreno che edifici) non necessitano di una rappresentazione in classi, in quanto il loro utilizzo si limita all’acquisizione dei dati all’interno dei due metodi della classe CityGraph, che ne fanno utilizzo.

Come si può vedere dallo schema di [figura 4.1], le 4 entità principale di un CityGraph (nodi, link, piazze e isolati), sono memorizzati in liste (in realtà le liste non contengono direttamente gli oggetti ma solo i puntatori a questi). Le liste vengono usate anche in altri casi, ad esempio all’interno di un nodo per elencare i link connessi. A seconda quindi dell’utilizzo si è preferito usare talvolta la classe deque e talvolta la classe list entrambe implementate nella libreria STL del C++. Entrambe le strutture dati permettono di accedere, inserire e cancellare elementi in testa e in coda alla lista con complessità costante. Le due strutture si differenziano per quanto riguarda l’accesso ai dati, la cancellazione e l’inserimento in posizioni che non siano di testa o di coda. La deque permette infatti l’accesso casuale agli elementi, i quali sono accessibili tramite indice, ma proprio per questo le operazioni di cancellazione e inserimento sono enormemente più lente. La lista invece non permette l’accesso casuale ai dati ma le operazioni di inserimento e cancellazione hanno complessità costante. [STROUS]

Di seguito si riporta in dettaglio la struttura delle classi più rappresentative e gli aspetti principali di ognuna di esse (vengono volutamente esclusi dalla descrizione metodi e attributi ausiliari, costruttori, distruttori e operatori standard).

4.2.1.

La classe ColorRGB

Questa classe rappresenta un pixel nello spazio di colore RGB attraverso i 3 canali Red,

Green e Blue. La classe contiene inoltre un attributo in più di tipo intero che serve a integrare

eventuali informazioni aggiuntive sul pixel (esempio può essere utile epr capire se il pixel è stato visitato o meno ecc).

char R, G, B: I tre canali nello spazio di colore RGB (1 byte per canale)

(5)

4.2.2.

La classe RasterImage

Questa classe rappresenta l’immagine attraverso una matrice di oggetti ColorRGB. Inoltre contiene i metodi usati per l’inizializzazione e la semplificazione dell’immagine. [par. 3.2] La classe fa ampio uso dei metodi messi a disposizione della libreria DevIL [DEVIL] per il caricamento in memoria e il salvataggio su di disco di un’immagine raster. [par. 1.3.1]

char* filename: Nome del file dell’immagine

ColorRGB** pixels: matrice a due dimensioni che memorizza i pixel dell’immagine.

unsigned int w: larghezza dell’immagine

unsigned int h: lunghezza dell’immagine

void ReduceColor (): Riduce il numero dei colori dell’immagine, individuandone un

insieme ristretto. [par. 3.2.1]

void DeleteColor (ColorRGB &c): Elimina dalla mappa il colore c, sostituendolo con

la moda dei colori confinanti. [par. 3.2.1]

void Skeletonization (int skeleton): Skeletonizza l’immagine, ma lo skeleton viene

rappresentato esclusivamente nei campi marker dei singoli elementi di tipo ColorRGB. Il parametro intero skeleton, specifica il valore del marker dei pixel da skeletonizzare ed è anche il valore da assegnare ai pixel che dopo l’algoritmo faranno parte dello skeleton. [par. 3.2.2]

bool nextpixel(int currx, int curry, float m, int &nextx, int &nexty, int n):

Restituisce l’enensimo pixel a aprtire da un punto lungo una determinate direzione. [par. 3.3.2]

void findnextPixelColor(int x0, int y0,int mark,int &nextx,int &nexty,float m, bool

semipiano): Restituisce l’oggetto di tipo ColorRGB più vicino al pixel dato, che abbia

un determinato marker. La ricerca permette di scegliere il semipiano tramite un parametro booleano. [par. 3.3.2]

(6)

4.2.3.

La classe TFW

Questa classe contiene tutti i parametri di conversione da coordinate in pixel a coordinate in valori reali. Fornisce anche i metodi necessari ad operare la conversione di un singolo punto. [par 3.4.1].

float A, B, C, D, E, F. A1, B1, C1, D1, E1, F1: questi sono i parametri che

permettono la trasformazione da coordinate in pixel a coordinate reali in viceversa. Sono spiegati nel dettaglio in [par 3.4.1].

void generate (float A, float E, float B,float D,float C,float F): Calcola i parametri

per la trasformazione da coordinate reali a coordinate in pixel.

bool generate (char* filename): Genera i parametri per la trasformazione

direttamente dal worldfile in input. Restituisce false nel caso non riesca ad aprire il file.

int Xpixel(float x, float y) e int Ypixel(float x, float y): calcola le coordinate in pixel

di un punto in coordinate reali.

float Xworld(int x,int y) e float Yworld(int x,int y): calcola le coordinate reali di un

punto in coordinate in pixel.

float Xmeters(int x,int y) e float Ymeters(int x,int y): calcola le coordinate in metri di

un punto in coordinate in pixel. In pratica sono le coordinate reali con l’origine traslata e coincidente con quella in pixel.

4.2.4.

Le classi Point2Int, Point2Float e Point3Float

Queste tre classi rappresentano rispettivamente un punto sull’immagine raster (due sole coordinate di tipo intero) e un punto nello spazio 3D (due o tre coordinate reali). Per semplicità viene descritta nel dettaglio solo la classe Point2Int.

int x,y: coordinate di un punto

(7)

void distancepoint (const Point3Int &p, int npixel): Calcola il punto che dista npixel

dal punto corrente rispetto al segmento, individuato dal punto corrente con il punto p.

void partitionpoint(const Point3Int &p, int npartition): Calcola il punto che dista una

lunghezza pari alla partizione n-esima (npartition) dal punto corrente rispetto al segmento, individuato dal punto corrente con il punto p.

4.2.5.

La classe Node

Questa classe rappresenta i nodi del CityGraph. [par 3.3]

int id: identificativo numerico del nodo

Point2Int p: Coordinate in pixel del nodo

Point3Float pf: Coordinate reali del nodo

unsigned int what: Tipo del nodo. Il nodo può essere “nullo” (0), “estremo di un

vicolo cieco” (1), “curva” (2), “incrocio” (3), “vertice di piazza” (4). [par 3.3]

square* square: Puntatore a all’eventuale piazza di cui potrebbe far parte il nodo. Se

il nodo non è un vertice di piazza, questo campo contiene il puntatore nullo.

list<link*> linkconnected: lista dei puntatori ai link connessi al nodo.

list<int> cyclesid: lista degli id dei cicli minimali a cui il nodo appartiene

deque<Point2Int> coord: lista di coordinate in pixel (in senso anti-orario) che

rappresentano i reali contorni del nodo. Il nodo ha un proprio reale contorno solo nel caso sia di tipo 3. In questo caso il nodo è per costruzione un poligono convesso.

deque<Point3Float> fcoord: lista di coordinate in metri che rappresentano il contorno

di un nodo.

deque<Point2Float> tcoord; Coordinate di texture del nodo

node* getNodeConnectedFromLink(link *l): restituisce il nodo connesso al nodo

(8)

void addLink(link *l): aggiunge un link in coda alla lista dei link (senza però

ri-ordinare la lista)

void removelink(link *l): rimuove il link l dalla lista.

void removeLinkExcept(link *l): rimuove tutti i link dallista eccetto il link l.

void OrdinateLinks(): Ordina la stella di link connessi al nodo secondo l’angolo di

inclinazione del link, considerando come origine il nodo stesso.

link* prevlink(link *l): Restituisce il link che si trova in lista prima del link in input

(nel caso in input ci sia il primo link, viene restituito l’ultimo).

link* nextlink(link *l): Restituisce il link che si trova in lista dopo il link in input (nel

caso in input ci sia l’ultimo link, viene restituito il primo).

bool hasLinkBetween(link*l1,link*l2): Restituisce true, se in lista esiste almeno un

link che si trova fra i due link dati in input.

link* getLinkFromNode(node *n): cerca i link che connette il nodo corrente con il

nodo passato in input.

4.2.6.

La classe Link

La classe link rappresenta i frammenti di strada, che connettono i nodi nel CityGraph. [par 3.3]

int id: identificativo numerico del link

unsigned int what: Tipo del link. Il link può essere “nullo” (0), può rappresentare una

strada (da 1 a 5 in ordine di importanza della strada), “corso d’acqua” (6), “ferrovia” (7). [par 3.3]

node* node1, node2: puntatori ai nodi connessi dal link

Point2Int coord[4]: Coordinate in pixel del contorno di un link. Il link è sempre

(9)

vengono memorizzate in questo modo: coord[0] è il punto a sinistra (o in alto di)

node1, coord[1] è quello a sinistra di node2, coord[2] a destra di node2 e coord[3]

quello a destra di node1.

Point3Float fcoord[4]: Coordinate in metri del contorno di un link.

Point2Float tcoord[4]: Coordinate di texture del link

float length: lunghezza in pixel del link (distanza da nodo a nodo)

float width: larghezza di un link calcolata nel suo punto medio. [par. 3.3.2]

float setlenght(): Calcola la lunghezza della strada come distanza fra i due nodi.

void linkRectangle(): Calcola il rettangolo che rappresenta idealmente il link, avendo

come riferimenti i due nodi e la larghezza. Questo passo è necessario a preparare la tessellazione vera e propria. [par. 3.4.3]

4.2.7.

La classe Square

La classe square rappresenta le piazze nel CityGraph. Ogni piazza è descritta tramite un lista di nodi che ne rappresentano il contorno ideale. I nodi sono scelti in modo che la piazza possa essere rappresentata sempre da un poligono convesso. [par. 3.3.3]

int id: identificativo numerico della piazza.

unsigned short what: Tipo della piazza. La piazza può essere “nulla” (0), una “piazza

vera e propria” (1), uno “specchio d’acqua” (2) o una “stazione ferroviaria” (3)

list<node*> vertex: lista di puntatori ai nodi che descrivono idealmente il contorno

della piazza. I nodi sono ordinati in senso antiorario.

deque<Point2Int> coord: lista di coordinate in pixel (in senso anti-orario) che

rappresentano il reale contorno della piazza, calcolato dopo la tessellazzione. [par. 3.4.3]

(10)

deque<Point3Float> fcoord: lista di coordinate in metri che rappresentano il contorno

di una piazza.

deque<Point2Float> tcoord; Coordinate di texture del nodo

float makePlaceFromNodeDeque(deque <node*> &nodeset): Dato un insieme di

nodi in input, ne calcola l’inviluppo convesso e riempie la lista dei vertici coi nodi trovati, memorizzandoli in senso antiorario. [par. 3.3.3]

node* nextvertex(node *n): Calcola il nodo della lista dei vertici, successivo a quello

in input.

node* prevvertex(node *n): Calcola il nodo della lista dei vertici, precedente a quello

in input.

link* getNextFromPreviousPlaceLate(node *n): Restituisce il link uscente dal nodo

in input, più vicino (con angolo minore) rispetto al lato della piazza, che collega il nodo col vertice precedente.

link* getPrevFromNextPlaceLate(node *n): Restituisce il link uscente dal nodo in

input, più vicino (con angolo minore) rispetto al lato della piazza, che collega il nodo col vertice successivo.

4.2.8.

La classe HouseBlock

La classe HouseBlock rappresenta gli isolati nel CityGraph. Ogni isolato è descritto tramite un lista di nodi che ne rappresentano il contorno. In realtà ogni isolato non è altro che un ciclo minimale del CityGraph. [par.3.3.4]

int id: identificativo numerico dell’isolato.

float fz: Altezza media degli eventuali edifici dell’isolato.

unsigned short what: tipo dell’isolato. L’isolato può essere “nullo” (0), un “edificio”

(da 1 a 3), un “giardino/parco” (4), uno “specchio d’acqua” (5), un “cortile/parcheggio asfaltato” (6).

(11)

deque <node*> nodes: lista di puntatori ai nodi che descrivono il cilo minimale del

CityGraph che rappresenta un isolato.

deque <Point2Int> coord: lista di coordinate in pixel (in senso anti-orario) che

rappresentano il reale contorno dell’isolato, calcolato dalla tessellazione degli altri elementi stradali. [par. 3.4.3]

deque <Point3Float> fcoord: lista di coordinate in metri che rappresentano il

contorno di un isolato.

deque <Point3Int> triangoles: L’isolato non è necessariamente un poligono convesso

per cui è necessario triangolarlo per poi venire rappresentato in 3D. In questa lista ogni tre vertici (in senso antiorario) viene definito un triangolo.

void triangulate(): Trangolarizza il poligono che rappresenta l’isolato. Per farlo

sfrutta una libreria esterna e open-source, implementata da John W.Ratcliff. [RATCH]

4.2.9.

La classe CityGraph

La classe CityGraph è la classe che rappresenta il CityGraph nella sua interezza e collega fra loro le varie entità dell’ambiente urbano.

Le quattro entità principali: nodi, link, piazze e isolati, sono accessibili alla classe CityGraph, tramite quattro (una per ognuna) liste di puntatori ai vari oggetti. I puntatori ai nodi oltre ad essere memorizzati in una lista, lo sono anche in un matrice (di dimensioni uguali alla mappa raster in input), in modo da velocizzarne notevolmente l’accesso, che avviene quindi anche tramite le coordinate in pixel di ciascun nodo.

La classe controlla inoltre i successivi stadi del processo di riconoscimento della mappa e di creazione dell’ambiente 3D.

int nodeidcount, linkidcount, placeidcount, houseblockidcount: id degli ultimi

elementi aggiunti al CityGraph.

TFW* tfw: oggetto TFW che contiene attributi e metodi per la conversione da

(12)

RasterImage* base: immagine raster “ripulita” della mappa 2D.

class NodeMatrix: inner class, costituita da una matrice e dai relative metodi per

accedere ai vari elementi, formata da puntatori ai nodi. Se per una coppia di coordinate non esiste un nodo di riferimento la cella contiene il puntatore nullo.

NodeMatrix* nmatrix: oggetto della classe NodeMatrix.

list<node*> nodes: lista di puntatori ai nodi del CityGraph.

list<link*> links: lista di puntatori ai link del CityGraph

list<square*> squares: lista di puntatori alle piazze del CityGraph

list<houseblock*> blocks: lista di puntatori agli isolati del CityGraph

ColorRGB c_street1, c_street2, c_street3, c_street4, c_street5, c_river, c_railway e ColorRGB c_building1, c_building2, c_building3, c_water, c_garden, c_carpark:

Colore con cui sono rappresentati sulla mappa (già ripulita) i vari tipi di link (ed eventualmente piazze) e di isolati. Se il campo marker della classe ColorRGB è posto a 0 significa che sulla mappa non ci sono elementi di quel tipo.

bool generateTFW(char *fname) e void generateTFW(float A, float E, float B, float

D, float C, float F): Generano i parametri di conversione Pixel-World direttamente da

file

bool addnode(node *n): aggiunge il puntatore a un nodo sia in coda alla lista dei nodi

sia nella matrice di nodi relativamente alle proprie coordinate sulla rastermap.

void addlink(link *l): aggiunge in coda alla lista dei link un puntatore al link l.

void addsquare (deque <node*> &setnode, unsigned short square_what, float

minarea, float maxarea): Data una lista di nodi candidata a far parte di una piazza ne

calcola l’eventuale inviluppo convesso e nel caso la piazza abbia i giusti requisiti di area minima e massima, la piazza viene aggiunta al CityGraph.

(13)

void addhouseblock(list <node*> &setnode): data una lista di nodi, ordinati e

caratterizzanti un ciclo minimale del CityGraph, crea un oggetto di tipo houseblock e ne aggiunge il puntatore alla relative lista.

link* addItem(const Point2Int& p1,const Point2Int& p2): Aggiunge i due nodi alla

struttura dati. Crea un link che li congiunge e aggiunge anch’esso al CityGraph.

node* clonenodeat (node *n, int x, int y): Crea o modifica (se già esistente), alla

posizione in input, un nuovo nodo con proprietà identiche a quello dato, esclusi ovviamente i link connessi. La funzione restituisce il nodo clonato.

node* movenode (node *n,int newx, int newy, bool linkrectangle=true): muove il

nodo dato nella nuova posizione. Se la posizione è già occupata da un altro nodo, lo cancella e lo sostituisce. Nel caso il parametro linktriangle sia posto a true, significa che deve essere rieseguita la funzione linktriangle() su tutti i link del nodo.

void collapseNodeAndMarkLink(link *l): “Collassa” assieme due nodi in uno (in una

posizione a metà strada fra le due). Il nuovo nodo contiene la somma dei link di entrambi i nodi che lo hanno generato. Il link che li congiungeva viene “segnato” (id=-1), per venire in seguito eliminato.

void markNodeforDelete(node *n): “segna” un nodo (id=-1) per una successiva

eliminazione.

void markLinkforDelete(link *l,bool piazza): “segna” un link (id=-1) per una

successiva eliminazione.

void delLinkAndMarkNode(link *l): cancella un link e “segna” un nodo (id=-1) per

una successiva eliminazione.

void setColorLink(const ColorRGB obj[8]): assegna il colore ad ogni tipo di link

(14)

void findcross(int tovisit=1,int visited=2,int mcross=3): Ricerca gli incroci sulla

mappa in seguito alla skeletonizzazione. “Segna” ogni singolo pixel come “incrocio visitato”, “da visitare”, “incrocio trovato”. [par. 3.3.1]

void findcurve(int tovisit=2,int visited=1,int mcross=3): Ricerca le curve sulla mappa

skeletonizzata e con gli incroci “segnati”. [par. 3.3.1]

float getWidth(const Point3Int &p, float m,Point3Int &p1,Point3Int &p2): Calcola

la larghezza del link. [par. 3.3.2]

void SemplifyNet (float l=4): Semplifica la rete, a seguito della ricerca incroci e

curve. Il parametro l indica la distanza massima dei nodi da accorpare. [par. 3.3.1]

void findplace(): Per ogni nodo esegue una ricerca in profondità sul grafo finché trova

nodi e link candidate a far parte di una piazza. Ogni insieme di nodi viene poi passato alla funzione addPlace. [par. 3.3.3]

void searchNodeforPlace(node *n, deque<node*> &nodeset, int recursion,unsigned

short place_what) e void searchNodeforPlace(node *n,deque<node*> &nodeset, unsigned short place_what): funzione ricorsiva che esegue una ricerca in profondità

fra tutti i possibili nodi candidati a far parte di una piazza e memorizza i nodi trovati nella lista nodeset.

bool PlaceFilling(place *p,deque <node*> &setnode): Esegue una scan line di una

piazza alla ricerca di possibili nodi interni da eliminare o spastare lung oil margine della piazza. [par. 3.3.3]

void moveNodeOnPlaceEdge(node* n, place* p): Muove un determinato nodo

interno alla piazza su un suo lato. Calcola l’intersezione dei suoi link uscenti coi vari lati della piazza ed eventualmente oltre a spostare il nodo lo clona anche in altre posizioni. [par. 3.3.3]

void ResolvePlaceIntersection(place *p): Controlla che due piazze riconosciute non

(15)

void semplifyNetAfterPlace(): Semplifica il CityGraph a seguito della creazione delle

piazze. [par. 3.3.3]

void semplifyPlacecontour(place *p, float mindist=10,float maxdist=25): Semplifica

il contorno della piazza, “collassando” nodi troppo vicini, o creandone di nuovi nel caso ci siano nodi troppo distanti. [par. 3.3.3]

void recalculateLinksRectangleCoordperNode(node *nodo): Calcola la tessellazione

dei link e dei nodi, in prossimità di incroci. e curve. [par. 3.4.3]

void recalculateLinksRectangleCoordperPlace(place *pzza): Calcola la tessellazione

dei link, dei nodi e delle piazze, in prossimità delle piazze. [par. 3.4.3]

void findcycles(): Ricerca dei cicli minimali all’interno del CityGraph. Ogni ciclo

minimale viene poi elaborato e aggiunto alla struttra dati del CityGraph attraverso la funzione addHouseBlock. [par. 3.3.4]

void cycleTriangulate(): triangolarizza tutti gli isolati.

void setTypeOfBlocks(): Riconosce il tipo di un isolato, in base alla moda dei colori

dei pixel interni al contorno dell’isolato stesso. [par. 3.3.4]

void TFWconverting(): Calcola le coordinate reali di ciascun elemento del CityGraph

bool findZground(char *name): carica il file DTM in input (se non ci riesce

restituisce false) e calcola l’altitudine dei nodi e di conseguenza di link e piazze.

void findZBuilding(char *name): carica il file DTM in input (se non ci riesce

restituisce false) e calcola l’altitudine media dei palazzi che fanno parte di un isolato.

void middlelinecoord(float length): Calcola le coordinate per l’eventuale riga di

mezzeria di una strada

void CalculateLinksTex(float texw, float texh): Calcola le texture coordinates degli

elementi stradali. Texw e Texh indicano le dimensioni reali del pezzettino di asfalto rappresentato dall’immagine usata come texture

(16)

void IDdefrag(): Riassegna gli ID ai vari oggetti, in modo che siano sequenziali e

senza salti.

4.3. Serializzazione degli oggetti del CityGraph

L’applicazione al termine del processo di creazione del CityGraph, permette di salvare la struttura dati creata in un semplice file ASCII.

Il file ASCII generato in output è diviso in 4 sezioni, ognuna identificata da un tag specifico. Ogni sezione rappresenta una lista di oggetti della stessa classe. In ogni sezione, uno per riga, si trovano le descrizioni degli oggetti di quella particolare classe. Ogni attributo è separato dagli altri da uno spazio. Nel caso l’oggetto contenga una lista di oggetti ad esso collegati (ad esempio: piazze e vertici), la lista sarà indicata da un tag che la rappresenta, il tag sarà seguito dal numero degli elementi e successivamente dall’identificativo degli elementi veri e propri, i quali saranno a loro volta separati da spazi. Se la lista non contiene elementi è seguita dal solo numero “0”. I tipi dei vari elementi sono espressi tramite interi. Se un nodo non fa parte di una piazza l’id della piazza è posto a -1.

<NODES>

id_n1 x y z tipo id_pzza <L> #link id_l1 id_l2 … id_ln <C> #cicli id_c1 id_c2 … id_cn id_n2 x y z tipo id_pzza <L> #link id_l1 id_l2 … id_ln <C> #cicli id_c1 id_c2 … id_cn

id_nn x y z tipo id_pzza <L> #link id_l1 id_l2 … id_ln <C> #cicli id_c1 id_c2 … id_cn <LINKS>

id_l1 tipo <N> id_n1 id_n2 …

<SQUARES>

id_p1 tipo <N> #nodi id_n1 id_n2 … id_nn

<BLOCKS>

id-b1 tipo altezza <N> #nodi id_n1 id_n2 … id_nn

Questa rappresentazione è di facile utilizzo e lettura quasi quanto un file in formato xml, ma meno ingombrante in termini di dimensioni del file. Rispetto a un file binario, può a fini di debug, essere facilmente editata manualmente. Ciò non toglie che in sviluppi futuri, per

(17)

ridurne l’ingombro e velocizzarne il trasporto in rete, il formato ideale per questo file sia appunto un formato binario.

4.4. Descrizione

dell’editor

Parallelamente all’applicazione che genera automaticamente il CityGraph è stato implementato, usando XVR, un semplicissimo editor visuale. L’editor permette di leggere in input il file contenente la descrizione del CityGraph e di apportarvi alcune modifiche quali lo spostamento, la creazione e la distruzione di nodi, link, piazze e isolati oppure la possibilità di cambiare le proprietà di ciascuno di questi elementi, come il tipo e l’altitudine, oppure per quanto riguarda i link anche la lunghezza e la larghezza.

Al fine di rendere più semplici le operazioni di authoring, il city graph viene sovrapposto alla mappa raster originale. Sono inoltre impostabili vari livelli di zoom o di scroll ed è possibile regolare la trasparenza dell’immagine sullo sfondo.

(18)

figura 4.2 - Alcuni screenshot dell'editor

Figura

figura 4.1 - Schema riassuntivo organizzazione delle classi
figura 4.2 - Alcuni screenshot dell'editor

Riferimenti

Documenti correlati