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