Funzionalità Avanzate per la Visualizzazione e Trasmissione di Dati

Transcript

Funzionalità Avanzate per la Visualizzazione e Trasmissione di Dati
UNIVERSITÀ DEGLI STUDI DI TRENTO
Facoltà di Scienze Matematiche, Fisiche e Naturali
Corso di Laurea (triennale) in INFORMATICA
Elaborato finale
Funzionalità Avanzate per la Visualizzazione
e Trasmissione di Dati Georeferenziati
Relatore:
Laureando:
Prof. Ronchetti Marco
Andreolli Michele
105093
Correlatori:
Ing. De Amicis Raffaele
Ing. Conti Giuseppe
Ing. Piffer Stefano
Anno Accademico 2006 - 2007
“L’unica difesa contro il Mondo
è conoscerlo
Bene”
John Locke
(1632-1704)
Ai miei Genitori
2
Ringraziamenti
Ormai è più di un anno che sono in GraphiTech.
É stato un anno impegnativo, trascorso tra gli ultimi esami, tra uno stage interminabile, tra la EuroGraphics Conference,
l’insegnamento alla scuola elementare e conclusosi con questa tesi.
Un anno di grandi cambiamenti, costellato da nuove preoccupazioni, nuovi impegni e responsabilità, ma anche da
momenti belli ed intensi che non sarebbero stati tali senza la presenza di persone veramente speciali.
Per prima cosa voglio ringraziare la mia famiglia, che mi ha sempre appoggiato durante questi anni, che ha sopportato i
miei (altalenanti) ritmi di studio e che ha reso finanziariamente possibile questo risultato, quindi grazie a mamma
Lorenza e papà Pier Giorgio.
Per quanto riguarda la stesura di questa tesi vorrei ringraziare il mio professore Marco Ronchetti che mi ha fatto
conoscere GraphiTech.
Un grazie enorme va a Raffaele De Amicis e Giuseppe Conti, per avermi accettato, prima come stagista, nonostante le
mie pressoché nulle conoscenze di Computer Graphics, e dopo come tesista.
Non posso dimenticare di ringraziare Stefano Piffer e Gabrio Girardi, per l’aiuto indispensabile che mi hanno dato, sia
durante lo sviluppo del progetto, che nella fase di scrittura dell’elaborato e per i tanti consigli.
Un grazie anche a Martin Witzel, per aver sopportato le mie lacune ad inizio stage e per avermi invogliato e inserito nei
progetti, rispondendo alle molte, forse troppe, domande.
Un grazie a tutti gli amici conosciuti Olga, Bita, Gianpaolo, Consuelo, Michael, Augusta, Arben, e Andrea con i quali
ho trascorso, con chi più e con chi meno, questo anno di lavoro, tra stage e tesi.
Ed eccoci ai ringraziamenti meno formali e più goliardici verso gli amici di università e non.
Grazie a Secco, Perzem, Paru compagni inseparabili nelle “lunghe” e troppo mattutine trasferte verso la facoltà di Povo
e nei “lunghi” e troppo mattutini rientri a casa post-serata.
Grazie a tutta la Calimocho Boys Band (+Giò) e ai Daft Punk (il più bel concerto di sempre
) per aver trasformato
questa estate, all’inizio poco invitante, in una estate indimenticabile.
Grazie a Cesenatico…
Grazie agli amici ormai di vecchia data, quelli veri, che hanno arricchito la mia vita e che continuano a farlo:
Massimella, Mit, Toss, Mecchenzie, Otzi, Bettina, Matteo, Giulia, Cannamozza, le sorelle Gamberinus, Toldo…
Veramente grazie a Giulia, per esserci sempre (o quasi), per ricordarmi la bellezza delle piccole cose, per l’entusiasmo
che sai metter in tutto, ma soprattutto… Grazie per le traduzioni
.
Potrei continuare con i ringraziamenti per molte pagine, ma sono sicuro che chi non ho citato non se la prenderà… se lo
segni e me lo ricordi alla prossima Laurea!
Michele
3
Indice
1.
Introduzione
1.1.
1.2.
1.3.
5
Definizioni, Acronimi e Abbreviazioni
Riferimenti
Anteprima
6
10
11
2.
Requisiti e Tools di Sviluppo
2.1. Java e IDE Utilizzati
2.1.1.
Eclipse
2.1.2.
JBuilder
2.2. PostgreSQL
2.3. OpenGL
2.4. JOGL
11
11
15
16
17
17
18
3.
Stato dell’Arte
18
3.1. GIS
3.2. Applicativi
3.2.1.
GoogleEarth
3.2.2.
API WorldWind
19
23
23
26
4.
Funzionalità Avanazate per la Trasmissione di Dati Georeferenziati
4.1. Introduzione allo Standard GeoRSS
4.2. Specifiche GeoRSS
4.3. Applicazione per la Gestione di Dati GeoRSS attraverso Database
29
29
33
35
5.
OpenGL
47
5.1.
5.2.
5.3.
5.3.1.
5.3.2.
5.4.
47
51
52
57
60
61
Introduzione a OpenGL
Modello di Macchina a Stati
Principali Primitive
Texturing
Blending
JOGL OpenGL per Java
6.
Personalizzazione Ambiente Tridimensionale
6.1. Gestione Trasparenze Tematismo
6.2. Gestione Informazioni GeoRSS
62
68
74
7.
Conclusioni
78
7.1.
7.2.
78
79
Campi d’Impiego
Possibili Sviluppi
8.
ScreenShots
80
9.
Bibliografia
87
4
1. Introduzione
Il corso di studi in Informatica dell’Università di Trento, prevede lo svolgimento di uno stage, per permettere agli studenti una più completa formazione universitaria in vista di un futuro inserimento nel campo lavorativo. Dopo un
interessante colloquio con il mio tutor universitario, professor Ronchetti Marco, ed aver deciso l’ambito del tirocinio,
su suggerimento dello stesso, mi sono messo in contatto con la Fondazione GraphiTech.
La Fondazione GraphiTech, Center for Advanced Computer Graphics
Technologies, è stata costituita come joint venture tra la Fondazione INIGraphicsNet (www.inigraphics.net), il Centro per la Ricerca Scientifica e
Tecnologica (ITC-irst) (www.itc.it) e l'
Università di Trento (www.unitn.it) al
fine di incentivare sul territorio trentino iniziative di ricerca scientifica e tecnologica nel campo della computer graphics e di favorire il trasferimento
tecnologico e lo sviluppo della cultura imprenditoriale in questo settore
disciplinare.
La Fondazione, collabora con enti, società sia pubblici che privati, sia italiani che stranieri, per promuovere e
organizzare attività ed iniziative di ricerca scientifica e tecnologica, di trasferimento delle conoscenze, di promozione e
sviluppo della cultura imprenditoriale, dello sviluppo economico, sociale e culturale, il tutto con preminente riferimento
all’area della Provincia Autonoma di Trento, ma senza che ciò comporti limitazioni territoriali.
Le attività ed iniziative spaziano anche nel campo imprenditoriale, volte ad agevolare ed incentivare l’implementazione,
l’applicazione e l’industrializzazione, sia nel mondo delle imprese sia della pubblica amministrazione, di idee,
innovazioni, konw-how, tecnologie, esperienze e competenze sviluppati dall’Università, da altri istituti o enti che
abbiano svolto attività di ricerca.
A tale fine, l’azienda partecipa anche a progetti finanziati dall’Unione Europea (UE), dalla Repubblica Italiana (RI) e da
altri enti e organizzazioni, sia pubblici che privati che mirano a favorire il trasferimento tecnologico alle imprese
facilitandone l’avviamento e lo sviluppo.
GraphiTech è un’azienda orientata principalmente all’innovazione , Ricerca e Sviluppo
nella vasta area della
“Advanced Computer Graphics (ACG)”, della “Virtual Reality (VR)”, della “Mixed Reality (MR)” e delle tecnologie
dell’informazione e della comunicazione “Information and Comunication Systems (ICS)”.
Dopo aver svolto l’attività di stage sul progetto europeo “Improve”, riguardante la visualizzazione e la comunicazione
tra clients in ambiente virtuale collaborativo ( www.improve-eu.info ), ho deciso di continuare il mio percorso di
formazione in GraphiTech, svolgendo anche il mio progetto di tesi.
L’ambito progettuale sul quale ci si è indirizzati è stata la modifica e implementazione di alcune funzionalità del
software base World Wind per permettere la visualizzazione e la trasmissione di dati georeferenziati.
Il prodotto derivato prenderà nome di “Project Anna”.
Project Anna è una personalizzazione e ottimizzazione della libreria open-source World Wind, sviluppata dalla NASA,
che permette di visualizzare immagini e oggetti tridimensionali di qualsiasi zona del pianeta, combinando foto
satellitari, aeree e dati SRTM (Shuttle Radar Topography Mission).
5
Numerosi sono i software per la visione e navigazione delle mappe satellitari, La parte riguardante la trasmissione dei
dati georeferenziati, invece, avviene grazie al supporto dell’innovativo formato GeoRSS. Si tratta di un formato leggero
e basato su XML ideato con lo scopo di georeferenziare il contenuto dei feed RSS.
Il percorso di sviluppo di tesi è stato sostanzialmente diviso in due parti:
1.
La fase di implementazione dell’applicazione per la gestione di un database di dati GeoRSS.
2.
La fase di sviluppo di Project Anna per supportare alcune nuove funzionalità rispetto alla versione base.
Entrambi le fasi sono state precedute da un periodo di ricerca e comprensione degli obiettivi finali da raggiungere e
delle tecniche migliori da adottare per affrontare lo sviluppo dell’applicazione.
Nella prima parte le lacune su alcuni concetti dell’interazione tra linguaggio Java e database sono stato abbastanza
rapidamente colmate, invece le difficoltà pervenute in Project Anna sono state decisamente più consistenti e sono state
superate con diversi tentativi pratici e con lo studio del codice, molto vasto e a tratti complicato.
Gli obiettivi preposti sono stati, comunque, raggiunti e saranno una buona base per un ulteriore sviluppo del progetto
che GraphiTech continuerà a portare avanti.
1.1. Definizioni, Acronimi e Abbreviazioni
API (Application Programming Interface): insieme di procedure disponibili al programmatore, raggruppate a
formare un set di strumenti specifici per un determinato compito.
ARB (Architectural Review Board): consorzio indipendente fondato nel 1992 che governa le specifiche
OpenGL e che ha approvato la più famosa ed utilizzata tra le librerie di estensioni, denominata appunto ARB.
Essa comprende funzioni e comandi stabili, supportati dalla maggior parte degli hardware.
BSD (Berkeley Software Distribution): famiglia di licenze permissive per software. Molte sono considerate
libere ed open source. Il loro nome deriva dal fatto che la licenza BSD originale fu usata originariamente per
distribuire il sistema operativo Unix Berkeley Software Distribution, una revisione libera di UNIX sviluppata
presso l'
Università di Berkeley.
CVS (Concurrent Versioning System): sistema per il controllo delle versioni di un progetto software. Molto
utilizzato in ambiente GNU/Unix, ed ovviamente in ambiente Linux, sta acquistando molta popolarità tra gli
sviluppatori di tutto il mondo in quanto utilizzato da tutti i maggiori team di sviluppo dei progetti GNU. CVS
permette di creare una history di tutti i sorgenti, registrando ogni modifica, ed associando ad ogni sorgente un
numero di revisione comprensivo di un breve commento sulle modifiche apportate. Con CVS, è inoltre
possibile recuperare, in ogni momento, qualsiasi versione precedente del progetto per poterla modificare, ed è
stato disegnato per essere utilizzato da un team di sviluppo, garantendo che i sorgenti restino sempre
consistenti, impedendo che le modifiche apportate da uno sviluppatore vengano soprascritte da altri. Infine,
permette di esportare le differenze fra due release diverse dello stesso progetto, creando i famosi file di patch.
DBMS (Database Management System): sistema software progettato per consentire la creazione e
manipolazione efficiente di database, ovvero di collezioni di dati strutturati.
6
DirectX (in origine chiamata "Game SDK"): è una collezione di API per lo sviluppo semplificato di
videogiochi per Windows. Il kit di sviluppo (SDK) è disponibile gratuitamente sul sito della Microsoft. Le
DirectX venivano distribuite dai produttori di giochi stessi insieme al videogioco, ma sono ora incluse
direttamente in Windows.
DOM (Document Object Model): un’interfaccia neutrale che permette ai programmi e agli script di accedere
dinamicamente ai documenti. Tale interfaccia permette di aggiornare il contenuto, la struttura e lo stile dei
documenti.
DTM (Digital Terrain Model): modello digitale del terreno, raster (griglia) o vettoriale, ricavato dalla
scansione di fotografie aeree o satellitari.
GEORSS (Geographically Encoded Objects for RSS feeds): formato leggero e basato anch’esso su XML
ideato con lo scopo di georeferenziare il contenuto dei feed RSS.
GIS (Geographic Information System): sistema informativo computerizzato che permette l'
acquisizione, la
registrazione, l'
analisi, la visualizzazione e la restituzione di informazioni derivanti da dati geografici
georeferenziati.
GL (Graphics Library): libreria OpenGL di base, contiene codice per oggetti geometrici primitivi, attributi,
trasformazioni, colore, illuminazione...
GLU (Graphics Library Utilities): contiene codice per oggetti non primitivi di uso comune (es. sfere), ed altre
funzioni di utilita'
, implementate su GL.
GLUT (Graphics Library Utility Toolkit): funzionalità minimali per dotare un programma che fa grafica in
OpenGL di un'
interfaccia utente in un ambiente a finestre.
GML (Geography Markup Language): grammatica XML definita dal OGC per esprimere oggetti geografici.
Serve come linguaggio di modellazione e di interscambio di dati via Internet. Molto più ampio del formato
GeoRSS.
GUI (Graphical User Interface): paradigma di sviluppo che mira a consentire all'
utente di interagire col
calcolatore manipolando graficamente degli oggetti, svincolandolo dall'
obbligo di imparare una serie di
comandi da impartire con la tastiera. È lo strato di un'
applicazione software che si occupa del dialogo con
l'
utente del sistema utilizzando un ambiente grafico.
IDE (Integrated Development Environment): software che aiuta i programmatori nello sviluppo del software.
Normalmente consiste in un editor di codice sorgente, un compilatore e/o un interprete, un tool di building
automatico, (solitamente) un debugger e designer per GUI.
7
JDBC (Java DataBase Connectivity): middleware per database che consente l'
accesso alle basi di dati da
qualsiasi programma scritto con il linguaggio di programmazione Java, indipendentemente dal tipo di DBMS
utilizzato. È costituito da una API, raggruppata nel package java.sql, che serve ai client per connettersi a un
database. Fornisce metodi per interrogare e modificare i dati. È orientata ai database relazionali ed è Object
Oriented.
JDK (Java Development Kit): è il corredo di sviluppo del Java, comprende compilatore Java e alcuni
applicativi che permettono agli utenti di generare le applicazioni in Java.
JOGL (Java OpenGL): libreria a basso livello per la programmazione OpenGL con supporto Java simile alla
libreria GLUT per il C++.
Khronos Group: consorzio industriale focalizzato nella creazione di API a standard aperto COLLAD,
OpenGL ES, OpenMAX, OpenVG, OpenSL ES e OpenML per rendere possibile l'
authoring e l'
accelerazione
di elementi multimediali dinamici su una grande varietà di piattaforme e dispositivi.
KML (Keyhole Markup Language):un linguaggio basato su XML creato per gestire dati geospaziali in tre
dimensioni nei programmi Google Earth, Google Maps e Google Mobile. La parola “keyhole” è un vecchio
nome che viene dal software da cui deriva Google Earth.
NASA (National Aeronautics and Space Administration): agenzia governativa civile responsabile per il
programma spaziale degli Stati Uniti d'
America e per la ricerca aerospaziale civile e militare.
Obiettivo delle API è ottenere un'
astrazione, di solito tra l'
hardware e il programmatore, o tra software a basso
ed alto livello.
OGC (Open Geospatial Consortium): organizzazione internazionale no-profit, basata sul consenso volontario,
che si occupa di definire specifiche tecniche per i servizi geospaziali e di localizzazione (location based). OGC
è formato da oltre 280 membri (governi, industria privata, università) con l'
obiettivo di sviluppare ed
implementare standard per il contenuto, i servizi e l'
interscambio di dati geografici che siano "aperti ed
estensibili”.
OpenGL (Open Graphics Library): specifica che definisce una API per più linguaggi e per più piattaforme per
scrivere applicazioni che producono computer grafica 2D e 3D.
Pipeline: Il termine pipeline in informatica e in elettronica si riferisce a un manufatto composto da più
elementi. Ogni elemento provvede a ricevere in ingresso un dato o un segnale, ad elaborarlo e poi a
trasmetterlo all'
elemento successivo.
RAD (Rapid Application Development): metodologia di sviluppo del software introdotta inizialmente da James
Martin negli anni ottanta. Questa metodologia coinvolge modelli di sviluppo iterativi, la costruzione di
prototipi e l'
utilizzo di strumenti CASE
8
Raster: Metodologia per la codifica delle informazioni che utilizza come elemento base una matrice ordinata
di righe e colonne composta da celle (o pixel) aventi forma regolare (generalmente quadrata). A ogni cella
viene associato un valore relativo a un determinato attributo. Le immagini digitali hanno struttura raster.
Rasterizing: La rasterizzazione è il lavoro di convertire un immagine bidimensionale descritta da vettori (in
grafica vettoriale), in un immagine raster o bitmap, ovvero formata da pixels. Questo lavoro è effettuato sia per
ottenere un immagine proiettabile su dispositivi video, come i monitors, sia per la stampa.
RDF(Resource Description Framework.): formato strutturato per la diffusione delle informazioni sul web.
Creato secondo le direttive del W3C per la descrizione dei metadati relativi alle risorse. Questa struttura è una
delle proposte alla base del cosiddetto web semantico e permette la condivisione di informazioni via web.
RSS (RDF Site Summary e Really Simple Syndication): uno dei più popolari formati, per la distribuzione di
contenuti Web, basati su XML, da cui ha ereditato semplicità, l'
estensibilità e la flessibilità.
SAX (Simple API for XML): interfaccia standard per il parsing XML basato su eventi, sviluppato in
collaborazione dai membri della mailing list XML-DEV, attualmente presentato da OASIS.
Shapefile ESRI: è un popolare formato vettoriale per sistemi informativi geografici. Emesso come (quasi)
open source, allo scopo di accrescere l'
interoperabilità fra i sistemi ESRI e altri GIS. Di fatto è diventato uno
standard per il dato vettoriale spaziale, e viene usato da una grande varietà di sistemi GIS.
SQL (Structured Query Language): linguaggio creato per l'
accesso e la manipolazione delle informazioni
memorizzate in database.
SWT (Standard Widget Toolkit): libreria di classi Java derivata da Eclipse che permette di creare interfaccie
grafiche native, utilizzando quindi oggetti del sistema operativo utilizzato.
Syndication: usato in termini giornalistici indica la vendita attraverso un’agenzia di stampa. In termini
informatici indica il “contratto” tra chi pubblica e chi diffonde notizie via web.
TIN (Triangulated Irregular Networks): è una struttura dati vettoriale basata su triangoli con maglia irregolare,
capace di fornire elevata risoluzione solo dove questa è necessaria.
UML (Unified Modeling Language): linguaggio di modellazione e specifica basato sul paradigma objectoriented.
USGS (United States Geological Survey): è un'
agenzia scientifica del Governo degli Stati Uniti. Gli scienziati
dell'
USGS studiano il territorio degli USA, le sue risorse naturali e i rischi naturali che lo minacciano.
L'
organismo si suddivide in dipartimenti che trattano quattro maggiori discipline scientifiche, biologia,
geografia, geologia e idrologia.
9
W3C(World Wide Web Consortium): associazione, di circa 300 membri, tra cui le più famose multinazionali
informatiche, con lo scopo di migliorare i protocolli e linguaggi esistenti per il World Wide Web e favorire lo
sviluppo del Web stesso aiutandolo a mettere in mostra tutte le sue potenzialità.
WMS (Web Map Service): con WMS si intende una specifica tecnica definita dall'
OGC: OpenGIS Web Map
Service Implementation Specification. Un OGC Web Map Service (WMS) produce dinamicamente mappe di
dati spazialmente riferiti a partire da informazioni geografiche. Questo standard internazionale definisce una
"mappa" come rappresentazione di informazioni geografiche restituendo un'
immagine digitale idonea ad essere
visualizzata sullo schermo di un computer.
XML (eXtensible Markup Language): metalinguaggio creato e gestito dal W3C. La struttura dell'
XML è
composta da tag creati dallo sviluppatore, che hanno due caratteristiche: devono essere comprensibili e devono
rispettare le regole di assegnazione dei nomi alle variabili, comuni a tutti i linguaggi di programmazione.
XSD (XML Schema Definition): schema di definizione della struttura di un documento XML realizzato dal
W3C. In pratica un documento XML rispetterà la struttura, definita nello Schema XML.
1.2. Riferimenti
Descrizione del progetto.
A cura della Fondazione GraphiTech.
Documentazione per Sviluppatori del progetto “World Wind”.
http://www.worldwindcentral.com/wiki/Category:WWJ_Dev_Documentation
A cura della NASA.
10
1.3. Anteprima
In sezione 2, si riportano i Requisiti da soddisfare per utilizzare l’applicazione e i Tools di sviluppo adottati.
In sezione 3, si illustra lo Stato dell’Arte del progetto.
In sezione 4, si illustra il formato GeoRSS e l’applicazione sviluppata per la gestione del Database.
In sezione 5, si riportano le caratteristiche principali della libreria grafica OpenGL e di quella JOGL per Java.
In sezione 6, si descrive la Personalizzazione dell’Ambiente Tridimensionale sviluppato.
In sezione 7, si traggono le Conclusioni, i Futuri Sviluppi e i possibili Campi d’Impiego.
In sezione 8, vengono riportati alcuni ScreenShot dell’applicazione.
In sezione 9, si delinea la Bibliografia di riferimento.
2. Requisiti e Tools di Sviluppo
Di seguito vengono riportate caratteristiche principali, requisiti e tools utilizzati durante la fase implementativa del
progetto di tesi. Alcune caratteristiche elencate vengono riportate per una completa visione d’insieme degli strumenti
adottati, ma non rientrando nell’ambito del progetto non sono state utilizzate.
2.1. Java e IDE Utilizzati
Il modello classico di programmazione, conosciuto come “paradigma procedurale”, può essere riassunto in due parole:
“Divide et Impera” ossia dividi e conquista.
Difatti secondo questa filosofia, un problema complesso viene suddiviso in problemi più semplici in modo che siano
facilmente risolvibili mediante programmi “procedurali”. E’ chiaro che in questo caso, l’attenzione del programmatore
è accentrata al problema con le limitazioni che l’architettura del calcolatore impone.
A differenza del primo, il paradigma Object Oriented accentra l’attenzione verso i dati. L’applicazione viene suddivisa
in un insieme di oggetti in grado di interagire tra di loro e codificati in modo tale che la macchina sia in gradi di
comprenderli.
Il primo cambiamento evidente è quindi a livello di disegno della applicazione. Di fatto l’approccio Object Oriented
non è limitato a linguaggi come Java o C++ . Molte applicazione basate su questo modello sono state scritte con
linguaggi tipo C o Assembler. Un linguaggio Object Oriented semplifica il meccanismo di creazione degli Oggetti allo
stesso modo con cui un linguaggio procedurale semplifica la decomposizione in funzioni.
Gli elementi fondamentali di tale paradigma sono gli oggetti che vengono, in un primo momento definiti, descrivendone
le caratteristiche, poi creati e allocati in memoria ed infine vengono usati in relazione l'
uno con l'
altro.
L’analisi delle modalità di interazione tra gli oggetti permetterà di riunire gli oggetti a formare l’applicazione.
È possibile, quindi, stabilire una basilare distinzione tra i due metodi di programmazione:
•
Nella programmazione tradizionale (o imperativa), i problemi vengono affrontati rivolgendo l'
attenzione alle
operazioni da svolgere: si cerca una decomposizione funzionale del problema.
11
•
Nella programmazione ad oggetti, si vuole innanzitutto stabilire quali sono le entità che interagiranno tra loro,
ricreando un modello adatto per descrivere il problema da risolvere. Tali entità sono gli oggetti con
determinate caratteristiche (attributi) e determinate funzionalità (metodi).
Con l’aumento delle prestazione dei calcolatori e di conseguenza con l’aumento della complessità delle applicazioni,
l’approccio procedurale ha iniziato a mostrare i propri limiti rendendo necessario definire un nuovo modello e nuovi
linguaggi di programmazione. I linguaggi come Java e C++ forniscono il supporto ideale al disegno ad oggetti di
applicazioni fornendo un insieme di regole sintattiche e semantiche che aiutano nello sviluppo di oggetti.
Evoluzione del Modello di Programmazione
Il linguaggio Java inizia la sua evoluzione durante l’aprile del 1991, quando un gruppo di impiegati della Sun
Microsystem, conosciuti come “Green Group”, iniziarono a studiare la possibilità di creare una tecnologia in grado di
integrare le allora attuali conoscenze nel campo del software
con l’elettronica di consumo.
Avendo subito focalizzato il problema sulla necessità di avere un linguaggio indipendente dalla piattaforma (il software
non doveva essere legato ad un particolare processore) il gruppo iniziò i lavori nel tentativo di creare un linguaggio
che estendesse il C++ (la sintassi infatti è simile). La prima versione del linguaggio fu chiamata Oak e, successivamente
per motivi di royalty??, Java.
Cronologia Versioni Java Rilasciate
JDK 1.1.4
12 Settembre 1997
J2SE 1.3
8 Maggio 2000
JDK 1.1.5
3 Dicembre 1997
J2SE 1.3.1
17 Maggio 2001
JDK 1.1.6
24 Aprile 1998
J2SE 1.4.0
13 Febbraio 2002
JDK 1.1.7
28 Settembre 1998
J2SE 1.4.1
16 Settembre 2002
JDK 1.1.8
8 Aprile 1999
J2SE 1.4.2
26 Giugno 2003
J2SE 1.2
4 Dicembre 1998
J2SE 5.0(1.5.0)
29 Settembre 2004
J2SE 1.2.1
30 Marzo 1999
Java SE 6 (1.6.0)
11 Dicembre 2006
J2SE 1.2.2
8 Luglio 1999
Java SE 7 (1.7.0)
Prevista per il 2008
Attraverso una serie di eventi, quella che era la direzione originale del progetto subì vari cambiamenti ed il target fu
spostato dall’elettronica di consumo al world wide web. Il 23 Maggio del 1995 la Sun ha prsentato formalmente Java.
Da quel momento in poi il linguaggio è stato adottato da tutti i maggiori “vendors” di software incluse IBM, Hewlett
Packard e Microsoft.
12
Java fu inizialmente rilasciato come Java Development Kit 1.0 (JDK 1.0).
Java Development Kit è un insieme di strumenti ed utilità ed è messo a disposizione gratuitamente da tanti produttori di
software. L’insieme base o standard delle funzionalità è supportato direttamente da Sun Microsystem ed include un
compilatore (javac), una Java Virtual Machine (java), un debugger e tanti altri strumenti necessari allo sviluppo di
applicazioni Java.
Inoltre il JDK comprende, oltre alle utilità a linea di comando, un completo insieme di classi pre-compilate e relativo
codice sorgente. Successivamente, Sun fornì un pacchetto che comprendeva solo Java Runtime, chiamato Java
RunTime Environment (JRE) che permetteva agli utenti finali di far girare applicazioni scritte in Java.
Normalmente gli utenti si riferiscono ad una particolare versione di Java attraverso la versione del JDK (es. JDK 1.4) Le
versioni JDK 1.2 e successive sono spesso chiamate Java 2. il nome ufficiale è quindi diventato Java(TM) 2 Platform,
Standard editino (J2SE).
Dalla prima versione del JDK il linguaggio non è stato sottoposto a grandi cambiamenti, ma la libreria di classi che
viene fornita con JDK è stata progressivamente ampliata e modificata in alcune parti ed è stata creata una grande
quantità di documentazione per poter usufruire al meglio della vastità di classi già implementate.
La documentazione è generalmente distribuita separatamente, è rilasciata in formato HTML e scaricabile dal sito:
http://java.sun.com/javase/downloads/index.jsp, e copre tutto l’insieme delle classi rilasciate con il JDK.
Java è stato creato cercando di tenere presente alcuni concetti fondamentali che stavano emergendo agli inizi di quegli
anni e che sono, successivamente, diventati suoi punti di forza.
Diamo ora una veduta d’insieme delle principali e più famose caratteristiche di Java:
1.
Affinità con il C e il C++
La similitudine sintattica con il più diffuso linguaggio di programmazione è grande; per esempio, le istruzioni for, if,
else sono del tutto analoghe a quelle del C. Inoltre, per rendere il linguaggio più semplice e lineare, sono state eliminate
in Java alcune caratteristiche del C e del C++, come le funzioni di allocazione e di liberazione della memoria e
l'
ereditarietà multipla. Altra caratteristica di Java sono le dimensioni ridotte del software, in modo che esso possa
funzionare anche su sistemi molto piccoli. L'
interprete, le classi e le "librerie" Java di base non superano nel loro
complesso i 250 Kbytes.
2.
Semplicità
Il linguaggio Java è stato progettato per essere semplice. I programmatori della Sun ritengono che il C++ sia un
linguaggio ridondante. Esso infatti deriva dal C, che non è orientato all'
oggetto, a cui sono state aggiunte le classi al fine
di creare un linguaggio orientato all'
oggetto. La conseguenza di ciò è che inevitabilmente il C++ possiede caratteristiche
che appartengono al C e che non rientrano nella filosofia dei linguaggi orientati all'
oggetto. Per questa ragione, tutte le
caratteristiche del C++ ritenute ridondanti sono state tolte da Java, in modo che quest'
ultimo potesse divenire un
linguaggio di programmazione più snello e facile da leggere.
3.
Linguaggio orientato all'
oggetto (Object-oriented)
Per essere considerato orientato all'
oggetto, un linguaggio di programmazione in linea di principio deve possedere
almeno questi quattro requisiti:
•
Incapsulamento: è possibile rendere riservata o astratta parte dell'
informazione.
•
Polimorfismo: gli stessi dati passati a oggetti differenti hanno effetti diversi a seconda dell'
oggetto coinvolto.
•
Ereditarietà: si possono definire classi sulla base di altre classi.
•
Collegamento dinamico: gli oggetti possono provenire da qualsiasi luogo, compresa la rete.
Java soddisfa piuttosto bene a queste quattro esigenze.
13
4.
Gestione automatica della memoria
In ogni programma Java è sempre attivo un thread a bassa priorità, detto “Automatic Garbage Collection”, che
provvede ad analizzare la memoria e a liberare quella che non è utilizzata. Una volta che un oggetto è stato creato, il
“Garbage Collector” in fase di esecuzione osserva la vita dell'
oggetto e provvede a liberare la memoria occupata quando
essa non viene più utilizzata dall'
oggetto in questione. Ciò solleva il programmatore dal provvedere alla gestione della
memoria, compito questo che in C e C++ conduce spesso all'
introdurre errori che si verificano in fase di esecuzione dei
programmi.
5.
Neutralità all'
architettura
La neutralità dell'
architettura rappresenta una caratteristica importante in un mondo informatico sempre maggiormente
popolato dai più svariati sistemi hardware e sistemi operativi. Con la fortissima crescita delle reti telematiche questa
esigenza è divenuta ancora più pressante. Inoltre, per sviluppare prodotti software per il World Wide Web, la neutralità
dall'
architettura costituisce un parametro assolutamente indispensabile.
Java tenta di risolvere il problema adottando lo slogan: “Write once, Run everywhere” e affida l'
esecuzione dei suoi
programmi ad una macchina virtuale. Più specificatamente, un sorgente Java viene tradotto dal compilatore Java (javac)
non in istruzioni macchina reali, ma in istruzioni macchina virtuali, i bytecodes. Sarà compito poi della macchina
virtuale Java (l'
interprete Java) di leggere ed eseguire queste istruzioni tramite la generazione "run time" del codice
macchina reale specifico per il sistema su cui il programma Java viene eseguito.
Portabilità del Codice Java
6.
Linguaggio Robusto
L'
assenza di puntatori, il fatto che stringhe e array siano oggetti e la gestione automatica della memoria, conferiscono a
Java una robustezza particolare. Oltre a ciò, il compilatore Java individua molte situazioni in cui un programma
potrebbe provocare problemi e grazie ad un sistema per la gestione delle eccezioni riesce ad evitare moltissimi errori di
esecuzione.
7.
Dinamicità
Java, permette di aggiornare le "librerie" di classi senza costringere gli utenti alla ricompilazione dei programmi. Alle
classi in "libreria" si possono infatti aggiungere metodi e variabili senza che questo abbia effetto sui vecchi programmi.
Ciò è possibile grazie al fatto che ogni classe in Java ha anche una rappresentazione "runtime" (bytecodes), la quale
permette di individuare comunque il tipo di oggetti che l'
utente richiede.
14
8.
Sicurezza
Siccome Java è stato progettato per funzionare in ambienti distribuiti o di rete, la sicurezza è un parametro molto
importante. In fatto di sicurezza, Java offre innanzitutto la sue caratteristiche strutturali, ma oltre a ciò, Java è stato
dotato di altre caratteristiche che provvedono ad aumentarne la sicurezza: la verifica dei bytecodes, la verifica durante il
caricamento delle classi, l’interfacciamento sicuro con i protocolli Internet ed in fine la crittografia.
9.
Linguaggio distribuito
Java possiede molte librerie (class java.net.*) che permettono facilmente l'
accesso a risorse remote tramite protocolli
basati sul TCP/IP, come lo HTTP. Tramite URL (class java.net.URL) una applicazione Java può accedere a oggetti
remoti come se essi fossero collocati su file presenti nel sistema ove essa funziona.
10. Linguaggio MultiThreading
Java è un linguaggio Multi-Threaded. Il Multi-Threading consente ad applicazioni Java di sfruttare il meccanismo di
concorrenza logica. Parti separate di un programma possono essere eseguite come se fossero (dal punto di vista del
programmatore) processate parallelamente.
11. Interazione con i Browser per Internet
Java possiede una classe apposita classe (class Applet) che permette di inserire in un documento HTML riferimenti ad
applicativi (Applet) che possono essere eseguiti a distanza dai più diffusi browser.
12. Vasta scelta di Librerie e Standardizzazione
Java possiede un’enorme libreria di classi standard che forniscono al programmatore la possibilità di operare su
funzioni comuni di sistema come la gestione delle finestre, dei collegamenti in rete e dell’input/output. Il pregio
fondamentale di queste classi sta nel fatto che rappresentano un’astrazione indipendente dalla piattaforma, per un’ampia
gamma di interfacce di sistema utilizzate comunemente.
Grazie ad alcune delle caratteristiche che il linguaggio offre, soprattutto per quel che riguarda la distribuzione su World
Wide Web e grazie alla scelta di numerose librerie utilizzabili, GraphiTech ha deciso di appoggiarsi a Java per
sviluppare il suo progetto e di conseguenza il lavoro di tesi si è basato su questo linguaggio.
La versione Java adottata è l’ultima finora rilasciata J2SE 6 con JRE 1.6.0.2 scaricabile dal sito ufficiale della Sun
Microsystem: http://www.sun.com .
Per sviluppare programmi in Java è teoricamente sufficiente un qualsiasi editor di testo.
Per un programmazione abbastanza estesa e complicata esistono diversi IDE (Integrated Development Environment,
ambiente di sviluppo integrato), alcuni gratuiti ed altri a pagamento.
2.1.1.
Eclipse
Eclipse è un progetto open source legato alla creazione e allo sviluppo di una piattaforma di sviluppo ideata da un
consorzio di grandi società quali Ericsson, HP, IBM, Intel, MontaVista Software, QNX, SAP e Serena Software,
chiamato Eclipse Foundation, e creata da una comunità strutturata sullo stile dell'
open source.
Pur essendo orientata allo sviluppo del progetto stesso, questo IDE è utilizzato anche per la produzione di software di
vario genere. Si passa infatti da un completo IDE per il linguaggio Java ad un ambiente di sviluppo per il linguaggio
C++ e a plug-in che permettono di gestire XML, PHP e persino di progettare graficamente una GUI per un applicazione
JAVA, rendendo di fatto Eclipse un ambiente RAD.
15
Il programma è scritto in linguaggio Java, ma anziché basare la sua GUI sulla libreria Swing di Java, il toolkit grafico di
Sun Microsystems, si appoggia sul SWT, librerie di nuova concezione che conferiscono ad Eclipse una straordinaria
reattività. Eclipse è strutturato con un'
architettura a plug-in che permette l'
aggiunta di ulteriori funzionalità
semplicemente scaricando ed installando il relativo pacchetto. Inoltre grazie alla sua licenza open source chiunque può
sviluppare e modificare i vari plug-in apportando così migliorie e nuove caratteristiche ad una piattaforma già
notevolmente avanzata.
Nella versione base è possibile programmare in Java, usufruendo di comode funzioni di aiuto quali: completamento
automatico, suggerimento dei tipi di parametri o dei metodi, possibilità di accesso diretto a CVS e riscrittura automatica
del codice in caso di cambiamenti nelle classi.
Nel progetto di tesi, Eclipse è stato utilizzato come software principale per la personalizzazione dell’ambiente virtuale
di Project Anna, in quanto già adottato da GraphiTech per altri progetti.
Essendo scritto in Java, Eclipse è disponibile per le piattaforme Linux, HP-UX, AIX, MacOSX e Windows.
La versione 3.3.0 di Eclipse è scaricabile dalla pagina web: http://www.eclipse.org .
2.1.2.
JBuilder
Uno degli IDE commerciali più diffusi è JBuilder prodotto dalla Borland.
JBuilder è un IDE per lo sviluppo in Java prodotto da Borland e disponibile per i sistemi operativi Windows, Linux e
Solaris. Fu introdotto sul mercato nel 1997, e da allora ha ricevuto numerosi premi internazionali come IDE più
avanzato per lo sviluppo in Java. Dal progetto JBuilder sono anche derivati altri strumenti di successo, come JDeveloper
di Oracle (basato su JBuilder) e Together (inizialmente concepito come plug-in di JBuilder e poi evoluto a prodotto
indipendente).
Per lo sviluppo della gestione database, contenente i dati georeferenziati, e per la creazione dell’interfaccia grafica
dell’applicazione è stato utilizzato, grazie al suo designer integrato, Borland JBuilder 2006 in licenza gratuita Personal
Edition e scaricabile dal sito: http://www.borland.com .
Al già avanzato IDE di JBuilder, in questa versione si aggiungono, capacità di collaborazione peer-to-peer che
consentono ai team sempre più distribuiti di utilizzare la "programmazione tra colleghi virtuali", un importante
aggiornamento del suo ambiente, leader di mercato, progettato per velocizzare lo sviluppo di applicazioni Java aziendali
di classe industriale.
JBuilder inoltre consente agli sviluppatori di ottimizzare migliaia di plug-in di terze parti, nonché di creare
miglioramenti personalizzati. È possibile creare processi di workflow flessibili e personalizzati per attività quali change
management o individuazione dei difetti, in modo da ottimizzare la produttività senza l'
imposizione di rigide strutture. I
team possono inoltre configurare personalità IDE per semplificare e personalizzare l'
interfaccia di ogni progetto.
La famosa case produttrice di JBuilder, la Borland è stata fra i membri fondatori della Eclipse Foundation, infatti la
nuova versione di JBuilder 2007 è basata sulla piattaforma open source Eclipse, nonostante resti un prodotto
commerciale a tutti gli effetti.
16
2.2. PostgreSQL
PostgreSQL è un completo database relazionale ad oggetti con licenza libera stile (BSD).
PostgreSQL è un'
ottima alternativa rispetto ad altri prodotti a codice chiuso come Oracle, Informix o DB2.
Offre caratteristiche uniche nel suo genere che lo pone per alcuni aspetti all'
avanguardia nel settore dei database.
PostgreSQL usa il linguaggio SQL per eseguire delle query sui dati. Questi sono conservati come una serie di tabelle
con chiavi esterne che servono a collegare i dati correlati.
La programmabilità di PostgreSQL è il suo principale punto di forza ed il principale vantaggio verso i suoi concorrenti:
PostgreSQL rende più semplice costruire applicazioni per il mondo reale, utilizzando i dati prelevati dal database.
I database SQL conservano dati semplici in tabelle, richiedendo che sia l'
utente a prelevare e raggruppare le
informazioni correlate utilizzando le query.
PostgreSQL permette agli utenti di definire nuovi tipi basati sui normali tipi di dato SQL, permettendo al database
stesso di comprendere dati complessi.
PostgreSQL, inoltre, permette l'
ereditarietà dei tipi, uno dei principali concetti della programmazione orientata agli
oggetti.
Inoltre la logica relazionale viene applicata direttamente dal server di database in una volta, riducendo il passaggio di
informazioni tra il client ed il server incrementando le prestazioni.
L’incremento dell'
affidabilità, è dovuto, invece alla centralizzazione del codice di controllo sul server, non dovendo
gestire la sincronizzazione della logica tra molteplici client e i dati memorizzati sul server.
Inserendo livelli di astrazione dei dati direttamente sul server, il codice del client può essere più snello e semplice.
Questi vantaggi fanno di PostgreSQL, probabilmente, il più avanzato sistema database dal punto di vista della
programmabilità, il che aiuta a spiegare il suo successo.
Utilizzare PostgreSQL può ridurre fortemente il tempo totale di programmazione di molti progetti, con i vantaggi
suddetti che crescono con la complessità del progetto stesso.
In particolare, nel caso affrontato, PostgreSQL è stato introdotto sia per la sua caratteristica di avvicinamento alla
programmazione ad oggetti, sia per la plug-in di supporto per la dichiarazione di dati georeferenziati, PostGIS.
Grazie a PostGIS, sviluppato dalla Refractions Research Inc. come progetto di ricerca sulla tecnologia spaziale per i
database, si possono manipolare ed usare diverse geometrie: point, line, polygon, multipoint, multiline, multipolygon e
geometrycollections.
Attualmente PostGis è integrato al database PostgreSQL 8.2.4 scaricabile dal sito ufficiale: http://www.postgresql.org .
La plug-in per la georeferenziazione è scaricabile anche separatamente dalla pagina web: http://www.postgis.org .
Per il progetto di tesi, si è deciso di avvalersi anche di PGAdminIII, software per la visualizzazione e gestione grafica
dei database PostgreSQL.
PGAdminIII 1.6.3 è un tool gratuito ad interfaccia grafica, sviluppato da una comunità di esperti PostgreSQL,
scaricabile dal sito: http://www.pgadmin.org di notevole aiuto per la facilità d’uso e la velocità di inserimento dei dati.
2.3. OpenGL
OpenGL è una potente libreria grafica che risolve si pone il compito di interfacciarsi con l'
hardware e fornire al
programma client una serie di primitive, più o meno essenziali, per lo sviluppo di applicazioni nel campo del rendering
tridimensionale.
17
Queste primitive comprendono funzioni per la manipolazione dei pixel, per la proiezione di poligoni in 3D e per la
gestione del movimento degli stessi, per la rappresentazione di luci e colori, per il Texture mapping etc.
Il prefisso Open sta ad indicare che OpenGL è una architettura aperta, ciò significa che il suo sviluppo è curato non da
una singola azienda, ma da una associazione di industrie leader del settore (ATI, Compaq, IBM, nVidia, HewlettPackard, Silicon Graphics) che hanno dato vita all'
ARB (Architectural Review Board).
Questa organizzazione, nata nel 1992, ha avuto il compito di sviluppare e standardizzare gli aggiornamenti di OpenGL
fino al 2006, quando gli standards OpenGL sono entrati a far aperte del Khornos Group che sostituisce la funzione della
precedente associazione ARB.
Una delle peculiarità di OpenGL che la distingue immediatamente dalle sue rivali (ad esempio DirectX di Microsoft) è
la portabilità. Infatti è disponibile su tutte le piattaforme più diffuse, Unix, Linux, Windows, Mac, Solaris etc.
OpenGL è oggi una delle più valide e potenti librerie grafiche disponibili e lo dimostra il fatto che grandi Software
House specializzate nel campo dei videogames l'
hanno scelta per sviluppare i propri prodotti. Tra i titoli targati OpenGL
troviamo Quake2, Quake3 e Doom III della ID Software, Unreal Tournament 1 e 2 della Epic Games, oppure Half Life
e tanti altri.
Per quanto riguarda la possibilità di utilizzare OpenGL nel proprio linguaggio preferito, nonostante essa sia stata
sviluppata inizialmente per essere utilizzata attraverso il linguaggio C, è disponibile in un'
ampia varietà di linguaggi tra
i quali C++, Java, Delphi e il neonato C# (C sharp di Microsoft).
OpenGL è scaricabile gratuitamente dai siti ufficiali delle aziende facenti parte dell’ARB, ovviamente ogni azienda ha
personalizzato le versioni della libreria a seconda delle proprie esigenze lasciando comunque inalterate le funzionalità
base della specifica.
2.4. JOGL
Jogl è una libreria wrapper che consente l’uso delle librerie OpenGL con il linguaggio di programmazione Java.
Il progetto Jogl deve essere ancora completato e la libreria è ancora sotto sviluppo da parte del Game Technology
Group presso la Sun Microsystem.
Jogl è l’implementazione di riferimento per JSR-231 (Java Binding for OpenGL), un’API disegnata a supporto delle
versioni più recenti di Java dalla release J2SE 1.4 alle successive.
L’albero sorgente di JOGL nella sua forma corrente è, appunto, uno spazio di lavoro sperimentale per il JSR-231 Java
Bindings per OpenGL. JOGL quindi, non è l’implementazione ufficiale di riferimento, ma uno spazio di lavoro in
evoluzione.
Questa è stata la libreria di riferimento per il progetto di tesi, scaricabile dal sito web: https://jogl.dev.java.net con una
vasta documentazione, numerosi esempi di utilizzo e forum.
3. Stato dell’Arte
Lo sviluppo continuo di tecnologie informatiche ed elettroniche permettono oggi, ad un numero sempre più elevato di
persone, di utilizzare sistemi basati su realtà virtuale sempre più complessi.
L’utilizzo di tali ambienti spazia dai più articolati software di simulazione scientifica ai comuni videogiochi.
18
Sono sempre più, i campi applicativi che richiedono l’ausilio di particolari software in grado di rappresentare diverse
tipologie di dati all’interno di scenari tridimensionali virtuali. Quest’ultima area, grazie ad un’enorme diffusione e un
conseguente abbattimento dei costi, ha permesso di sviluppare sistemi per la simulazione di ambienti virtuali con
scenari di ampi spazi aperti. Oggi questi sistemi permettono la visualizzazione d’informazioni territoriali finora
accessibili solo in maniera cartacea e con uno spreco di risorse elevato.
Attualmente, grazie all’integrazione di dati GIS con informazioni correlate a luoghi od elementi presenti su un
determinato territorio, è possibile ottenere sistemi in grado di legare tali dati alla corrispettiva area geografica.
La navigazione tridimensionale, la visualizzazione di mappe tematiche, la pianificazione di business in determinate
regioni, sono solo alcuni aspetti facenti parte di una vasta gamma di applicazioni connesse all’informazione
georeferenziata.
Uno dei settori che ha tratto un sicuro vantaggio dallo sviluppo di queste tecnologie è il settore turistico, che utilizza
questi software per pubblicizzare e valorizzare luoghi naturali e culturali poco conosciuti.
3.1. GIS
La definizione per delineare caratteristiche, componenti e funzionalità di un sistema GIS non è mai stata univoca, ma ha
subito diverse variazioni, anche a seconda delle nuove tecnologie sviluppate e dei nuovi concetti di lavoro collaborativo
tra diversi sistemi. Quella che forse esprime meglio un sistema GIS è quella di P.A.Burrough del 1986:
“Il GIS è composto da una serie di strumenti software per acquisire, memorizzare, estrarre, trasformare e visualizzare
dati spaziali dal mondo reale.”
Dagli anni ’80 fino ad oggi il concetto di Sistema Informativo Geografico si è evoluto, dando così di volta in volta un
diverso significato alla “S” finale dell’acronimo GIS, e cambiando anche l’ambito di utilizzo del sistema:
•
•
•
Anni 1980: Geographic Information Systems.
−
Tecnologia per l’acquisizione e la gestione di dati spaziali.
−
software per uso professionale , es. cartografi…
Anni 1990s: Geographic Information Science.
−
messa a punto dei modelli concettuali di descrizione dei dati e dei processi nello spazio e nel tempo.
−
Teoria e modelli concettuali su cui si basa la tecnologia.
Anni 1990s: Geographic Information Studies.
−
•
Definizione degli aspetti sociali, legali ed etici associati all’uso e all’applicazione dei GIS.
Anni 2000s: Geographic Information Services.
−
Siti Web e servizi web per gli utenti (es. Siti cartografici delle regioni, interrogazioni su percorsi, ecc…).
L’acronimo GIS (Geographic Information System), è possibile ormai definirlo come un ambiente informativo in grado
di rappresentare, organizzare e processare dati georeferenziati. Il GIS offre uno strumento completo adatto alla
rappresentazione del territorio ed al trattamento delle informazioni associate agli oggetti georeferenziati:
19
•
Geographic: tratta oggetti per i quali è possibile stabilire una
localizzazione sulla superficie terreste. A questi oggetti (punti, linee,
aree) sono assegnate le coordinate spaziali congruenti con la base
cartografica di riferimento.
•
Information: gestisce dati relativi agli oggetti geografici e consente
di recuperare informazioni (analisi, valori, ecc…).
•
System: la sua struttura è costituita da numerosi elementi che si
integrano e concorrono al raggiungimento degli obiettivi finali.
Esempio di Struttura GIS
In particolare un’applicazione GIS è un prodotto che permette di visualizzare delle informazioni tipo:
•
Modelli digitali del terreno (DTM);
•
Ortofoto satellitari o aeree;
•
Geometrie.
Prima di poter essere utilizzate, tali informazioni devono subire un processo di geo-referenziazione,vengono trovate
delle corrispondenze e successivamente sfruttate per poter eseguire una perfetta sovrapposizione.
Il mondo reale può essere rappresentato in un sistema informativo geografico attraverso due tipologie principali di dato:
il dato vettoriale e il dato raster:
•
Il dato raster permette di rappresentare il mondo reale attraverso una matrice di celle, generalmente di forma
quadrata o rettangolare, dette pixel. A ciascun pixel sono associate le informazione relative a ciò che esso
rappresenta sul territorio. La dimensione del pixel (detta anche pixel size), generalmente espressa nell'
unità di
misura della carta (metri, chilometri etc.), è strettamente relazionata alla precisione del dato.Generalmente
vengono rappresentati in questo formato il DTM e le immagini.
•
I dati vettoriali sono costituiti da elementi semplici quali punti, linee e poligoni, codificati e memorizzati sulla
base delle loro coordinate. Un punto viene individuato in un sistema informativo geografico attraverso le sue
coordinate reali (x1, y1); una linea o un poligono attraverso la posizione dei sui nodi (x1, y1; x2, y2; ...). A
ciascun elemento è associato un record del database informativo che contiene tutti gli attributi dell'
oggetto
rappresentato. Questo formato è utile per rappresentare oggetti e percorsi.
I dati vettoriali e i dati raster si adattano ad usi diversi. La cartografia vettoriale è particolarmente adatta alla
rappresentazione di dati che variano in modo discreto (ad esempio l'
ubicazione dei cassonetti dei rifiuti di una città o la
rappresentazione delle strade o una carta dell'
uso del suolo), la cartografia raster è più adatta alla rappresentazione di
dati con variabilità continua (ad esempio un modello digitale di elevazione o una carta di acclività del versante).
Per la rappresentazione dei dati in un GIS occorre formalizzare un modello rappresentativo flessibile che si adatti ai
fenomeni reali, ne esistono difatti diverse tipologie di informazioni per una più facile strutturazione del modello:
•
Geometrica: relative alla rappresentazione cartografica degli oggetti rappresentati; quali la forma (punto, linea,
poligono), la dimensione e la posizione geografica;
•
Topologica: riferite alle relazioni reciproche tra gli oggetti (connessione, adiacenza, inclusione ecc…);
•
Informativa: riguardanti i dati (numerici, testuali ecc…) associati ad ogni oggetto.
20
I dati geometrici e topologici possono provenire da svariate fonti e la loro produzione è legata all’utilizzo di strumenti
tecnici di vario genere: scannerizzazione, digitalizzazione, input da tastiera e mouse, telerilevamento, fotografia aerea…
I dati informativi invece provengono da censimenti, anagrafe, campagne di rilevamento, indagini di settore, ricerche,
archivi di vario genere, ecc...
Si tratta in prevalenza di dati numerici e alfanumerici memorizzati sotto forma di tabelle, ma possono essere anche
documenti complessi che prevedono l’integrazione di immagini e suoni.
Le funzioni principali di un sistema GIS prevedono:
•
Creazione, immissione, verifica dati.
•
Trasformazione.
•
Analisi.
•
Output dei risultati.
Il sistema informativo geografico per quel che riguarda la fase di immissione e archiviazione dei dati può essere visto
come una forma di DBMS, in grado di gestire dati geografici.
L'
aspetto che caratterizza di più il GIS è quello geometrico di creazione dei dati: esso memorizza la posizione del dato
impiegando un sistema di proiezione reale che definisce la posizione geografica dell'
oggetto.
La trasformazione dei dati è un insieme di operazioni che servono a correggere e ad omogeneizzare l’insieme dei dati
(trasformazioni di coordinate, editing, ecc.).
L’analisi, invece, applica dei modelli concettuali ai dati rilevati e trasformati che riproducono il fenomeno fisico
esaminato, con conseguente creazione di nuova informazione.
L’output di un sistema GIS può essere diverso a seconda dei dati trattati, del software utilizzato e del risultato finale che
si vuole ottenere.
Il GIS consente di mettere in relazione tra di loro dati diversi, sulla base del loro comune riferimento geografico in
modo da creare nuove informazioni a partire dai dati esistenti offrendo, così, ampie possibilità di interazione con
l'
utente e un insieme di strumenti che ne facilitano la personalizzazione e l'
adattamento alle problematiche specifiche
dell'
utente.
21
I GIS presentano delle funzionalità di analisi spaziale ovvero di trasformazione ed elaborazione degli elementi
geografici degli attributi:
•
L'
overlay topologico: in cui si effettua una sovrapposizione tra gli elementi dei due temi per creare un nuovo
tematismo (ad esempio per sovrapporre il tema dei confini di un parco con i confini dei comuni per
determinare le superfici di competenza di ogni amministrazione o la percentuale di area comunale protetta);
•
Le query spaziali, ovvero delle interrogazioni di basi di dati a partire da criteri spaziali (vicinanza, inclusione,
sovrapposizione etc.)
•
Il buffering: da un tema puntuale, lineare o poligonale definire un poligono di rispetto ad una distanza fissa o
variabile in funzione degli attributi dell'
elemento
•
La segmentazione: algoritmi di solito applicati su temi lineari per determinare un punto ad una determinata
lunghezza dall'
inizio del tema;
•
La network analysis: algoritmi che da una rete di elementi lineari (es. rete stradale) determinano i percorsi
minimi tra due punti.
•
Analisi geostatistiche: algoritmi di analisi della correlazione spaziale di variabili georeferite.
Le prime applicazioni GIS aventi come scopo l’elaborazione e la visualizzazione di informazioni territoriali, sono nate
per fini esclusivamente militari. La possibilità di avere sottomano una ricostruzione geometrica del territorio
dell’avversario costituisce sicuramente un punto di forza strategica notevole.
Oggi queste applicazioni grazie anche alle nuove funzionalità descritte sopra sono state re-implementate e permettono
di aiutare l’uomo in tutte quelle attività dove alla base si deve avere una conoscenza accurata di un territorio.
Normalmente le applicazioni che operano su questo settore possono essere distinte in due grandi categorie, questo
basandosi sull’obiettivo per la quale vengono pensate e sviluppate:
•
Gestione Dati GIS: sono applicazioni che curano in modo molto specifico l’aspetto legato al trattamento delle
informazioni territoriali e la loro georeferenziazione. Queste applicazioni si occupano del trattamento delle
ortofoto, che non sono solamente delle immagini da visualizzare ma sono delle vere e proprie sorgenti
informative. Un altro secondo compito è la prima manipolazione dei dati geometrici come DTM, mappe di
percorsi stradali e altre informazioni legate al territorio come mappe idrografiche, vegetazione ecc…
•
Viewer 3D: lo scopo principale di queste applicazioni è creare un ambiente virtuale immersivo nel quale sia
possibile avere un idea visiva di una mappa territoriale e di tutte le informazioni ad essa legata. Generalmente
questi software utilizzano le informazioni provenienti dal altre applicazioni per creare ambienti più o meno
dettagliati.
Entrambe le tipologie di applicazioni richiedono piattaforme hardware con notevoli capacità sia di calcolo che di
memoria. Alcuni sviluppatori, per ovviare ai pesanti requisisti, cercano di sgravare i costi computazionali tramite
l’impiego di server, o sistemi di calcolo distribuito.
L’inconveniente di questa soluzione è che l’utilizzatore dovrà essere sempre vincolato ad una rete.
22
3.2. Applicativi
Vediamo ora quali sono i principali software, commerciali e non, finalizzati all’elaborazione dei dati GIS e alla loro
visualizzazione tridimensionale.
3.2.1.
GoogleEarth
Google Earth, è un software, fruibile via web, che genera una immagine virtuale della Terra utilizzando immagini
satellitari, fotografie aeree e dati topografici memorizzati in una piattaforma GIS. Il programma è distribuito
gratuitamente dalla società Google all’indirizzo internet: http://earth.google.it .
Inizialmente il programma si chiamava Keyhole ed era sviluppato dalla Keyhole Inc., ma nel 2004 la società venne
acquisita da Google e il software rinominato di conseguenza.
Il programma richiede un sistema operativo Microsoft Windows, MacOSX o Linux.
Google Earth utilizza una tecnologia di streaming broadband e grafica tridimensionale, consentendo agli utenti di
navigare sulla superficie terrestre e di esplorare l’intero pianeta.
Google Earth è disponibile in più versioni: Free, Pro ed Enterprise, ciascuna delle quali permette di gestire dati e
funzionalità di complessità crescente.
I livelli di dettaglio delle ortofoto e dei DTM utilizzati per la generazione degli ambienti tridimensionali, sono
opportunamente impostati in modo automatico dall’applicazione attraverso un algoritmo di riduzione dei poligoni, per
consentire fluidità alla navigazione, garantendo comunque il massimo grado di realismo.
Il modello virtuale del territorio viene creato attraverso una struttura tridimensionale del terreno (TIN) generata grazie a
un insieme sparso di punti quotati costituenti una rete di triangoli il più equilateri possibile.
Triangulated Irregular Network
A partire dalla griglia di triangoli è possibile interpolare curve di livello, condurre analisi di visibilità, generare profili
longitudinali, effettuare analisi di pendenza e di esposizione, cliviometrie, ecc…
Successivamente il modello delineato viene passato all’algoritmo per la riduzione dei poligoni determinando la
precisione morfologica del terreno.
L’immagine sottostante evidenzia il diverso numero dei poligoni prima e dopo l’applicazione dell’algoritmo: le linee di
colore grigio mostrano la griglia di dettaglio prima dell’applicazione dell’algoritmo, mentre le linee rosse individuano i
poligoni dopo l’applicazione dell’algoritmo.
23
È evidente come il numero dei poligoni rossi sia nettamente inferiore a quelli grigi e come si concentrino e si
ridimensionano nelle zone morfologicamente meno regolari.
Triangulated Irregular Network prima e dopo l’applicazione dell’Algoritmo di Riduzione dei Poligoni
Per quel che riguarda la qualità della visualizzazione Google Earth si appoggia a diversi livelli (layer) con diversa
definizione. Le informazioni sono fornite direttamente dallo streaming in rete garantendo un aggiornamento abbastanza
regolare.
Le principale caratteristiche dell’applicazione sono:
1.
Riproduzione 3D dell’intera superficie terrestre.
2.
Posizionamento di edifici ed oggetti 3D nelle zone di maggior
interesse.
3.
Possibilità di interrogare il sistema per avere informazioni
real-time su determinate aree attraverso feeds KML e ora
anche GeoRSS.
4.
Possibilità di inserire propri dati quali foto, mappe e
informazioni attraverso questi due linguaggi.
5.
Ricerca di edifici o punti di interesse in un determinata area:
ristoranti, stazioni, monumenti, ecc…
6.
Memorizzazione di località specifiche.
7.
Sofisticata tecnologia streaming per il recupero dei dati dalla
rete.
8.
Possibilità di creare itinerari per ottenere indicazioni stradali
accurate nonché un'
anteprima in volo del percorso.
9.
Possibilità di attivare diversi livelli di informazioni di
mappatura, quali strade, negozi, servizi, caratteristiche
geografiche, edifici 3D, stazioni di rifornimento, ristoranti,
alloggi.
10. Google Earth consente di stampare, salvare e inviare
immagini e viste per email.
Due immagini tratte dall’utilizzo di Google Earth
24
I risultati ottenibili da questa applicazione hanno un ottimo impatto visivo.
Il cantiere di Ground Zero con edifici 3D, New York
In Google Earth Pro le funzionalità aumentano ed è possibile, per esempio, integrare l’applicazione con un sistema GPS
in grado di localizzare mezzi anche in movimento all’interno del territorio con la possibilità di assegnare ad ogni
veicolo un preciso percorso urbano.
Il Colosseo con le informazioni ricavate dal sistema, Roma.
Google Earth non ha solo pregi, ma anche difetti:
•
Il sistema è particolarmente lento con connessioni via modem a 56Kbps e la fluidità della visualizzazione ne
risente parecchio.
25
•
La risoluzione ad alta definizione non comprende l’intero pianete, ma solo specifiche zone di interesse. Nelle
zone con bassa risoluzione non coperte dal sistema si possono apprezzare gli agglomerati urbani e le
caratteristiche dei terreni, ma non edifici ed oggetti tridimensionali.
3.2.2.
API WorldWind
World Wind è un globo virtuale open source sviluppato dalla
NASA e dalla comunità open source per l'
uso su personal
computers con sistema operativo Windows2000/XP.
Il programma sovrappone immagini satellitari e fotografie
aeree USGS ad un modello tridimensionale della Terra, ma
non solo… World Wind visualizza anche riproduzioni 3D dei
pianeti e satelliti del nostro sistema solare, stelle e galassie.
ScreenShot iniziale di World Wind
Venere, Giove e una Galassia
L'
utente interagisce con il pianeta selezionato applicando una rotazione, inclinando la visione e aumentando o
diminuendo la scala. La visualizzazione delle immagini avviene attraverso l’overlay di diverse immagini e a seconda
della distanza dal terreno, ci si avvale di immagini satellitari o di immagini ad alta definizione acquisite attraverso voli
aerei. Sono inclusi cinque milioni di toponimi, confini politici, linee di latitudine e longitudine e altre informazioni.
World Wind fornisce la possibilità di navigare tra mappe e dati geospaziali usando Open Geospatial Consortium Web
Map Service nonché l'
importazione di ESRI Shapefiles e placemarks da files kml/kmz.
Altre caratteristiche di World Wind: supporto per i modelli Microsoft .X realizzati con DirectX, modelli e effetti visivi
avanzati quali dispersione atmosferica e ombreggiatura.
Nel download iniziale di World Wind è incluso in bassa risoluzione il dataset Blue Marble.
In aggiunta vi sono altri dataste con risoluzione migliore che possono essere scaricati gratuitamente. La grandezza dei
dati disponibili sul server è circa 4,6 terabytes. I dataste di World Wind disponibili per la Terra sono:
26
•
Blue Marble Next Generation imagery;
•
immagini Landsat 7:
•
•
−
NLT Landsat (Visibile e pseudo colore);
−
[HeartSat Geocover] 1990 e 2000 (pseudo colore);
−
OnEarth (visibile e pseudo colore);
−
i-cubed (visibile).
Immagini USGS:
−
Digitale Ortorettificata (monocroma, National Reconnaissance Office, fotografie satellite spia KH-11);
−
Ortorettificate area urbana (montaggio delle foto aeree a colori delle maggiori aree metropolitane USA);
−
Mappe topografiche.
Immagini Zoomit! (layer prodotto dalla comunità):
−
LINZ (montaggio delle foto aeree a colori della Nuova Zelanda);
−
GSWA (mappe topografiche e geologiche dell'
Australia dell'
ovest);
−
US imagery (montaggio delle foto a colori delle maggiori aree metropolitane USA).
•
SRTM (SRTM30Plus/SRTMv2/USGS NED) dati di elevazione (inclusa la batimetria).
•
Layers di dati animati:
−
MODIS;
−
GLOBE;
−
NRL tempo atmosferico attuale.
I dati, non sono ristretti alla NASA, ma possono provenire da un qualsiasi server che supporti la specifica WMS
stipulata dall’OGC, ad esempio Microsoft ha concesso l'
utilizzo dei propri dati non commerciali presenti sul suo portale
Virtual Earth, attraverso l'
apposito plug-in.
Le funzionalità di World Wind possono essere estese usando svariati add-ons; essendo open source, l’utente può
personalizzare a proprio piacimento il software, sia creando degli add-on in maniera autonoma (programmi scritti in C#,
VB o J#) oppure sfruttando quelli già esistenti che più gli interessano, scaricabili gratuitamente dal sito ufficiale di
WorldWind: www.worldwindcentral.com/wiki/Main_Page .
Possibili tipi di add-ons già implementati sono:
•
Layers puntiformi: XML che mostrano l'
allocazione (placemarks) di punti di interesse.
•
Layers traccia: percorsi (strade, confini).
•
Layers lineari: XML con una lista di punti visualizzati come linea continua.
•
Forme poligonali: XML con una lista di punti visualizzati come un poligono pieno (piatto o estruso).
•
Forme modello : XML usato per caricare maglie strutturate 3D.
•
Toponimi: punti specifici (quali città, alture, edifici) ai quali vengono assegnate etichette testuali.
•
Layers Immagine: Immagini di varie parti del mondo.
•
Scripts: files che controllano il movimento e l'
inclinazione del punto di vista.
27
ScreenShots con diversi Layers di WorldWind
Nonostante sia un programma open source, World Wind rimane ristretto al sistema operativo Windows di Microsoft e si
appoggia alle librerie Microsoft .NET e a DirectX, giunte rispettivamente alla versione 2.0 e 9.0c.
La prima release multipiattaforma Java è prevista per la metà del 2007, ma ancor oggi non distribuita.
World Wind è giunto alla versione 1.4.0 scaricabile dal sito della NASA: http://worldwind.arc.nasa.gov .
Le future versioni di World Wind saranno sviluppate in Java con OpenGL; esse avranno un'
architettura API-centrica,
con funzionalità trasferite ai componenti modulari lasciando alle API il cuore dell'
applicazione. Questo rifacimento
consentirà di accedere a World Wind attraverso un browser.
Proprio questo cambiamento è stato preso in considerazione da GraphiTech, oltre al fatto che la scelta di tale
piattaforma, se paragonata ad altre applicazioni analoghe quali Google Earth, fornisce l’enorme vantaggio di potere
gestire data base in maniera autonoma. In effetti, il maggiore problema nell’utilizzo di Google Earth è costituito dal
fatto che i dati non possono essere ospitati su un proprio server, bensì essi sono gestiti da Google che provvede (ad
intervalli di alcune settimane) all’aggiornamento del database, perdendone di fatto sia il controllo che la proprietà e
dunque senza garanzia alcuna che tali informazioni siano accessibili a titolo gratuito nel futuro. Pertanto la scelta di
WorldWind, che peraltro rappresenta il maggiore concorrente di Google in questo campo, permette sia l’utilizzo di una
piattaforma standard in tutto il mondo e dunque di larga diffusione, sia soprattutto di gestire autonomamente i dati
tramite la configurazione di server realizzati “ad hoc” e di cui il fornitore di servizi ha il totale controllo in termini di
accesso e aggiornamento dei dati.
28
4. Funzionalità Avanazate per la Trasmissione di Dati Georeferenziati
Come precedentemente descritto il progetto di tesi è stato suddiviso in due parti: la fase di implementazione per la
gestione di un database di dati GeoRSS e la fase di sviluppo di Project Anna per la modifica all’ambiente World Wind.
Viene ora descritta la prima fase di sviluppo.
4.1. Introduzione allo Standard GeoRSS
Per comprendere appieno lo standard GeoRSS, bisogna tener presenti le basi su cui si fonda questo linguaggio
strutturato, la tecnologia dei feeds RSS.
RSS è basato su XML, da cui ha ereditato la semplicità, l'
estensibilità e la flessibilità.
RSS definisce una struttura adatta a contenere un insieme di notizie, ciascuna delle quali sarà composta da vari campi
(nome autore, titolo, testo, riassunto, ...). Una volta pubblicata la notizie in formato RSS, la struttura viene aggiornata
con i nuovi dati.
Essendo il formato predefinito, un qualunque lettore RSS potrà presentare in una maniera omogenea notizie provenienti
dalle fonti più diverse.
Vengono ora presentate tre definizioni per comprendere meglio struttura dei feed RSS sulla quale, come si vedrà in
seguito, si basano anche i feed GeoRSS:
•
Syndication:
To sell (a comic strip or column, for example) through a syndicate for simultaneous publication in newspapers
or periodicals.
Sta prendendo piede anche in Europa il modello syndication, cioè l'
affidamento dei testi a un'
agenzia che provvede a
distribuirli a siti e riviste. La parola è usata anche per un sistema di collaborazione e collegamento tra reti televisive o
radiofoniche. Una rete produce un programma e poi lo distribuisce su un certo numero di stazioni locali.
Il concetto centrale, è quello della redistribuzione e del riuso dei contenuti.
RSS, si propone, quindi, come una delle basi di qualunque sistema di content management.
Il linguaggio è molto semplice, di facile intuizione, è estendibile a piacere e soprattutto è poco vincolato da norme che
limitino il suo uso. Con questo standard e possibile distribuire le informazioni in svariati modi: su un portale, sul
weblog, per e-mail, creare documenti in formato PDF ecc...
L’informazione via web sta diventando uno strumento ormai fruibile da tutti, grazie alla diffusione di connessioni e
servizi collegamento.
•
Feed:
The transmission or conveyance of a local radio or television program, as by satellite, on the Internet, or by
broadcast over a network of stations.
•
Channel:
A course or pathway through which information is transmitted.
29
La produzione di un feed è l’invio un flusso di news (item), che si possono interpretare come le trasmissioni televisive
che si succedono nell'
arco di una giornata. L'
aggiunta di un feed al news aggregator, implica una “subscription”
(abbonamento o sottoscrizione), esattamente quello che si userebbe per una pay TV o una rivista.
Una delle prime aziende a comprendere le potenzialità di questa strategia e di RSS è stata Moreover fornendo feeds di
news a migliaia di siti, anche se il business vero è stato il mercato aziendale.
Molti siti di informazione (compresi i weblog personali), producono direttamente i loro feed RSS e li rendono pubblici.
Inoltre, l'
introduzione di software (news aggregator)
che fungono da “lettori o interpreti” di documenti RSS
consentono a chiunque di attingere direttamente alla fonte senza nessuna mediazione esterna.
RSS fu lanciato per la prima volta da Netscape che denominò la versione 0.9.
Circa nello stesso periodo W3C avanzò con la sua proposta, con la conseguente release RSS versione 1.0, di creare un
linguaggio del tutto conforme a RDF, ma dando la possibilità di estendere il formato con nuovi moduli e il supporto
XML.
Quasi contemporaneamente, la Userland Software, rilasciò la versione di RSS, figlia del formato utilizzato da Netscape,
denominata 0.91.
A causa della popolarità del formato adottato da Netscape, che eliminava gli aspetti più complessi, e da quello Userland
poi, il formato 0.91 iniziò a convivere accanto a quello proposto dal W3C, nonostante l’incompatibilità delle due
versioni.
Il formato 0.91 si è evoluto perdendo alcune limitazioni nella versione 0.92 ed è stato ulteriormente perfezionato nella
versione 2.0 (rilasciato da Userland nel 2002).
Al momento attuale convivono tre diverse versioni dello standard RSS:
•
RSS 0.91: il più vecchio tra gli standard oggi in uso, diretta evoluzione del formato usato originariamente da
Netscape. In alcuni casi si è preferito usare il successivo RSS 0.92;
•
RSS 2.0: rilasciato da Userland nel 2002, è l'
evoluzione del formato 0.92, di cui eredita la semplicità, ma a cui
aggiunge il supporto per moduli aggiuntivi;
•
RSS 1.0: è il formato ufficiale del W3C, conforme ad RDF, estensibile e modulare.
La distribuzione in formato RSS risulta così, limitata, in quanto l’incompatibilità delle versione rende necessaria una
scelta su quale adottare, o appesantita, nel caso si vogliano adottare tutte e tre le versioni.
Nonostante le differenti implementazioni delle diverse versioni, i documenti RSS condividono tutti la stessa struttura di
base, che prevede:
un elemento <channel>, che contiene le informazioni sulla fonte dei contenuti (nel caso di un quotidiano online
potrebbe contenere il nome della testata, la data di pubblicazione, informazioni sul copyright, ecc.)
una serie di elementi <item>, ognuno dei quali corrisponde ad un singolo elemento di contenuto (ad es. l'
articolo di un
giornale) e ne presenta tutte le informazioni (titolo, testo completo, nome dell'
autore, ecc.)
La fruizione di un documento RSS è un processo molto semplice.
Le modalità più diffuse sono due: attraverso appositi software che interpretano un feed permettendo agli utenti di
visualizzarne i contenuti, o integrando i contenuti del feed all'
interno di un sito Web.
Nel primo caso un'
applicazione (feed reader) in grado di interpretare un documento RSS ne effettua il parsing
individuando i tag, isolando i diversi elementi, per poi convertire i contenuti decodificati nel formato utile all'
obiettivo.
Nel secondo caso, invece un feed RSS proveniente da un sito può essere facilmente importato da un altro sito Web, per
incorporarne i contenuti all'
interno delle proprie pagine.
30
In seguito all'
aumento di popolarità del formato RSS e alla sua standardizzazione, sono nati diversi servizi online che
fungono da "collettori" di contenuti: i cosiddetti aggregatori. L'
obiettivo è quello di fornire un unico punto d'
accesso a
notizie provenienti da varie fonti; la standardizzazione del formato e la sua diffusione sono gli ingredienti che hanno
reso possibile perseguire tale obiettivo.
Il vantaggio per l'
utente è notevole, poiché ha la possibilità di accedere a tutte le notizie attraverso un unico sito Web
(l'
aggregatore), evitando dunque di dover visitare, uno per uno, i siti da cui provengono le notizie.
La diffusione dei feed RSS ha trovato impiego in molti campi oltre all’informazione tradizionale.
Uno di questi è il settore geospaziale, che, nonostante abbia ritardato la fruizione della diffusione pubblica e in ampia
scala delle informazioni, ha aderito anch’esso allo standard RSS.
GeoRSS offre la possibilità ai feed RSS di descrivere informazioni anche attraverso la loro localizzazione sul territorio
dando vita ad un nuovo termine che descrive questa associazione, il GeoTagging.
Il GeoTagging associa a qualunque oggetto o servizio (reale o virtuale), precise informazioni sul suo posizionamento
sulla Terra tramite coordinate geografiche e altri dati come altezza e velocità, in modo da poter facilmente organizzare,
ricercare e visualizzare graficamente le informazioni su mappe digitali.
La parola “dove” viene standardizzata in un linguaggio informatico con abbastanza semplicità e un potenza descrittiva
in grado di soddisfare le esigenze di localizzazione dei contenuti sul Web.
GeoRSS dovrebbe essere considerato come un linguaggio facile da usare, con poche regole e tag (essendo derivato da
XML) con strutture di default già predisposte, ma con la possibilità di venir estese e aggiornate e rese compatibili con i
formati più complessi come GML (Geography Markup Language) del OGC.
In più, lo standard per la georeferenziazione delle informazioni produce un’estensione vera e propria del vocabolario
geografico del W3C, aggiungendo importanti tipi di locazioni (punti, linee, e aree) e altre quindi ulteriori estensibilità.
Come esempio prendiamo in considerazione un’escursione in kayak.
Ogni località dell’escursione, in un feed GeoRSS, potrebbe essere descritta come un semplice punto. Ma l’intero
viaggio è chiaramente un percorso lineare continuo.
La descrizione della primitiva di linea è
particolarmente
importante
per
descrivere gli itinerari dei percorsi dando
informazioni su lunghezza, intersezioni,
località e così via…
I confini, invece, hanno rilevanza nel
momento in cui si vogliono specificare i
limiti territoriali di un’area, quali aree
agricole, città, vicinati, stati ecc..
Forse i vantaggi maggiori dell’uso dei
feed GeoRSS sarà possibile notarli nella
possibilità delle ricerche geografiche.
GeoRSS Model
31
Dando le giuste coordinate, e l’argomento di ricerca, sarà possibile recuperare tutte le informazioni relative a quella
determinata località, area o tragitto. Un giorno quando la maggior parte dei feed RSS conterranno le informazioni per la
localizzazione geografica, applicazioni di ricerca, come quella sopra descritta, saranno possibili e troveranno parecchio
spazio all’interno di ambiti ben definiti. Ora l’uso dei GeoRSS è ancora limitato, ma anche grazie a Google Earth che da
pochi mesi lo ha adottato, andrà via via a prendere più spazio all’interno del ramo GeoTagging.
La parte sinistra dello schema UML, sopra riportato, rappresenta la struttura GeoRSS, mentre quella destra è la parte di
contenuti esterna che lo standard usa per formale le informazioni. Nel modello, la classe “where” rappresenta
un’associazione tra una geometria e diversi possibili contenuti, in quanto lo standard non impone nessuna limitazione
sul tipo o sul formato delle informazioni da descrivere.
Lo standard GeoRSS è esso stesso identificato dal namespace “georss” e permette l’inclusione di qualunque altro
elemento da namespaces diversi.
Il modello descritto in figura è di per se un concetto astratto, e per usarlo deve essere espresso attraverso una struttura
linguistica concreta ed efficiente come l’XML, l’RDF, ecc…
Questo processo viene definito serializzione, ovvero il salvataggio di un oggetto in un supporto di memorizzazione
lineare o, come in questo caso, la trasmissione su una connessione di rete. La serializzazione può essere in forma binaria
o può utilizzare codifiche testuali, come quelle GeoRSS, direttamente leggibili. Lo scopo di questo processo è di
trasmettere l’intero stato dell’oggetto in modo che esso possa essere successivamente ricreato nel medesimo stato dal
processo inverso, detto deserializzazione.
Allo stato attuale delle cose esistono tre differenti versioni dello standard per salvare i dati spaziali:
1.
la versione del W3C
2.
la versione definita Simple GeoRSS
3.
la versione GeoRSS GML (o Pro GeoRSS)
Ognuna è differente anche solo per delle sottigliezze, ma nessuna ha ancora raggiunto uno standard formale.
La versione del W3C è stata la prima rilasciata, nel 2003 e supportava solo la primitiva “punto” differenziando le
coordinate nel seguente modo: <geo:Point>
<geo:lat>55.701</geo:lat>
<geo:Point>12.552</geo:lat>
</geo:Point>
La versione definita Simple estende quella del W3C con il supporto alle “linee” e al riconoscimento di aree e altezze.
Costruita anche sulla base di un subset di comandi semplici, del formato molto più complicato denominato GML, la sua
forma è del tipo:
<georss:polygon>
45.256 – 110.45 46.46 – 109.48 43.84 – 109.86 45.256 – 110.45
</georss:polygon>
La versione GML è un ulteriore passo avanti sia per la definizione degli oggetti spaziali, che per il livello di
complessità. Usata spesso in laboratori specifici e di ricerca. I tag che vengono utilizzati dal formato GeoRSS Simple,
vengono evidenziati con il prefisso gml: point <gml:Point>
line <gml:LineString>
polygon <gml:Polygon>
box <gml:Envelope>
32
4.2. Specifiche GeoRSS
Per definire le diverse specifiche dello standard GeoRSS, bisogna introdurre il concetto di sistema di riferimento per le
coordinate terrestri.
La Terra non ha un vero e proprio sistema di riferimento, tutte le coordinate GeoRSS devono, far riferimento al sistema
di riferimento definito per convenzione sia da geodeti che da sviluppatori software. Il documento che specifica il nuovo
sistema di riferimento, dal titolo “OGC Abstract Specification Topic 2, Spatial Referencing by Coordinates”, è
scaricabile al seguente indirizzo: https://portal.opengeospatial.org/files/?artifact_id=6716 .
Questo sistema è un modello matematico della Terra visto da un punto di vista geometrico, geodetico e gravitazionale,
costruito sulla base delle misurazioni e conoscenze scientifiche e tecnologiche, nel quale vengono definite latitudine e
longitudine e la loro unità di misura, i gradi decimali.
Le forme geometriche primitive che possono essere usate per rappresentare le località nel linguaggio GeoRSS sono
punti, line e aree (diverse funzioni per definirle).
Un punto è formato da una singola coppia di coordinate, formata a sua volta da un valore per la latitudine e un valore
per la longitudine. Per favorire la serializzazione si è adottata la convenzione di separare i due valori con uno spazio.
Una linea è definita da due o più coppie di coordinate. Ogni coppia è formata dai due valori per latitudine e longitudine
separati da uno spazio e ogni coppia è separata anch’essa da uno spazio per favorire la serializzazione.
Un box contiene esattamente 2 coppie di coordinate, definite
esattamente come quelle sopra descritte.
La prima coppia definisce l’angolo in basso quello posto più a
sud-ovest, invece la seconda definisce l’angolo in alto posto a
nord-est. Un box è sempre definito fino a quando non contiene
la linea posta a 180° di longitudine (est o ovest) e/o i due poli
Nord e Sud. Un box è generalmente definito per rimarcare un’
area contenente al suo interno altri dati fruibili.
Box
Un poligono contiene almeno quattro coppie
di coordinate. Le coppie vengono definite con
i due valori di latitudine e longitudine separati
da uno spazio. La serializzazione viene
favorita spaziando anche le diverse coppie.
L’ultima coppia di coordinate deve essere
uguale alla prima per poter definire una forma
chiusa. A causa della rotondità terrestre,
dobbiamo porre dei limiti geometrici per
ovviare alla creazione di forme ambigue.
Limiti per Latitudine e Longitudine
Per essere in grado di rappresentare facilmente il quadrato rosso nella figura sovrastante, dove la parte sinistra è posta a
160 gradi di longituidne e la parte destra a -175 gradi, è stato imposto che due punti che formano una linea non devono
distare più di 179 gradi.
33
Questo limite evita ad altri approcci che richiedono informazioni addizionali per la creazione di figure geometriche e ne
preclude la loro rappresentazione. Line e poligoni devono seguire questa regole, invece I box sono svincolati.
La geometria GeoRSS ha lo scopo di rappresentare le reali caratteristiche della superficie terrestre, e quindi, grazie al
modello GeoRSS, si permette l’inserimento all’interno di ogni singola stringa di un tag, detto “featuretypetag”, per la
descrizione della caratteristica.
L’intento è quello di far emergere e diffondere una caratteristica raggruppabile in una determinata categoria di ricerca
attraverso internet, facilitando così la diffusione delle informazioni.
GeoRSS inoltre è un buon metodo per mettere in relazione i contenuti Web con le caratteristiche del globo terrestre. Lo
standard permette, anche in questo caso, di avere un tag speciale definito come, “relationshiptag”.
Per la caratteristica di altezza, lo standard mette a disposizione il tag elev.
Elev contiene il valore espresso in metri, derivato o dal modello matematico o da un rilevamento GPS di facile lettura.
Un altro tag usufruibile è il tag floor, che restituisce il numero di edifici in una determinata zona e il tag radium che
descrive il raggio che un singolo punto deve avere.
Qualche esempio di sintassi GeoRSS, dove si nota l’influenza del linguaggio GML molto più grande e complesso:
•
Point
Un punto consiste di un elemento <Point> che definisce la figura geometrica con un elemento figlio <coords> per le
coordinate.
<entry>
...
<georss:where>
<gml:Point>
<gml:pos>45.256 -71.92</gml:pos>
</gml:Point>
</georss:where>
</entry>
•
Line
Una linea consiste di un elemento <LineString> che definisce la figura geometrica con un elemento figlio <coordsList>
per le coordinate. Le coppie di coordinate devono essere almeno due e soddisfare i requisiti sopra citati.
<entry>
...
<georss:where>
<gml:LineString>
<gml:posList>
45.256 -110.45 46.46 -109.48 43.84 -109.86
</gml:posList>
</gml:LineString>
</georss:where>
</entry>
•
Polygon
Un poligono consiste di un elemento <Polygon> che definisce la figura geometrica con un elemento figlio <exterior>
(specifica la parte esterna di un’are), <LinearRing> (le coordinate dovrebbero essere connesse da un'
unica linea) e
<coordList> per le coordinate. Le coppie di coordinate devono essere almeno 4 e soddisfare i requisiti sopra citati.
34
<entry>
...
<georss:where>
<gml:Polygon>
<gml:exterior>
<gml:LinearRing>
<gml:posList>
45.256 -110.45 46.46 -109.48 43.84 -109.86 45.256 -110.45
</gml:posList>
</gml:LinearRing>
</gml:exterior>
</gml:Polygon>
</georss:where>
</entry>
•
Box
Un box definisce una regione rettangolare. La specifica GML si differenzia da quella GeoRSS Simple definendo un box
come Envelope. Che è costituito da un elemento <Envelope>
con due figli, uno <lowerCorner> e l’altro
<upperCorner>.
<entry>
...
<georss:where>
<gml:Envelope>
<gml:lowerCorner>42.943 -71.032</gml:lowerCorner>
<gml:upperCorner>43.039 -69.856</gml:upperCorner>
</gml:Envelope>
</georss:where>
</entry>
Tutto le informazioni codificate dovrebbero essere appoggiate da una definizione formale. Nel caso dei feeds gli XML
schema, forniscono un valido mezzo per impostare la definizione strutturale. Questo aiuterà gli sviluppatori a venire a
conoscenza della grandi possibilità del linguaggio potendo così spaziare anche su altri casi non ancora affrontati.
4.3. Applicazione per la Gestione di Dati GeoRSS attraverso Database
SplashScreen
35
In questa sezione verranno descritte le caratteristiche dell’applicazione sviluppata per la gestione dei dati GeoRSS
contenuti nel database.
Come già esposto, si è deciso di utilizzare PostgreSQL come applicativo per la creazione, gestione e salvataggio dei
dati. La decisione di basarsi su questo applicativo risiede, in primo luogo, nella sua conoscenza e utilizzo durante il
corso di studio triennale, in secondo luogo, in una visione futura del progetto in quanto, grazie al plug-in PostGIS
integrato, si potranno manipolare diverse geometrie attraverso dei veri e propri tipi di dato (point, line, polygon,
multipoint, multiline, multipolygon e geometrycollections).
Causa una non ancora completa e funzionale implementazione di tutti questi nuovi tipi di dato, che PostGIS metterà a
disposizione, e per motivi di semplicità e sviluppo del progetto, allo stato attuale, si è scelto di non utilizzare il plug-in,
tenendo comunque presente la possibilità di un suo uso futuro.
L’applicazione è stata sviluppata interamente in Java, utilizzando JBuilder 2006 come IDE di sviluppo.
Anch’esso durante il corso di studi è stato usufruito più volte in diversi progetti, grazie anche alla possibilità di creare
rapidamente intefaccie grafiche per mezzo del suo designer integrato.
Il tool di progetto intende sviluppare una GUI semplice ed intuitiva per permettere all’utente una più rapida e facile
consultazione dei dati conservati nella struttura dati PostgreSQL.
Le direttive di implementazione richiedevano alcune tra le funzione elementari per la gestione di un database, quali:
inserimento dati, rimozione dati, importazione dati da strutture risidenti su file, esportazione dati su file con loro
strutturazione e la possibilità di interrogazione database (query).
L’applicazione è composta dalle seguenti undici classi che verranno brevemente esposte in ordine di utilizzo:
Classi
AddFrame
Application
ExpFrame
Frame
ImpFrame
ItemGeoRSS
JavaGIS
Parser
RmFrame
SelectFrame
Splash
La classe comprendente il “main” dell’applicazione è la classe Application.
Il main come prima cosa genera un breve splash screen di presentazione dell’applicazione.
Lo splash screen è un’istanza della classe Splash che prende in input un’immagine e la inserisce all’interno di una
JWindow appositamente estesa per potergli attribuire ulteriori informazioni riguardanti la visualizzazione, quali:
il caricamento immagine da file, la durata in millisecondi dell’istanza della classe, settaggio della JProgressBar e suo
avanzamento.
Dopo aver settato il LookAndFeel dell’applicazione, il main, crea un nuova istanza di Application che setterà le
proprietà di posizionamento, dimensione e titolo del Frame principale che verrà visualizzato.
36
Main Frame
La classe Frame è la classe principale del tool sviluppato.
Essa funge sia da visualizzatore dei dati, sia da chiamante delle funzioni di gestione database.
Il main Frame è stato creato con Layout liquido per permettere il ridimensionamento della finestra, sfruttando le
proprietà di posizionamento degli oggetti del BorderLayout.
Esso è composto da cinque JPanel, di cui due funzionali (centro e sud) e tre puramente decorativi.
Il pannello centrale viene utilizzato dal Container di una JTable per la visualizzazione dei dati pervenuti
dall’interrogazione del database.
La connessione a database è realizzata utilizzando lo
Applicazione JAVA
standard di Java per l'
accesso a database JDBC. Grazie a
questo standard è possibile scrivere programmi in Java
che utilizzano database di tipo diverso, senza doverli
Driver Manager
riscrivere ogni volta. Infatti i dettagli specifici della
connessione ad un tipo di database sono incapsulati in un
Driver Locale
driver.
Driver Remoto
JDBC ammette che esistano diverse implementazioni e
vengano utilizzate dalla stessa applicazione. L'
API
Database Locale
Database Remoto
fornisce un meccanismo che carica dinamicamente i
driver appropriati e li registra nel JDBC Driver Manager.
Le connessioni JDBC supportano la creazione e l'
esecuzione delle istruzioni. Esse possono essere comandi SQL come
INSERT, UPDATE, DELETE, interrogazioni come SELECT o chiamate a stored procedure. I tipi di istruzioni
supportati sono:
•
Statement - l'
istruzione viene inviata al database di volta in volta.
37
•
Prepared Statement - l'
istruzione viene compilata una sola volta, in modo che le chiamate successive siano più
efficienti.
•
Callable Statement - usati per chiamare le stored procedure.
//The Connection to the Database
I
java.sql.Connection conn;
UPDATE e DELETE restituiscono un valore
//Vectors, Columns and Rows
comandi
di
scrittura
come
INSERT,
che indica quante righe sono state manipolate
Vector columnNames = new Vector();
Vector row;
(inserite, modificate, cancellate) dall'
istruzione.
Vector data = new Vector();
Essi non restituiscono altre informazioni.
//The Statement
Le interrogazioni restituiscono invece un set di
Statement s;
risultati attraverso la classe ResultSet. È
//Results
ResultSet r;
possibile spostarsi nel set di risultati, riga per
ResultSetMetaData md;
riga, tramite il metodo next(). Si può accedere
alle colonne di ogni singola riga chiamandole
public void database() {
per nome o per numero. Il result set può essere
try {
costituito da un numero qualsiasi di righe e
// Load the JDBC driver and establish a connection.
Class.forName("org.postgresql.Driver");
comprende dei metadati che indicano valori
String url = "jdbc:postgresql://localhost:3306/georss";
per il nome, il tipo, il numero delle colonne…
conn = DriverManager.getConnection(url, "postgres", postgres");
Questi metadati sono accessibili grazie ai
// Create a statement and execute a select query
s = conn.createStatement();
metodi della classe ResultSetMetaData.
r = s.executeQuery("SELECT * from georss");
I dati visualizzati vengono ricavati attraverso
md = r.getMetaData();
l’istanziazione della classe JavaGIS ed in
columns = md.getColumnCount();
particolare della funzione database()
// Get column names
che si
for (int i = 1; i <= columns; i++) {
occupa del collegamento a PostgreSQL e
columnNames.addElement(md.getColumnName(i));
dell’estrapolazione dei valori.
}
In un primo momento viene caricato il driver
// Get row data
per la connessione, e successivamente viene
while (r.next()) {
row = new Vector(columns);
creata una variabile contenente locazione e
for (int i = 1; i <= columns; i++) {
porta accessibile del database, per stabilire la
row.addElement(r.getObject(i)); }
connessione nella riga successiva.
data.addElement(row); }
In secondo momento viene creato un Statement
// Close the statement and the connection
s.close();
(un canale per le asserzioni) per interrogare il
conn.close();
database attraverso una query SQL.
}
Successivamente vengono estrapolati i Metadati (numero colonne, nome colonne) e inseriti in Vector per un successivo
utilizzo. Infine viene chiuso lo Statement e la connessione al database.
Dopo la fase di recupero dei valori dalla tabella del
//Create the JTable, data to fill the table and the metadata to create the columns
database l’applicazione, nel main Frame, crea un
table = new JTable(new MyTableModel(gisdatabase.data,
gisdatabase.columnNames));
propria JTable per dare all’utente la possibilità di
visualizzare i dati ottenuti.
38
La JTable viene istanziata utilizzando un TableModel per gestire alcune funzionalità particolari di questa struttura,
come la non editabilità delle celle, in seguito viene aggiunta al pannello centrale.
Il pannello posto a sud invece contiene i JButton funzionali per le operazioni fruibili dall’utente.
CommandPanel
Gli eventi (ActionEvent) su queste componenti sono gestiti da un unico ascoltatore (ActionListener) che implementa il
suo unico metodo (actionPerformed) per ottenere, a seconda della sorgente dell’evento, l’operazione richiesta.
Verranno ora descritte le funzionalità implementate per ogni singola componente, così da avere una visione più
dettagliata delle caratteristiche del tool sviluppato.
−
La funzionalità di inserimento viene attivata dall’evento occorso sul JButton “Insert” del main Frame, generando
una nuova istanza della classe AddFrame, estendensione della classe JDialog. Le finestre di dialogo sono delle
sotto-finestre che assicurano l’invio di
messaggi di diagnostica e l’acquisizione
di
valori
forniti
dall’utente
per
l’applicazione; pertanto ogni JDialog (nel
nostro caso AddFrame) richiede un
JFrame (il main Frame) di cui è
dipendente. Le finestre di dialogo sono
costruite a partire da usuali componenti
Swing e bloccano l’attività del Frame
padre se istanziate in modalità modale,
come nel nostro caso: non è possibile
accedere ad altre funzionalità del main
Frame se la finestra di dialogo per la
funzionalità di inserimento è visibile.
Ereditarietà JDialog e JFrame
InsertFrame
39
La struttura della finestra è formata similmente a quella del main Frame: il pannello centrale contiene una JTable
editabile per l’inserimento dei dati da parte dell’utente formata da un unico vettore senza elementi. I metadati per la
creazione delle colonne con il nome vengono recuperati dall’interrogazione del database. Nel pannello inferiore vi
sono i JButton per attivare l’operazione di inserimento dei dati (Insert) o per chiudere la finestra di dialogo senza
alcuna operazione (Cancel).
L’inserimento avviene passando alla
//String SQL to the Query
String sql = new String();
funzione
public void insert(String[] ins) {
JavaGIS
try {
insert()
il
della
vettore
di
classe
stringhe
contenente i dati dell’utente. In
// Load the JDBC driver and establish a connection.
questa funzione, come in quella vista
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:3306/georss";
precedentemente,
conn = DriverManager.getConnection(url, "postgres", postgres");
connessione al database PostgreSQL
// Create a statement and execute a select query
si
crea
la
e lo Statement. Nella riga successiva
s = conn.createStatement();
viene
//Create a Insert Query
sql = "INSERT INTO georss( title, description,elevation,radius,type,coord,color,transparency)
definita
l’istruzione
da
eseguire secondo la sintassi Java per
VALUES ('
" +ins[0] + "'
,'
" + ins[1] + "'
,'
" + ins[2] + "'
,'
" + ins[3] + "'
,'
"
SQL: INSERT INTO Nome Tabella
+ins[4] + "'
,'
" + ins[5] + "'
,'
" + ins[7] + "'
,'
" + ins[8] + "'
) ";
(colonna1,
//Execute a Insert Query
VALUES
s.executeUpdate(sql);
colonna
2,...)
(valore1, valore2,....).
// Close the statement and the connection
L’istruzione definita dalla variabile
s.close();
di tipo stringa sql, viene passata al
conn.close(); }
metodo
executeUpdate()
che
inoltrerà l’istruzione al database. Poi la connessione viene chiusa.
−
La funzionalità di rimozione dei dati viene attivata selezionando il JButton “Remove” dal main Frame istanziando
così un oggetto di tipo RmFrame che, come nel caso della funzione di inserimento, estende la classe JDialog con le
stesse caratteristiche viste sopra.
RmFrame
La struttura è del tutto simile a quelle precedentemente descritte. La funzionalità viene attivata selezionando le
righe da rimuovere dalla JTable (non editabile e creata interrogando il database come per il main Frame), e
cliccando sul tasto “Remove” dell’interfaccia.
40
public void remove(Integer[] keys) {
try {
// Load the JDBC driver and establish a connection.
Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost:3306/georss";
conn = DriverManager.getConnection(url, "postgres", postgres");
L’ActionEvent
sulla
Component
viene
catturato
dall’ActionListener che esegue l’operazione descritta nel
metodo actionPerfomed, recuperando la chiave primaria
univoca (id) delle righe selezionate per poi passare il vettore,
contenente i valori, al metodo remove() della classe JavaGIS.
// Create a statement and execute a select query
Come nel caso dell’inserimento viene creata la connessione
s = conn.createStatement();
al database fornendo le direttivi già viste, e lo Statement.
//Create a Insert Query
La rimozione prevede la selezione di più righe dalla JTable,
for (int i = 0; i < keys.length; i++) {
sql = "DELETE FROM georss WHERE ID= " + keys[i] + " ";
//Execute a Delete Query
s.executeUpdate(sql);
}
s.close();
implicando la ripetizione dell’operazione.
Per questo motivo la stringa sql e il metodo executeUpdate()
sono stati inseriti in un ciclo “for” che ripete l’operazione a
seconda del numero di righe selezionate.
conn.close();
L’operazione prevede: DELETE FROM Nome Tabella
}
WHERE Colonna = Valore.
Nell’applicazione sviluppata, il passaggio della chiave primaria come colonna per effettuare la rimozione dei dati è
stato incentivato dalle caratteristiche di unicità e auto-incremento della chiave stessa. In questo modo si è fornito un
identificativo univoco ad ogni riga ovviando il problema dell’uguaglianza di nomi e valori.
A termine operazione vengono chiusi sia lo Statement che la connessione e la JTable della finestra di dialogo viene
automaticamente aggiornata settando un nuovo TableModel, dopo aver recuperato i dati ancora conservati dal
database, dopo la precedente rimozione.
−
L’operazione di Refresh della JTable principale è gestita all’interno della classe Frame attraverso due metodi: il
primo aggiorna automaticamente i dati ad intervalli regolari di tempo, utilizzando le potenzialità del
MultiThreading che Java mette a disposizione.
L'
ambiente Java fornisce, attraverso la libreria
//Declarations
java.util.*, le classi Timer e TimerTask per gestire
MyThread mt = new MyThread();
thread di esecuzione sequenziali. La classe Timer
java.util.Timer timer = new java.util.Timer();
fornisce gli strumenti utili alla esecuzione schedulata
//Inner Class that Override the Method Run to Execute the Table Update
private class MyThread extends TimerTask {
di alcune operazioni descritte attraverso particolari
estensioni della classe TimerTask. Ciascuna istanza
public void run() {
//Create new Table (table_update) from a new connection to the Database
di questa classe viene gestita da un unico thread che,
JavaGIS gisdatabase_update = new JavaGIS();
in
//Get New Data from Database
sequenziale delle azioni. La classe Timer dispone di
gisdatabase_update.database();
background,
strumenti
//Set Table_Update Properties
table_update = new JTable(new MyTableModel(gisdatabase_update.data,
gisdatabase_update.columnNames));
che
si
preoccupa
permettono
di
dell’esecuzione
programmare
l’esecuzione di diversi task, sia in istanti singoli che
ad intervalli di tempo prestabiliti.
table_update.setGridColor(Color.darkGray);
//Add the Table_Update and the same ScrollPane to the Center Panel
centre.add(table_update, java.awt.BorderLayout.CENTER);
Per l’aggiornamento automatico si è creata una classe
MyThread che estende la classe TimerTask, descritta
centre.add(scrollPane, java.awt.BorderLayout.CENTER);
sopra, e una variabile di tipo timer per intervallare il
//Add the Table_Update to the ScrollPane-ViewPort
tempo.
scrollPane.getViewport().add(table_update); } }
41
All’interno della classe definita, si è sovrascritto il metodo run() delineando le operazioni da svolgere quali: il
collegamento al database; il recupero dei dati; la creazione di una nuova JTable con i dati appena ottenuti e
l’aggiunta al pannello centrale del Frame.
Il metodo run() viene invocato con la chiamata: timer.schedule(mt,0,5000); sull’oggetto di tipo Timer. I parametri
che vengono passati fanno riferimento alla classe MyThread, al delay di prima chiamata del metodo run() e al
tempo di attesa tra una chiamata e l’altra. Lo stesso codice è eseguito all’interno della funzione actionPerformed
invocata alla pressione di JButton Refresh sul main Frame che fornisce il secondo metodo di aggiornamento.
−
L’applicazione è stata sviluppata soprattutto pensando all’importazione di grandi quantità di dati attraverso file xml
con struttura GeoRSS già esistenti. Alla pressione del JButton “Import” viene istanziata la classe ImpFrame che
estende anch’essa un JDialog. In questa finestra di dialogo vi è inserito un JFileChooser per dare la possibilità di
ricerca del file all’utente.
ImpFrame
Un file chooser è un oggetto grafico che permette di
//Inner Class to Implement xmlFiles Filter
public class xmlFilter
navigare il file system e di selezionare uno o più file
extends FileFilter {
su cui eseguire una determinata operazione. Per
//Methods Overriding
//Description of the Files needed
conoscere il risultato dell'
interrogazione è possibile
public String getDescription() {
usare i seguenti metodi:
return "GeoRSS Source File (*.xml)";
−
}
File
getCurrentDirectory():
restituisce
la
directory corrente.
//Description of the Extension Accepted
−
public boolean accept(java.io.File file) {
return file.isDirectory() || file.getName().toLowerCase().endsWith(".xml");
} }
File
getSelectedFile():
restituisce
il
file
selezionato.
Inoltre vi è la possibilità di applicare dei filtri alla
selezione per visualizzare solo i files interessati, implementando l’interfaccia FileFilter e applicandoli con
l’apposito metodo addChoosableFileFilter(filtro), dopo aver posto la condizione setAcceptAllFileFilterUsed(false).
Nell’applicazione sviluppata, si sono implementati tre filtri, uno per i file XML, un per quelli XSD e uno per tutti
gli altri tipi di file. La loro visualizzazione dipende dalla scelta dell’utente modificando il menù a tendina sotto la
voce Tipo di File.
42
Dopo aver scelto il file, l’utente decide se approvare la sua scelta cliccando su Import invocando la gestione
dell’evento. Nell’actionPerfomed viene ricavato il file selezionato attraverso il metodo getSelectedFile() e passato
al costruttore della classe Parser.
La classe Parser è una delle classi fondamentali dell’applicazione. In essa vi sono le direttive per leggere i file presi
in input dal JFileChooser e salvare i loro valori.
In principio si è effettuata una ricerca su quale metodo di parsing da adottare per lo sviluppo futuro
dell’applicazione.
Le tecnologie analizzate sono state essenzialmente due: SAX (Simple API for XML) e DOM (Document Object
Model).
Le differenze tra le due sono sostanzialmente riferite alle modalità di interazione tra le API (Application
Programming Interface) e l’applicazione che ne fa uso.
Un parser SAX funziona in un modo molto semplice: legge, carattere dopo carattere, tutto il documento XML dato
in input, e genera una serie di eventi (callback) ogni volta che riconosce la presenza di particolari informazioni. Tali
informazioni sono solo notificate ai vari handler che poi le utilizzeranno nel modo opportuno.
La sequenzialità con cui opera un parser SAX, dovendo rileggere più volte il documento, rende però dispendioso
l’utilizzo delle risorse e del tempo. Per ovviare a tale problema è stato sviluppato il parser DOM.
Il DOM, a differenza di SAX, è una specifica del W3C (come XML). Per ogni elemento all’interno del documento
XML, è prevista la definizione di un’interfaccia.
Il DOM permette di disporre, in memoria, la totalità delle informazioni contenute nel documento XML e di un
meccanismo per elaborarle. Conservare in memoria tutte le informazioni è molto vantaggioso nel caso di modifica
dei dati estrapolati; ciò sarebbe ancora più evidente nel caso in cui la modifica di alcune informazioni dipendesse
dalla loro globalità.
In caso della mancata validità del documento, il parser si interromperà e visualizzerà un messaggio d’errore.
Ma anche il parser DOM ha i suoi svantaggi, concernenti l’uso della memoria, specie quando i file XML esaminati
hanno dimensioni onerose.
A fine ricerca si è giunti alla conclusione che il parser migliore sarebbe stato un mix delle due tecnologie, trovando
così in ROME le caratteristiche cercate.
Ospitato sulla suite di collaboration di Sun Microsystems, ROME è un set open source per il parsing, la
generazione e la gestione non solo di feed RSS, ma anche Atom, sviluppato da tre ingegneri Sun.
Basato su parser XML SAX e DOM, ROME supporta i vari formati RSS 0.90, RSS 0.91 Netscape, RSS 0.91
Userland, RSS 0.92, RSS 0.93, RSS 0.94, RSS 1.0, RSS 2.0, Atom 0.3 e Atom 1.0, e contiene anche alcuni
sottoprogetti. Tra questi ROME Modules, che permette di aggiungere a ROME il supporto per altre estensioni di
feed, come GeoRSS, Microsoft SSE e SLE, Google GData ecc…
Un altro progetto utile, se si deciderà di approdare a ROME, è “rome-eclipse-plugins”; un plug-in per Eclipse, che
permette di facilitare l'
accesso a ROME.
Sono disponibili al seguente indirizzo: https://rome.dev.java.net, oltre al download dei binari, anche i sorgenti, la
documentazione realizzata con Javadoc e il Wiki, in cui sono presenti, tra l'
altro, articoli e tutorial.
Per il momento però e per semplicità, vista anche la difficoltà di sviluppo incontrata, si è deciso di implementare il
parsing solo su un file con una determinata struttura, in futuro, quasi sicuramente, si adotterà un parser più
generale.
43
La struttura di un file GeoRSS per l’applicazione sviluppata, dovrà comprendere:
•
Il tag di apertura (<rss…>) della definizione delle versione XML che andrà chiuso a fine file (</rss>).
•
I tag (<item>) per la definizione degli oggetti con il relativo tag di chiusura (<item>).
•
Il tag (<title>) per la definizione del titolo dell’oggetto e il tag di chiusura relativo (</title>).
•
Il tag (<description>) per una breve descrizione dell’oggetto e il tag di chiusura (</description>).
•
I tag per la descrizione delle caratteristiche geometriche dell’oggetto quali:
<georss:point>,
<georss:line>,
<georss:box>,
<georss:polygon>
con
le
relative
chiusure
</georss:point>, </georss:line>, </georss:box>, </georss:polygon>
•
I tag per gli attributi: <georss:elev>, <georss:color>, <georss:transparency>, <georss:radius> con le loro
chiusure </georss:elev>, </georss:color>, </georss:transparency>, </georss:radius>.
<rss version="2.0" xmlns:gdas=http://www.gdacs.orgxmlns:icbm=http://postneo.com/icbm/
xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:asgard="http://asgard.jrc.it"
xmlns:geo="http://www.w3.org/2003/01/geo/"xmlns:glide="http://glidenumber.net"
xmlns:georss="http://www.georss.org/georss" xmlns:gml="http://www.opengis.net/gml">
<item>
<title>Linea Semplice</title>
<description>Visualizzazione Linea Semplice al suolo</description>
<georss:line>46.15 10.60 46.15 10.80 </georss:line>
<georss:color>142,35,35</georss:color>
<georss:transparency>50</georss:transparency>
</item>
….
</rss>
La classe Parser prende in input, attraverso il
public class Parser {
String line;
costruttore, il file di lettura, strutturato come visto
File infile;
precedentemente.
String tempitem = "";
ItemGeoRSS ig = null;
L’acquisizione può essere sia locale che distribuita
FileInputStream input;
attraverso la rete, in quanto viene istanziato un
public Parser() {}
oggetto della classe URL. La classe URL è una classe
public Parser(File file) {
fondamentale del package java.net.*: grazie a questa
infile = file;
classe è possibile creare semplici applicazioni di rete.
try { //Get the file Address
URL url = new URL(infile.toURL().toString());
La classe URL rappresenta un Uniform Resource
//Open an Input Stream
Locator, un puntatore ad una risorsa nel World Wide
InputStream in = url.openStream();
Web che può essere un file, una directory, o un
//Create a BufferReader to read every line
BufferedReader dis = new BufferedReader(new InputStreamReader(in));
oggetto di rete generico.
//Loop every line of the file, if it’s not null
Leggere il contenuto di una URL è semplice, grazie
while ( (line = dis.readLine()) != null) {
all'
apposito metodo di InputStream, openStream().
//When it find the tag <item>, it create a new ItemGeoRSS Object
Quest'
ultimo restituisce un InputStream con il quale è
if (line.contains("<item>")) {
possibile leggere direttamente dalla URL.
ig = new ItemGeoRSS();
Per leggere riga per riga si è utilizzato un
//Read until tag </item>
while (!line.contains("</item>")) {
BuffedReader su questo canale di input.
44
//Call to the function inserintodb from the class ItemGeoRSS
ig.inserintodb();
Il ciclo termina quando non vi sono più righe da leggere e al suo
interno contiene diverse operazioni condizionali a seconda del
}
//It search all different tags for the GeoRSS Object
tag riscontrato durante la lettura.
Se il parsing trova il tag <item> istanzia una nuova classe
if (line.contains("<title>")) {
ItemGeoRSS dedicata al salvataggio dei valori recuperati in
//Get the comlete String line
String tempname = line.substring(line.indexOf(">") + 1);
//Index of the String
fase di lettura e successivamente, quando viene riscontrato il tag
</item> i dati vengono inseriti nel database.
int buffer = 0;
buffer = (tempname.indexOf("</title>"));
La lettura dei valori, con le caratteristiche geometriche degli
oggetti, avviene leggendo l’intera stringa e creando delle
//Get the Value of the String
tempname = tempname.substring(0, buffer);
tempitem = tempname;
apposite sottostringhe per ovviare al problema della lettura dei
tag posti sulla stessa riga. Per questo ci si è avvalsi del metodo
System.out.println(tempitem);
//Assign the Value into the ItemGeoRSS variable
substring, che crea una sotto stringa da un determinato carattere
di partenza e indexOf che restituisce l’indice della prima
ig.title = tempitem; }
….
occorrenza del carattere specificato.
//And so on for the other tags…
Una volta letto il file e recuperati i valori la classe, ItemGeoRSS si dedica al loro inserimento per mezzo del
metodo inserintodb().
L’inserimento avviene, come già descritto: la stringa SQL comprende tutte le colonne del database tranne,
ovviamente, la chiave primaria (id) generata automaticamente e auto-incrementata.
//Create a Insert Query
sql = "INSERT INTO georss( title, description,elevation,radius,type,coord,color,transparency)
VALUES ('
" +title + "'
,'
" + description + "'
,'
" + elev + "'
,'
" + radius + "'
,'
"+
type + "'
,'
" + coord + "'
,'
" + color + "'
,'
" + transparency + "'
) ";
−
La funzionalità di Export dei dati dal database avviene alla pressione del JButton “Export” sul main Frame.
L’evento genera l’istanziazione di una nuova finestra di dialogo, implementata nella classe SelectFrame, del tutto
simile a quella per la rimozione dei dati.
SelectedFrame
Questa finestra permette di selezionare una o più righe, settare e/o modificare i due campi per gli attributi degli
oggetti: color e transparency.
45
JColorChooser e JOptionPane di Input
Alla pressione dei JButton dedicati, vengono visualizzati un
JColorChooser e un JOptionPane per il settaggio dei nuovi
valori e il loro inserimento in database, attraverso le funzioni
SQL di update recuperando l’identificativo univoco.
Il colore viene scomposto nel modello RGB additivo, basato
sui tre colori, Rosso, Verde e Blu attraverso i metodi appositi
della classe JColorChooser: getRed(), getGreen() e getBlue().
La JTable per la visualizzazione dei dati viene aggiornata
//Create a Insert Query for the Transparency
automaticamente nello stesso modo di quella, vista in
for (int i = 0; i < selectedrows.length; i++) {
precedenza, per la rimozione.
sql = "UPDATE georss SET transparency='
" + transparency +
"'WHERE id='
" + identificativo[i] + "'
";
Una volta impostati i valori degli attributi, l’utente ha la
possibilità di selezionare i dati da esportare e cliccare sul tasto
….
di approvazione generando un JfileChooser, per definire il
//Create a Insert Query for the Colors
percorso dove creare il nuovo file GeoRSS generato dal
for (int i = 0; i < selectedrows.length; i++) {
sql = "UPDATE georss SET color='
" + colorerosso + "," +
database.
coloreverde +"," + coloreblu + "'
Anche in questo caso, come per il JFileChooser di Import,
WHERE id='
" + identificativo[i] + "'
";
sono stati creati appositi filtri per dare alternative all’utente nel
….
scegliere quale formato selezionare: XML o XSD.
output.println(" xmlns:geo=\http://www.w3.org/2003/01/geo/\
if (e.getActionCommand().toString() == "ApproveSelection") {
xmlns:glide=\"http://glidenumber.net\"");
//Get the Selected Filter
output.println(" xmlns:georss=\"http://www.georss.org/georss\"
selectedfilter = fileChooser.getFileFilter();
xmlns:gml=\"http://www.opengis.net/gml\">");
//Different Cases for Diffrent Filters
output.println("");
if (selectedfilter == xmlfilter) {
//Write Data
try { //Creation of the File with a Specific Extension
for (int i = 0; i < selectedrows.length; i++) {
File f = fileChooser.getSelectedFile();
output.println(" " + "<item>");
f = new File(f.getAbsolutePath() + ".xml");
output.println("
//Checking if the File Already Exists
" + "<title>" +
table.getValueAt(selectedrows[i], 0) + "</title>");
if (!f.exists()) {
output.println("
out = new FileOutputStream(fileChooser.getSelectedFile().
" + "<description>" +
table.getValueAt(selectedrows[i], 1) +"</description>");
getAbsolutePath() + ".xml");
if (table.getValueAt(selectedrows[i], 4).toString().equals("point")) {
//Stream to Print on the File
output.println("
PrintStream output = new PrintStream(out);
" + "<georss:point>" +
table.getValueAt(selectedrows[i], 5) + "</georss:point>");
//Write XML Version
output.println("<rss version=\"2.0\" xmlns:gdas=\http://www.gdacs.org\
xmlns:icbm=\"http://postneo.com/icbm/\"");
} //And so on for the other tags
….
//Close tag <rss> and the File
output.println(" xmlns:dc=\http://purl.org/dc/elements/1.1/\
output.println("</rss>");
xmlns:asgard=\"http://asgard.jrc.it\"");
output.println("");
//Next Column
out.close();
46
Si è, inoltre, implementato il controllo sulla duplicazione del nome dando la possibilità della sovrascrittura.
La scrittura avviene creando un oggetto di tipo File, appartenente alla libreria java.io.*.
L’estensione del File viene controllata dai filtri implementati e concatenata a fine path.
Successivamente avviene il controllo sull’unicità del nome del file: se esiste già, l’utente riceverà un warning
dandogli la possibilità di decidere se sovrascrivere il file esistente o cambiare nome.
Una volta passato questo check, viene istanziato un canale per l’output (FileOutputStream) indirizzato sul file
selezionato in precedenza.
PrintStream aggiunge ulteriori funzioni al flusso di output, dando la possibilità di scrittura su file, attraverso la
semplice funzione println().
Per rendere la struttura del file in fase di generazione del tutto simile a quello di input, come prima cosa vengono
scritte le righe che specificano la versione XML da adottare.
Successivamente vengo scritti i valori recuperati dell’interrogazione delle righe della JTable.
A fine funzione viene chiuso il tag </rss> e il flusso di output.
La comparazione tra input e output è stata fatta manualmente visionando entrambi i file, ed è risultata corretta.
−
L’ultima funzionalità dell’applicazione, la funzionalità di query sul database, deve ancora essere implementata. In
futuro verrà sicuramente sviluppata con l’introduzione del modulo PostGIS che permetterà query spaziali sui dati,
fornendo all’utente ulteriori alternative di visualizzazione.
Queste sono le principali funzionalità sviluppate per la gestione di file GeoRSS da database PostgreSQL.
Le maggiori difficoltà riscontrate, ad inizio sviluppo, erano causate da una scarsa conoscenza della relazione tra
linguaggio di programmazione Java e i database. Le difficoltà sono state superate con uno studio più approfondito
dell’argomento, e con la partecipazione a diversi forum online.
5. OpenGL
5.1. Introduzione a OpenGL
Il progresso dei dispositivi hardware di output grafico ha determinato, in modo del tutto naturale, un’evoluzione delle
applicazioni software e ha portato alla realizzazione di librerie grafiche di alto livello, indipendenti da qualsiasi
periferica grafica di input e output e con una portabilità simile a quella dei linguaggi di programmazione di alto livello.
OpenGL è una libreria grafica piuttosto recente, che consente di realizzare e manipolare immagini in due e tre
dimensioni, e utilizza inoltre le tecniche più avanzate di rendering.
OpenGL è un’interfaccia software per hardware grafico. L’interfaccia consiste di un insieme di circa 250 diverse
funzioni e procedure che consentono al programmatore di specificare gli oggetti e le operazioni coinvolte nella
produzione di immagine grafiche di alta qualità, quali immagini a colori di oggetti tridimensionali. A livello più basso
OpenGL è una specifica, ovvero si tratta semplicemente di un documento che descrive l’insieme di funzioni ed il
comportamento preciso che queste devono avere.
Da questa specifica, i produttori di hardware creano implementazioni, ovvero librerie di funzioni create rispettando
quanto riportato sulla specifica OpenGL, facendo uso dell'
accelerazione hardware ove possibile. I produttori devono
comunque superare dei test specifici per poter fregiare i loro prodotti della qualifica di implementazioni OpenGL.
47
Esistono realizzazioni software che portano OpenGL su piattaforme che non hanno il supporto dei costruttori hardware,
ma di sicuro non raggiungono i livelli basati anche sui dispositivi grafici fisici.
Come già detto è usato per sviluppare nell'
industria dei videogiochi (nella quale compete con DirectX su Microsoft
Windows), per applicazioni di CAD, realtà virtuale, e CAE.
OpenGL è stata derivata dall’interfaccia GL, sviluppata per le workstation Silicon Graphics, e progettata per il
rendering in tempo reale, ad alta velocità. OpenGL è il risultato dei tentativi di trasferire i vantaggi di GL ad altre
piattaforme hardware: sono state rimosse funzioni input e windowing e ci si è concentrati sugli aspetti di rendering
dell’interfaccia, realizzando così una libreria estremamente portabile, e conservando allo stesso tempo le caratteristiche
che hanno fatto di GL un’interfaccia molto potente per i programmi di applicazione.
Al fine di imporre le sue caratteristiche multi-linguaggio e multi-piattaforma, vari bindings sono stati sviluppati per
OpenGL in molti linguaggi. Tra i più notevoli, la libreria Java 3D può appoggiarsi su OpenGL per sfruttare
l'
accelerazione hardware. Molto recentemente, Sun ha rilasciato le versioni beta del sistema JOGL, che fornisce binding
ai comandi OpenGL in C, diversamente da Java 3D che non fornisce tale supporto a basso livello. La pagina OpenGL
ufficiale elenca vari bindings per i linguaggi Java, Fortran 90, Perl, Pike, Python, Ada, e Visual Basic. I binding sono
disponibili anche per C++ e C#.
Una delle caratteristiche più apprezzate in ambito professionale è la retrocompatibilità tra le diverse versioni di
OpenGL: programmi scritti per la versione 1.0 della libreria devono funzionare senza modifiche su implementazioni
che seguono la versione 2.1.
OpenGL integra la grafica 3D per la computer grafica in ambiente Unix, ma può essere integrato in altri sistemi
Window, Linux, PlayStation 3 della Sony e MacOSX.
Come già accennato, la specifica di OpenGL è stata supervisionata dall'
OpenGL Architecture Review Board (ARB),
che si è formato nel 1992. L'
ARB consiste di un insieme di aziende interessate a creare un'
API coerente e ampiamente
disponibile. Secondo il sito Web ufficiale di OpenGL, i membri votanti dell'
ARB nel aprile del 2006 erano: 3Dlabs,
Apple Computer, ATI Technologies, Dell, IBM, Intel, NVIDIA, SGI e Sun Microsystems. Microsoft, uno dei membri
fondatori, ha lasciato il gruppo nel marzo del 2003 per implementare le proprie librerie grafiche, le DirectX. Con il
coinvolgimento di numerose aziende con interessi molto diversi, OpenGL è diventata nel tempo una API ad uso
generico, con un ampio ventaglio di capacità.
Il controllo di OpenGL è passato a Khronos Group alla fine del 2006, nel tentativo di migliorare il marketing di
OpenGL e per rimuovere le barriere tra lo sviluppo di OpenGL e OpenGL ES (OpenGL per dispositivi embedded).
OpenGL fornisce un controllo diretto sulle operazioni fondamentali di grafica in due e tre dimensioni. Ciò include la
specificazione di parametri quali matrici di trasformazione, o operazioni di aggiornamento dei pixel, ricezione di
primitive come punti, linee e poligoni, e di convertirli in pixel (rasterizing). Ciò è realizzato attraverso una pipeline
grafica nota come “OpenGL state machine”. La maggior parte dei comandi OpenGL forniscono primitive alla pipeline
grafica o istruiscono la pipeline su come elaborarle. Inoltre, OpenGL non impone un particolare metodo per la
descrizione degli oggetti geometrici complessi, ma fornisce piuttosto i mezzi di base per mezzo dei quali gli oggetti,
indipendentemente da come siano stati descritti, possono essere ottenuti. È un’API procedurale che opera a basso
livello, richiede al programmatore i passi precisi per disegnare una scena.
Questo approccio si pone in contrasto con le API descrittive ad alto livello le quali, operando su struttura dati ad albero
(scene graph), richiedono al programmatore solo una descrizione generica della scena, occupandosi dei dettagli più
complessi del rendering.
48
Analizziamo ora, in modo schematico, il funzionamento di OpenGL. Per prima cosa, possiamo pensare al pacchetto
grafico come ad una scatola nera, ossia un sistema le cui proprietà sono descritte solo per mezzo di input e output; senza
che nulla sia noto sul suo funzionamento interno. In particolare, gli input sono costituiti dalle funzioni chiamate dal
programma applicativo o provenienti da altri dispositivi quali mouse e tastiera, ed infine dai messaggi del sistema
operativo.
Gli output sono per la maggior parte di tipo grafico, sono infatti prevalentemente costituiti da primitive geometriche da
visualizzare sul monitor. Questo stesso schema caratterizza anche molte altre librerie grafiche.
Schema funzionamento libreria grafica
Le primitive geometriche sono disegnate in un frame buffer sulla base di alcuni attributi. Ogni primitiva geometrica, che
può essere un punto, un segmento, un poligono, un pixel o una bitmap, è definita da gruppi di uno o più vertici. Un
vertice definisce un punto, l’estremo di un lato, il vertice di un poligono dove due lati si incontrano. Gli attributi
possono essere cambiati indipendentemente, e il setting degli attributi relativi ad una primitiva non influenza il setting
degli attributi di altre. I dati (coordinate e attributi) sono associati ai vertici, ed ogni vertice è processato
indipendentemente.
La specificazione di attributi e primitive e la descrizione delle altre operazioni avviene inviando comandi sotto forma di
chiamate di funzioni o procedure. Le funzioni contenute in una libreria grafica possono essere classificate a seconda
della loro funzionalità:
1.
Le funzioni primitive definiscono gli oggetti di basso livello che il sistema grafico può visualizzare. A seconda
della libreria, le primitive possono includere punti, segmenti lineari, poligoni, pixel, testi e vari tipi di curve e
superfici.
2.
Le funzioni attributo governano il modo con cui le primitive appaiono sullo schermo. Gli attributi consentono
infatti di specificare colore, pattern, tipo di caratteri...(Texture mapping, Alpha Blending, Lighting…)
3.
Le funzioni di visualizzazione consentono di descrivere la posizione e l’orientazione, e di fissare la
visualizzazione delle immagini, in modo tale che le primitive appaiano entro una regione specifica dello
schermo.
4.
Le funzioni di trasformazione permettono all’utente di eseguire trasformazioni di oggetti quali traslazioni,
rotazioni e trasformazioni di scala (Z-Buffering).
5.
Le funzioni di input consentono all’utente di interagire con le diverse forme di input che caratterizzano i
sistemi grafici moderni, quali gli input da tastiera, mouse, e data tablet.
6.
Le funzioni di controllo permettono di comunicare con i sistemi window, per inizializzare i programmi, e per
gestire eventuali errori che possono verificarsi nel corso dell’esecuzione del programma applicativo. Spesso
infatti ci si deve preoccupare della complessità che nasce dal lavorare in ambienti in cui si è connessi ad una
rete a cui sono collegati anche altri utenti.
I nomi delle funzioni di OpenGL iniziano con le lettere gl e sono memorizzate in una libreria, usualmente detta GL.
L’utente può inoltre avvalersi di altre librerie collegate.
OpenGL è composto essenzialmente da due librerie (GL e GLU), alle quali se ne affianca una terza opzionale (GLUT).
49
•
GL (Graphics Library) E'il nucleo della libreria grafica. E'qui che vengono fornite le funzioni di basso livello:
il tracciamento dei poligoni, le trasformazioni, l’illuminazione e la gestione dei vari buffer di disegno.
•
GLU (OpenGL Utility Library) Estende GL con una serie di operazioni e primitive di utilità generale,
implementate con le primitive definite in GL. E'qui, per esempio, che trovano posto funzioni come il
posizionamento di una telecamera o la gestione delle superfici NURBS.
•
GLUT (OpenGL Utility Toolkit ) E'una libreria opzionale che fornisce al programmatore OpenGL la
possibilità di avere una gestione di una interfaccia a finestre svincolata dal sistema in cui ci si trova. Su GLUT
si trovano comandi in grado di aprire una finestra, controllarne lo stato, ricevere eventi da mouse e tastiera,
gestire menù ed in generale tutto quello che si può fare con un normale window manager.
Reperire queste librerie è abbastanza semplice diversi sono i siti web, dei membri del Khoronos Gruop e non, che
offrono il download.
Organizzazione delle librerie
La maggior parte dei comandi inviati a OpenGL può venire accumulata in una display list, che verrà successivamente.
Altrimenti i comandi saranno inviati attraverso il processing pipeline. Durante il primo stadio vengono approssimate
curve e superfici geometriche valutando funzioni polinomiali sui valori di input. Nel secondo stadio si opera sulle
primitive geometriche descritte dai vertici: i vertici sono trasformati e illuminati, e le primitive sono tagliate al volume
di osservazione, per essere inviate allo stadio successivo, la rasterizzazione. La rasterizzazione produce una serie di
indirizzi e valori per il frame buffer, utilizzando una descrizione bidimensionale di punti, segmenti e poligoni. Ogni
frammento così prodotto viene quindi inviato allo stadio successivo in cui si eseguono delle operazioni sui frammenti
individuali, prima che essi finalmente modifichino il frame buffer. Queste operazioni includono, oltre alle operazioni
logiche sui valori dei frammenti, l’aggiornamento del frame buffer in base ai dati in entrata memorizzati
precedentemente, e la colorazione dei frammenti entranti con i colori memorizzati. Infine, i rettangoli di pixel e le
bitmap possono bypassare lo stadio relativo all’elaborazione dei vertici, ed inviare, attraverso la rasterizzazione, blocchi
di frammenti alle operazioni sui frammenti individuali.
50
Diagramma a blocchi di OpenGL
5.2. Modello di Macchina a Stati
Un altro aspetto peculiare di OpenGL è la sua impostazione come macchina a stati. OpenGL ha infatti molte opzioni
che possono essere attivate o disattivate oppure possono essere alterate durante l’esecuzione di un programma.
Ad esempio, il colore con cui vengono tracciate le primitive è una delle più usate variabili di stato: quando viene
modificata con il comando glColor il colore specificato diventa quello corrente, tutte le primitive disegnate fino alla
prossima chiamata di glColor verranno disegnate con quel colore.
Nell’esempio seguente, verranno disegnati tre vertici. Utilizzando il colore appena definito i primi due vertici verranno
disegnati rossi ed il terzo blu. Il cambio di colore intermedio, non essendo seguito da alcun comando di disegno, non
verrà ovviamente preso in considerazine.
// colore rosso
glColor3f( 1.0, 0.0, 0.0);
glVertex3i( 5, 3, 2);
glVertex3i( 7, 4, 2);
// colore verde
glColor3f( 0.0, 1.0, 0.0);
// colore blu
glColor3f( 0.0, 0.0, 1.0);
glVertex3i( 9, 5, 2);
Esistono inoltre variabili di stato booleane, ad esempio la attivazione del depth buffer o quella della nebbia. Queste
variabili possono essere modificate in generale con i comandi glEnable() e glDisable() utilizzando come parametri
alcune costanti di OpenGL.
Ogni variabile parte con un valore di default ed è inoltre sempre possibile interrogare il sistema per conoscerne lo stato.
A tal fine esistono alcune funzioni di query, la famiglia delle glGet. Un buon approccio è quello di inizializzare tutte
quelle che si sta per usare fornendo così una maggiore leggibilità del codice.
51
5.3. Principali Primitive
Fra le caratteristiche implementate possiamo trovare:
•
Gestione delle viste ortogonali e prospettiche
•
Illuminazione
•
Texturing
•
Trasparenze
•
Effetti come nebbia, motion blur e messa a fuoco
•
Anti-aliasing
Differenziandosi dall’approccio di molte altre librerie, OpenGL ha deciso di specializzarsi esclusivamente in operazioni
grafiche di basso livello; queste sono state implementate in modo da massimizzarne l’efficienza e la flessibilità. Non
esistono comandi con cui descrivere oggetti complessi; essi devono essere costruiti dall’utente tramite le primitive
offerte. Questo può sembrare un lavoro improbo, ma alla lunga è proprio quello che rende OpenGL così flessibile. Per
dare una idea della espandibilità di questa libreria, fra le caratteristiche che non fanno parte di OpenGL ma che sono
state realizzate successivamente da utenti, troviamo effetti come riflessioni, ombre, sistemi di particelle e luci
volumetriche.
Durante la prima stesura delle direttiva di OpenGL c’è stato un ampio dibattito riguardante quali e quante primitive
dovrebbero essere mantenute in una libreria grafica, dibattito non ancora del tutto risolto.
Da un lato le librerie dovrebbero contenere un insieme ristretto di primitive, quelle che tutti i sistemi hardware sono in
grado di gestire. Questi sistemi minimali di solito mantengono primitive quali linee, poligoni e qualche forma di testo
(stringhe di caratteri), tutte generabili dall’hardware in modo efficiente.
Dall’altro lato ci sono le librerie che possono mantenere una grossa varietà di primitive, tra cui anche cerchi, curve,
superfici e solidi, al fine di rendere l’utente in grado di realizzare applicazioni più sofisticate. Tuttavia, poiché pochi
sistemi hardware sono in grado di sostenere questa varietà di primitive, i programmi basati su questi pacchetti grafici
risultano poco portabili.
OpenGL sta in una posizione intermedia tra le due tendenze. La libreria di base contiene un insieme limitato di
primitive, mentre la libreria GLU contiene un insieme molto ricco di oggetti derivati dalle primitive di base.
1.
Vertici e segmenti
Le primitive di base di OpenGL sono specificate attraverso una serie di vertici.
I vertici possono definire un’ampia varietà di oggetti geometrici, e un diverso numero di vertici risulta necessario, a
seconda dell’oggetto geometrico da rappresentare. Possiamo raggruppare quanti vertici vogliamo usando le funzioni
glBegin e glEnd. L’argomento di glBegin specifica la figura geometrica che vogliamo che i nostri vertici definiscano
(GL_POLYGON, GL_TRIANGLE, GL_QUAD e molt altre…).
Il programmatore definisce quindi un oggetto attraverso una sequenza di comandi della forma:
glBegin(tipo di figura geometrica);
glVertex*( . . . );
…
glVertex*( . . . );
glEnd();
Il comando glVertex*(); si usa per specificare un singolo vertice.
52
OpenGL mette a disposizione dell’utente diverse forme per descrivere un vertice, in modo che l’utente possa
selezionare quella più adatta al problema. Il carattere * indica il numero di argomenti che si devono passare al comando
OpenGL (2, 3, o 4) e il loro tipo (interi (i), virgola mobile (f), doppia precisione (d)). Infine la presenza del carattere “v”
come ultimo carattere della primitiva indica che le variabili sono specificate per mezzo di un puntatore ad un vettore o
da una lista.
Se si vuole lavorare in due dimensioni con interi, allora il comando più appropriato è: glVertex2i(GLint x, GLint y);
mentre il comando: glVertex3f(GLfloat x, GLfloat y, GLfloat z); descrive un punto in tre dimensioni usando i numeri in
virgola mobile.
Se invece l’informazione è memorizzata in un vettore possiamo usare il comando: glVertex3fv(vertex);
Tra la coppia di comandi glBegin e glEnd, possono naturalmente trovarsi altre istruzioni o chiamate di funzioni. Ad
esempio si possono modificare gli attributi oppure eseguire dei calcoli per determinare il vertice successivo.
I possibili oggetti geometrici, tutti definibili in termini di vertici o segmenti di linea, messi a disposizione da OpenGL
sono riassunti nella tabella. Presi complessivamente, questi tipi di oggetto soddisfano le necessità di quasi tutte le
applicazioni grafiche. Naturalmente anche un segmento di linea è specificato da una coppia di vertici, ma esso risulta
talmente importante da essere considerato quale un’entità geometrica di base. I segmenti possono essere usati per
approssimare curve, per connettere valori di un grafico, come lati di poligoni.
Primitiva
Interpretazione dei vertici
GL_POINTSGL_POINTS
ogni vertice descrive la locazione di un punto.
GL_LINESGL_LINES
ogni coppia di vertici descrive un segmento di linea.
GL_LINE_STRIPGL_LINE_STRIP
GL_LINE_LOOPGL_LINE_LOOP
GL_POLYGONGL_POLYGON
GL_TRIANGLEGL_TRIANGLE
GL_QUADGL_QUAD
GL_TRIANGLE_STRIPGL_TRIANGLE_STRIP
GL_QUAD_STRIPGL_QUAD_STRIP
serie di segmenti di linea connessi: ogni vertice dopo il primo è
un estremo del segmento successivo.
è come il line strip, ma un segmento viene aggiunto tra il vertice
finale ed il vertice iniziale.
line loop formato da vertici che descrive il contorno di un
poligono convesso.
ogni triade di vertici consecutivi descrive un triangolo.
ogni gruppo consecutivo di quattro vertici descrive un
quadrilatero.
ogni vertice, ad eccezione dei primi due, descrive un triangolo
formato da quel vertice e dai due precedenti.
ogni coppia di vertici, ad eccezione dei primi due, descrive un
quadrilatero formato da quella coppia e dalla coppia precedente.
ogni vertice, ad eccezione dei primi due, descrive un triangolo
GL_TRIANGLE_FANGL_TRIANGLE_FAN
formato da quel vertice e dal vertice precedente e dal primo
vertice.
Primitive Geometriche di OpenGL
Come risulta da questa tabella, ci sono più scelte per la visualizzazione delle primitive geometriche. Ad esempio per i
segmenti di linea ci sono il tipo GL_LINES, che interpreta ogni coppia di vertici come estremi di un segmento; il tipo
GL_LINE_STRIP che consente di connettere i segmenti successivi; ed infine il tipo GL_LINE_LOOP che aggiunge un
segmento di linea tra il primo e l’ultimo vertice.
53
Tipi di segmenti di linea
2.
Poligoni
Una delle differenze concettuali più importanti tra i tipi di oggetto è se essi abbiano o meno una regione interna. È
possibile visualizzare un poligono in diversi modi. Ad esempio si possono visualizzare solo i suoi lati. Oppure possiamo
riempire la regione interna con un colore, o con un pattern, e i lati possono essere visualizzati oppure no. Nonostante i
lati di un poligono siano facilmente definibili tramite una lista di vertici, se la regione interna non è ben definita, il
rendering del poligono può risultare scorretto. Di conseguenza è necessario stabilire come poter definire la regione
interna di un poligono.
In due dimensioni, fino a quando nessuna coppia di lati si interseca, abbiamo un poligono semplice, con una regione
interna chiaramente definita. Dunque le locazioni dei vertici determinano se il poligono è semplice oppure no.
Un oggetto si definisce convesso se tutti i punti su un segmento di linea che congiunge due punti al suo interno, o sul
suo bordo, si trovano all’interno dell’oggetto.
Poligoni semplici e complessi - Poligoni convessi
Molte librerie grafiche garantiscono un corretto riempimento delle figure geometriche solo quando queste sono
convesse. In particolare OpenGL richiede che i poligoni siano semplici, convessi e senza buchi: nel caso queste
condizioni non siano rispettate, non è assicurata una visualizzazione corretta. Figure complesse che richiedono poligoni
con queste proprietà si ottengono formando l’unione di poligoni semplici convessi, come fanno alcune delle funzioni
della libreria GLUT.
In tre dimensioni si presenta qualche difficoltà in più poiché le figure possono non essere piane. Se un poligono non è
planare, per effetto di trasformazioni, ad esempio una proiezione, si può ottenere un poligono non semplice. Molti
sistemi grafici sfruttano la proprietà che tre vertici non allineati determinano sia un triangolo che il piano in cui giace il
triangolo. Quindi, usando sempre i triangoli è possibile garantire un rendering corretto degli oggetti.
54
Tornando ai diversi tipi di OpenGL illustrati in tabella, per le figure con
regione interna abbiamo queste possibilità. Il tipo GL_POLYGON produce
la stessa figura che si ottiene usando LINE_LOOP. I tipi GL_TRIANGLES
e GL_QUADS sono casi speciali di poligoni: gruppi successivi di tre e
quattro
vertici
sono
interpretati
come
triangoli
e
quadrilateri,
rispettivamente.
GL_TRIANGLE_STRIP,
GL_QUAD_STRIP,
GL_TRIANGLE_FAN,
GL_QUAD_FAN sono invece tipi basati su gruppi di triangoli e
quadrilateri che condividono vertici ed archi.
Tipologie di poligoni
Triangle_strip e Quad_strip
3.
Oggetti curvilinei
Si possono usare le primitive disponibili per approssimare curve e superfici. Ad esempio un cerchio può essere
approssimato attraverso un poligono regolare di n lati; nello stesso modo, una sfera può essere approssimata con un
poliedro.
Un approccio alternativo è quello di partire dalle definizioni matematiche degli oggetti curvilinei, e quindi di costruire
funzioni grafiche per implementarle. Oggetti quali superfici quadratiche, curve polinomiali parametriche, e superfici
hanno una chiara definizione matematica, e possono essere specificati attraverso opportuni insiemi di vertici. Ad
esempio, una sfera può essere definita dal suo centro e da un punto sulla sua superficie.
Quasi tutti i sistemi grafici consentono di seguire entrambi gli approcci. In OpenGL possiamo usare la libreria GLU che
mette a disposizione una collezione di approssimazioni di curve e superfici comuni, e possiamo anche scrivere nuove
funzioni per definire altre figure.
4.
Attributi
In un sistema grafico moderno vi è una distinzione tra il tipo di primitiva e la sua visualizzazione. Una linea tratteggiata,
ad esempio, ed una linea continua sono dello stesso tipo geometrico, ma sono visualizzate diversamente. Si definisce
attributo qualsiasi proprietà che determina come una primitiva
geometrica deve essere visualizzata. Il colore è un attributo ovvio,
così come lo spessore delle linee ed il pattern usato per riempire i
poligoni.
Ad ogni attributo Ë associato un valore corrente, il quale può
essere modificato con apposite funzioni di modifica.
Alcuni attributi per linee e poligoni
55
Il valore corrente di un attributo si applica a tutte le operazioni che seguono, fino alla successiva modifica. Inizialmente
gli attributi hanno ciascuno un proprio valore di default.
Gli attributi possono essere associati alle primitive in diversi punti del processing pipeline. Nel modo immediato, le
primitive non sono memorizzate nel sistema, ma vengono visualizzate non appena sono state definite. I valori attuali
degli attributi sono parte dello stato del sistema grafico. Nel sistema non rimane dunque memoria della primitiva; solo
l’immagine appare sul display, e una volta cancellata dal display, la primitiva è persa. Le display list consentono invece
di mantenere oggetti nella memoria, in modo che essi possano essere visualizzati nuovamente.
Ad ogni tipo geometrico è associato un certo insieme di attributi.
Un punto prevede attributi per il colore e la dimensione: glPointSize(Glfloat size);
Un segmento lineare può avere un colore, uno spessore, che si imposta con: void glLineWidth(Glfloat size) ;
ed un tipo di tratto (continuo, tratteggiato, punteggiato), che si imposta con: void glLineStipple(Glint factor, Glushort
pattern); dove pattern è costituito da 16 bit che rappresentano il tratto, e factor il fattore di scala.
Le primitive dei poligoni hanno più attributi, poiché si deve specificare il riempimento delle regioni interne: possiamo
usare un a tinta unita, o un pattern, possiamo decidere se riempire o meno il poligono, se visualizzare o meno il suo
contorno. Il tipo di rendering dei poligoni si determina con la primitiva: void glPolygonMode(Glenum face, Glenum
mode); dove face può essere GL_FRONT (solo la faccia di fronte), GL_BACK (solo la faccia posteriore),
GL_FRONT_AND_BACK (entrambe le facce), mentre mode può essere GL_POINT (solo i vertici), GL_LINE (solo i
lati) o GL_FILL (riempimento della parte interna).
5.
Colore
Ci sono diverse tecniche per la visualizzazione del colore. Nel sistema RGB, ogni pixel ha componenti separate per i tre
colori, un byte per ciascuno. Dato che la libreria grafica deve essere il più possibile indipendente dal sistema hardware,
è importante avere la possibilità di specificare il colore indipendentemente del numero di bit nel frame buffer, e lasciare
all’hardware del sistema il compito di approssimare il colore richiesto nel miglior modo possibile, compatibilmente con
il display disponibile.
Una tecnica molto diffusa è quella basata sul cosiddetto color cube: le componenti di colore vengono specificate tramite
i numeri compresi tra 0.0 e 1.0, dove 1.0 denota il valore massimo del corrispondente colore primario, e 0.0 il valore
nullo. In OpenGL il color cube si implementa nel modo seguente. Per disegnare usando, ad esempio, il colore rosso si
chiama la funzione: glColor3f(1.0, 0.0, 0.0);
Poiché il colore fa parte dello stato, si continuerà a disegnare in rosso fino a quando il colore viene cambiato. Se si fa
riferimento al sistema RGBA, si utilizza il valore alpha come indice per l’opacità o la trasparenza.
Uno dei primi compiti che devono essere eseguiti in un programma è quello di ripulire l’area dello schermo (la drawing
window) destinata alla visualizzazione dell’output; e questa operazione deve essere ripetuta ogni volta che si deve
visualizzare una nuova immagine, ad esempio: glClearColor(default color, 0.0);
Quando invece si utilizza il sistema di colorazione basato sulle tabelle look-up, i colori vengono selezionati attraverso la
funzione: glIndexi(element); che seleziona un particolare colore dalla tabella.
56
5.3.1.
Texturing
Il Texture mapping è una tecnica molto utilizzata nel campo del rendering, poiché è in grado elevare notevolmente il
realismo della scena.
Sostanzialmente consiste nell'
applicare un'
immagine ad un oggetto composto da uno o più poligoni.
Per esempio, supponendo la rappresentazione di un muro, un'
immagine che rappresenta dei mattoni possiamo applicarla
ai poligoni ottenendo così l'
effetto realistico.
Dato che il costo per la manipolazione dell'
immagine non dipende da ciò che è rappresentato, ma dalla risoluzione,
possiamo utilizzare immagini ricche di particolari. Infatti è ormai pratica comune utilizzare direttamente (o dopo piccoli
ritocchi) le foto di una camera digitale.
Quando vogliamo texturizzare un oggetto dobbiamo creare una Texture, partendo dall'
immagine che vogliamo
applicare. La Texture è un tipo di dato particolare che solitamente viene gestito direttamente dalla libreria grafica di
basso livello, perchè bisogna eseguire diverse operazioni per adattare l'
immagine all'
oggetto.
Solitamente un'
immagine viene visualizzata come un rettangolo la cui larghezza ed altezza dipendono dal numero di
pixel impiegati, ma quando viene applicata a un poligono deve assumere la forma e la dimensione di quest'
ultimo. Ciò
significa che se il nostro oggetto è molto grande la nostra immagine dovrà essere "tirata", se invece il nostro oggetto è
piccolo o lontano, l'
immagine sarà molto ridotta. Inoltre è necessario che durante le trasformazioni geometriche
dell'
oggetto (rotazioni, traslazioni, ecc…) l'
immagine sia sempre visualizzata in modo corretto.
In OpenGL il Texture Mapping è validamente supportato.
Per abilitare o disabilitare un determinato tipo di Texture Mapping si utilizzano i parametri:
•
GL_TEXTURE_2D (Texture 2D).
•
GL_TEXTURE_1D (Texture 1D, altezza uguale a 1).
•
GL_TEXTURE_3D (Texture 3D, ancora poco usate).
I passi da seguire per creare una Texture sono i seguenti:
1.
1.
Generazione di un riferimento alla Texture.
2.
Attivazione del riferimento.
3.
Settaggio dei parametri.
4.
Creazione della Texture mediante l'
immagine.
5.
Rappresentazione della Texture
Generazione di un riferimento alla Texture
Si tratta di indicare ad OpenGL che vogliamo riservare spazio per una o più Texture che utilizzeremo
successivamente.
Per distinguere univocamente le diverse Texture, per ogni riferimento creato viene restituito un numero intero.
La funzione da utilizzare è: void glGenTextures(GLsizei n, GLuint *TextureNames);
dove n è il numero di Texture che vogliamo creare: TextureNames è l'
indirizzo di un intero o di un array di interi
dove saranno memorizzati gli identificativi per ogni Texture creata.
57
2.
Attivazione del riferimento
Questa operazione consiste nel rendere attuale, cioè attiva, una delle Texture create. OpenGL infatti, in ogni
momento, può lavorare su una sola Texture.
Per
tale
compito
usiamo
la
funzione:
void
glBindTexture(GLenum
target,
GLuint
TextureName);
dove target è quale tipo di Texture attivare, TextureName è l'
identificativo della Texture che abbiamo ottenuto con
la chiamata a glGenTextures.
3.
Settaggio dei parametri
Questa fase è la più complicata, poiché si devono impostare i parametri che andranno a influire sulla
rappresentazione della Texture.
I parametri più importanti che si devono modificare sono i filtri e precisamente il Magnification filter e il
Minification filter.
Per modificare dei parametri della Texture, utilizziamo la funzione:
void glTexParameter{if}(GLenum target, GLenum pname, TYPE param);
dove target è il tipo di Texture, pname è il parametro che vogliamo modificare, param è il valore che assumerà il
parametro.
Il Magnification filter entra in azione quando un pixel reale rappresenta solo una piccola parte di una texel, cioè di
un pixel della Texture. Questo succede quando la nostra Texture è molto piccola e viene applicata su un oggetto
molto grande, oppure quando l'
oggetto è molto vicino alla vista dell'
utente.
Il Minification filter è invece esattamente il contrario del Magnification. Viene utilizzato quando la Texture è più
grande dell'
oggetto su cui viene incollata o quando l'
oggetto è lontano; questo significa che la texel rappresenta più
pixel reali.
Altri settaggi importanti che in OpenGL vanno sotto il nome di Texture Functions, sono il modo in cui i colori delle
Texture influiscono sugli oggetti. Si utilizza: void glTexEnv{if}(GLenum target, GLenum pname, TYPE param);
dove, target deve essere uguale a GL_TEXTURE_ENV, pname sarà uguale a GL_TEXTURE_ENV_MODE
mentre param può assumere uno dei seguenti valori:
4.
•
GL_BLEND (trasparenza).
•
GL_DECAL (sostituzione colore originale con quello Texture).
•
GL_MODULATE (modulazione dei due colori).
Creazione della Texture
Possiamo infine indicare ad OpenGL, quale immagine vogliamo utilizzare per creare la nostra Texture. La funzione
per eseguire tale compito è:
void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint
border, GLenum format, GLenum type, const GLvoid *pixels);
dove i parametri sono del tutto simili alle funzioni viste precedentemente con l’aggiunta del parametro
internalFormat per descrivere il formato delle Texels, la larghezza e l’altezza dell’immagine, il tipo di bordo, il
formato dati dell’immagine (GL_RGB, GL_RGBA...), il tipo di dato (GL_UNSIGNED_BYTE, GL_SHORT...) e il
puntatore all’immagine con l’ultimo parametro, pixels.
58
5.
Rappresentazione delle Texture
Una volta creata la Texture, per utilizzarla dobbiamo attivarla e indicare le sue coordinate rispetto al poligono.
Per attivarla chiamiamo glBindTexture passandogli l'
identificativo.
Viene creato un nuovo sistema di riferimento con origine in un vertice del poligono e le coordinate delle Texture
varieranno a secondo della distanza dalla nuova origine.
In un quadrato definito dalle coordinate:
Le coordinate delle Texture saranno:
Vertice in basso a sinistra: -1.0, -1.0;
Vertice in basso a sinistra: 0.0, 0.0;
Vertice in basso a destra : 1.0, -1.0;
Vertice in basso a destra: 1.0, 0.0;
Vertice in alto a destra : 1.0, 1.0;
Vertice in alto a destra: 1.0, 1.0;
Vertice in alto a sinistra : -1.0, 1.0;
Vertice in alto a sinistra: 0.0, 1.0;
La funzione per indicare le coordinate è semplicemente: void glTexCoord2{if}(TYPE coords);
quindi ritornando all’esempio visto in precedenza, si avrà:
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 0.0);
glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 0.0);
glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 0.0);
glTexCoord2f(-1.0, 1.0); glVertex3f(-1.0, 1.0, 0.0);
glEnd();
Uno dei settaggi, forse più usato sulle texture, è il Mipmapping.
Per migliorare la qualità di visualizzazione delle Texture, quando queste si presentano più piccole, è possibile creare un
certo numero di Texture con la stessa immagine, ma con dimensioni differenti. In questo modo, a seconda della
dimensione
del poligono
al quale
deve essere
applicata, OpenGL utilizzerà la Texture più adatta.
Questa operazione può essere fatta o attraverso chiamate multiple a glTexImage settando il parametro level con valori
crescenti, oppure utilizzando una funzione di utilità della libreria glu:
int gluBuild2DMipmaps(GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum type,
void *data);
dove components, corrisponde all'
internal format di glTexImage.
Questa funzione costruirà automaticamente una serie di Texture più piccole partendo da quella originale.
I parametri per il Minification filter vengono settati utilizzando uno dei seguenti valori:
•
GL_NEAREST_MIPMAP_NEAREST la Texture più vicina alla risoluzione del poligono e il filtro GL_NEAREST
•
GL_NEAREST_MIPMAP_LINEAR la Texture più vicina alla risoluzione del poligono e il filtro GL_LINEAR
•
GL_LINEAR_MIPMAP_NEAREST usa interpolazione tra 2 Texture vicine e il filtro GL_NEAREST
•
GL_LINEAR_MIPMAP_LINEAR usa interpolazione tra le 2 Texture vicine e il filtro GL_LINEAR
59
5.3.2.
Blending
Nell’ambito del progetto di tesi è stata presa in particolare considerazione, per la sovrapposizione di livelli e oggetti, la
caratteristica della trasparenza, detta Blending.
Il Blending è utile per effetti come la trasparenza, ad esempio l'
acqua, il vetro, le finestre, etc.
La stringa per definire un colore glColor3f è usata per indicare che il colore è specificato in accordo al modello RGB a
tre colori, e che i valori delle componenti di colore, sono in virgola mobile. Se si fa riferimento al sistema RGBA, si
utilizza un ulteriore valore. Questo valore alpha viene interpretato come indice per l’opacità o la trasparenza (un oggetto
opaco è un oggetto attraverso cui non passa la luce, mentre un oggetto è trasparente se lascia passare la luce).
Un valore di alpha = 0, identifica una superficie totalmente trasparente, mentre un valore = 1 identifica una superficie
totalmente opaca.
Pertanto la funzione di Blending, glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR), prende come input due valori.
Uno è il valore del colore sorgente (Source, il valore che andrà aggiunto), l'
altro è valore del colore destinazione
(Destination, valore che già esiste nel buffer.)
La miscelazione avviene secondo la seguente formula, dove i Blending Factors, blendsource e blenddest, sono specificati
dal programmatore: (R, G,B, A) new = (R, G,B, A)sourceblendsource + (R, G,B, A)destblenddest
Le combinazioni possibili sono innumerevoli e variano a seconda del risultato che si vuole ottenere, come si può vedere
dalla seguente tabella.
La prima colonna indica la costante che si vuole prendere in considerazione, la colonna “Relevant Factors” indica se la
costante può essere utilizzata come sorgente o come destinazione, e la terza colonna indica i colori che devono essere
miscelati.
Constant
Relevant Factors
Compute Blend Factor
GL_ZERO
S/D
(0, 0, 0, 0)
GL_ONE
S/D
(1, 1, 1, 1)
GL_DST_COLOR
S
(R, G, B, A)d
GL_SRC_COLOR
D
(R, G, B, A)s
GL_ONE_MIINUS_DST_COLOR
S
1-(R, G, B, A)d
GL_ONE_MIINUS_SRC_COLOR
D
1-(R, G, B, A)s
GL_SRC_ALPHA
S/D
(As, As, As, As)
GL_ONE_MIINUS_SRC_ALPHA
S/D
1-(As, As, As, As)
GL_DST_ALPHA
S/D
(Ad, Ad, Ad, Ad)
GL_ONE_MIINUS_DST_ALPHA
S/D
1-(Ad, Ad, Ad, Ad)
GL_SRC_ALPHA_SATURATE
S
(f,f,f,1), f=min(As,1- Ad)
GL_CONSTANT_COLOR
D
(R, G, B, A)c
GL_ONE_MINUS_CONSTANT_COLOR
S/D
1-(R, G, B, A)c
GL_CONSTANT_ALPHA
S/D
(Ac, Ac, Ac, Ac)
GL_ONE_MIINUS_CONSTANT_ALPHA
S/D
1-(Ac, Ac, Ac, Ac)
Come già detto nel capito precedente, OpenGL è una macchina a stati, e di default la funzione di Blending è disabilitata.
60
Per poter cambiare i valori della trasparenza abilitiamo il blending, passando il flag GL_BLEND alla funzione
glEnable: glEnable(GL_BLEND); (per disabilitarla: glDisable(GL_BLEND);).
Verranno elencati una serie di esempi esplicativi, per mostrare le differenti combinazioni di trasparenze:
In figura A il colore descritto da (GL_ONE, GL_ZERO). Ciò fa sì che il colore destinazione non venga usato. In questo
caso ha importanza l’ordine con cui vengono disegnati gli oggetti.
In figura B si usa la combinazione (GL_ONE, GL_ONE). Fondamentalmente, viene preso il colore destinazione e il
colore sorgente e vengono sommati e il colore è quello risultante. Ad esempio, un misto di rosso e verde, formerà il
giallo e così via.
La figura C è una combinazione di (GL_ONE, GL_ONE_MINUS_DST_ALPHA). GL_ONE_MINUS_DST_ALPHA
dove si incorpora il valore di alpha del colore destinazione. Come si può notare, ciò crea un lieve miglioramento della
trasparenza, ma il giallo si mescola al verde rimanendo ancora giallo.
La figura D visualizza la combinazione (GL_SRC_ALPHA, GL_ONE), che crea una migliore forma di trasparenza. I
rettangoli ora appaiono tutti trasparenti. Il rettangolo giallo è più opaco perché ha un valore di alpha di 0.75. Il blu è
molto trasparente poiché ha un valore di alpha di 0.25.
5.4. JOGL OpenGL per Java
Al fine di imporre le caratteristiche multi-linguaggio e multi-piattaforma, vari bindings sono stati sviluppati per
OpenGL in molti linguaggi. Tra i più notevoli, la libreria Java 3D che può appoggiarsi su OpenGL per sfruttare
l'
accelerazione hardware. Molto recentemente, Sun ha rilasciato le versioni del sistema JOGL, che fornisce binding ai
comandi OpenGL in C.
Jogl supporta la maggior parte delle caratteristiche OpenGL e l’integrazione con le principali librerie grafiche di Java,
AWT e i set di componenti Swing, e fornisce inoltre un’API facile e malleabile per la gestione dei risultati associati alla
costruzione di applicazioni OpenGl multithreaded. Fornisce l’accesso alle ultime routines di OpenGL (OpenGL 2.0) e
ad alcune delle più comuni funzionalità introdotte da altre bindings di Java per OpenGL come GL4Java, LWJGL e
Magician.
Il binding di Jogl è quasi completamente inserito nel linguaggio di programmazione di Java. Alla base dei sorgenti di
Jogl vi sono approssimativamente 150 linee di codice C scritte in header files, il resto del codice nativo si autogenera
durante il processo di costruzione grazie a un nuovo strumento chiamato GlueGen, programmato specificatamente per
facilitare la creazione di JOGL.
Il design della struttura presenta vantaggi e svantaggi derivanti dalla traslazione dal linguaggio C, dove la natura
procedurale e il sistema di macchina a stati, erano sicuramente più consistenti. Trova invece miglioramento per quel che
concerne la velocità di conversione di esistenti applicazioni C in applicazioni Java. Inoltre, vista l’autogenerazione del
codice di Jogl, le modifiche apportate alle API OpenGL per il C, vengono aggiunte rapidamente alla libreria per Java.
61
In più Jogl sfrutta la caratteristica più famosa di Java, la portabilità, essendo un platform multi-piattaforma.
Usare OpenGL con Jogl è abbastanza semplice, e può essere brevemente presentato tenendo presente che è necessario
importare le classi appropriate, per poter utilizzare le funzionalità OpenGL.
•
Tutte le chiamate alle funzioni GL hanno il prefisso “gl.”.
•
Tutte le chiamate alle funzioni GL hanno il prefisso “glu.”.
•
Le costanti ed enumerazioni OpenGL hanno come prefisso “GL.”.
•
I tipi Java sono usati al posto di quelli OpenGL, così da richiedere o cast o tipi specifici.
Codice C
Codice Java
glBegin(GL_POLYGON);
gl.glBegin(GL.GL_POLYGON);
glVertex3f(0.25, 0.25, 0.0);
gl.glVertex3f(0.25f, 0.25f, 0.0f);
glVertex3f(0.75, 0.25, 0.0);
gl.glVertex3f(0.75f, 0.25f, 0.0f);
glVertex3f(0.75, 0.75, 0.0);
gl.glVertex3f(0.75f, 0.75f, 0.0f);
glVertex3f(0.25, 0.75, 0.0);
gl.glVertex3f(0.25f, 0.75f, 0.0f);
glEnd();
gl.glEnd();
Si nota come, nella versone Jogl, il tipo passato come argomento nella definizione dei vertici, venga ribadito
aggiungendo il suffisso “f” dopo ogni singolo valore. Questa accortezza è stat introdotta solo per gli argomenti di tipo
float, rendendo così più facile e veloce l’uso solamente di valori double:
gl.glBegin(GL.GL_POLYGON);
gl.glVertex3d(0.25, 0.25, 0.0);
gl.glVertex3d(0.75, 0.25, 0.0);
gl.glVertex3d(0.75, 0.75, 0.0);
gl.glVertex3d(0.25, 0.75, 0.0);
gl.glEnd();
Vi sono anche alcune differenze per quanto riguarda gli argomenti nelle strutture, in particolare nel passaggio degli
array alle funzione OpenGL. Per esempio, quando vengono usati i vettori per i vertici gl.glVertex3dv()o per i colorior
gl.glColor3dv(), si deve aggiungere un secondo argomento con valore zero:
double[] p = { 1.0, 1.0, 2.0 };
gl.glVertex3dv(p, 0);
Come si può notare, le cose in comune tra la versione OpenGL per C e Jogl per Java, sono notevoli, mentre le principali
differenze sono solo di natura sintattica e poco evidenti.
6. Personalizzazione Ambiente Tridimensionale
Tra i vari prodotti che la rivoluzione informatica ha prodotto negli ultimi anni, i Sistemi Informativi Geografici
(Geographic Information System, GIS), rappresentano una innovazione notevole nella gestione e nella produzione
cartografica. Questi sistemi, come abbiamo visto, si basano sulla fusione di due capisaldi dell'
innovazione informatica: i
sistemi di disegno computerizzato e i data base relazionali.
62
Il primo sistema ha permesso il disegno computerizzato delle entità geografiche, e il secondo l'
immagazzinamento dei
dati e delle informazioni legate a queste entità.
È facile constatare come l’applicazione sviluppata, non si discosti dalle basi su cui sono fondati i sistemi informativi
territoriali. La loro diffusione permette di analizzare una entità geografica, sia nella sua completa natura geometrica sia
nel suo totale contenuto informativo. Negli ultimi anni quasi tutta la cartografia geografica tradizionale, di ogni genere e
tipo, sta divenendo una cartografia geografica digitale, e in breve andrà a fare parte di sistemi informativi territoriali
che, attraverso i GIS, saranno in grado di produrre carte geografiche e tematiche per tutte le nostre esigenze e finalità.
Una tale rivoluzione ha portato un grande cambiamento nelle tradizionali applicazioni delle Scienze della Terra e del
territorio, che hanno sempre elaborato carte tematiche dettagliate sugli aspetti fisici dell'
ambiente.
Nel momento in cui la tecnologia del Telerilevamento è stata in grado di produrre una grande quantità di immagini
sempre più dettagliate della superficie terrestre, e i sistemi di archiviazione informatica sono stati in grado di gestire
queste immagini come qualunque altra informazione, si è sviluppato un insieme di nuovi approcci allo studio
dell'
ambiente fisico e del territorio, che sono alla base della Geomatica. Tutti gli impieghi integrati di informazioni
sull'
ambiente fisico, dai dati topografici tradizionali a quelli prodotti dal GPS, dai dati geologici e geomorfologici di
campagna, ai dati sulle falde freatiche sotterranee, dai dati sullo scorrimento delle acque superficiali ai dati sui
cambiamenti climatici, dai dati sulla attività sismica e vulcanica ai dati sul dissesto idrogeologico, etc., etc., sono oggi
gestiti ed elaborati attraverso i Sistemi Informativi Geografici.
L’applicazione sviluppata, trova in questo settore la sua perfetta collocazione, consentendo ad un qualunque utente la
visualizzazione del territorio e di produrre una notevole quantità di carte tematiche digitali e dati georeferenziati.
Il software è stato ideato come tecnologia Java Web Start, basato essenzialmente sulla possibilità di utilizzare
un’applicazione standalone “remota”, dando allo stesso tempo all’utente la possibilità di non dover sempre passare per
il browser web per poterla utilizzare. Essa consente inoltre di aggiornare in continuazione il software, senza rendere
necessaria una nuova installazione che molto spesso è pesante e difficoltosa.
La soluzione adottata unisce i vantaggi del download e l’utilizzo di applicazioni attraverso Internet (prerogativa sempre
molto utilizzata nella piattaforma Java, se si pensa alle applet), a quelli di avere un’applicazione “praticamente
standalone”, in modo che l’utente possa accedervi come a un qualunque altro programma che ha installato sulla propria
macchina.
L’applicazione è composta da due Frame principali. Il primo predisposto all’elencazione dei diversi tematisimi
applicabili sul territorio. La seconda è la finestra di visualizzazione del globo virtuale di Project Anna.
63
I due Frame principali
Le modifiche apportate all’ambiente Nasa World Wind, non hanno interessato solamente la parte di visualizzazione dei
dati georeferenziati, ma anche la parte di interazione uomo-macchina attraverso la modifica della GUI preposta per la
selezione dei tematismi.
Il codice di World Wind non è di facile ed immediata comprensione, tenendo conto anche della vastità dei sorgenti.
Quindi verranno discusse solamente le classi modificate per il progetto di tesi.
Momentaneamente si sta sviluppando l’applicazione come versione demo, e non ancora commerciale, per il Parco
Adamello Brenta. Questo giustifica l’uso di determinate icone, immagini di background e layout.
La classe tocManager2, invocata nella classe BasicDemo contenente il main e anche l’inizializzazione del Frame di
visualizzazione, è un’estensione di JFrame ed implementa parte della GUI dell’applicazione.
Alla classe tocManager2, vengono passati: una stringa per definire il titolo del Frame, e un oggetto di tipo
WorldWindGLCanvas. Questo oggetto è un’istanzia di un’estensione della classe GLCanvas che crea una sottofinestra,
gestita dalla libreria grafica, per il rendering di oggetti a più dimensioni.
Nell’applicazione WorldWindGLCanvas è la classe di visualizzazione del globo virtuale che invoca i metodi per un
corretto rendering: posizionamento, movimento, repainting e altre funzionalità di definizione dell’intero modello 3D.
Nella classe di gestione dei tematismi, la prima parte è solamente una pura definizione di alcune caratteristiche del
Frame, quali: definizione Layout, caricamento dell’icona per il Frame, settaggio dell’immagine di sfondo, e per finire la
creazione di un JPanel, trasparente, che andrà a contenere le voci per il menù dei tematismi.
Successivamente vengono recuperati dalla classe BasicDemo, attraverso le direttive per il collegamento al server,
definite nella classe Costanti, gli oggetti di tipo StreamingLayerProperties che identificano ogni singolo Layer per
rappresentare un determinato tematismo.
public class StreamingLayerProperties {
private String LayerName; //Name of the Layer
private boolean ShowAtStartup; //Visibility at StartUp of the Layer
private int levelnode; //Level in the TreeMenù for the GUI
private String ParentName; //The name of the Parent in the TreeMenù
64
I Layer sono dati vettoriali che vengono
public class CheckNodeTreeExample extends JPanel {
public CheckNodeTreeExample(List<StreamingLayerProperties> str) {
setOpaque(false);
rasterizzati attraverso il servizio offerto
dal server WMS, definendo una Texture
int temp_level_prev = 0;
String actual_level="";
che verrà mappata sul territorio una volta
CheckNode root=new CheckNode("PAB");//Set the Root Node
selezionato il tematismo.
//Set the Selection Mode and the Properties
In seguito viene definito un oggetto
root.setSelectionMode(CheckNode.SINGLE_SELECTION);
CheckNodeTreeExample al quale viene
root.setSelected(false);
//The List for the Parents
passata la lista dei Layer.
List<CheckNode> parentList = new ArrayList<CheckNode>();
Questa sarà la struttura che unisce le
parentList.add(root);
funzionalità di oggetti CheckBox su
//Loop on the Layers List
visualizzazione JTree. La selezione dei
for(StreamingLayerProperties s: str){
CheckBox può essere propagata ai figli
//New CheckNode
CheckNode nodeChild=new CheckNode(s.getLayerName());
attraverso l’apposito setting:
nodeChild.setSelectionMode(CheckNode.SINGLE_SELECTION);
SINGLE_SELECTION.
//The same Level of the Node do nothing
Un oggetto CheckNode è un oggetto che
if (temp_level_prev == s.getLevelnode()){}
//The Level of the Node is > getParentName and add the LayerName in the Parents List
estende la classe della libreria Swing
DefaultMutableTreeNode.
if (temp_level_prev < s.getLevelnode()){
String tempString ="";
Queste componenti sono formate da un
int buffer = 0;
normale
tempString = s.getParentName();
CheckBox
con
una
Label
buffer = tempString.lastIndexOf(",");
associata, e offrono tutti i metodi che
tempString = tempString.substring(0,buffer);
formalizzano la loro selezione da parte
buffer = tempString.lastIndexOf(",");
dell’utente, e possono essere associati,
if (buffer!=-1){
tempString = tempString.substring(buffer+1);}
come nodi, ad una struttua ad albero.
CheckNode parent=new CheckNode(tempString);
I nomi per le diverse voci del menù
parent.setSelectionMode(CheckNode.SINGLE_SELECTION);
vengono
parentList.get(parentList.size()-1).add(parent);
attraverso la lettura di ogni singolo Layer
parentList.add(parent);
generati
automaticamente
recuperando l’informazione sul livello di
actual_level = actual_level +"-";
profondità del nodo nella struttura ad
temp_level_prev = s.getLevelnode();}
//The Level of the Node is < getParentName and remove the LayerName from Parents List
if (temp_level_prev > s.getLevelnode()){
albero descritta in seguito.
Per poter ottimizzare al meglio questo
parentList.remove(parentList.size()-1);
actual_level = actual_level.substring(0,actual_level.lastIndexOf("-"));
automatismo ci si è serviti di un ulteriore
temp_level_prev = s.getLevelnode();}
lista per l’inserimento e/o rimozione dei
parentList.get(parentList.size()-1).add(nodeChild);}
nodi padre, dopo aver effettuato il check
//New JTree with some Properties
sul livello di profondità.
JTree tree = new JTree(root );
Gli items per la generazione dell’albero
tree.setOpaque(false);
tree.setBackground(null);
menù dei tematismi e la sua struttura
tree.setCellRenderer(new CheckRenderer()); //How render the Cell Layout
vengono generati anch’essi in maniera
tree.getSelectionModel().setSelectionMode
automatica, attraverso la lettura di un file
(TreeSelectionModel.SINGLE_TREE_SELECTION );
tree.putClientProperty("JTree.lineStyle", "Angled"); //How render the Tree Layout
tree.addMouseListener(new NodeSelectionListener(tree));
getContentPane().add(tree,BorderLayout.CENTER); }}
65
di configurazione scaricato dal server ad
ogni avvio dell’applicazione.
Anche per questa semplice parte di customizzazione dell’interfaccia si sono dovute prendere in considerazione diverse
classi, rendendo lo sviluppo un po’ più complicato del previsto.
<ChildLayerSet Name="Parent ONE" ShowAtStartup="false">
<QuadChildLayerSet Name="fiumi_C_F" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="aree_prod" ShowAtStartup="false">
</QuadChildLayerSet>
<ChildLayerSet Name="Parent TWO" ShowAtStartup="false">
<QuadChildLayerSet Name="usr_urb_boschi" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="usr_urb_agric_pregio" ShowAtStartup="false">
</QuadChildLayerSet>
</ChildLayerSet>
<QuadChildLayerSet Name="prguso_ins_sto" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="puppflu" ShowAtStartup="false">
</QuadChildLayerSet>
</ChildLayerSet>
<QuadChildLayerSet Name="ambsic05" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="paleoalvei" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="coll_funz" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="usr_urb_boschi,fiumi_C_F,ammprv,puppflu,coll_funz,ambsic05"
ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="grotte" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="viapri_viab_princ" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="parchi_nat_prov" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="parchi_naz" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="riserva_contr" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="riserva_guid" ShowAtStartup="false">
</QuadChildLayerSet>
<QuadChildLayerSet Name="riserva_integr" ShowAtStartup="false">
</QuadChildLayerSet>
Il file sopra riportato è un semplice file di testo, che adotta una forma a tag simile ai formati XML.
Grazie a questa sua caratteristica è facile ricostruire, anche solo visivamente, la struttura ad albero da esso codificata.
L’applicazione si interessa alla lettura del file attraverso il metodo ReadLayerRemoteFile() della classe principale
BasicDemo.
Attraverso le direttive della classe Costanti, il metodo si connette al server, recupera e prende in input il file Config.txt,
istanziando un oggetto di tipoi ArrayList che verrà utilizzato per contenere e fornire le diverse proprietà di tutti i Layer
derivanti dalla lettura del file.
66
while ( (line = dis.readLine ()) != null) {
La lettura avviene esattamente come
nel caso del parsing dei file GeoRSS,
if(line.contains("<ChildLayerSet")){ //If it’s a Node
childcount++;
sfruttando le funzioni sulle stringhe
String tempname=line.substring(line.indexOf("Name=\"")+6);
subString() e IndexOf().
int buffer =0;
buffer = (tempname.indexOf("\""));
Il file di configurazione è formato da
tempname=tempname.substring(0,buffer);
due
ParentName=ParentName + tempname + ",";} //Get the Name
<QuadChildLayerSet> con le relative
tag
<ChildLayerSet>
e
chiusure.
if(line.contains("</ChildLayerSet")){ //If the line include the tag to close
childcount--;
Il primo identifica un nodo padre,
int buffer =ParentName.lastIndexOf('
,'
);
mentre il secondo identifica una
ParentName=ParentName.substring(0,buffer);
foglia, ovvero un Layer con le
buffer =ParentName.lastIndexOf(",");
ParentName=ParentName.substring(0,buffer+1);} //Get the Name
relative proprietà che, a fine lettura,
vengono settate per mezzo delle
apposite
if(line.contains("<QuadChildLayerSet")){ //If it’s a Leaf
String tempname=line.substring(line.indexOf("Name=\"")+6);
funzioni
della
classe
StreamingLayerProperties.
int buffer =0;
Il risultato è una struttura, le cui voci
buffer = (tempname.indexOf("\""));
tempname=tempname.substring(0,buffer);
che la compongono vengono caricate
LayerProperties = new StreamingLayerProperties(); //New Object for the Properties
dinamicamente attraverso l’uso di un
//Set the Properties
file di configurazione remoto.
LayerProperties.setLayerName(tempname);
In questo modo l’applicazione potrà
LayerProperties.setLevelnode(childcount);
LayerProperties.setParentName(ParentName);
essere customizzata a piacere e
LayerProperties.setAbsnumber(absnumber);
completamente slegata dal codice
Layer.add(LayerProperties);}
sorgente.
if(line.contains("</QuadChildLayerSet")){} //Close tag for the Leaf
}
La modifica a livello di interfaccia grafica può essere fatta semplicemente modificando il file di configurazione, dando
la possibilità di averne più di uno, magari selezionando a piacere le voci da visualizzare e/o nascondere, in un
determinato istante.
Le modalità di selezione sono state customizzate in modo tale da far sì che che i Layer vengano attivati e visualizzati
solamente se tutti i loro nodi padre sono selezionati.
Questa parte è inserita nell’ascoltatore del click del mouse, NodeSelectionListener, all’interno del metodo
mouseClicked() che gestisce l’evento.
Il setting della modalità di selezione avviene scorrendo l’albero nei due versi, dalle foglie alla radice e viceversa,
controllando la selezione dei nodi padri e successivamente quali foglie debbano attivare il tematismo.
Nella prima colonna è riportato il codice che controlla l’albero dalle foglie alla root, invece il metodo scorrialbero() è la
funzione inversa, richiamata a fine primo controllo.
67
//Flag to know the Selection
private void scorrialbero(CheckNode node, boolean onoff) {
boolean isSelected = !(node.isSelected());
CheckNode check=new CheckNode();
//Click of the Mouse
//Two flags one for the Parent and one for the Children
if(e.getButton()==1||e.getButton()==2){
//Set Node Selection
boolean onoffparent=onoff;
boolean onoffchild;
node.setSelected(isSelected);
//Another flag
//Check if it’s a Leaf
if(node.getChildCount()!=0){
boolean onoff=isSelected;
//Loop ont the Children to know wich are selected
//New CheckNode to read each Node
for(int i=0;i<node.getChildCount();i++){
try{ CheckNode walker= null;
check=(CheckNode)node.getChildAt(i);
walker = (CheckNode) node.getParent();
onoffchild=check.isSelected;
//Set a New Value of the Flag
//Ricursive function until it has 0 Children
onoff=onoff&&walker.isSelected;
if(check.getChildCount()!=0){
//Check and Loop backward
scorrialbero(check,onoffparent&&onoffchild);}
if(walker.isSelected);
//Set the New Flag for the Leaf
while(walker!=null&&walker.isSelected){
else{ onoffchild=onoffparent&&onoffchild;
CheckNode parent=walker;
//Get Layers
walker=(CheckNode)parent.getParent();
LayerList layers =BasicDemo.m.getLayers();
onoff=onoff&&walker.isSelected;}
Layer layerToRemove = null;
} }catch(Exception exception){}
//Loop on the Layer
//In the Root call at method scorrialbero()
for (Layer layer : layers){
scorrialbero(node, onoff);
//Check the Name
//Than repaint the canvas
if (layer.getName().equals(check.toString())){
wwdtoc.repaint();
//Enable or Disable the Layer
…. }
layer.setEnabled(onoffchild);}}}}}
else{
LayerList layers =BasicDemo.m.getLayers();
Layer layerToRemove = null;
for (Layer layer : layers){
if (layer.getName().equals(node.toString())){
Layer.setEnabled(onoff);}
}}}
6.1. Gestione Trasparenze Tematismo
World Wind offre gratuitamente il dataset a bassa risoluzione Blue Marble, integrato nell’applicazione.
Su Blue Marble sono state inserite le ortofoto provinciali provenienti dal server WMS scaricate in automatico ad ogni
avvio dell’applicazione con il loro inserimento nella cache del computer.
In fase di sviluppo sono state utilizzate le ortofoto ortoretificate del volo sul trentino dell’anno 2000, fornite dalla
Compagnia Generale Ripreseaeree S.p.a, con risoluzione 1 pixel = 1 metro, facenti parte del progetto IT2000.
Su questa mappa territoriale ad alta risoluzione possono venire applicati i diversi Layer selezionati dall’utente.
La visualizzazione dei tematismi è la funzionalità principale dell’applicazione e la possibilità della loro trasparenza è
fondamentale.
Per utilizzare questa opportunità è stato implementato un Popup visualizzabile alla pressione del tasto destro del mouse
sui Layer selezionati dall’utente.
Sull’albero di visualizzazione del menù degli item per i tematismi, è stato implementato un ascoltatore
NodeSelectionListener che estende la classe MauseAdapter e che implementa la funzione mouseClicked per
l’esecuzione di determinate operazioni ad evento occorso.
68
In principio vengono istanziati gli
class NodeSelectionListener extends MouseAdapter {
//Definitions and new Instance
oggetti e le variabili che verranno
JTree tree;
utilizzati, in particolare: un JPanel, un
//The JPanel
JPanel pjs=new JPanel();
JSlider, una Label e un Popup.
//The JSlider
Per la creazione della finestra di Popup
JSlider js = new JSlider();
viene utilizzato un Design Pattern che
//The JLabel
offre una soluzione generica per un
JLabel jl=new JLabel();
//The Listener on the JSlider
problema ricorrente.
SliderListener cl=new SliderListener();
Nell’applicazione considerata, il punto
//The Popup and the Creation Pattern
fondamentale era risolvere problemi di
Popup popup;
PopupFactory factory = PopupFactory.getSharedInstance();
prestazioni,
causati
dalla
creazione di istanze della
…
medesima
classe per ogni evento occorso. Il
NodeSelectionListener(JTree tree) {
this.tree = tree;}
problema, in questo modo, viene risolto
appunto assicurandosi che sia creata
public void mouseClicked(MouseEvent e) {
una sola istanza di una determinata
//Timer to hide the Popup until a specific time
Timer
continua
classe. È stato quindi introdotto un
timer = new Timer();
TimerTask task = new MyTask();
pattern creazionale Singleton
…
con lo
scopo di permettere la creazione di una
TreePath path = tree.getPathForRow(row);
if (path != null) {
e una sola istanza di una data classe,
CheckNode node = (CheckNode)path.getLastPathComponent();
usato insieme ad un altro pattern
//Only if it’s a Leaf in the Tree
creazionale
if(node.isLeaf()){
//Check on the Node Selection and on the Source of the Event
if(node.isSelected && e.getButton()==3){
chiamato
Factory.
Quest'
ultimo descrive le modalità di
creazione attuali di un oggetto da parte
di specifiche classi.
if(flag==false){
//The JLabel Properties
jl.setText("Transparency: "+path.getLastPathComponent());
//The JSlider Properties
La classe PopupFactory può creare
oggetti Popup chiamando il metodo
js.setMajorTickSpacing(20);
getSharedInstance() di PopupFactory.
js.setPaintLabels(true);
in seguito si crea un oggetto Popup
js.setPaintTicks(true);
chiamando il metodo getPopup() della
js.setOpaque(false);
factory, passando come parametri il
js.setValue(50);
js.addChangeListener(cl); //Add the Listener
componente genitore, i suoi contenuti,
//The JPanel Properties
e le coordinate.
pjs.setLayout(new FlowLayout());
Come nel caso dell’aggiornamento
pjs.setBorder(border);
delle
//Add the Objects into JPanel
JTable
nell’applicazione
del
pjs.add(jl);
database, anche in questo caso si è
pjs.add(js);
implementata una funzione per la
//Creation of the Popup
scomparsa automatica del Popup dopo
popup = factory.getPopup(tree, pjs,150, 100);
popup.show();
alle classi Timer e TimerTask per
flag=true;
timer.schedule( task, 10000 );
un lasso di tempo prestabilito grazie
}….
69
gestire thread di esecuzione.
class SliderListener implements ChangeListener {
Il Popup è composto da un JPanel che funge da
Container per i due componenti, JSlider e
public void stateChanged(ChangeEvent e) {
//Find the right item in the JTree
JLabel.
int row = tree.getRowForLocation(x, y);
Quest’ultimo visualizza il nome del tematismo
TreePath path = tree.getPathForRow(row);
CheckNode node = (CheckNode)path.getLastPathComponent();
selezionato, mentre lo slider offre la possibilità
//Get the Layers
all’utente di manipolare la trasparenza del
LayerList layers =BasicDemo.m.getLayers();
Layer.
for (Layer layer : layers)
L’ascoltatore
{
sullo
slider
implementa
la
//Check wich Layer
funzione stateChange che recupera i valori della
if (layer.getName().equals(node.toString())){
barra numerica, attraverso l’assegnazione alla
//Get the Value
variabile opacity di un determinato valore che in
double opacity=js.getValue()/200.0;
termini di Blending rappresenterà il fattore
//Set the Opacity
layer.setOpacity(opacity); }
alpha. Successivamente, opacity, viene passata
}
al
//Repaint the Canvas
Layer
attraverso
l’apposita
funzione
setOpacity.
wwdtoc.repaint();
Come ultima operazione viene eseguita una
}
repaint() dell’intera Canvas.
}
Il check if (layer.getName().equals(node.toString())) è utilizzato per far in modo che le proprietà di trasparenza vengano
settate solamente al Layer selezionato.
Menù ad albero e popup trasparenza
La problematica della trasparenza ha richiesto un notevole
sforzo implementativo e di ricerca, in quanto si sono
riscontrati problemi per quel che concerne il classico uso
della funzione di Blending.
Nella prima fase di sviluppo di Project Anna si è cercato di
adattare la tecnica del Blending, vista in precedenza, alle
Texture utilizzate dall’applicativo NASA.
Quest’ultime
vengono
richieste
al
server
mediante
l’utilizzo di apposite coordinate che vengono calcolate
utilizzando la tecnica di Tile.
Ovvero, il mondo, identificato come un oggetto sferico, viene suddiviso in sezione quadrate denominate Tiles secondo
lo schema sottostante.
70
Tecnica del Tiling
Su ogni sezione vengono applicate, attraverso l’uso della tecnica del Mipmapping vista nel capitolo precendente, le
Texture più idonee alle dimensioni della Tile. L’applicazione della Texture può avvenire grazie al sistema di assi
cartesiani ridefinito per ogni Tile, con l’origine posta nell’angolo in basso a sinistra.
La possibilità dello Zoom, su una determinata zona terrestre, implica un ricodificamento della grandezza delle Tile e
quindi dei propri assi, così da ottenere una visualizzazione delle Texture sempre ottimale, sfruttando anche i filtri già
descritti.
Questa tecnica viene utilizzata anche per quel che concerne il caricamento e mappatura dei Layer. Un volta che i dati
vettoriali vengono rasterizzati, i Layer possono essere considerati delle vere e proprie Texture da applicare alle diverse
Tile.
La classe dedicata a questo è la classe TiledImageLayer.
La classe viene richiamata più volte nell’intero progetto, essendo una delle classi fondamentali e più complesse
diell’intero sistema World Wind.
Al suo interno sono presenti numerose funzioni applicabili sia a Tile che a Texture, sia per la fase di caricamento, di
posizionamento e di rappresentazione delle Texture Layer sulle Tile.
Il metodo principale sul quale si sono apportate le modifiche per poter usufruire della caratteristica della trasparenza è
stato il metodo draw().
71
La prima parte del metodo è dedicata ai check per
private void draw(DrawContext dc)
{
controllare alcune proprietà di visualizzazione dei
// Clean up any unused textures while within a OpenGL context thread.
Layer, quali: la loro abilitazione, attivazione e
TextureTile.disposeTextures();
visibilità. Attraverso il metodo assembleTile(),
//Check on the Layer.
richiamato sulla classe stessa, si determina la
if (!this.isEnabled())
return; // Don'
t check for arg errors if we'
re disabled
Texture da rappresentare e viene inserita in un
if (!this.isLayerActive(dc))
vettore per il riordino al momento del caricamento
return;
di altri tematismi.
if (!this.isLayerInView(dc))
Successivamente vengono applicate le funzionalità
return;
this.referencePoint = this.computeReferencePoint(dc);
di Jogl, con la chiamata gl.glPushAttrib().
// Determine the tiles to draw.
Il check sul valore ricavato
this.assembleTiles(dc);
dalla chiamata al
if (this.currentTiles.size() >= 1)
metodo isUseTransparentTextures(), informa il
{
sistema se sul determinato Layer è possibile o
// New Texture and sort the Vector.
meno applicare la trasparenza.
TextureTile[] sortedTiles = new TextureTile[this.currentTiles.size()];
sortedTiles = this.currentTiles.toArray(sortedTiles);
In seguito, dopo l’aggiunta di ulteriori attributi per
la rappresentazione, è stata implementata la parte
Arrays.sort(sortedTiles, levelComparer);
riguardante la trasparenza.
// Load the Command Stack.
GL gl = dc.getGL();
gl.glEnable(GL.GL_TEXTURE_2D)
//Push the Attributes in the Stack.
gl.glPushAttrib(GL.GL_COLOR_BUFFER_BIT | GL.GL_POLYGON_BIT);
// Check on the Transparency of the Layer.
abilita la
visualizzazione delle Texture 2D.
gl.glColor4d(1d, 1d, 1d, .1d) applica il colore
bianco come filtro per attuare l’effetto trasparenza.
if (this.isUseTransparentTextures()){
//Push the Attributes in the Stack.
gl.glEnable(GL.GL_BLEND) abilita la funzionalità
gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT
di Blending.
| GL.GL_COLOR_BUFFER_BIT
| GL.GL_ENABLE_BIT
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_
| GL.GL_TEXTURE_BIT
ONE_MINUS_SRC_ALPHA) applica il filtro come
| GL.GL_TRANSFORM_BIT
visto nell’apposita sezione.
| GL.GL_VIEWPORT_BIT
Sono stati effettuati diversi tentativi per stabilire
| GL.GL_CURRENT_BIT);
quali combinazioni, tra colore sorgente e colore di
// BLENDING.
gl.glEnable(GL.GL_TEXTURE_2D);
destinazione, fossero le migliori per lo sviluppo.
gl.glColor4d(1d, 1d, 1d, 1d);
Due sono state quelle più idonee, ognuna delle
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glDisable(GL.GL_DEPTH_TEST);
quali comprendente ovviamente il fattore alpha:
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_
ONE_MINUS_SRC_ALPHA) e gl.glBlendFunc(
//END BLENDING.
}
GL.GL_DST_ALPHA, GL.GL_ONE_MINUS_
// Polygon Properties.
SRC_ALPHA).
gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
gl.glEnable(GL.GL_CULL_FACE);
Dopo aver settato la trasparenza,
gl.glCullFace(GL.GL_BACK);
prevede il settaggio di alcune proprietà riferite al
//Render of the Tile.
il metodo
poligono e viene inizializzata la fase di rendering.
dc.getSurfaceTileRenderer().renderTiles(dc, this.currentTiles, this);
….
}
4
72
Oltre al classico metodo per il settaggio della trasparenza, mediante l’utilizzo della funzione di Blending, si è fatta una
ricerca su un altro metodo per ottenere lo stesso effetto.
Dopo diverse ricerche si è potuto notare come l’utilizzo della luminanza, come attributo delle Texture poteva fornire un
buon punto di partenza per il raggiungimento di un risultato del tutto analogo.
La luminanza è definita come il rapporto tra l'
intensità luminosa emessa da una sorgente verso una superficie
perpendicolare alla direzione del flusso e all'
area della superficie stessa.
Il problema principale incontrato in questa fase è stato quello dell’individuazione del livello, dove attuare la modifica.
Il metodo setOpacity() era già definito, ma la sua invocazione non influenzava la visualizzazione. Il motivo è stato
riscontrato nel fatto che il valore settato non veniva mai passato alla funzione dedicata al processo di renderizzazione e
pertanto il Layer non cambiava la sua caratteristica di trasparenza.
Alcuni Layer, come BMNGSurfaceLayer, CountryBoundariesLayer, USGS e quelli caricati dal server di GraphiTech
sono basati sulla classe BasicTiledImageLayer che estende la classe, in parte descritta, TiledImageLayer. Quest’ultima,
attraverso la chiamata dc.getSurfaceTileRenderer().renderTiles(dc, this.currentTiles, this), utilizza la classe
SurfaceTileRender alla quale è stata apporta la più significativa modifica, dando la possbilità di trasparenza a qualsiasi
Texture.
public void renderTiles(DrawContext dc, Iterable tiles, AbstractLayer layer) {
Nel metodo di render public void
//It’s too long to report the complete function
renderTiles() sono state aggiunte le
...
righe per il settaggio del valore
if (!dc.isPickingMode()) {
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_REPLACE);
della
luminanza,
attraverso
il
} else {
settaggio del Texture Environment.
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_COMBINE);
Il Texture Environment permette
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_SRC0_RGB, GL.GL_PREVIOUS);
di
gl.glTexEnvf(GL.GL_TEXTURE_ENV, GL.GL_COMBINE_RGB, GL.GL_REPLACE);
}
specificare
come
si
vuole
combinare il colore della Texture
if(layer!=null){
con il colore corrente del pixel di
// Set Luminance
destinazione,
gl.glTexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, GL.GL_MODULATE);
modifiche ai valori RGB e al valore
gl.glColor4f(1, 1, 1, (float)layer.getOpacity());
apportando
delle
alpha.
}
...
La funzione che interessa questa
// To not affect other Calls we must Overload the method
caratteristica è:
public void renderTiles(DrawContext dc, Iterable tiles) {
void glTexEnvf( GLenum target,
this.renderTiles(dc, tiles, null);
GLenum pname, const GLfloat
}
param );
dove, target deve essere GL_TEXTURE_ENV, se pname è GL_TEXTURE_ENV_MODE, param deve specificare una
Texture Function che per default è definita dalla costante GL.GL_MODULATE.
GL_MODULATE modula i valori del colore dei frammenti e il valore alpha attraverso i valori della Texture.
La necessità di poter scegliere una determinata trasparenza da parte dell’utente del client è emersa, a seguito della
richiesta di poter verificare e validare la corretta posizione dei Layer tematici sovrapposti all’ortofoto nell’ambiente
tridimensionale, e la possibilità di ricreare determinati fotomontaggi con i diversi tematismi.
73
6.2. Gestione Informazioni GeoRSS
La gestione delle informazioni GeoRSS avviene importando il file
XML con l’apposita funzionalità inserita nella GUI.
Molte funzionalità dell’interfaccia non sono state descritte perché
appartenenti all’ambito del progetto di tesi.
Una volta ricercato il file attraverso un JFilechooser e importato
per mezzo del JButton “Import”, esso viene preso in input
dall’applicazione e successivamente letto. La classe che gestisce
la scelta del file e la sua lettura è la classe ImportVectorialData.
Frame di Import
Dopo la prima parte adibita all’inizializazione
public static List<Renderable> parseShapes(Document xmlDoc)
dei componenti di iterazione con l’utente, nella
{ ….
ArrayList<Node> shapeNodes = new ArrayList<Node>();
seconda viene creato, dal file selezionato, un
ArrayList<Node> attributeNodes = new ArrayList<Node>();
oggetto di tipo Document e successivamente
// Shapes
nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "polygon");
if (nodes != null && nodes.getLength() > 0)
semplicemente validato con un DOM parser.
Il parser, vero e proprio, per il recupero e
utilizzo dei dati georeferenziati è il metodo
addNodes(shapeNodes, nodes);
….
parseShapes() della classe GeoRSSParser, al
// Attributes
nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "elev");
if (nodes != null && nodes.getLength() > 0)
quale viene passato il Document poco prima
istanziato. Scorrendo il file, attua la lettura di
ogni
addNodes(attributeNodes, nodes);
….
singolo
tag
attraverso
il
metodo
getElementsByTagNameNS(); controlla il suo
//GT Attributes
nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "color");
if (nodes != null && nodes.getLength() > 0)
valore e se diverso da null lo inserisce
nell’ArrayList
appositamente
creato
in
precedenza per le shape.
addNodes(attributeNodes, nodes);
nodes = xmlDoc.getElementsByTagNameNS(GEORSS_URI, "transparency");
if (nodes != null && nodes.getLength() > 0)
Lo stesso metodo viene utilizzato anche per gli
attributi;
addNodes(attributeNodes, nodes);
l’unica
variazione
risiede
....
nell’ArrayList di destinazione.
//Loop and Calls at the right Functions
Successivamente si è implementato un loop su
for (Node node : shapeNodes){
ogni singolo elemento della lista contenente le
Renderable shape = null;
shape.
String localName = node.getLocalName();
Ad
if (localName.equals("point"))
ciclo,
attraverso
il
metodo
getLocalName(), viene recuperato il nominativo
shape = makePointShape(node, attributeNodes);
else if (localName.equals("line"))
del nodo, il quale sarà la caratteristica
shape = makeLineShape(node, attributeNodes);
necessaria per la chiamata alla funzione corretta.
else if (localName.equals("polygon"))
In queste funzioni vengono calcolate e attribuite
shape = makePolygonShape(node, attributeNodes);
alcune caratteristiche della shape.
else if (localName.equals("box"))
shape = makeBoxShape(node, attributeNodes);
Viene
if (shape != null)
shapes.add(shape);
ogni
riportato
solamente
il
metodo
makePolygonShape(), ma il funzionamento è
}
del tutto simili anche per le altre geometrie.
return shapes; }….
74
Inizialmente viene recuperata, attraverso apposite chiamate a funzioni, la posizione in latitudine e longitudine dei vertici
della figura. Successivamente vengono assegnati i valori agli attributi.
Come si può notare l’assegnazione avviene attraverso un preventivo check sull’attributo e la successiva chiamata alla
rispettiva funzione per ottenere il valore.
private static Renderable makePolygonShape(Node node,
//Get the Colors
Iterable<Node> attrs)
private static Color getColor(Node shapeNode, Iterable<Node> attrs) {
{ ….
Color color=Color.WHITE; //Default Color
ArrayList<LatLon> positions = new ArrayList<LatLon>();
Node colorNode = findSiblingAttribute("color", attrs, shapeNode);
for (int i = 0; i < values.size(); i += 2)
if (colorNode != null) //Get the Node for the Color and its check
{ positions.add(LatLon.fromDegrees(values.get(i), values.get(i + 1))); }
//Attributes
{ ArrayList<Double> colors =
getDoubleValues(colorNode.getTextContent()); //Get the Values
double elevation = attrs != null ? getElevation(node, attrs) : 0d;
if (colors != null && colors.size() > 0)
float transparency = attrs != null ? getTrans(node, attrs) : 0f;
{ //Istanziate the New Color with the new Values
Color c = attrs != null ? getColor(node, attrs) : null;
color = new Color(
//Set the Color
Double.valueOf(colors.get(0)).floatValue()/255,
Color v=new
Double.valueOf(colors.get(1)).floatValue()/255,
Color(c.getRed()/255,c.getGreen()/255,c.getBlue()/255,transparency);
Double.valueOf(colors.get(2)).floatValue()/255);
if (elevation != 0)
} else { //Error message
{ //if it’s not mapped on the terrain
String message = WorldWind.retrieveErrMsg(
Polyline pl = new Polyline(positions, elevation);
"GeoRSS.MissingElementContent") + "color";
pl.setColor(v);
WorldWind.logger().log(java.util.logging.Level.FINE, message); } }
pl.setFilled(true);
return color;
pl.setFollowGreatCircles(true);
}
return pl;
} else //Mapped on the terrain
//Get the Transparency
{ return new SurfacePolygon(positions,v);
private static float getTrans(Node shapeNode, Iterable<Node> attrs)
}
{float trans = 1.0f; //Default Transparency
} //And so on for the other Shapes…
Node transNode = findSiblingAttribute(
"transparency", attrs, shapeNode); //Get the Node for the Transparency
if (transNode != null) // Check on the Node
{ArrayList<Double> transparency = //Get the Values
getDoubleValues(transNode.getTextContent());
if (transparency != null && transparency.size() > 0)
//Istanziate the New Transarency with the new Values
{ trans=Double.valueOf(transparency.get(0)).floatValue()/100;
} else { //Error message
String message = WorldWind.retrieveErrMsg(
"GeoRSS.MissingElementContent") + "transparency";
WorldWind.logger().log(java.util.logging.Level.FINE, message); } }
return trans;
}}
I due metodi implementati sono quelli per il riconoscimento degli attributi colore e trasparenza e riportati nella seconda
colonna. Essi recuperano i valori da utilizzare attraverso la funzione già implementata getDoubleValues(), dopo avere
recuperato il nodo con l’apposito metodo findSiblingAttribute(), e semplicemente istanziano un nuovo oggetto che sarà
il valore di ritorno per la funzione precedente.
La classe Color permette ovviamente la sua l’istanziazione in diversi modi e con diversi parametri.
Uno di questi, è la classica e più volte discussa in questa tesi, codifica RGBA.
75
Quindi il nuovo oggetto, che descrive tutte le nuove caratteristiche introdotte, verrà creato attraverso la seguente
chiamata con quattro parametri: Color v=new Color(c.getRed()/255,c.getGreen()/255,c.getBlue()/255,transparency);
Per la rappresentazione della geometria, ci si appoggia a due classi distinte a seconda se deve essere mappate sul terreno
o meno. Questo sistema è, ovviamente, dovuto alll’irregolarità del territorio.
La classe Polyline si occupa della rappresentazione della figura ad una determinata altezza dal suolo, prendendo in input
il valore di questo attributo e le coordinate per il posizionamento.
Viene creato un oggetto di tipo Position per ogni vertice, avente le caratteristiche di latitudine, longitudine e elevazione
ed inserito in un ArrayList. Dopo la fase di inizializzazione vengono creati e posizionati i vertici della figura tenendo
conto della sfericità del globo terrestre attraverso due metodi makeGreatCircleVertices() e makeVertices(), e solo
successivamente la shape viene renderizzata attraverso l’apposita funzione di render() sotto riportata.
public void render(DrawContext dc){
…. //Inizialize tvertices
if (this.vertices == null)
{ this.intializeGeometry(dc);
if (this.vertices == null)
return; }
// Load the Command Stack. And the Attributes
GL gl = dc.getGL();
int attrBits = GL.GL_HINT_BIT | GL.GL_CURRENT_BIT;
if (!dc.isPickingMode())
{ attrBits += GL.GL_CURRENT_BIT;
if (this.color.getAlpha() != 255)
attrBits += GL.GL_COLOR_BUFFER_BIT; }
gl.glPushAttrib(attrBits);
gl.glPushClientAttrib(GL.GL_CLIENT_VERTEX_ARRAY_BIT);
dc.getView().pushReferenceCenter(dc, this.referenceCenter);
try //Blending of the Shape
{ if (!dc.isPickingMode()) {
if (this.color.getAlpha() != 255) {
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA,
GL.GL_ONE_MINUS_SRC_ALPHA);}
//Get Colors
dc.getGL().glColor4ub((byte) this.color.getRed(),
(byte) this.color.getGreen(), (byte) this.color.getBlue(),
(byte) this.color.getAlpha()); }
//Properties to Draw the Shape
int hintAttr = GL.GL_LINE_SMOOTH_HINT;
if (this.filled)
hintAttr = GL.GL_POLYGON_SMOOTH_HINT;
gl.glHint(hintAttr, this.antiAliasHint);
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, GL.GL_DOUBLE, 0, this.vertices.rewind());
int primType = GL.GL_LINE_STRIP;
if (this.filled)
primType = GL.GL_POLYGON;
//Draw
gl.glDrawArrays(primType, 0, this.vertices.capacity() / 3);
} finally { //Remove Attributes from Stack
gl.glPopClientAttrib();
gl.glPopAttrib();
dc.getView().popReferenceCenter(dc);
} }
76
La classe SurfacePolygon estende la classe, più generale, SurfaceShape e disegna la figura “spalmata” sul terreno.
SurfacePolygon calcola i valori delle coordinate dei vertici per il posizionamento e attraverso il costruttore richiama
SurfaceShape che crea un’immagine 2D della figura che verrà usata come Texture da applicare sulla Tile del territorio.
public abstract class SurfaceShape implements Renderable, Disposable
{
public SurfaceShape(Iterable<LatLon> positions, Color color, Color borderColor)
{ ….
//Create the New Texture from the position of the Vertices
private void createTextureTiles(Sector sector)
{ this.tile = new TextureTile(sector); }
//Get the Texture Size
public int getTextureSize()
{ return textureSize; }
//Set the Texture Size
public void setTextureSize(int textureSize)
{ this.textureSize = textureSize;
this.getTextureTile().setTextureData(null);
}
….
//Function to Draw
public void render(DrawContext dc)
{
….
GL gl = dc.getGL();// Load the Command Stack. And the Attributes
gl.glPushAttrib(GL.GL_COLOR_BUFFER_BIT | GL.GL_POLYGON_BIT);
try //Blending of the Shape
{ if (!dc.isPickingMode()) {
gl.glEnable(GL.GL_BLEND);
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
} //Properties to Draw the Shape
gl.glPolygonMode(GL.GL_FRONT, GL.GL_FILL);
gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK);
//Draw
dc.getSurfaceTileRenderer().renderTile(dc, this.tile);
} finally
{
//Remove Attributes from Stack
gl.glPopAttrib(); } }
private TextureData makeTextureData(int size)
{ //Create the Image to use as Texture
BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_4BYTE_ABGR);
TextureData td = new TextureData(GL.GL_RGBA, GL.GL_RGBA, false, this.drawShape(image));
td.setMustFlipVertically(false);
return td;
}
}
Le due classi si comportano in maniera diversa anche rispetto al passaggio del valore del nuovo oggetto Color. La
classe Polyline implementa il metodo apposito setColor(), mentre la classe SurfacePolygon accetta direttamente il
valore passato attraverso il costruttore.
77
Ai metodi per la creazione delle geometrie e la loro visualizzazione non sono state apportate modifiche.
Dopo un’analisi delle diverse funzionalità implementate per la creazione delle shape sul territorio, si è notato che queste
caratteristiche erano già state previste e la customizzazione è stata più rapida.
7. Conclusioni
7.1. Campi d’Impiego
I campi d’impiego dell’applicazione e le problematiche a cui un GIS può essere di supporto:
•
In tutti i settori in cui l’impiego della cartografia geografica o topografica (settori militari, industriali,
amministrativi etc.) risulta strategico: come la gestione dei fondi per la difesa di uno stato, che andranno ad
esempio indirizzati verso le regioni di confine; nella scelta su dove collocare nuove cliniche e ospedali,
fondamentale per i responsabili del settore sanitario; oppure nella scelta, altrettanto fondamentale per una società di
trasporti, dei percorsi da seguire per effettuare le proprie consegne.
•
In tutti i settori di impiego e sviluppo della cartografia geotematica, geologica, geomorfologia, idrogeologica, delle
risorse, forestale, ambientale. Una compagnia forestale, ad esempio, deve sapere dove piantare o tagliare degli
alberi e deve conoscere strade e sentieri per accedervi; un servizio geologico deve conoscere la distribuzione di
frane, sorgenti, cave, etc..
•
In tutti i settori di pianificazione territoriale: un ente pubblico che gestisce il territorio impiega GIS per la redazione
e lo sviluppo dei piani urbanistici (piani regolatori, piani territoriali di coordinamento o piani strutturali); un turista
o chiunque si trovi a effettuare un viaggio deve fare delle scelte sul luogo in cui recarsi, su come recarvisi e sul
posto in cui eventualmente alloggiare.
Il sistema, essendo ancora in fase di sviluppo, ha una notevole possibilità di diffusione d’impiego, ma i due settori di
spicco, in cui questo progetto esprime al meglio le sue potenzialità sono il settore turistico e quello ambientale.
•
Turismo
L’utente interagendo con l’applicazione, può pianificare comodamente da casa propria, luoghi da visitare e definire
itinerari e percorsi.
L’utente è facilitato nell’utilizzo anche grazie ad una GUI user-friendly facilmente personalizzabile e accessibile.
Come accennato in precedenza, l’applicazione dà la possibilità all’utente di:
−
Selezionare e visitare scenari all’interno della scena 3D.
−
Effettuare una ricerca tra i vari punti d’interesse, mantenendo così solamente le informazioni
desiderate.
−
Interrogare monumenti, edifici o aree naturalistiche di particolare interesse per ottenere
maggiori informazioni.
•
Raccolta dati territoriali
L’applicazione permette innanzitutto di dare una visione globale di un territorio dal punto di vista geografico.
In questo ambito possono essere sviluppate funzionalità legate allo studio del territorio, studio dei fenomeni atmosferici
e climatici in diverse zone e visualizzazione degli impatti ambientali di possibili infrastrutture.
È quindi possibile costruire un sistema di raccolta dati.
78
Questi dati possono essere immagazzinati (per un’analisi futura) o istantaneamente georeferenziati e trasmessi ad un
elaboratore con lo scopo di visualizzare istantaneamente le informazioni. Tale soluzione dovrebbe portare ad un sistema
di monitoraggio ambientale molto più semplice, sia dal punto realizzativo, sia da quello dell’interpretazione dei dati,
attraverso una soluzione allo stesso tempo economica e versatile.
7.2. Possibili Sviluppi
Il progetto, come già detto, è in fase di crescita, non è uno strumento verticale e proprio grazie a questa sua peculiarità,
le funzioni implementabili e gli aggiornamenti varieranno a seconda dell’ambito in cui si vorrà inserire l’applicazione.
Grazie ad un modello di programmazione orientata agli oggetti, è possibile implementare tali aggiornamenti in modo
funzionale, e inoltre permettere di gestire efficientemente il livello di personalizzazione del software, che può essere
quindi modificato al fine di soddisfare molteplici problematiche.
Pertanto il progetto non vuole essere un’applicazione pronta al mercato, ma una base su cui poter aggiungere nuove
funzionalità.
Come risultato di un lavoro di tesi, il progetto presenta ancora limiti legati all’implementazione: come già evidenziato il
parsing dei file GeoRSS può sicuramente essere migliorato, adottando un metodo di lettura migliore, in grado di poter
prendere in input qualsiasi tipo di file con caratteristiche simili a quelle proposte, ma molto più generalizzato.
Le funzionalità di trasparenza possono essere riviste, utilizzando un vero e proprio Blending sulle Texture, e anche il
Layout della GUI può essere rivisitato per consentire un accesso all’utente più user-frindly.
Ci sono inoltre ancora alcuni aspetti da migliorare per quel che concerne le funzionalità proposte, come ad esempio
l’opportunità non ancora implementata, della ricezione di dati geospaziali in tempo reale. Sfruttando le funzionalità GIS
dell’applicazione, attraverso un dispositivo GPS sarà possibile creare un sistema di tracking volto alla localizzazione di
oggetti, persone o autoveicoli. Questa funzionalità risulterà particolarmente interessante in quanto gli oggetti saranno
inseriti direttamente nell’ambiente tridimensionale, fornendo all’utente diverse informazioni a seconda dell’utilizzo,
quali: traffico, incidenti, soccorso alpino, localizzazione veicoli ecc…
Inoltre, la ricezione di dati sensoriali del territorio possono essere istantaneamente georeferenziati e trasmessi ad un
elaboratore con lo scopo di visualizzare istantaneamente le informazioni come: precipitazioni, temperatura,
inquinamento ecc... Tale soluzione dovrebbe portare ad un sistema di monitoraggio ambientale molto più semplice sia
dal punto realizzativo sia da quello dell’interpretazione dei dati, attraverso una soluzione allo stesso tempo economica e
versatile.
Inoltre, la creazione di un database più ampio che conservi località, percorsi e tour georeferenziati sarebbe di sicuro uno
sviluppo importante per quest’applicazione, oltre alla possibilità di estenderla fuori dai confini regionali.
Quello che è stato presentato in questo progetto di tesi, è la base per partire con lo sviluppo di un pacchetto applicativo,
con l’obiettivo principale per un’organizzazione di dati complessi georeferenziati che possa essere di aiuto all’uomo
come sistema di diffusione e visualizzazione di informazioni territoriali.
79
8. ScreenShots
Immagine di Blue Marble a bassa Risoluzione
Ortofoto dell’intero territorio Provinciale
80
IRST - Zoom ad alta risoluzione
Riva del Garda visualizzazione 3D
81
Tematismi selezionati: boschi, corsi d’acqua, confini e zone di interesse comunale
Modifica della trasparenza dei tematismi sopra selezionati
82
Tematismi selezionati: fiumi e aree agricole di pregio
Modifica della trasparenza mettendo in evidenza il tematismo delle aree agricole di pregio
83
Visione 3D dei Tematismi applicati al territorio
Modifica alla trasparenza del tematismo in 3D
84
Shapes importate da file GeoRSS con colori e trasparenze diverse
Shape “spalmata” sul terreno
85
Due Shapes, la rossa al suolo e la verde elevata
Shape elevata che interseca il territorio
86
9. Bibliografia
Feed RSS – GeoRSS
http://georss.org
http://webdesign.html.it/articoli/leggi/188/introduzione-a-rss/1
http://it.wikipedia.org/wiki/Really_simple_syndication
http://www.directionsmag.com/article.php?article_id=2197&trv=1
https://portal.opengeospatial.org/files/?artifact_id=6716
OGC White Paper “An Introduction to GeoRSS: A Standard Based Approch for Geo-enabling RSS feed
Jogl
https://jogl.dev.java.net
http://www.cs.umd.edu/~meesh/kmconroy/JOGLTutorial
http://ak.kiet.le.googlepages.com/theredbookinjava.html
http://jerome.jouvie.free.fr/OpenGl/Tutorials
http://jcp.org/en/jsr/detail?id=231
http://www.felixgers.de/teaching/jogl/index.html
Learning Java Bindings for OpenGL
A Beginner s Guide and Tutorial
OpenGL
http://openskills.info/infobox.php?ID=899
http://www.vhn.itabc.cnr.it/Oss_OpenGL.htm
http://www.disi.unige.it/person/MagilloP/DISPENSE_IG/opengl01.html
http://www.wmlscript.it/opengles/corso_19.php
http://nehe.gamedev.net/data/articles/article.asp?article=20
The Official Guide to Learning OpenGL, Version 1.1 (Addison-Wesley, 1997 second Edition)
GIS
http://www.disat.unimib.it/VAST/lezioni/file%20pdf/introduzione%20ai%20GIS.pdf
World Wind
http://www.worldwindcentral.com/wiki/
http://www.worldwindcentral.com/wiki/Transparency%2C_multi-layer
http://www.worldwindcentral.com/wiki/Google_Earth_comparison
http://www.p2pforum.it/forum/showthread.php?t=45282
http://theballoonproject.blogspot.com/
87
PostgreSQL - PostGIS
http://forum.html.it/forum/forumdisplay.php?forumid=79
http://www.megaoverclock.it/POSTGISUNO.html
http://jdbc.postgresql.org
Parser
http://www.javaportal.it/bv/jip.dll/portal/ep/contentView.do?contentType=EDITORIAL&contentId=24731
http://www.siforge.org/articles/2003/09/30-usare-xml.html
http://en.wikipedia.org/wiki/Simple_API_for_XML
http://forum.html.it/forum/showthread.php?threadid=364093
https://rome.dev.java.net/
88