Conversie van GML naar SVG Een methode om GML documenten snel en eenvoudig om te zetten naar SVG.
Afstudeerscriptie van Ronald van den Berg S1376837 Maart 2005 Rijksuniversiteit Groningen Informatiekunde Scriptiebegeleider: Dr. E.A. Koster Tweede lezer: Dr. E.H. Klein
Inhoudsopgave VOORWOORD............................................................................................................................................................ 2 1.
INLEIDING ........................................................................................................................................................ 3
2.
GML .................................................................................................................................................................... 6 2.1 2.2 2.3 2.5
3.
SVG.................................................................................................................................................................... 16 3.1 3.2 3.3 3.4 3.4.1 3.4.2 3.5
4.
WAT IS SVG? ............................................................................................................................................ 16 VECTOR PLAATJES ..................................................................................................................................... 17 EXTRA MOGELIJKHEDEN SVG ................................................................................................................... 18 BASISOBJECTEN EN DE OPBOUW VAN EEN SVG DOCUMENT ...................................................................... 19 De opbouw van een SVG document ..................................................................................................... 19 Basiselementen SVG............................................................................................................................. 20 LAYERS...................................................................................................................................................... 24
HET CONVERSIEPROGRAMMA ............................................................................................................... 26 4.1 4.2 4.3 4.4 4.5
5.
WAT IS GML? ............................................................................................................................................. 6 FEATURES .................................................................................................................................................... 6 XML SCHEMA ............................................................................................................................................. 7 BASIS GEOMETRISCHE ELEMENTEN ............................................................................................................ 10
INLEIDING .................................................................................................................................................. 26 DE INVOER EN HET OP DE SERVER PLAATSEN VAN HET GML DOCUMENT .................................................. 27 BEWERKINGEN OP HET GML DOCUMENT .................................................................................................. 28 GEGEVENS FILTEREN UIT HET GML DOCUMENT ........................................................................................ 31 EXTRA FEATURES ...................................................................................................................................... 34
PROBLEMEN .................................................................................................................................................. 38 5.1 5.2
OPGELOSTE PROBLEMEN............................................................................................................................ 38 NIET OPGELOSTE PROBLEMEN.................................................................................................................... 43
6.
CONCLUSIE EN AANBEVELINGEN.......................................................................................................... 44
7.
LITERATUURLIJST ...................................................................................................................................... 47
8.
BIJLAGEN........................................................................................................................................................ 49 8.1 8.2
HET CGI BESTAND ...................................................................................................................................... 49 XSLT BESTANDEN ..................................................................................................................................... 55
1
Voorwoord Bij mijn zoektocht naar een geschikt onderwerp voor mijn scriptie kwam ik, dankzij de hulp van mijn scriptie begeleider, de heer Koster, bij mijn huidige onderzoeksonderwerp. Na maanden werken aan een literatuurstudie en het daadwerkelijke onderzoek is het resultaat dan daar. Ik wil de volgende personen bedanken voor hun hulp aan dit onderzoek: y Mijn scriptiebegeleider, Dr. E.A. Koster, voor het lezen, corrigeren en de verdere hulp bij het onderzoek; y De tweede lezer van mijn scriptie, Dr. E.H. Klein. Ronald van den Berg Zwolle, 13 februari 2005
2
1.
Inleiding
Duizenden jaren voor Christus maakten mensen al gebruik van geografische kaarten, rond 2500 voor Christus maakten de Babyloniërs kaarten op kleitabletten. Eeuwenlang moesten cartografen geografische informatie opslaan in de vorm van geografische kaarten om zodoende een goed beeld te krijgen van de omgeving of om bij een volgende keer niet te verdwalen. De enige andere methode die men had kunnen gebruiken voor de opslag van geografische gegevens was het opslaan van de objecten als tekst op papier. Sinds het tijdperk van de computer en met name het toenemend gebruik van het internet, in de jaren 90, is er, ook voor cartografen, veel verandert. Nieuwe webtalen werden ontwikkeld en het kon niet uitblijven, ook op geografisch terrein werd er geautomatiseerd. Cartografen hebben tegenwoordig de beschikking over het speciaal voor de opslag van geografische objecten ontwikkelde GML (Geography Markup Language). GML beschrijft de echte wereld, volgens Guo1, in termen van geografische entiteiten welke features genoemd worden. Daarnaast heeft men de beschikking over SVG (Scalable Vector Graphics), een XML (EXtensible Markup Language) variant waarmee objecten grafisch, als kaarten, kunnen worden weergegeven. Het voordeel van XML bestanden is dat het wijzigbare tekstbestanden zijn en daarnaast verschaffen zij een platform onafhankelijk formaat, voor het uitwisselen van informatie tussen heterogene systemen, via het internet (Zaslavsky2). Het opslaan van geografische gegevens in GML biedt cartografen voordelen, het gaat sneller, het kan beter worden bewaard en de bestanden zijn eenvoudig uit te wisselen. GML heeft, zoals Bonati, Fortunati en Fresta3 aangeven, een eigen structuur om ruimtelijke data mee te associëren en om deze te combineren met andere datatypen, zoals XML. Naast deze voordelen zit er ook een groot nadeel aan deze opslagmethode, alle gegevens die worden opgeslagen in een GML document worden als tekst opgeslagen. Een huis bijvoorbeeld, is een object dat op een bepaalde locatie staat. Het huis heeft een diepte en een breedte (alles is 2 dimensionaal dus de hoogte wordt niet opgeslagen) en er behoort een bepaalde omschrijving bij het huis. Op het moment dat iemand wil weten waar het huis precies staat zal deze persoon het GML document moeten openen, de inhoud van het document verschijnt vervolgens in de vorm van een XML document en men moet zoeken naar de gegevens van het desbetreffende huis. Wat deze gebruiker zal vinden zijn de coördinaten van het huis en eventueel wat extra gegevens. Wat de locatie van het huis is ten opzichte van andere objecten in de omgeving, en hoe groot het huis is ten opzichte van deze andere objecten is niet duidelijk. GML heeft niet de mogelijkheid om de geografische objecten grafisch weer te geven en dat is erg jammer aangezien vooral cartografen zich toch bezig houden met de grafische kant van geografische objecten. In SVG kunnen objecten, in tegenstelling tot in GML, wel grafisch worden weergegeven. Het probleem is alleen dat deze twee webtalen, ondanks het feit dat beide talen XML varianten zijn, weinig met elkaar van doen hebben. De opzet van een GML document is significant anders dan de opbouw van SVG documenten. Het zou ideaal zijn als de inhoud van GML documenten eenvoudig omgezet zou 1
Guo, e.a., 162. Zaslavsky, 3. 3 Bonati,e.a., 4. 2
3
kunnen worden naar SVG. In deze scriptie wordt onderzocht of dit mogelijk is. De algemene onderzoeksvraag luidt daarom als volgt: Hoe kan een GML bestand, bestaande uit elementen, eenvoudig en zonder extra aanpassingen worden omgezet naar een SVG bestand? De primaire doelgroep die baat heeft bij de resultaten uit dit onderzoek bestaat onder andere uit cartografen die gebruik maken van GML documenten en deze documenten ook wel eens (willen) omzetten naar de SVG variant. Naast de cartografen zijn er diverse beroepsgroepen die gebruik maken van GML documenten en voor wie het nuttig zou zijn als de documenten kunnen worden omgezet naar SVG. Historici die gegevens van oude kaarten hebben ingevoerd in GML documenten kunnen deze gegevens om laten zetten naar SVG om zodoende de SVG kaart te vergelijken met de originele versie van de kaart. Voor degenen die voor zakelijk of privé-gebruik GML documenten schrijven, en niet tot de primaire doelgroep behoort, is dit onderzoek vanzelfsprekend ook een prima methode om de gegevens uit de GML documenten eens als SVG kaart te aanschouwen. Voor de conversie van GML naar SVG wordt in deze scriptie gebruik gemaakt van een XSLT (eXtensible Stylesheet Language Transformation) bestand. Een XSLT bestand is een onderdeel van XML. De reden voor het gebruik van XSLT voor het omzetten van GML naar SVG is dat met een XSLT onderdelen uit een XML document kunnen worden geselecteerd en kunnen worden weggeschreven in een ander document, eventueel een XML document, of zoals Meynert4 aangeeft: “XSLT is het natuurlijke conversiemiddel voor GML en SVG”. Omdat beide talen XML talen zijn kunnen gegevens door middel van een XLST uit het GML bestand worden gehaald en kunnen deze, bewerkt, als SVG weer in een nieuw bestand worden geplaatst. De algemene XML taal is een taal die gebruik maakt van door de gebruiker zelf ontworpen elementen zoals bijvoorbeeld het begin- en eindelement. XML lijkt wat dat betreft wel wat op
Figuur 1: Begin- en eindelementen
HTML (HyperText Markup Language ) maar met dat verschil dat er binnen HTML geen gebruik gemaakt mag worden van door deze gebruiker zelf ontworpen elementen. Binnen deze elementen kan informatie worden opgeslagen, en deze informatie kan op het moment dat een XML bestand wordt aangeroepen in de browser worden getoond. Stel dat in een XML document de naam, het adres en de woonplaats van diverse personen worden opgeslagen. Door middel van een XSLT bestand kunnen deze persoonsgegevens in de browser worden getoond. Een XSLT bestand kan XML documenten omzetten naar HTML documenten. In dit geval kan er worden bepaald dat de inhoud van alle Persoon elementen wordt omgezet naar bijvoorbeeld Naam: inhoud van het element Persoon gevolgd door een return(nieuwe regel). De 4
Meynert, 3.
4
gebruiker zal in zijn browser nu in plaats van alle tekst uit het XML document een HTML document zien bestaande uit een lijst van personen. Voor het converteren van GML naar SVG zal deze constructie ook worden toegepast. Elementen uit een GML document worden omgezet naar de SVG variant van deze elementen. De gebruiker ziet na de conversie een SVG document met daarin een plaatje / kaart van het GML document dat is ingevoerd. Het programma dat ontwikkeld is om GML bestanden te converteren naar SVG bestanden leest een door de gebruiker ingegeven GML document in om deze vervolgens te bewerken. Het conversieprogramma is online beschikbaar zodat er geen ingewikkelde installatieprocedure aan vooraf hoeft te gaan. Eenvoud is een belangrijk aspect van het systeem, gebruikers moeten, met enkel een basiskennis van het gebruik van het internet, de procedure kunnen doorlopen. Deze basiskennis bestaat uit het openen van webpagina´s en het kunnen omgaan met webformulieren. Het ingegeven GML document wordt online opgeslagen zodat de bewerkingen op het document eenvoudig en snel kunnen worden uitgevoerd. Als het gaat om een goed GML document, bestaande uit standaard GML elementen, dan zal een XSLT bestand op zoek gaan naar deze elementen om deze vervolgens als SVG variant weer op te slaan in een nieuw aangemaakt SVG document. De gebruiker krijgt het nieuw aangemaakte SVG document in de browser te zien maar kan het bestand tevens op de eigen computer opslaan zodat het GML document niet steeds hoeft te worden geconverteerd. De op de eigen computer opgeslagen SVG documenten kunnen door middel van een gratis SVG browser lokaal worden bekeken. Deze scriptie is als volgt opgebouwd, in hoofdstuk twee wordt een verdere uitleg gegeven over wat GML precies is, hoe het functioneert en wat de voor- en nadelen van deze XML variant zijn. Het derde hoofdstuk geeft een nadere uitleg van SVG, wat de mogelijkheden zijn van SVG en wat vector graphics zijn. In het vierde hoofdstuk worden de gebruikte programmeertalen nader toegelicht. In hoofdstuk vijf en zes wordt het daadwerkelijke onderzoek gepresenteerd, wat zijn de ontwerpbeslissingen, hoe functioneert het programma en welke eventuele problemen zijn aan het licht gekomen tijdens het onderzoek. Tot slot wordt er in de laatste hoofdstukken gekeken naar de toekomst en volgt de conclusie waarin antwoord wordt gegeven op de onderzoeksvraag.
5
2.
GML
2.1
Wat is GML?
GML, een XML variant, is een webtaal speciaal ontwikkeld door het Open GIS Consortium (OGC)5 voor de opslag, het transport en de weergave van geografische objecten. In mei 2000 is de eerste versie van GML gepubliceerd door het OGC, inmiddels is in februari 2004 versie 3.1 geïntroduceerd. In een GML document kunnen gegevens worden opgeslagen die de echte wereld als objecten omschrijven6, dit kan variëren van gedetailleerde gegevens van een huis met achtertuin tot een minder gedetailleerde versie die de oppervlakte van een geheel land omschrijft. Het is bijvoorbeeld mogelijk om alle objecten in het centrum van Zwolle door middel van tekst in een GML document op te slaan zodat het document een zeer gedetailleerde omschrijving van het centrum bevat. Alle gebouwen kunnen als gesloten figuren worden opgeslagen met daarbij de juiste lengte en breedte en een juiste omschrijving van het desbetreffende gebouw. Straten en kanalen kunnen met de juiste locatie en de juiste lengte en richting en omschrijving worden opgeslagen, zelfs relatief kleine objecten als bomen kunnen met hun locaties en namen in een GML document worden opgeslagen. In dit hoofdstuk worden een aantal fundamentele onderdelen van de GML taal uitgelegd om zodoende een goed beeld te krijgen van de mogelijkheden van GML.
2.2
Features
Een object heet binnen een GML document een feature. Een feature is volgens de opengis GML 3.1 specificaties7 een abstracte weergave van een verschijnsel uit de echte wereld: iets is een geografische feature als er een associatie gemaakt kan worden met een locatie op de wereld. Zoals men in de specificaties verder aangeeft: een digitale representatie van de wereld kan worden gezien als een verzameling features. De specificaties van een feature worden bepaald door een set eigenschappen, bij eigenschappen kan worden gedacht worden aan {naam, type, waarde}. Hoeveel eigenschappen een feature mag bevatten wordt bepaald door de type definitie van deze feature. De type definitie van een feature wordt omschreven in een XML Schema, zie § 2.3. De features kunnen ook vallen in een feature groep, deze feature groep heeft van zichzelf ook weer een naam en een type en een eigen type definitie die bepaald in welke volgorde de features die vallen onder deze groep aan bod mogen komen. Er is door het OGC een verschil gemaakt tussen de soorten features, er zijn de zogenaamde simpele features en niet simpele features. De simpele features zijn features waarbij het coördinatiesysteem uitgaat van een 2 dimensionale weergave van de werkelijkheid. Nadeel van deze simpele features is dat simpele features bij een eventuele conversie alleen vector data 5
http://www.opengeospatial.org Guo, e.a., 162. 7 http://portal.opengis.org/files/?artifact_id=4700 6
6
ondersteunen. Verder is het niet mogelijk om een perfecte weergave van de werkelijkheid te geven aangezien het geen hoogte weer kan geven. In de laatste GML versie 3.1 kan er gebruik gemaakt worden van een coördinatiesysteem dat een 3 dimensionale weergave van de werkelijkheid kan geven.
Figuur 2: Model van simpele features8
2.3
XML Schema
Als er geen regels zouden zijn voor het opmaken van een XML documenten zou er geen structuur in XML documenten zitten en zouden deze onbruikbaar zijn voor andere gebruikers die gegevens uit een XML document willen opvragen, zij weten immers niet waar deze gegevens zouden moeten staan. Juist voor een duidelijke structuur in de XML bestanden is XML Schema ontwikkeld. XML Schema is eigenlijk de opvolger van de, in veel XML bestanden gebruikte, DTD (Document Type Definition). Het OCG heeft drie vaste Schema’s gebouwd voor de opbouw van GML documenten. Ten eerste is er het Geometry schema (geometry.xsd) waarin alle standaard geografische elementen staan die gebruikt mogen worden in een GML document. Daarnaast is er een schema waarin alle feature verzamelingen staan (feature.xsd) en tot slot is er een schema waarin XLink attributen staan (xlinks.xsd), om linkjes mogelijk te maken. In het GML document staat, als er gebruik gemaakt wordt van deze schema’s, een verwijzing naar het te gebruiken schema. Een schema wordt als volgt aangeroepen: xmlns:gml='http://www.opengis.net/gml', in dit geval wordt er aangegeven dat het geometry.xsd schema in het GML document gebruikt dient te worden. Xmlns geeft aan dat het om een schema gaat en gml is de te gebruiken namespace. Een namespace is een unieke naam waarmee aangegeven wordt uit welk schema het gebruikte element afkomstig is. Als er in dit geval een element wordt gebruikt uit het geometry schema dan moet er voor de naam van het 8
Cox, S., e.a., 6.
7
element gml: worden geplaatst
wordt . Als dit niet gebeurt is tijdens het opvragen van het GML document niet duidelijk uit welk schema het desbetreffende element afkomstig is en of het element wel gebruikt mag worden, het document zal dan ook worden afgekeurd. In het volgende gedeelte worden de mogelijkheden van een XML Schema behandeld aan de hand van het geometry Schema. W3schools9 geeft aan dat in een XML Schema de volgende punten worden bepaald: Het definiëren van de elementen die mogen voorkomen in een GML document. <element name="Box" type="gml:BoxType" /> Voorbeeld 1: Element met de naam Box
De naam van het te gebruiken element is Box en het type is in dit geval een gml:BoxType. In het GML document mag de gebruiker een element met de naam Box gebruiken als deze voldoet aan de eisen van het type BoxType.
Het definiëren van het soort data dat elk afzonderlijk element of attribuut mag bevatten. Het soort data wordt aangegeven door het attribuut type. In het vorige voorbeeld moest het element Box van het type BoxType zijn, dit type wordt verderop in hetzelfde Schema omschreven. <documentation>The Box structure defines an extent using a pair of coordinate tuples. <extension base="gml:AbstractGeometryType"> <sequence> <element ref="gml:coord" minOccurs="2" maxOccurs="2" /> <element ref="gml:coordinates" />
Voorbeeld 2: Omschrijving waaraan het type BoxType moet voldoen.
9
Het definiëren van de attributen die mogen voorkomen in een GML document. Voorbeeld 2 maakt duidelijk dat het type BoxType aangeeft dat het element Box of het attribuut gml:coord of het attribuut gml:coordinates moet bevatten. Wat de
http://www.w3schools.com/schema/schema_intro.asp
8
voorwaarden zijn voor het gebruik van gml:coord en gml:coordinates staat ook in het Schema omschreven.
Het definiëren van de volgorde waarin deze subelementen voor mogen komen. Voorbeeld 2 geeft tevens aan dat er een volgorde zit in het gebruik van de attributen. Deze volgorde wordt aangegeven door het gebruik van sequence. <sequence> <element ref…..
Het definiëren van elementen die weer een onderdeel zijn van een ander element (subelementen). In voorbeeld 2 staan de elementen gml:coord en gml:coordinates binnen het type BoxType en het type BoxType is weer een onderdeel van het element Box. Zowel gml:coord als gml:coordinates is daardoor een subelement van het element Box.
Het definiëren van het aantal subelementen. Bij het element gml:coord in voorbeeld 2 staan de attributen Max- en minOccurs, deze attributen geven aan hoevaak het desbetreffende element voor mag komen. Binnen het element Box mag het subelement gml:coord maximaal twee keer en minimaal twee keer voorkomen, kortom het element gml:coord moet twee keer voorkomen binnen het element Box..
Het definiëren van het feit of een element leeg is of dat een element tekst mag bevatten. Als het om een leeg element gaat dan wordt er een restriction in het element opgenomen. <documentation> This abstract base type for geometry collections just makes the srsName attribute mandatory.
Voorbeeld 3: Het gebruik van restriction
In voorbeeld 3 is AbstractGeometryCollectionBaseType een leeg element met voorwaarden welke worden afgeleid van AbstractGeometryType.
Het definiëren van eventuele vaste waarden en vooraf ingevulde waarden van elementen en attributen.
9
Tot slot is er nog de mogelijkheid om een vaste waarde te laten weergegeven, dit is mogelijk door het gebruik van de value=”…”.
2.5
Basis geometrische elementen
Binnen de door de OGC opgestelde schema’s zijn een aantal basis geometrische elementen voorgedefinieerd. Deze voorgedefinieerde elementen en eigenschappen worden in drie verschillende levels weergegeven, te weten de formele namen, de beschrijvende namen en de applicatie specifieke namen. De formele en de beschrijvende namen komen voor in het Feature schema om de standaard geometrische eigenschappen te benoemen, bijvoorbeeld multiGeometryProperty. Geometrie Type (basiselementen) Point LineString LinearRing Polygon Box MultiGeometry MultiPoint MultiLineString MultiPolygon coord coordinates
Beschrijvende naam
Formele naam
Location, centerOf, position edgeOf, centerLineOf
pointProperty lineStringProperty
extentOf,coverage
polygonProperty boundedBy multiGeometryProperty multiPointProperty
multiLocation, multiCenterOf, multiPosition multiCenterLineOf, multiEdgeOf multiCoverage, multiExtentOf
multiLineStringProperty multiPolygonProperty
Tabel 1: Basis Geometrische eigenschappen10
Hoe de basiselementen in het schema omschreven zijn wordt verder in dit onderdeel behandeld. Binnen alle basiselementen wordt gebruik gemaakt van of het element coord of coordinates daarom is het van belang dat ook deze elementen omschreven worden. In GML gelden vaste regels voor het gebruik van hoofd- en kleine letters bij het gebruik van elementen en attributen. Als een element verwijst naar een type binnen GML dan mag er gebruik gemaakt worden van een elementnaam die begint met een hoofdletter. Als het gaat om een eigenschap dan moet er gebruik gemaakt worden van een kleine letter. De woorden die zijn opgesloten binnen een naam van een eigenschap worden ook geschreven met een hoofdletter, bijvoorbeeld multiLocation. Alle basiselementen worden in een voorbeeld weergegeven om zodoende een beeld te scheppen van de mogelijkheden binnen de GML taal. In het voorbeeld wordt een onderdeel van de stad Zwolle door middel van deze elementen beschreven. 10
Cox, S., e.a., 10.
10
In GML documenten wordt gebruik gemaakt van verschillende soorten elementen om coördinaten weer te geven. Het element gml:coordinates bevat coördinaten die als één grote string met X- en Y waarden achter elkaar geplakt zijn. 10,10 20,10 20,20 10,20 10,10 Het coördinatensysteem dat meestal gebruikt wordt in deze situatie is het systeem waarbij de coördinaten van een object op wereldniveau wordt bepaald door middel van een bepaald aantal graden in latitude en longitude11. Daarnaast is het element coord en deze heeft als subelementen X en Y. In deze subelementen staan waarden voor X en voor Y. <X>1020 Het coördinatensysteem dat gebruikt wordt bij een Box is het systeem van een X- en een Y-as, de relatieve afstanden tussen objecten worden door middel van de X- en Y-as weergegeven. Bij het gebruik van de algemene elementen wordt, om de positie van het object te kunnen bepalen, gebruik gemaakt van de elementen coord of coordinates. Als het gaat om een coördinatiesysteem bestaande uit een X- en een Y-as dan wordt coord gebruikt en in alle andere gevallen wordt coordinates gebruikt. Het coördinatiesysteem dat wordt gebruikt in het voorbeeld is geen officieel coördinatiesysteem. Box De Box, ofwel de rechthoek kan goed worden gebruikt om de buitenste grenzen van het gebied aan te geven dat wordt gebruikt in dit voorbeeld. Alle elementen die worden gebruikt zullen qua coördinaten binnen het vierkant vallen.
→ Figuur 3 en 4: Gedeelte van Zwolle dat wordt omgezet naar GML
Het schema geeft aan dat een Box zowel coord als coordinates mag gebruiken. Bij gebruik van coord moeten er minimaal en maximaal twee X en twee Y waarden worden opgegeven. Dit is logisch aangezien een rechthoek kan worden gecreëerd door de opgave van slechts twee punten, de linker onderhoek en de rechter bovenhoek.
11
Jones, 61-62
11
<sequence> <element ref="gml:coord" minOccurs="2" maxOccurs="2" /> <element ref="gml:coordinates" />
Het gedeelte van Zwolle dat gebruikt wordt in dit voorbeeld valt tussen de coördinaten 28,22 en 48,42, de X waarden mogen dus nooit kleiner zijn dan 28 en ze mogen nooit groter zijn dan 48 en de Y waarden mogen nooit kleiner zijn dan 22 en nooit groter zijn dan 42. <X>28 22 <X>48 42
LineString en MultiLineString Een stad bestaat uit straten met daaraan gelegen gebouwen, deze straten kunnen worden omschreven door middel van het LineString element omdat met dit element rechte lijnen worden gecreëerd. In het schema wordt dan ook aangegeven dat er tenminste twee punten moeten worden ingegeven omdat er anders geen sprake is van een lijn maar van een punt. Het maakt ook bij het LineString element niet uit of de coördinaten worden ingegeven door middel van coord of door coordinates. <sequence> <element ref="gml:coord" minOccurs="2" maxOccurs="unbounded" /> <element ref="gml:coordinates" />
In figuur 5 zijn drie straten aangegeven die worden omgezet naar GML. Bij gebruik van het LineString element kan er echter maar één lijn worden opgegeven, om meerdere lijnen op te kunnen geven moet het MultiLineString element worden gebruikt. Het MultiLineString element bestaat uit een verzameling van LineString elementen. Straat 3 wordt beschreven met het LineString element en de straten 1 en 2 zijn beschreven door het MuiltiLineString element.
Figuur 5: Drie straten die als LineString worden weergegeven
12
28,28 48,32
Straat nummer drie start op het punt X=28 en Y=28 en eindigt op het punt X=48 en Y=32. In het Schema wordt aangegeven dat een MultiLineString kan bestaan uit een onbepaald aantal lineStringMembers en binnen deze lineStringMembers wordt weer het element LineString gebruikt. <sequence> <element name="lineStringMember" maxOccurs="unbounded"> <sequence> <element ref="gml:LineString" />
De straat met het nummer één loopt van het punt X=28 en Y=28 tot aan het punt X=36 en Y=42. In het coordinates element worden de getallen, in dit geval, zonder decimalen achter de komma opgegeven, het is echter ook mogelijk om getallen met decimalen te gebruiken. Decimalen staan altijd achter een punt, bijvoorbeeld 38.95. <MultiLineString> 28,28 36,42 36,42 48,32
Point Rechtsboven in de plattegrond is een stukje groen te zien, dit stukje groen bestaat uit diverse planten en bomen die door middel van het point element kunnen worden aangegeven. In dit voorbeeld wordt uitgegaan van een reeks van drie bomen die op rij aan de rand van straat 2 staan. Het schema geeft aan dat de coördinaten van een point kunnen worden aangegeven door of het coord of het coordinates element. <sequence> <element ref="gml:coord" /> <element ref="gml:coordinates" />
13
Bij gebruik van het point element kan er maar één point worden ingegeven, daarom moet ook hier weer gebruik gemaakt worden van een element die een verzameling punten kan bevatten, in dit geval het MultiPoint element. Binnen dit MultiPoint element kan het element Point meerdere keren worden opgenomen. <MultiPoint> <pointMember> <X>4240 <pointMember> <X>4438 <pointMember> <X>4736
Polygon Wat vanzelfsprekend niet mag ontbreken zijn de diverse gebrouwen die langs de straten zijn gebouwd. Aangezien het hier om een woonwijk draait moeten er blokken van huizen worden ingegeven. Het is niet praktisch om deze huizenblokken door middel van het LineString element in te voeren daarom is er het polygon element. In het Schema staat aangegeven dat een polygon element bestaat uit een outerBoundaryIs element en eventuele innerBoundaryIs elementen. <sequence> <element name="outerBoundaryIs"> <sequence> <element ref="gml:LinearRing" /> <element name="innerBoundaryIs" minOccurs="0" maxOccurs="unbounded"> <sequence> <element ref="gml:LinearRing" />
Het outerBoundaryIs element bevat een LinearRing (dit is een lijn bestaande uit tenminste vier punten waarvan de laatste coördinaten gelijk moeten zijn aan de eerste coördinaten zodat het een gesloten geheel vormt), met daarin coord elementen of één coordinates element, en is de buitenste ring van de polygoon. De eventuele innerBoundaryIs elementen bestaan uit een LinearRing met daarin meerdere coord elementen of één coordinates element en deze innerBoundaryIs elementen mogen elkaar niet overlappen. Voor de creatie van een blok huizen is het polygon element goed geschikt aangezien ieder apart huis als een polygoon kan worden beschouwd.
14
33,31 44,33 44,34 33,32 33,31 33,31 37,31 37,32 33,32 33,31 37,31 40,32 40,33 37,32 37,31 40,32 44,33 44,34 40,33 40,32
Het element outerBoundaryIs geeft nu de totale omvang van het blok huizen weer, de drie innerBoundaryIs elementen omschrijven elk een apart huis. Mochten er meerdere polygonen gebruikt moeten worden dan kan ook nu weer gebruik worden gemaakt van een element dat meerdere polygon elementen kan bevatten, in dit geval het MultiPolygon element. Tot slot is er nog de mogelijkheid om een verzameling van verschillende soorten elementen in één verzamelelement, het MultiGeometry element, onder te brengen. Dit kan handig zijn bij bijvoorbeeld een deur aangezien deze bestaat uit een rechthoek (polygon), het deurkozijn (LineStrings) en een deurknop (Point). Het kan natuurlijk voorkomen dat de standaard schema’s van het OGC onvoldoende mogelijkheden bieden voor het invoeren van geografische objecten in een GML document. De oplossing is elementen in een door de gebruiker gemaakt schema toevoegen. Voor het maken van deze GML schema’s zijn echter een aantal regels opgesteld zie § 2.3. y De features die gecreëerd zijn in het nieuwe schema moeten zijn afgeleid van de al bestaande types uit de standaard schema’s. y Een nieuw schema mag geen naam, definitie of datatype van een standaard GML element veranderen. y De abstracte data definities mogen vrij worden uitgebreid of beperkt. y Het schema moet vrij toegankelijk zijn voor iedereen die gebruik wil maken van dat schema. y Het nieuwe schema moet een namespace hebben die anders is dan de gml: namespace.
15
3.
SVG
3.1
Wat is SVG?
SVG is een XML taal waarin gegevens kunnen worden opgeslagen die, door middel van een plug-in in de webbrowser, als vector plaatje kunnen worden getoond. Net als GML is SVG tekst gebaseerd maar met dit verschil dat de gegevens van een SVG bestand wel als plaatje kunnen worden getoond. De eerste officiële versie van SVG, versie 1.0, werd geïntroduceerd in september 2001 door het World Wide Web Consortium (W3C)12. W3C is tevens de ontwikkelaar van SVG. W3C is de organisatie die bepaald welke “web” talen worden geaccepteerd op het internet, denk daarbij bijvoorbeeld aan HTML, XML of PHP. Doordat W3C zelf de ontwikkelaar is van SVG is de kans groot dat SVG in de toekomst een grote rol gaat spelen op het web. De laatste officiële versie is versie 1.1 en deze kreeg een W3C aanbeveling op 14 januari 2003. Momenteel is men bezig met versie 1.213, deze versie is alleen nog maar als “draft” versie aanwezig en is dus nog niet officieel erkend door het W3C. Omdat SVG een variant van XML is kan het relatief eenvoudig worden gebruikt of worden omgezet naar andere soorten XML documenten. Wat maakt SVG nou zo speciaal dat W3C zich bezig houdt met de ontwikkeling van deze taal, er zijn immers genoeg alternatieven voor de weergaven van grafische figuren. Een groot voordeel van SVG ten opzichte van andere formaten, zoals jpg, gif en png, is ten eerste dat het gaat om vectorplaatjes. Een vectorplaatje is over het algemeen kleiner, voor wat betreft de benodigde opslagcapaciteit, dan een plaatje in rasterformaat (jpg, gif en png), dit komt door de gebruikte opslagmethode (zie verder § 3.2). Ten tweede hoeven de SVG plaatjes niet per definitie statisch te zijn maar kan er net als in de bestandsformaten gif, png en swf (Macromedia Flash) gebruik worden gemaakt van animaties. Een verschil met het formaat gif en png is wel dat de animaties binnen SVG, net zoals in Flash, interactief kunnen worden gemaakt, dit vergroot de gebruikersmogelijkheden van SVG aanzienlijk. De mogelijkheden die Flash biedt worden over het algemeen ook aangeboden door SVG. De grote verschillen tussen een programma als Flash en SVG is het feit dat Flash een commercieel product is dat moet worden aangeschaft voordat het kan worden gebruikt, SVG is een XML taal waar geen speciaal programma voor moet worden aangeschaft en is dus gratis. Daarnaast is het Flash opslagformaat FLA (het formaat waarin wijzigingen in het bestand kunnen worden aangebracht) alleen te lezen in het programma Flash, de codes worden omgezet naar binary code. De code van een SVG document kan overal en door iedereen worden geraadpleegd omdat de broncode niet direct wordt omgezet in machinetaal maar wordt weergegeven in normaal leesbare ASCII tekens. Een SVG document kan door andere gebruikers worden ingelezen, bewerkt en in een ander bestand worden opgeslagen. Tot slot heeft SVG als voordeel, omdat SVG tekst gebaseerd is, dat het doorzoekbaar is. In een SVG document dat een kaart van Zwolle weergeeft kan onder andere gezocht worden op de straatnamen die op de kaart voorkomen. Eigenlijk is het heel logisch dat in de code, van
12 13
http://www.w3.org Jackson, D., http://www.w3.org/TR/SVG12/
16
bijvoorbeeld een plaatje van een huis, staat dat het om een huis gaat, dit is echter een eigenschap van SVG die bij andere grafische formaten niet voorkomt.
3.2
Vector plaatjes
De gegevens van een SVG document worden als vectorplaatjes in de webbrowser weergegeven. Er zijn twee algemeen geaccepteerde formaten waarin plaatjes kunnen worden opgeslagen, één het vectorformaat en twee het rasterformaat. Een vectorplaatje bestaat uit punten en lijnen die geometrisch en wiskundig met elkaar verbonden zijn. De plaats van een punt wordt door middel van coördinaten aangegeven (X,Y) en een lijn wordt bepaald door een reeks van punten met hun coördinaten (X1,Y1) Æ (X2,Y2). Een rasterplaatje bestaat uit zogenaamde pixels, deze pixels zijn punten die een bepaalde kleur hebben en elke pixel kan maar één kleur bevatten. In figuur 6 zijn twee figuren zichtbaar van het formaat 10 * 10. Het eerste figuur is een plaatje in rasterformaat, deze bestaat uit 10 * 10 = 100 pixels. Alle 100 pixels moeten een kleur krijgen, in dit geval hebben de pixels witte en grijze kleuren. In de tweede illustratie, het vectorplaatje, zijn punten opgegeven waartussen lijnen zijn getrokken. Figuur 6: Raster- en vectorplaatje
Een voordeel van een vectorplaatje ten opzichte van een figuur in rasterformaat is dat vectorplaatjes over het algemeen kleiner zijn. De reden hiervoor is dat, zoals in figuur 6 zichtbaar is, bij een rasterfiguur alle pixels een kleur moeten krijgen en alle pixels moeten dus ook worden opgeslagen en bij een vectorplaatje worden enkel de punten opgeslagen met daartussen de lijnen. Het grootste voordeel van een vectorplaatje ten opzichte van een rasterfiguur is echter dat een vectorplaatje, zonder verlies van kwaliteit, kan worden vergroot en verkleind. Dit is bij een illustratie in rasterformaat niet mogelijk. Figuur 7: Inzoomen op een rasterplaatje.
Figuur 8: Inzoomen op een vectorplaatje.
17
Het verschil in kwaliteitsverlies, door het inzoomen, tussen raster- en vectorplaatjes is duidelijk zichtbaar in figuur 7 en 8. De reden voor het grote kwaliteitsverlies bij rasterplaatjes is het feit dat het aantal pixels waaruit een plaatje bestaat tijdens het inzoomen gelijk blijft. Het gevolg hiervan is dat alle pixels sterk worden uitvergroot, wat weer tot gevolg heeft dat de individuele pixels zichtbaar worden. In een vectorplaatje worden tijdens het inzoomen de lijnen opnieuw berekend en dus niet zoals bij een plaatje in rasterformaat vergroot. Daarnaast is vector niet resolutie afhankelijk, 10 pixels blijven bij vectorplaatjes niet zoals bij de rasterplaatjes 10 pixels maar het geheel wordt over meerdere pixels op het beeldscherm verdeeld. Tot slot is er nog het verschil dat in een vectorplaatje kan worden gezocht terwijl dit binnen een rasterplaatje niet mogelijk is. In een artikel van Köbben en Barend14 wordt aangegeven dat een groot nadeel van rasterplaatjes het feit is dat deze als ware een “stomme visualisatie van de data zijn, van welke de daadwerkelijke informatie tenietgaat.” Men bedoeld hiermee dat als er op een plaatje bijvoorbeeld een gebouw zichtbaar is, er in de data van het plaatje niets staat dat aangeeft dat het hier om een gebouw gaat. Binnen vectorplaatjes is dit wel mogelijk.
3.3
Extra mogelijkheden SVG
Zoals in § 3.1 al is aangegeven, SVG heeft een aantal kenmerken die illustraties met bestandsformaten als jpg, gif en png niet hebben of waarbij het kenmerk, zoals animaties in gif en png, enkel zijn aan te passen in een speciaal programma. De volgende punten maken SVG tot een grafisch formaat met mogelijkheden: y Animaties – In een SVG document kan door middel van het element een animatie worden ingesteld voor een bepaald figuur. Deze animatie kan variëren van een simpele verplaatsing van het object tot aan een reactie op een beweging van de muis. Het object dat geanimeerd dient te worden bevat een speciale ID attribuut en het animatieelement verwijst vervolgens door middel van een xlink naar dit ID attribuut. Voorbeeld:
Köbben, Barend, 1.
18
3.4
Basisobjecten en de opbouw van een SVG document
SVG documenten moeten, om te kunnen worden herkend door de speciale browsers, een aantal speciale regels bevatten die aangeven dat het om een SVG document gaat. Zonder deze regels zal het document worden afgekeurd en dus niet zichtbaar zijn. Naast deze standaard regels bevatten SVG documenten ook standaard objecten die gebruikt worden om plaatjes mee op te bouwen. Deze basisobjecten en de standaard regels zullen in dit onderdeel aan de orde komen. Met basisobjecten worden die elementen bedoeld die als standaard figuren binnen SVG en GML zitten, zoals de polygonen, de lijnen, rechthoeken, cirkels en in SVG nog de ellipse. Het gaat dus puur om de figuren, niet om standaardelementen zoals coördinaten. 3.4.1 De opbouw van een SVG document Aangezien SVG een XML variant is moet in het document worden aangegeven dat het om een XML document gaat. Daarnaast moet er een verwijzing in het document staan naar de DTD van de gebruikte SVG versie, door middel van deze DTD kan gecontroleerd worden of het document voldoet aan de voorwaarden waaraan een SVG document moet voldoen. Om gebruik te kunnen maken van de standaard SVG objecten moet er tot slot nog een verwijzing in het document staan naar het Schemabestand. <svg width="5cm" height="5cm" version="1.1" xmlns="http://www.w3.org/2000/svg"> De SVG viewbox is een belangrijk onderdeel van een SVG pagina aangezien het de kaders weergeeft waarbinnen een SVG plaatje zichtbaar is. De hoogte en de breedte van het kader wordt aangegeven door pixels, bijvoorbeeld 800 pixels bij 600 pixels. Als een plaatje minder dan 800 pixels breed en 600 pixels hoog is dan kan het, in dit geval, in zijn totaliteit worden weergegeven zonder dat de gebruiker hoeft te schuiven. Op het moment dat een plaatje groter is dan de opgegeven waarden valt een gedeelte van het plaatje buiten de viewbox en moet de gebruiker het plaatje verschuiven om ook dat gedeelte te kunnen zien. Bij een breedte van 1000 pixels gaat dit nog wel, dan is het een kwestie van iets naar links of iets naar rechts schuiven maar op het moment dat een geografische kaart van 100.000 pixels breed moet worden weergegeven is het schuiven vrijwel niet meer te doen. In GML documenten worden coördinatiesystemen gebruikt met waarden die vele malen groter zijn dan het pixelgebied van het beeldscherm. Om alles toch op het scherm te kunnen laten zien moet er gewerkt worden met een bepaalde schaal. Alles kan worden weergegeven op een schaal van bijvoorbeeld 1:2, 1 staat tot 2, alles wordt twee keer zo klein weergegeven, 1:4, alles wordt 4 keer zo klein weergegeven. Daarnaast is het mogelijk om binnen de viewbox een ander startpunt van coördinaten te gebruiken. Normaal gesproken is het beginpunt X = 0 en Y = 0, bij een GML document dat als laagste coördinaten -32.000 en +32.000 heeft en als hoogste -31.900 en 32.100 is dit standaard startpunt niet te gebruiken. Het onderdeel dat zichtbaar zou moeten zijn, in dit geval een vierkant van -32.000 - -31.900 = 100 bij 32.100 - 32.000 = 100 is in een scherm van 32.100 bij 32.100 niet meer zichtbaar. De gebruiker kan, binnen de viewbox aangeven dat het 0,0 punt nu -32.000
19
+32.000 moet zijn. De viewbox beschouwt het punt -32.000, +32.000 nu als het nieuwe startpunt en de bovenstaande punten -31.900 en 32.100 worden als de punten 100,100 aangezien, op deze manier is het vierkant van 100 bij 100 wel goed zichtbaar. De viewbox bevat vier waarden, de eerste twee getallen zijn de beginwaarden, het punt van waaruit gestart kan worden en de achterste twee getallen in de viewbox geven de schaal aan. Voorbeeld: Binnen een svg scherm met afmetingen van 200 * 200 moet een plaatje van een vierkant met de afmetingen 800 * 800 getoond worden, zie figuur 9.
Figuur 9: Viewbox eigenschappen
De eerste twee getallen in de viewbox zijn 0,0, de laatste twee zijn net als de SVG afmetingen 200 * 200. In het kader is nu slechts een gedeelte van het vierkant zichtbaar. Als nu de laatste twee getallen uit de viewbox worden gewijzigd naar 400 * 400 dan bestaat het totale pixelgebied niet meer uit 200 * 200 pixels maar uit 400 * 400 pixels. Het vierkant is 800 * 800 pixels groot dus er is al een groter gedeelte van het vierkant zichtbaar maar er moet nog steeds geschoven worden. Om het vierkant helemaal zichtbaar te krijgen moet het pixelgebied worden vergroot naar 800 * 800, 4 keer de SVG afmetingen van 200 pixels, de schaal is nu dus 1:4. Door deze aanpassing is het totale vierkant in een oogopslag zichtbaar. Objecten met grote afmetingen kunnen dankzij de instellingen van de viewbox toch in zijn geheel zichtbaar worden gemaakt.
3.4.2 Basiselementen SVG Voor de omschrijving van de SVG basiselementen zal het voorbeeld uit hoofdstuk 2.5 worden gebruikt. In dit voorbeeld is een gedeelte van de kaart van Zwolle omgezet tot GML en deze onderdelen die zijn omgezet naar GML worden nu verder omgezet naar SVG. Door middel van het rect element kan in SVG een rechthoek worden gecreëerd. In het voorbeeld wordt eerst een kader gemaakt dat later alle onderdelen zal bevatten. Dit kader kan worden aangemaakt met het rect element. De volgende attributen kunnen worden geplaatst in het element rect: 20
y y
x =: Het attribuut x geeft de horizontale startpositie van de rechthoek aan. y =: Het attribuut y geeft de verticale startpositie aan. ! Bij het bepalen van de Y positie moet rekening worden gehouden met het feit dat SVG de Y positie niet zoals gebruikelijk van beneden naar boven berekend maar van boven naar beneden. De positieve Y-waarden staan onder de X-as en de negatieve Y-waarden boven de X-as.
Figuur 10: Bepalen van de Y coördinaten
Figuur 11:rect in SVG
Het plaatje uit figuur 10 geeft een X- en Y-as weer zoals deze er normaal gesproken uitziet, X-positief naar rechts en Y-positief naar boven. Figuur 11 laat de X- en Y-as zien zoals deze er uit ziet in SVG, X-positief wederom naar rechts en Y-positief naar beneden in plaats van naar boven. Het zwarte vierkant in figuur 10 is het vierkant zoals deze behoort te zijn volgens het voorbeeld uit § 2.5 Het startpunt van het zwarte vierkant 28,22, dus 28 naar rechts en 22 naar boven, het eindpunt is 48,42, 48 naar rechts en 42 naar boven. Als deze coördinaten zouden worden doorgevoerd in figuur 11 met het SVG X-en Y-as stelsel dan zou het vierkant, zoals zichtbaar in figuur 11, onder de X-as staan. Het startpunt 28,22 betekent in SVG immers 22 naar rechts en 28 naar beneden. Het eindpunt zou eveneens op een andere plaats verschijnen, 48,42 wordt namelijk 48 naar rechts en 42 naar beneden. Het vierkant in het SVG stelsel staat gespiegeld afgebeeld ten opzichte van het vierkant uit een normaal X- en Y-as stelsel. In § 5.1 staat beschreven hoe een figuur normaal om te zetten naar een figuur in het SVG stelsel zonder dat deze daarbij wordt gespiegeld.
21
y y y
width =: Hoe breed moet de rechthoek zijn? (20) height =: Hoe hoog moet de rechthoek worden? (20) rx & ry: Door middel van deze attributen kan de hoek van een rechthoek worden afgerond.
De straten kunnen het beste worden weergegeven door het line of polyline element. Het line element is het element waarmee horizontale, verticale en schuine lijnen mee kunnen weergegeven. Een lijn bestaat uit twee punten waartussen de daadwerkelijke lijn wordt getrokken, daarom moeten er vier attributen worden opgegeven in een line element. x1 =: Het horizontale startpunt van de lijn. y1 =: Het verticale startpunt van de lijn. x2 =: Het horizontale eindpunt van de lijn. y2 =: Het verticale eindpunt van de lijn. In het voorbeeld zitten de drie straten aan elkaar vast, daarom is het in dit geval beter om gebruik te maken van het polyline element omdat met dit element een reeks van aaneengesloten lijnen, door middel van punten, kan worden ingegeven. Binnen het point attribuut moeten coördinaten worden opgegeven om het verloop van de lijnen aan te geven. Alleen de eerste straat (nummer 1) zal door middel van het line element worden ingegeven. Straat 1: Straten 2 en 3: <polyline points="36,8 48,18 28,22" fill="none" stroke="black"/>
Figuur 12: SVG lines en polylines
In figuur 12 zijn de straten te zien zoals ze zichtbaar zijn als line en polyline elementen in een SVG document. De dikte van de lijnen kan in het SVG document worden ingesteld. Het volgende onderdeel dat naar SVG moet worden omgezet zijn de bomen die als Point elementen in GML staan. Deze punten kunnen het beste worden omgezet naar de SVG variant,
22
het element circle. Met het circle element kunnen perfect ronde cirkels worden gemaakt. Binnen het circle element kan gebruik worden gemaakt van de volgende attributen: cx =: De horizontale startpositie van de cirkel. cy =: De verticale startpositie van de cirkel. r =: De radius van de cirkel De drie bomen:
Figuur 13: Het circle element
In figuur 13 staan nu drie stippen op de plaatsen waar de bomen horen te staan, de dikte van deze stippen is door middel van de radius aan te passen. Het laatste onderdeel dat in het voorbeeld vanuit GML naar SVG moet worden dat zijn de gebouwen aan de kant van de weg. Net zoals in GML kan ook in SVG gebruik worden gemaakt van het polygon element om figuren met meerdere hoeken te creëren. De punten van een polygoon kunnen door middel van het point attribuut worden ingegeven. Het nadeel van het polygon element is dat het figuur een gesloten figuur moet zijn, de begin- en eindcoördinaten moeten hetzelfde zijn. <polygon points="33,19 44,17 44,16 33,18 33,19" fill="none" stroke="black" strokewidth="0.1"/> <polygon points="33,19 37,18.3 37,17.4 33,18 33,19" fill="none" stroke="black" strokewidth="0.1"/> <polygon points="37,18.3 40,17.6 40,16.7 37,17.4 37,18.3 " fill="none" stroke="black" strokewidth="0.1"/> <polygon points="40,17.6 44,17 44,16 40,16.7 40,17.6" fill="none" stroke="black" strokewidth="0.1"/> Voor het aanmaken van het huizenblok is gebruik gemaakt van vier polygon elementen, de eerste is de buitenste rand waarin alle drie de huizen vallen. De overige drie polygonen bevatten de coördinaten van de individuele huizen. 23
In figuur 14 is het uiteindelijke resultaat zichtbaar. Alle onderdelen die waren omgezet naar GML zijn nu getransformeerd naar SVG. Alle gebruikte basiselementen kunnen nog verder worden bewerkt zodat de lijnen dikker worden of een andere kleur krijgen of polygonen die veel gedetailleerdere informatie geven.
Figuur 14: SVG plattegrond
Naast de, in het voorbeeld, gebruikte basiselementen is er nog één SVG basiselement dat nog niet aan bod is gekomen, dat is het ellipse element. Het ellipse element heeft veel weg van het circle element maar met dit verschil dat een ellipse niet perfect rond hoeft te zijn. Door middel van dit element kan bijvoorbeeld de vorm van een ei worden weergegeven. De volgende attributen kunnen worden gebruikt: y cx en cy =: De horizontale- en verticale startpositie van de ellipse y rx en ry =: Het attribuut rx is de horizontale radius, dus hoever moet de ellipse vanuit het midden naar links en naar rechts en ry is de verticale radius. <ellipse cx=”300” cy=”100” rx=”50” ry=”20” />
3.5
Layers
In een SVG document kan er gewerkt worden met zogenaamde layers, lagen met objecten. Deze layers kunnen afzonderlijk van elkaar zichtbaar / onzichtbaar worden gemaakt door middel van een javascript. Objecten die bij elkaar horen, bijvoorbeeld gebouwen, kunnen in één groep worden geplaatst en deze groep kan weer een layer vormen. Zo is het mogelijk om binnen geografische kaarten er voor te kiezen om alleen de straten zichtbaar te laten zodat de aandacht niet wordt afgeleid door andere objecten op een kaart. Door middel van het aan en uitvinken van layers kunnen layers zichtbaar dan wel onzichtbaar worden gemaakt. De volgorde van layers is op geografisch gebied zeer belangrijk, een straat plaats je logischerwijze niet boven op een groep bomen, andersom is wel mogelijk. De onderste layer bestaat uit de verschillende soorten landschappen, bijvoorbeeld weiland en akkerland15. De volgende laag bestaat uit alle soorten objecten die het landschap tekenen zoals gebouwen, bomen, hekjes en bruggen. De derde laag bestaat uit wegen, rivieren en treinsporen, tot slot bevat de bovenste laag de grenzen van de landen, provincies en gemeenten.
15
Jones, C. 30.
24
Figuur 15: Layers in SVG
25
4.
Het conversieprogramma
4.1
Inleiding
In dit onderdeel wordt het daadwerkelijke conversieprogramma onder de loep genomen en worden ontwerpbeslissingen toegelicht. Het programma is ontwikkeld als een webapplicatie om zodoende de toegankelijkheid van het programma, voor zoveel mogelijk gebruikers, te vergroten. Er is gekozen voor een webapplicatie, en niet voor een programma dat kan worden gedownload, omdat een webapplicatie voor vrijwel iedereen, in elke browser, beschikbaar is. Een programma daarentegen, zal in verschillende versies moeten worden geleverd, omdat niet alle besturingssystemen dezelfde opmaak van het programma aankunnen. Een programma voor een Unix computer zit significant anders in elkaar dan een programma voor een windows computer. Een ander groot voordeel van een webapplicatie is dat het programma ten allen tijde, overal, beschikbaar is. Het nadeel is dat het beperkingen oplevert voor wat betreft de bestandsgrootte van de GML bestanden die worden ingegeven. De maximale bestandsgrootte van een GML document hangt af van de verbinding die de gebruiker heeft met het internet. Indien een GML document via een telefoonverbinding met het internet op de server moet worden geplaatst, is de maximale bestandsgrootte niet zo groot als bij gebruik van kabelinternet. Bij het gebruik van kabelinternet is de maximale bestandsgrootte zo rond de 950 kb. Geeft de gebruiker een bestand in dat groter is dan de maximale bestandsgrootte dan zal het programma de bewerking op een bepaald moment stoppen en krijgt de gebruiker de melding dat de webpagina op het moment niet beschikbaar is. De gebruiker heeft dus, om gebruik te kunnen maken van het programma, in ieder geval een wat snellere internetverbinding nodig, een internetverbinding via de telefoon is niet geschikt voor de conversie van GML documenten. Degenen die gebruik willen maken van de applicatie hoeven dus niet eerst allerlei programma’s te downloaden en te installeren, het enige wat de gebruiker nodig heeft is een, voor de grotere GML bestanden, snelle internetverbinding en zoals vanzelfsprekend een GML document. Het uiteindelijke resultaat van het programma is te vinden op http://www.onlinecentrum.nl/rug/scriptie/index.html. Deze webpagina is voor iedereen toegankelijk, wat betekent dat ook iedereen gebruik kan maken van het conversieprogramma. Het programma is opgebouwd uit drie delen: 1. het gedeelte waar de gebruiker GML documenten kan ingeven en waar deze op de server worden geplaatst; 2. het onderdeel dat bewerkingen uitvoert op het document dat zojuist op de server is geplaatst; 3. tot slot het gedeelte dat de juiste onderdelen uit het bewerkte GML document filtert en deze componenten omzet in correct SVG.
26
4.2
De invoer en het op de server plaatsen van het GML document
Na een korte en simpele introductie van het programma aan de gebruiker krijgt de gebruiker de mogelijkheid een GML document in te voeren zodat deze kan worden omgezet naar een SVG document. In figuur 15 is het invoerscherm zichtbaar zoals het op de website staat.
Figuur 16: Invoerscherm conversieprogramma
In het met het nummer 1 aangegeven onderdeel kan het GML document worden geselecteerd dat naar SVG omgezet moet worden, dit GML document moet op de computer staan van degene die het GML document invoert. Nadat het GML document is ingegeven kan het document worden verzonden en kan het resultaat worden bekeken. Achter de schermen wordt het opgegeven GML document verder behandeld door een PHP-script. Aangezien PHP een vrij robuuste scripttaal is kan het goed worden gebruikt om de door de gebruikers opgegeven GML documenten op de server te plaatsen. Het PHP-script controleert het opgegeven document eerst op grootte, is het document te groot dan krijgt de gebruiker een melding dat het document niet kan worden verwerkt. Deze melding verschijnt ook als blijkt dat het document een verkeerde extensie heeft, bijvoorbeeld html in plaats van xml, en daardoor dus onverwerkbaar is. Is het document goedgekeurd omdat het de juiste grootte en de juiste extensie heeft, dan wordt de naam van het document verlengd met de datum en tijd van dat moment, zodat het document een unieke naam heeft die geen enkel ander opgegeven document kan hebben. Het document wordt overgeheveld naar de server (uploaden) waar het bewerkt kan worden. Naast het uploaden van GML-bestanden wordt PHP in het programma gebruikt voor het toepassen van XSLT-bestanden op het opgegeven bestand, en de na enkele bewerkingen gecreëerde bestanden. In het PHP-script staan de locatie en de extensie van het bronbestand, de locatie van het XSLT-bestand en wordt de locatie en de naam en de extensie van het nieuw te
27
creëren bestand aangegeven. Op deze nieuwe locatie ontstaat zodoende een nieuw bestand dat later weer verder kan worden bewerkt of dat kan worden getoond aan de gebruiker.
4.3
Bewerkingen op het GML document
Naast PHP wordt in het programma ook gebruik gemaakt van de programmeertaal Perl, dat net zoals PHP erg goed gebruikt kan worden om webpagina’s dynamisch te maken. Daarnaast is Perl erg nuttig omdat het goed overweg kan met reguliere expressies. Door middel van reguliere expressie kunnen bepaalde onderdelen uit een tekst worden gefilterd. Perl wordt in het programma gebruikt om het ingegeven GML-document te bewerken en om bepaalde informatie uit het GML-document te filteren. Nadat de gebruiker het GML-document heeft ingegeven wordt het document op de server geplaatst en worden de eerste coördinaten uit het document gehaald die aangeven binnen welke grenzen de in het GML-document gebruikte coördinaten vallen. Alle coördinaten in het document worden geacht binnen de gestelde grenzen te vallen, doen ze dat niet dan is dat gedeelte van het GML-document later in het SVG-document niet zichtbaar. Deze eerste coördinaten zijn opgeslagen in het bestand coordinate.xml. In het onderstaande voorbeeld worden de coördinaten bepaald, die het kader aangeven waarbinnen alle coördinaten die gebruikt gaan worden zullen vallen. De X- en de Y-coördinaten worden van elkaar gescheiden door gebruik van reguliere expressies. foreach my $line (@regels) { $line =~ s/Start://; $line =~ s/\s/\n/g; $line =~ s/,/\ny/g; print BESTAND2 $line; } Voorbeeld 4: Reguliere expressies
In voorbeeld vier wordt elke regel uit de array regels apart bekeken, stel dat de volgende regel in de array voorkomt: Start:277971.000,-185990.000 280016.000,-185990.000 280028.000,-188025.000 277964.000,-188035.000 277971.000,-185990.000.
Stap 1 $line =~ s/Start://; :indien in een regel het woord Start, gevolgd door een dubbele punt
(Start:) voorkomt, dan wordt deze combinatie verwijdert. In dit geval is dit waar en wordt deze combinatie vervangen door niets, de combinatie wordt verwijderd. Het resultaat is nu: 277971.000,-185990.000 280016.000,-185990.000 280028.000,-188025.000 277964.000,-188035.000 277971.000,-185990.000
Stap 2 $line =~ s/\s/\n/g; : vervolgens wordt er gecontroleert of deze gegevens al zijn opgesplitst
in een hoogste en laagste X- en Y-coördinaat of dat de coördinaten achter elkaar geplakt staan, bijvoorbeeld (10,20 20,30). Als de coördinaten achter elkaar geplakt zijn moeten deze worden opgesplitst in een hoogste en laagste X- en Y-coördinaat. De spaties (\s) die in de regel
28
voorkomen worden omgezet naar een return, ofwel een nieuwe regel (\n). In de regel komen inderdaad spaties voor, dus worden deze vervangen door nieuwe regels: 277971.000,-185990.000 280016.000,-185990.000 280028.000,-188025.000 277964.000,-188035.000 277971.000,-185990.000
Stap 3 $line =~ s/,/\ny/g; :tot slot wordt er gecontroleerd op komma’s. De coördinaten die nu overgebleven zijn bestaan immers uit een X- en een Y-coördinaat die van elkaar gescheiden zijn door middel van een komma. Stel dat enkel de komma verwijderd wordt dan is het niet meer duidelijk of het nu om een X- of om een Y-coördinaat gaat, de Y-coördinaat krijgt daarom een extra teken mee waaraan het verderop in het programma kan worden herkend. De komma’s worden vervangen door nieuwe regels, gevolgd door de letter y. Het uiteindelijke resultaat na het gebruik van reguliere expressies: 277971.000 y-185990.000 280016.000 y-185990.000 280028.000 y-188025.000 277964.000 y-188035.000 277971.000 y-185990.000
Alle X- en Y-coördinaten uit het bestand ‘coord.xml’ worden nu in aparte arrays geplaatst. Gaat het om een X-coördinaat dan behoort deze in de x_as array en gaat het om een Y-coördinaat dan behoort de coördinaat in de y_as array. open(BESTAND3,"coord.xml") or &dienice("Kan coord.xml niet openen om te lezen: $!"); while (my $nummer = ) { if($nummer =~/y/) { $nummer =~ s/y//; push(@y_as, $nummer); } else { push(@x_as, $nummer); } } Voorbeeld 5: Opdelen van de X- en Y-coördinaten
Het systeem, zie voorbeeld 5, weet wanneer het om een X- of een Y-coördinaat gaat dankzij de de letter y die voor alle Y-coördinaten is geplaatst.
29
Na het opdelen in X- en Y-coördinaten worden de aparte coördinaten gecontroleerd en bewerkt. Wanneer het gaat om een y-coördinaat dan wordt de letter ‘y’, die net voor deze coördinaat geplaatst is, weer verwijderd. In deze stap wordt verder bepaald wat de hoogste en de laagste Xen Y-coördinaten zijn om zodoende de breedte en de hoogte van de te gebruiken viewbox te kunnen bepalen. my $hoogste_y = -1000000000; my $laagste_y = 1000000000; foreach my $test_y (@y_as) { if($test_y > $hoogste_y) { $hoogste_y = $test_y; } if($test_y < $laagste_y) { $laagste_y = $test_y; } } Voorbeeld 6: Zoeken naar de hoogste en laagste Y-coördinaat
Alle waarden in de x_as en de y_as array worden doorlopen om de hoogste en de laagste X- en Y-coördinaat te kunnen bepalen. Deze waarden worden vergeleken met de op dat moment hoogste en laagste waarde. Een probleem hierbij is dat de eerste X- en Y-coördinaat niet kan worden vergeleken met een bepaalde waarde aangezien er nog geen hoogste en laagste waarden zijn, daarom worden er eerst, zoals in voorbeeld 6, een aantal variabelen aangemaakt die waarden bevatten die extreem hoog en laag zijn. De variabele $hoogste_y heeft als basis een negatief getal, en niet bijvoorbeeld nul, omdat het voor kan komen dat de hoogste Y-coördinaat een negatief getal is en in dat geval zou de standaard nulwaarde nog steeds groter zijn dan deze waarde en dat is niet de bedoeling. De eerste Y-coördinaat wordt vergeleken met de standaardwaarde en is zeker groter dan deze standaardwaarde waardoor $hoogste_y nu de waarde van de eerste Y-coördinaat krijgt. Vanaf nu worden de coördinaten vergeleken met een eerder gebruikte Y-coördinaat uit het GML document. Dezelfde eerste Y-coördinaat wordt vervolgens vergeleken met de variabele $laagste_y , waarbij $laagste_y de waarde van de eerste coördinaat krijgt. Op het moment dat een Y-coördinaat kleiner is dan de huidige waarde van de variabele $laagste_y krijgt deze variabele de waarde van de Y-coördinaat. Alle X-coördinaten doorlopen precies dezelfde stappen als de Y-coördinaten, met dit verschil dat de X-coördinaten vanzelfsprekend worden vergeleken met de hoogste en laagste X-coördinaat. Zoals aangegeven in § 3.4.1 bevat de SVG-viewbox vier getallen, de eerste twee geven de laagste X- en Ycoördinaat aan zodat punt 0,0 niet begint op 0,0 maar op de laagste X- en Y-coördinaat, het derde en vierde getal geven de breedte en de hoogte aan van de viewbox. Als de laagste X-coördinaat 2 is en de hoogste X-coördinaat is 2 dan is de breedte van de viewbox 2 - -2 = 4, alle Xcoördinaten vallen in dat geval tussen X=-2 en X=2. Doordat de gebruiker bij het ingegeven van het GML document ook de viewbox grootte heeft bepaald, zie § 4.1, worden de correcte viewboxgrootte gegevens in het bestand ‘viewbox.xml’ weggeschreven. 30
Indien het GML bestand, voor het bepalen van de buitenste ring, geen gebruik maakt van een reeks coördinaten maar van individuele X- en Y-coördinaten uit het gmlBox element, moeten er andere stappen worden doorlopen voor het bepalen van de hoogste en laagste coördinaten. De coördinaten uit het ‘coord.xml’ bestand worden bekeken en er wordt bepaald om welke coördinaat het gaat. Als er een X1 in de regel staat dan gaat het om de eerste X-coördinaat, X2 om de tweede en Y1 en Y2 zijn de eerste en tweede Y-coördinaat. my my my my my
$X_hoogst; $Y_hoogst; $hoogst; $laagste_x; $laagste_y; if($X1 > $X2) { $X_hoogst = ($X1 - $X2); $laagste_x = $X2; } if($X2 > $X1) { $X_hoogst = ($X2 - $X1); $laagste_x = $X1; }
Voorbeeld 7: bepalen van de laagste X-coördinaat
In voorbeeld 7 wordt getest of $X1 groter is dan $X2, als dit het geval is dan kan de breedte bepaald worden door $X2 van $X1 af te trekken, tevens is duidelijk dat $X2 de laagste Xcoördinaat is. De laagste Y-coördinaat en de hoogte worden op dezelfde wijze bepaald. Als de breedte groter is dan de hoogte wordt de breedte gebruikt voor het bepalen van de viewbox, in het andere geval andersom.
4.4
Gegevens filteren uit het GML document
Nu de randvoorwaarden voor het maken van een SVG document gereed zijn wordt het tijd om alle onderdelen uit het GML document die kunnen worden omgezet ook daadwerkelijk om te zetten naar SVG. Het omzetten naar SVG gebeurt in twee stappen, eerst worden door middel van het ‘svg1.xslt’ bestand alle GML basisobjecten uit het GML document gefilterd en weggeschreven in een XML bestand, ‘opzet1.xml’. Vervolgens wordt dit XML bestand als input gebruikt voor het aanmaken van het SVG document. Een tweede XSLT bestand, ‘svg2.xslt’ haalt de gegevens uit het XML bestand en schrijft ze weg in ‘opzet2.svg’. De reden voor het gebruik van deze tussenstap is dat op deze manier, per basisobject, een unieke ID gegenereerd kan worden waardoor in het SVG document alle basisobjecten als aparte groepen aan en uit kunnen worden gezet, de gebruiker kan kiezen welke groep basisobjecten wel en welke niet zichtbaar moeten zijn. Het eerste XSLT bestand, ‘svg1.xslt’ schrijft om te beginnen eerst alle namespaces die in het SVG document gebruikt moeten worden in het XML document weg zodat deze namespaces later bij het openen van het SVG document herkend worden. Als de namespaces zijn weggeschreven kan er worden gezocht naar de GML elementen die moeten worden omgezet naar SVG. In GML 31
documenten kan er gebruik gemaakt worden van elementen die door de gebruiker zelf zijn aangemaakt en waarvoor geen SVG elementen aanwezig zijn, deze elementen kunnen daarom onmogelijk worden omgezet en moeten worden genegeerd. De elementen die wel kunnen worden omgezet zijn de basisobjecten, box, linestring, point en polygon. Naast deze elementen zijn er nog de basiselementen, MultiPolygon, MultiLineString, MultiPoint en MultiGeometry zie § 2.5, maar op deze basisobjecten wordt niet apart gezocht in een GML document omdat de vier basisobjecten uit tabel 2 altijd subelementen van deze elementen zijn. Een MultiPolygon element bestaat uit meerdere Polygon elementen en deze worden wel uit het GML document gefilterd. In tabel 2 zijn de GML basisobjecten en hun SVG tegenhangers te zien zoals beschreven door Bonati, Fortunati en Fresta’s16 GML Basisobject Box Point LineString Polygon
SVG element rect rect, circle, path polyline, path path
Tabel 2: GML basisobjecten en de SVG elementen
In tabel 2 zijn de SVG elementen, zoals gebruikt in het programma als tegenhanger voor de GML basisobjecten, in het rood geschreven. <xsl:template match="/"> <poly_object id="all_polygon"><xsl:apply-templates select="//gml:Polygon"/> <xsl:apply-templates select="//gml:LineString"/> <point_object id="all_points"><xsl:apply-templates select="//gml:Point"/> <xsl:apply-templates select="//gml:Box"/> Voorbeeld 8: De zoektocht naar alle GML objecten
Het XSLT bestand maakt, zoals zichtbaar in voorbeeld 8, een element poly_object aan en begint met de zoektocht naar het aantal malen dat het gml:Polygon element voorkomt. Zodra het een gml:Polygon heeft gevonden wordt het overeenkomstige template, in dit geval gml:Polygon, doorlopen. <xsl:template match="gml:Polygon"> <xsl:variable name="Ran_id"> <xsl:value-of select="generate-id(.)"/> ……. <path style="stroke:black; stroke-width:.001cm;" d="M{$polygon_rep}"/> ……. Voorbeeld 9: Omzetten van gml:Polygon naar SVG path 16
Bonati, e.a., 7.
32
Er wordt een unieke ID, Ran_id genaamd, gegenereerd en er wordt een groep aangemaakt binnen welke alle gml:Polygonen zullen vallen, zie voorbeeld 9. De Y-coördinaten van de polygoon worden omgezet van negatief naar positief of andersom om de polygoon in het SVG bestand zichtbaar te krijgen. In hoofdstuk 5 wordt precies uitgelegd waarom de Y-coördinaten moeten worden omgezet. Vervolgens wordt er een element path aangemaakt waarin de coördinaten van het gml:Polygon komen te staan. Het GML element gml:Polygon is nu omgezet naar de SVG variant van dit element en kan binnen een SVG document als SVG figuur in een browser worden getoond. Als er in het GML document geen gml:Polygonen meer aanwezig zijn wordt er verder gezocht naar het volgende GML element, gml:LineString. Alle GML elementen worden op deze manier omgezet naar de SVG variant. Nu het XML document alle GML basisobjecten bevat worden deze middels ‘svg2.xslt’ omgezet naar het SVG document. De te gebruiken namespaces worden in het SVG document weggeschreven en de waarden van de viewbox worden ingevuld. Boven in het SVG document wordt een variabele ViewDoc aangemaakt die een link naar het document ‘viewbox.xml’ bevat, in dit document staan, zoals aangegeven in § 4.2. alle waarden die de viewbox rondom de basisobjecten moet bevatten. <xsl:variable name="ViewDoc" select="document('viewbox.xml')"/> …… <svg id="mainMap" x="0" y="15" viewBox="{$ViewDoc/root/laagste_x} {$ViewDoc/root/laagste_y} {$ViewDoc/root/viewbox_size} {$viewb_getal4}" width="553" height="700"> Voorbeeld 10: het viewbox.xml document
Verderop in het SVG document wordt een nieuw svg element aangemaakt waarin alle basisobjecten komen te staan. Dit nieuwe svg element bevat, zoals zichtbaar in voorbeeld 10, een viewbox met daarin de waarden uit het ‘viewbox.xml’ document. De basisobjecten die zijn opgeslagen in het ‘opzet1.xml’ document worden als subelementen binnen het svg element geplaatst. <xsl:apply-templates select="//poly_object/g"/>
Er wordt een nieuwe groep aangemaakt, in dit geval all_polygon, en binnen deze groep wordt er gezocht naar het aantal keren dat het element polygon voorkomt met de daarbij behorende informatie zoals het FeatureID (fid) en een eventuele omschrijving van de polygoon. Als alle elementen in het SVG document zijn geplaatst en het SVG document compleet is, wordt de gebruiker teruggestuurd naar de invoerpagina. Door een klik op de knop met ‘Bekijk resultaat’ wordt de gebruiker naar de zojuist gecreëerde SVG pagina gestuurd. Figuur 17 toont een GML document en het resultaat van het omzetten van dit document naar SVG. Naast de SVG kaart zijn er nog aantal extra mogelijkheden in het SVG document aangebracht waardoor de gebruiker optimaal gebruik kan maken van het SVG bestand, deze extra features worden beschreven vanaf § 4.4.
33
Figuur 17: GML en het resultaat in SVG
Naast de locaties van de basisobjecten bevat een GML document meestal nog extra informatie over deze basisobjecten. Deze extra informatie kan zijn opgeslagen binnen een Featuremember element maar dat is niet noodzakelijk. Gebruikers kunnen zelf elementen hebben aangemaakt waarbinnen zij informatie hebben opgeslagen en deze zijn, omdat het geen standaardelementen zijn, niet bruikbaar voor de conversie naar SVG. De enige extra informatie die uit een GML document wordt gehaald tijdens de conversie zijn een eventuele omschrijving, een naam en een Feature ID (fid). Aan de hand van de Feature ID kan de gebruiker objecten uit een SVG document terugzoeken in het GML document.
4.5
Extra features
Naast de SVG kaart die de gebruiker te zien krijgt zijn er nog een aantal extra mogelijkheden aan het SVG document toegevoegd. Alle toegevoegde mogelijkheden hebben als doel het de gebruiker zo eenvoudig en zo duidelijk mogelijk te maken. Zowel het script voor het zoomen en panning, als het script dat coördinaten laat zien, zijn ontwikkeld door Juliana Williams en Andreas Neumann van carto.net17.
17
http://www.carto.net/papers/svg/navigationTools/
34
Figuur 18: Extra mogelijkheden SVG document
Zoomen en panning In een SVG document kan er altijd worden ingezoomd op de figuren die in de browser worden getoond, daarnaast kan door middel van de Alt toets het gehele SVG plaatje worden verschoven. Een echte gebruiksvriendelijke oplossing is dit niet, vandaar dat deze mogelijkheden wat zijn aangepast zodat het voor iedere gebruiker duidelijk is hoe in te zoomen en hoe het figuur te verschuiven. Aan de rechterzijde van de SVG kaart is het plaatje in figuur 18 zichtbaar, het kleine SVG kaartje is een exacte kopie van de grote SVG kaart met dit verschil dat tijdens het inzoomen de kleine kaart niet veranderd. Met de schuifbalk in figuur 18, nummer 1, kan er worden ingezoomd op de SVG kaart. Het plusje betekent inzoomen en met de min kan er worden uitgezoomd. Alle onderdelen op de SVG kaart kunnen, in tien stappen, tot maximaal 100 keer de huidige breedte en hoogte worden vergroot. Stap 1: <xsl:variable name="viewb_getal3"> <xsl:value-of select="$ViewDoc/root/viewbox_size"/> <xsl:variable name="viewb_getal4zoom"> <xsl:value-of select="($ViewDoc/root/viewbox_size) div 100"/> Stap 2: myMainMap = new map("mainMap", ]]> <xsl:value-of select="$viewb_getal3"/>,<xsl:value-of select="$viewb_getal4zoom"/>
35
Stap 3: myMainMap = new map("mainMap", 2065,20.65 Voorbeeld 11: Inzoomen
In het XSLT bestand worden, zoals te zien is in stap 1 van voorbeeld 11, een aantal variabelen aangemaakt, in dit geval de variabelen viewb_getal3en viewb_getal4zoom. Deze variabelen hebben als waarde het getal dat te vinden is via de link $ViewDoc/root/viewbox_size, $ViewDoc is een variabele die verwijst naar het bestand ‘viewbox.xml’. Bij de bepaling van viewb_getal4zoom wordt de uitkomst gedeeld door 100. De waarden van viewb_getal3 en viewb_getal4 worden in stap 2 gebruikt om het maximale en het minimale zoomniveau te bepalen. In stap 3 is het minimale zoomniveau 2065 en het maximale zoomniveau 20,65. Het grote voordeel van dit inzoomsysteem, in vergelijking met het standaard SVG inzoomsysteem, is dat de gebruiker niets steeds op de rechter muistoets hoeft te klikken om te kiezen voor in- of uitzoomen, bovendien kan er op deze manier dieper op de SVG kaart worden ingezoomd. Tot slot wordt er alleen op de SVG kaart ingezoomd en niet zoals bij het standaardsysteem op de gehele pagina. Nummer twee in figuur 18 laat een donkergrijze rechthoek binnen een lichtgrijze rechthoek zien. Met deze donkergrijze rechthoek kan, binnen het kleine kaartje, snel naar de juiste locatie worden geschoven, dit fenomeen staat beter bekend als panning. De donkergrijze rechthoek geeft de oppervlakte aan wat de gebruiker op de grote kaart ziet. Hoe dieper de gebruiker op de kaart inzoomt hoe kleiner de donkergrijze rechthoek zal worden. <xsl:variable name="little_cross"> <xsl:value-of select="($ViewDoc/root/viewbox_size) div 10"/> ]]> <xsl:value-of select="$little_cross"/>
Op een gegeven moment, tijdens het inzoomen, wordt de donkergrijze rechthoek zo klein dat deze nauwelijks meer zichtbaar is. Op dat moment worden er om het rechthoekje een aantal streepjes geplaatst zodat er een kruisje ontstaat. Dit kruisje kan, net zoals de donkergrijze rechthoek, worden verplaatst zodat de locatie die zichtbaar is ook verandert. Omdat de hoogte en breedte van GML documenten steeds weer anders zijn kan er in het SVG document geen vaste waarde worden weggeschreven die aangeeft dat het kruisje moet verschijnen. Op het moment dat een gebruiker zover heeft ingezoomd dat alles tien keer vergroot is, moet het kruisje verschijnen. In voorbeeld 12 krijgt de variabele little_cross de waarde van de grootte van de viewbox gedeeld door tien. Als deze waarde wordt bereikt tijdens het inzoomen, wordt het kruisje getoond. Stel dat de breedte van de viewbox 48000 is, er kan nu worden ingezoomd totdat de echte kaart 100 keer is vergroot, de breedte is bij maximaal inzoomen niet 48000 maar 48000 / 100 = 480. Als er tot 10 keer is ingezoomd, en de breedte niet 48000 maar 48000 / 10 = 4800 is, verschijnt het kruisje om de rechthoek.
36
Omdat de kleine kaart een kopie van de grote kaart is wordt een wijziging van locatie op de kleine kaart ook doorgevoerd op de grote kaart, dat wat de gebruiker aanklikt op het kleine kaartje is zichtbaar op de grote kaart. Het voordeel van de kleine kaart is dat de gebruiker in één oogopslag ziet waar hij of zij zich bevindt. Coördinaten bijhouden Het is van groot belang voor een gebruiker om duidelijk te weten waar, qua coördinaten, deze gebruiker zich op de kaart bevindt. In het programma worden de coördinaten bijgehouden en wordt bij elke beweging van de muis op de SVG kaart in nummer 3 van figuur 18, de locatie in X- en Y-coördinaten weergegeven. Op deze manier is het mogelijk om een afstand tussen bepaalde objecten door middel van het coördinatensysteem te berekenen. Voor het berekenen van de coördinaten worden de hoogte en de breedte van de viewbox gebruikt. Het startpunt voor de berekening is het startpunt van de viewbox. Het kan voorkomen dat van een SVG kaart alleen een bepaalde groep objecten zichtbaar moet zijn, door middel van de opties onder “Aan- en uitschakelen layers” bij nummer vier in figuur 18, kunnen alle vier groepen basisobjecten onafhankelijk van elkaar aan- en uit worden geschakeld. Wil de gebruiker bijvoorbeeld alleen alle Punten op de kaart zien dan moeten de Polygonen, Lijnen en Rechthoeken worden uitgeschakeld. Bij nummer vijf uit figuur 18 wordt tenslotte de informatie weergegeven die bij een bepaald onderdeel op de SVG kaart behoort. Heeft een object een Feature ID dan wordt deze achter fid getoond als de gebruiker met de muis op het desbetreffende object staat. Achter informatie wordt de informatie die in het GM document bij dit object is toegevoegd weergegeven. Is er geen specifieke informatie over dit object aanwezig dan zal, indien aanwezig, de naam van het object worden getoond. Het uiteindelijke conversieprogramma is een programma geworden waarin GML documenten eenvoudig kunnen worden ingevoerd. Deze ingevoerde GML documenten worden bewerkt, en er worden gegevens uit de GML documenten gehaald, waarmee in een latere fase van het conversieproces, in het uiteindelijke SVG document, een viewbox kan worden opgebouwd. Vervolgens haalt een XSLT bestand alle basisobjecten, welke genoemd zijn in § 4.4, uit het GML document en wordt er per basisobject een unieke ID gegenereerd. Deze basisobjecten met unieke ID worden opgeslagen in een apart XML document. Een tweede XSLT bestand haalt de bewerkte basisobjecten uit het XML bestand en creëert vervolgens het uiteindelijke SVG bestand. De gebruiker merkt niets van al deze bewerkingen en keert, na het invoeren van het GML document, terug naar de hoofdpagina waar hij of zij de mogelijkheid heeft om het nieuw aangemaakte SVG document te bekijken. Tijdens de bouw van het programma zijn er een aantal problemen naar voren gekomen die moesten worden opgelost omdat anders het programma niet optimaal zou werken. Een van deze problemen is het feit dat in SVG de Y-coördinaten niet van bovenaf naar beneden worden berekend maar van beneden naar boven worden berekend. Dit probleem is opgelost, zodat de Ycoördinaten uit een GML document kunnen worden omgezet naar SVG, en wordt in hoofdstuk vijf behandeld. Hoofdstuk vijf geeft een overzicht en een uitleg van alle onvolkomenheden die zijn opgemerkt tijdens de bouw van het programma.
37
5.
Problemen
Tijdens, en voor het bouwen van het conversieprogramma zijn er vanzelfsprekend ook een aantal problemen tevoorschijn gekomen, deze problemen en de oplossingen die gebruikt zijn, worden beschreven in dit hoofdstuk. Als er geen kant en klare oplossing voor een bepaald probleem te vinden was, dan staat bij het probleem beschreven hoe met het probleem is omgegaan, en wat voor maatregelen zijn genomen. Het hoofdstuk is verdeeld in twee delen, ten eerste het gedeelte met problemen die zijn opgelost en het tweede gedeelte bevat die onderdelen die niet kunnen worden opgelost.
5.1
Opgeloste problemen
Y coördinaten in GML en SVG De posities van de objecten in een SVG document worden bepaald door de coördinaten die bij het desbetreffende object behoren. Door middel van deze coördinaten wordt het object in de SVG browser getoond. De coördinaten bestaan uit een X en een Y waarde, de positie op de horizontale as en de positie op de verticale as. De eerste coördinaat, de X waarde, kan zowel positief als negatief zijn, als het getal positief is dan wordt de positie aan de rechterzijde vanaf het nulpunt berekend, is het getal negatief dan wordt het getal aan de linkerzijde van het nulpunt geplaatst. Bij de Y waarde geldt dat als het om een positief getal gaat de waarde boven het nulpunt wordt geplaatst, is het getal negatief dan wordt het getal onder de horizontale as geplaatst. In SVG wordt de Y waarde echter precies andersom berekend als dat normaal het geval is, een positief getal wordt onder de horizontale as geplaatst en een negatief getal boven deze as.
Figuur 19: Bepaling van de X-en Y waarden
38
In figuur 19 staat het object A1, met de coördinaten (-40, 50 -60,50 -60,70 -40,70) op de gebruikelijke plaats in het raster. Als dit object, met dezelfde coördinaten, in een SVG document wordt geplaatst dan verandert de locatie van het object, object A2 is het object zoals het er in dat geval uit zal komen te zien. De Y waarden 50 en 70 moeten -50 en -70 worden om het object op de juiste locatie te krijgen. Voor object B1 geldt precies hetzelfde als voor A1, de coördinaten van B1 (20,20 40,20 50,40 30,40) worden in een SVG document vertaald naar de positie van object B2. Om het object op de juiste plaats te krijgen moeten ook hier de Y waarden worden omgezet van een, in dit geval, positief getal naar een negatief getal. Negatieve Y waarden moeten worden omgezet naar een positief getal.
Figuur 20: Normaal X- en Y-as stelsel
Figuur 21: SVG X-en Y-as stelsel
In figuur 20 staat een driehoek met de coördinaten 10,10 40,10 25,20 10,10. Om deze driehoek op dezelfde locatie in SVG te krijgen moeten de Y-coördinaten van positief naar negatief of andersom worden gedraaid. Het punt 10,10 wordt in SVG nu dus 10,-10 omdat -10 aangeeft dat het punt boven de x-as moet worden geplaatst. De volgende punten zijn vervolgens: 40,-10 25,-20 en 10,-10, het resultaat is zichtbaar in figuur 21. Het coördinatensysteem in een GML document maakt, in tegenstelling tot het systeem van SVG, wel gebruik van de meest gangbare manier van het plaatsen van de X en Y waarden. Als een document wordt omgezet van GML naar SVG dan moet er dus rekening worden gehouden met de bepaling van de Y-as. De Y-waarden uit een GML document die positief zijn moeten zoals
39
aangegeven, om een juist plaatje te creëren in een SVG document, worden omgezet naar een negatief getal. Coordinates.xslt Het omzetten van de Y-waarden gebeurt binnen het programma op twee plaatsen door middel xslt bestanden. Het eerste xslt bestand, coordinates.xslt, welke de waarden van de viewbox bepaalt, verwijdert een eventueel minteken voor een Y-waarde. Mocht er geen minteken voor de Y waarde staan, het gaat om een positief getal, dan wordt er een minteken aan de Y-waarde toegevoegd. <xsl:when test="contains(.//gml:coordinates[1],',-')"> <xsl:variable name="y_coord"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates[1]"/> <xsl:with-param name="search-string" select="',-'"/> <xsl:with-param name="replace-string" select="','"/> Figuur 22: Omzetten positieve en negatieve Y-waarden18
In het xslt bestand wordt er gezocht naar de eerste coördinaten die voorkomen in dit document, deze coördinaten gelden als buitenste ring waarin alle andere coördinaten vallen. Het eerste getal van de coördinaten is steeds de X-waarde, met de X-waarde hoeft niets te gebeuren, en de tweede waarde, welke vooraf wordt gegaan door een komma, is de Y-waarde en die moet worden aangepast. In deze reeks coördinaten wordt gezocht naar een komma gevolgd door een minteken, zie figuur 22. Als deze reeks aanwezig is, en er dus negatieve Y-coördinaten in de reeks staan, dan wordt de komma gevolgd door een minteken vervangen door een enkele komma. Het minteken is verwijderd en het getal is nu een positief getal en wordt op de juiste locatie in het SVG document geplaatst. Als er geen komma gevolgd door een minteken in de reeks voorkomt dan is er sprake van een positieve Y-waarde en wordt de komma vervangen door een komma gevolgd door een minteken. svg1.xslt De vier verschillende soorten GML basisobjecten worden ieder op een andere manier omgezet naar hun SVG tegenhanger, het omzetten van de Y-coördinaat, van positief naar negatief of andersom, verschilt dan ook per soort object. Het omzetten van de Y-coördinaten binnen het basisobject gml:Polygon verschilt met het omzetten van de Y-coördinaten uit gml:Point. Binnen het svg1.xslt bestand worden deze verschillende basisobjecten aangeroepen en als SVG element weggeschreven. gml:Polygon Æ polygon Op het moment dat het gml:polygon element wordt gevonden in het GML document wordt er binnen dit element gezocht naar de coördinaten van deze polygoon. Komt in de reeks binnen
18
O'Reilly books, specifically, Sal Mangano, the author of XSLT Cookbook (ISBN 0-596-00372-2)
40
gml:coordinates een komma gevolgd door een minteken voor dan wordt deze omgezet naar de reeks XXX. <xsl:when test="contains(.//gml:coordinates,',-')"> <xsl:variable name="polygon_rep1"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="',-'"/> <xsl:with-param name="replace-string" select="'XXX'"/>
Vervolgens worden alle komma’s die niet worden gevolgd door een minteken, deze Y coördinaat is dus positief, omgezet naar een komma die wel wordt gevolgd door een minteken. Tot slot worden de XXX reeksen omgezet naar enkele komma’s. Deze tussenstap, van “,-“ naar XXX, is nodig omdat anders de enkele komma die zou zijn ontstaan direct weer zou worden omgezet naar een komma minteken. <xsl:variable name="polygon_rep2"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$polygon_rep1"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="',-'"/> <xsl:variable name="polygon_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$polygon_rep2"/> <xsl:with-param name="search-string" select="'XXX'"/> <xsl:with-param name="replace-string" select="','"/> <polygon style="fill:none; stroke:black; stroke-width:.001cm;" points="{$polygon_rep}"/>
Als alle Y coördinaten zijn omgezet wordt er een SVG polyon getekend die als punten de nieuwe reeks coördinaten bevat. Het kan natuurlijk ook voorkomen dat er geen combinatie van komma minteken voorkomt in het element gml:coordinates, in dat geval worden alle komma’s omgezet naar komma’s gevolgd door een minteken, extra stappen zijn niet nodig. gml:LineString Æ polyline In geval van een gml:LineString kunnen de coördinaten op twee manieren zijn opgeslagen, via gml:coordinates of via gml:coord. Mocht het element gml:coord zijn gebruikt dan wordt de Y coördinaat binnen gml:coord gecheckt, gml:Y, als deze kleiner is dan 0 dan staat er een minteken voor het getal en deze wordt verwijdert om er een positief getal van te maken. Gaat het om een positief getal dan wordt het getal van 0 afgetrokken om er een negatief getal van te maken, bijvoorbeeld +500 wordt: 0 – 500 = -500. Indien de coördinaten zijn opgeslagen in gml:coordinates dan worden deze, op dezelfde manier als bij de gml:polygon, omgezet naar een positief, dan wel negatief getal. Er is een verschil in beide methodes omdat de coördinaten in gml:coord al losse coördinaten zijn, terwijl de 41
coördinaten in gml:coordinates als één reeks achter elkaar geplaatst zijn, hier gaat het dus nog niet om aparte getallen en deze kunnen daarom ook nog niet als dusdanig behandeld worden. gml:Point Æ circle Net zoals bij het gml:LineString element kunnen ook bij het gml:Point element de coördinaten worden opgeslagen in gml:coordinates of in gml:coord. Als er gebruik gemaakt is van gml:coord dan wordt de Y coördinaat (het is er maar één aangezien het om een punt gaat) op dezelfde wijze omgezet als bij het gml:LineString element. Het plaatsen van de juiste waarden in het SVG circle element gebeurt door middel van een variabele. <xsl:variable name="point_X"> <xsl:value-of select="gml:coord/gml:X"/> <xsl:variable name="point_Y"> <xsl:value-of select="$point_rep"/>
De X coördinaat wordt een variabele point_X en kan gewoon worden overgenomen vanuit het GML document aangezien deze niet hoeft te worden aangepast. De Y waarde is aangepast en wordt als variabele point_Y opgeslagen. Bij het tekenen van het element circle in SVG worden beide variabelen op de juiste plaats aangeroepen. Mocht het element gml:coordinates zijn gebruikt voor de opslag van de coördinaten dan worden de X- en de Y coördinaat ook opgeslagen als variabelen alleen op een andere wijze als bij gml:coord omdat in het gml:coordinates element de coördinaten achter elkaar zijn geplaatst. Beide coordinaten worden gescheiden door een komma en is de X coördinaat, point_X, het gedeelte voor de komma. Het gedeelte na de komma is de Y coördinaat welke is omgezet van positief naar negatief of andersom en deze is opgeslagen als variabele point_Y. <xsl:variable name="point_X" select="substring-before(gml:coordinates,',')"/> <xsl:variable name="point_Y" select="substring-after($point_rep,',')"/>
gml:Box Æ rect In het rect element moeten vier waarden worden opgegeven, de eerste X- en Y coördinaten en de breedte en de hoogte. Deze waarden worden afgeleidt van het gml:Box element uit het GML document. Als het element gml:coord is gebruikt dan wordt gekeken of één van beide Y coördinaten, of misschien beide, een negatief getal bevat. De Y coördinaten worden net als bij de vorige elementen weer omgezet. Om de breedte van de rechthoek te kunnen bepalen wordt de eerste X coördinaat van de tweede X coördinaat afgetrokken. Bij de bepaling van de hoogte van de rechthoek wordt de eerste Y coördinaat van de tweede Y coördinaat afgetrokken. <xsl:variable name="box_width1"> <xsl:value-of select="$box_X2 - $box_X1"/> <xsl:variable name="box_height1"> <xsl:value-of select="$box_Y2 - $box_Y1"/>
42
In geval van gml:coordinates worden de twee Y waarden omgezet en wordt gml:coordinates opgedeeld in twee stukken, de eerste X- en Y coördinaten en de tweede X- en Y coördinaten. Coordinaten worden binnen gml:coordinates van elkaar gescheiden door een spatie dus deze spatie is ook het teken voor het scheiden van de eerste en tweede groep coördinaten. Het eerste blok en het tweede blok coördinaten wordt vervolgens bij de komma weer opgesplitst in een Xen Y coördinaten en deze kunnen worden gebruikt voor de breedte en hoogte van de rechthoek. Alle GML basisobjecten worden omgezet naar de SVG variant en alle Y coördinaten worden omgedraaid om het juiste plaatje in SVG te kunnen creëren
5.2
Niet opgeloste problemen
GML te vrijblijvend Binnen de GML taal zijn er een aantal standaard elementen die door de gebruiker gebruikt kunnen worden en waar de gebruiker zich aan moet houden maar verder staat het de gebruiker vrij zijn of haar eigen elementen te creëren. Het is prettig dat er weinig regels zijn omdat iedereen op deze manier zelf bepalen kan welke naam een element krijgt, een straat kan bijvoorbeeld de elementnaam ‘gml:Straat’, ‘gml:Weg’ of misschien ‘gml:Road’ krijgen. Zoveel vrijheid heeft echter ook nadelen, het is lastig om variabele gegevens om te zetten naar een andere taal dan GML. Stel dat iemand een element wil aanmaken genaamd gml:Straat, dit element heeft als basis een LineString element en het element representeert alle straten die binnen het GML document voorkomen. Voor de gebruiker is het nu duidelijk dat een gml:Straat met de bijhorende coördinaten een straat is. Op het moment dat dit element wordt omgezet van GML naar SVG ziet het conversieprogramma een LineString element en weet dat deze moet worden omgezet naar een line element. Het programma herkend echter niet dat het hier om een straat gaat omdat gml:Straat geen standaard element is en daarom niet bekend is in de standaardschema’s. Als iedereen een straat nu gml:Straat zou noemen dan kan het programma alle gml:Straat elementen als LineStrings van het soort Straat zien, maar helaas noemt niet iedereen een straat een straat. Een Engelsman noemt het een Road, een Duitser een Strasse en een gml:Straat kan ook gml:Weg of een andere benaming bevatten. Voor het conversieprogramma is het dus nooit duidelijk wat er wordt bedoeld met gml:Straat of een ander nieuw aangemaakt element. Om deze reden converteert het programma alleen standaardelementen zoals Polygon en LineString naar SVG en worden van de onbekende elementen alleen de subelementen met de coördinaten geconverteerd.
43
172,50 165,94 207,155 246,145 256,105 253,57 247,33 172,50 Voorbeeld 13: gml:Huis, een nieuw ontwikkeld element
In voorbeeld 13 wordt er gebruik gemaakt van het nieuw aangemaakte element gml:Huis, omdat het programma dit element niet kent wordt er naar de subelementen gekeken en hier staat het element gml:Polygon, een element dat wel bekend is in het programma. Het nieuwe element zal dus wel naar SVG worden omgezet, als gml:Polygon element, en niet als gml:Huis element. Indien er rondom gml:Huis een FeatureMember element staat, met daarin een Name of een Description dan wordt deze overgenomen en wordt deze getoond als de gebruiker met de muis over de desbetreffende Polygon ofwel Huis gaat. Maximale bestandsgrootte Zoals al eerder aangegeven, in § 4.1, zit er een maximum aan de grootte van de in te voeren GML documenten. GML documenten zijn over het algemeen vrij grote bestanden omdat er veel geografische gegevens in worden opgeslagen. Dit maximum zorgt ervoor dat niet alle GML documenten die de gebruiker zou willen invoeren ook ingevoerd kunnen worden. De maximale grootte hangt samen met de internetverbinding van de gebruiker. Bij een internetverbinding via de telefoon is de maximale bestandsgrootte kleiner dan bij een internetverbinding via de kabel. Hoe sneller de verbinding hoe groter het GML bestand mag zijn.
6.
Conclusie en aanbevelingen
De onderzoeksvraag, “Hoe kan een GML bestand, bestaande uit elementen, eenvoudig en zonder extra aanpassingen worden omgezet naar een SVG bestand?”, die aan het begin van het onderzoek gesteld was kan als volgt beantwoord worden: Een GML bestand bestaande uit standaardelementen, kan eenvoudig en zonder dat de gebruiker extra aanpassingen moet verrichten, worden omgezet naar SVG door middel van enkele aanpassingen in het GML document, zodat door middel van een XSLT bestand, gegevens uit het document kunnen worden gefilterd en het document kan worden geconverteerd naar SVG. Het programma dat ontwikkeld is, om een antwoord te kunnen geven op de onderzoeksvraag, is zo opgebouwd dat het daadwerkelijk zeer eenvoudig is voor een gebruiker om een GML document in te kunnen geven en om vervolgens het resultaat in SVG te kunnen aanschouwen. Een voorwaarde voor het bouwen zo’n programma is dat de gebruiker geen belangrijke keuzes hoeft te maken voor wat betreft het ingeven van GML documenten. 44
In het uiteindelijke conversieprogramma kan de gebruiker een GML document zoeken op zijn of haar PC, om deze vervolgens, door een druk op de knop ‘verzenden’ te versturen. Het GML document wordt op de server geplaatst en een Perl-script haalt bepaalde gegevens uit het document die later weer van nut zijn bij het maken van het SVG document. In de volgende stap worden, door middel van een XSLT bestand, basisobjecten uit het GML document gefilterd en weggeschreven in een XML bestand. De volgende GML basisobjecten worden door het programma uit het GML document gefilterd: gml:Polygon, gml:LineString, gml:Point en gml:Box. De overige basisobjecten zijn verzamelelementen, dat wil zeggen elementen waarbinnen meerdere elementen zitten, bijvoorbeeld een verzamelelement die Polygon elementen bevat. Tijdens de zoektocht naar de basiselementen worden ook de elementen uit de verzamelelementen gevonden, en dus ook in het XML bestand weggeschreven. Alle basisobjecten die worden gevonden krijgen een unieke ID toegewezen en worden in groepen in het XML bestand geplaatst, alle gml:Polygon elementen behoren tot de groep Polygonen en de gml:Point elementen behoren tot de groep Points. Het voordeel van het aanmaken van deze groepen is dat de gebruiker, in het nieuw aangemaakte SVG document, bepaalde groepen aan of uit kan schakelen, ofwel zichtbaar of onzichtbaar kan maken. Nadat alle basisobjecten zijn weggeschreven wordt door middel van een tweede XSLT bestand het daadwerkelijke SVG document aangemaakt. Het XSLT bestand schrijft de standaard SVG regels in het document weg, voegt vervolgens de basisobjecten uit het XML bestand toe en voegt regels aan het SVG bestand toe waardoor de gebruiker de volgende extra mogelijkheden heeft: y De gebruiker kan in- en uitzoomen op de SVG kaart, vooral als het gaat om een grote SVG kaart, met veel verschillende elementen, is het inzoomen een erg nuttige optie. De gebruiker kan tot 100 keer de oorspronkelijke grootte inzoomen op de SVG kaart. y Via panning, kan de gebruiker direct, en zonder over de kaart te hoeven scrollen, dat gedeelte aanklikken dat de gebruiker wil zien. y Dankzij een coördinatiesysteem, ingebouwd in het SVG document, kan de gebruiker, tijdens het schuiven van de muis over de SVG kaart, zien op welke locatie de muis zich in het document bevindt. Door het plaatsen van de muis op een object, op een bepaalde locatie, kunnen de coördinaten van het desbetreffende object worden gevonden. Tevens wordt bij het plaatsen van de muis op een object, de naam van het object en het FeatureID nummer van het object, getoond. Als alle stappen zijn doorlopen, keert het programma terug bij het invoerscherm, en kan de gebruiker kiezen voor de optie ‘resultaat bekijken’. Het kan voorkomen dat een bepaald SVG document vaker gebruikt dient te worden, in dat geval is het voor de gebruiker praktischer om het SVG bestand te downloaden, zodat het GML document niet steeds hoeft te worden geconverteerd. Het voordeel van zowel GML als SVG documenten is, dat het beide XML afgeleide webtalen zijn, en dus een zelfde opzet hebben, wat het mogelijk maakt om door middel van enkele aanpassingen het GML document te converteren naar een SVG document. Naast dit voordeel zit er echter een groot nadeel aan de GML taal, GML elementen kunnen moeilijk worden geconverteerd omdat GML een zeer vrije webtaal is waarin gebruikers zelf elementen aan kunnen maken.
45
Het is onmogelijk voor een conversieprogramma om te weten wat de gebruiker met deze zelf aangemaakte elementen bedoelt. Meynert19 geeft aan dat er in GML geen standaard elementen voor geografische objecten als straten, rivieren en gebouwen zijn, dit betekend dat als iemand een straat in GML wil invoeren er een nieuw element moet worden aangemaakt. Stel dat een gebruiker een element test:Strasse aanmaakt, het programma weet nu niet hoe dit element te interpreteren, gaat het hier om een straat, of om een weg. De GML taal zou eigenlijk moeten worden uitgebreid met een aantal standaard elementen die alle geografische objecten zoals straten, rivieren en gebouwen kan weergeven. Het aantal geografische objecten is relatief klein en is dus zeker als standaardelement in te voeren. In principe kunnen alle geografische objecten als standaard element worden aangemaakt, net als bij de huidige standaardelementen moet de voertaal Engels zijn. Te denken valt aan standaardelementen als: gml:Road, gml:River, gml:Lake, gml:Building en gml:Railway. Per geografisch object zou een element moeten worden aangemaakt zodat deze later, indien nodig, eenvoudig kunnen worden herkend en kunnen worden omgezet. Aanbevelingen voor verder onderzoek In dit onderzoek zijn een aantal punten naar voren gekomen waarvoor in een vervolgonderzoek oplossingen gevonden zouden kunnen worden. De volgende punten zijn geschikt voor een vervolgonderzoek: y Hoe kan de GML taal worden verbeterd zodat het goed gebruikt kan worden in combinatie met andere webtalen. Uitgangspunt moet wel zijn dat GML een vrijblijvende taal is en blijft. y Zodra de GML taal zich beter leent voor eventuele conversies naar andere XML talen, zou er een vervolgonderzoek plaats kunnen vinden met als doel een programma dat alle elementen uit een GML document kan converteren. In dat geval kan de gebruiker, in plaats van enkel basisobjecten uitschakelen, groepen met geografische objecten uit en aan kunnen schakelen. Als bijvoorbeeld alleen de straten zichtbaar moeten zijn dan moeten de gebouwen, rivieren en parken worden uitgeschakeld. Het SVG document dat is gecreëerd kan veel meer bieden dan dat het op dit moment doet. y Een oplossing voor de maximale bestandsgrootte zou tevens een aandachtspunt kunnen zijn in een vervolgonderzoek. Het maximum belet gebruikers om grote GML documenten te converteren.
19
Meynert, 2.
46
7.
Literatuurlijst
Bonati, L.P., Fortunati, L., Fresta, G. ‘SVG Explorer of GML Data’. (2003). Geraadpleegd op 14 februari 2005. Beschikbaar via http://www.svgopen.org/2003/papers/SvgExplorerOfGmlData/index.html Bradley, N., The XML Companion. 3e druk. Harlow: Pearson Education Limited, 2002. Carto.net, www.carto.net Converse, T., Park, J., PHP Bible. 2e druk. Indianapolis: Wiley Publishing, 2002. Cox, S., Cuthbert, A., Daisey, P., e.a. ‘OpenGIS Implementation Specification’. (2002). Geraadpleegd op 14 februari 2005. Beschikbaar via http://www.opengeospatial.org/docs/02069.pdf Guo, Z., Zhou, S., Xu, Z. e.a. ‘G2ST: a novel method to transform GML to SVG’. Proceedings of the eleventh ACM international symposium on Advances in geographic information systems. (2003): 161 – 168. Hammond, M., Programming for Linguists. 1e druk. Malden: Blackwell Publishing Ltd., 2003. Jackson, D.’Scalable Vector Graphics’. (2004). Geraadpleegd op 14 februari 2005. Beschikbaar via http://www.w3.org/TR/SVG12/ Jones, C., Geographical Information Systems and Computer Cartography. 1e druk. Harlow: Pearson Education Limited, 1997. Köbben, Barend. ‘SVG and the TOP10NL project’. (2003). Geraadpleegd op 14 februari 2005. Beschikbaar via http://kartoweb.itc.nl/kobben/publications/SVG_in_Top10NL.pdf. Meynert, A. ‘Publishing GML data as interactive SVG maps’. (2003). Geraadpleegd op 14 februari 2005. Beschikbaar via http://www.svgopen.org/2003/papers/cleopatra/index.html Open GIS Consortium, http://www.opengeospatial.org O'Reilly books, specifically, Sal Mangano, the author of XSLT Cookbook (ISBN 0-596-00372-2) Pohlmann, R.’SVG tutorial’. (2003). Geraadpleegd op 14 februari 2005. Beschikbaar via http://svg.tutorial.aptico.de/index.php W3schools, http://www.w3schools.com Williams, J., Neumann, A. ‘Navigation Tools for SVG Maps’ Carto.net. (2005). Geraadpleegd op 14 februari 2005. Beschikbaar via http://www.carto.net/papers/svg/navigationTools/
47
World Wide Web Consortium, www.w3.org Zaslavsky, I. ‘A New Technology for Interactive Online Mapping with Vector Markup and XML’. Cartographic Perspectives, 37 (2000): 12-24.
48
8.
Bijlagen
8.1
Het cgi bestand
#!D:\programma\perl\bin\perl.exe -wT use CGI qw(:standard); use CGI::Carp qw(warningsToBrowser fatalsToBrowser); use strict; # print the html headers print header; print start_html("Environment"); # view_size is de grootte van de viewbox. Deze wordt als GET variabele meegegeven. # my $input_file = "coordinate1.xml"; # Het input bestand leest de door de XSLT gecreeerde coordinaten xml in. my $input_file = "C:\\PHP\\scriptie\\coordinate.xml"; open(INFO,$input_file) or &dienice("Kan $input_file niet open om uit te lezen: $!"); open(BESTAND2,">coord.xml") or &dienice("Kan coord.xml niet open om in weg te schrijven: $!"); # teller telt het aantal regels dat met start begint. # regels is een array waarin alle afzonderlijke regels uit het bestand komen te staan. # y_as is een array in welke alle y-waarden staan. # x_as is een array in welke alle x-waarden staan. my $teller = 0; my @xy; my @regels; my @y_as; my @x_as; # Het bestand inlezen en als regel met start: begint dan teller +1 en de regel in array regels plaatsen. # Geen start? Dan zal het om een gmlBox gaan, deze hebben X en Y waarden. while (my $regel = ) {
}
if($regel =~/Start:/) { $teller++; push(@regels, $regel); } else { push(@xy, $regel); }
49
# Als de teller groter dan 0 dan staan er dus coordinaten in de regels en dus verder gaan met bewerken. if($teller > 0) { # Elke variabele in de array regels wordt bewerkt. # Eerst Start: verwijderen, vervolgens elke spatie omzetten in een return en elke komma omzetten in # een nieuwe regel en een y, om zodoende de y-waarden te kunnen herkennen. # Tot slot de regel wegschrijven in het bestand coord.xml. foreach my $line (@regels) { $line =~ s/Start://; $line =~ s/\s/\n/g; $line =~ s/,/\ny/g; print BESTAND2 $line; } # Het bestand coord.xml moet worden afgesloten omdat deze vervolgens weer geopend dient te worden # om zodoende het bestand te kunnen inlezen. close(BESTAND2); open(BESTAND3,"coord.xml") or &dienice("Kan coord.xml niet open om in weg te schrijven: $!"); # Nummer bevat elke keer een aparte regel uit het bestand coord.xml # Als de regel begint met een y, en dus een y-waarde is dan moet deze # waarde worden weggeschreven in de array waarin alle y-waarden staan. # Staat er geen y dan wordt de waarde weggeschreven in de array met xwaarden. open(TEST,">test.xml") or &dienice("Kan test.xml niet open om in weg te schrijven: $!"); my $nummer1; while (my $nummer = ) { if($nummer =~/y/) { $nummer =~ s/y//; push(@y_as, $nummer); } else { push(@x_as, $nummer); } } # hoogste_x en y bevatten straks de hoogste x- en y waarde. # laagste_x en y de laagste x- en y waarde. my $hoogste_y = -1000000000; my $hoogste_x = -1000000000; my $laagste_y = 1000000000; my $laagste_x = 1000000000; # De array y_as inlezen en als ingelezen waarde hoger is dan hoogste ywaarde dan vervangen. # Is waarde lager dan laagste waarde, ook dan vervangen. Ditzelfde geldt voor de x-array. foreach my $test_y (@y_as)
50
{
if($test_y > $hoogste_y) { $hoogste_y = $test_y; } if($test_y < $laagste_y) { $laagste_y = $test_y; }
} foreach my $test_x (@x_as) { if($test_x > $hoogste_x) { $hoogste_x = $test_x; } if($test_x < $laagste_x) { $laagste_x = $test_x; } } close(BESTAND3); # De breedte kan worden uitgerekend door de laagste x-waarde van de hoogste x-waarde af te trekken. # De hoogte kan worden berekend door de laagste y-waarde van de hoogste y-waarde af te trekken. my $breedte = ($hoogste_x - $laagste_x); my $hoogte = ($hoogste_y - $laagste_y); # Laagste x en y afronden naar beneden, tevens breedte en hoogte afronden naar boven $laagste_y =~ s/\..*//; $laagste_x =~ s/\..*//; if($laagste_y =~/-/) { $laagste_y--; } if($laagste_x =~/-/) { $laagste_x--; } $breedte =~ s/\..*//; $breedte = $breedte + 1; $hoogte =~ s/\..*//; $hoogte = $hoogte + 1; # Welke is groter, de breedte of de hoogte? # Het grootste getal moet net zolang gedeeld worden totdat het kleiner is dan view_size. my $grootste; if($breedte > $hoogte) { $grootste = $breedte; }
51
else {
$grootste = $hoogte;
}
# Viewbox krijgt straks de uiteindelijke afmetingen. # tel_view telt het aantal stappen. # verm_view is de vermenigvuldigingsfactor met welke de afmetingen moeten worden vermenigvuldigd. my $viewbox; # Zoland grootste groter is dan de afmetingen van de viewbox deze stappen doorlopen. $viewbox = $grootste; # print "Size: $view_size
Tel_view: $tel_view
Grootste: $grootste
Vermenigv: $verm_view
Nieuwe size: $viewbox
"; # Vervolgens het bestand coordinaten.xml openen om de waarden in weg te kunnen schrijven. # Dit bestand wordt een xml bestand uit welke straks de waarden voor de SVG viewbox kunnen worden gehaald. open(BESTAND4,">C:\\PHP\\scriptie\\viewbox.xml") or &dienice("Kan coordinaten.xml niet open om in weg te schrijven: $!"); print BESTAND4 ""; print BESTAND4 "$laagste_x$laagste_y$breedte$hoogte$viewbox"; close(BESTAND4); } else { # Als geen coordinaten dan uitgaan van een gmlBox en hier verder gaan. # X1..Y2 zijn variabelen die de waarden van X1..Y2 uit het bestand overnemen. # Voor elke waarde staat X1:, X2: etc. Dit moet verwijdert worden. my $X1; my $X2; my $Y1; my $Y2; foreach my $line (@xy) { if($line =~/X1:/) { $line =~ s/X1://; $X1 = $line; } if($line =~/X2:/) { $line =~ s/X2://; $X2 = $line; }
52
if($line =~/Y1:/) { $line =~ s/Y1://; $Y1 = $line; } if($line =~/Y2:/) { $line =~ s/Y2://; $Y2 = $line; } } # X_hoogst is de hoogste X-waarde - laagste X-waarde, zelfde geldt voor Y_hoogst alleen dan met Y-waarden. # hoogst heeft de hoogste waarde van de twee variabelen X_hoogste en Y_hoogst. # laagste_x en y bevat de dempelwaarde van X en van Y. my $X_hoogst; my $Y_hoogst; my $hoogst; my $laagste_x; my $laagste_y; if($X1 > $X2) { $X_hoogst = ($X1 - $X2); $laagste_x = $X2; } if($X2 > $X1) { $X_hoogst = ($X2 - $X1); $laagste_x = $X1; } if($Y1 > $Y2) { $Y_hoogst = ($Y1 - $Y2); $laagste_y = $Y2; } if($Y2 > $Y1) { $Y_hoogst = ($Y2 - $Y1); $laagste_y = $Y1; } my $breedte; my $hoogte; $breedte = $X_hoogst; $hoogte = $Y_hoogst; if($X_hoogst > $Y_hoogst) { $hoogst = $X_hoogst; } else { $hoogst = $Y_hoogst; }
53
# Viewbox krijgt straks de uiteindelijke afmetingen. # tel_view telt het aantal stappen. # verm_view is de vermenigvuldigingsfactor met welke de afmetingen moeten worden vermenigvuldigd. my $viewbox; $viewbox = $hoogst; # Vervolgens het bestand coordinaten.xml openen om de waarden in weg te kunnen schrijven. # Dit bestand wordt een xml bestand uit welke straks de waarden voor de SVG viewbox kunnen worden gehaald. open(BESTAND4,">C:\\PHP\\scriptie\\viewbox.xml") or &dienice("Kan coordinaten.xml niet open om in weg te schrijven: $!"); print BESTAND4 ""; print BESTAND4 "$laagste_x$laagste_y$breedte$hoogte$viewbox"; close(BESTAND4); } close(INFO); # Tot slot naar deze link. print "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"0; URL=http://localhost/RuG/scriptie/pag3.php\">"; # print "<META HTTP-EQUIV=\"Refresh\" CONTENT=\"2; URL=test3.cgi\">"; print end_html; sub dienice { my($errmsg) = @_; print "Error
\n"; print "$errmsg
\n"; print end_html; exit; }
54
8.2
XSLT bestanden
SVG1.XSLT <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:gml='http://www.opengis.net/gml' xmlns:svg="http://www.w3.org/2000/svg" version="1.0"> <xsl:output method="xml" /> <xsl:variable name="ViewDoc" select="document('viewbox.xml')"/> <xsl:variable name="komma_space"> <xsl:text disable-output-escaping = "no">, <xsl:variable name="X_min"> <xsl:text disable-output-escaping = "no">XXX- <xsl:variable name="just_space"> <xsl:text disable-output-escaping = "no"> <xsl:variable name="all_X"> <xsl:text disable-output-escaping = "no">XXX <xsl:variable name="space_komma"> <xsl:text disable-output-escaping = "no">, <xsl:variable name="linestring_stroke"> <xsl:value-of select="($ViewDoc/root/viewbox_size) * 0.0001"/> <xsl:template match="/"> <poly_object id="all_polygon"><xsl:apply-templates select="//gml:Polygon"/> <xsl:apply-templates select="//gml:LineString"/> <point_object id="all_points"><xsl:apply-templates select="//gml:Point"/> <xsl:apply-templates select="//gml:Box"/> <xsl:template match="gml:Polygon"> <xsl:variable name="Ran_id"> <xsl:value-of select="generate-id(.)"/> <xsl:if test="not(../../@fid) = '' "> <xsl:element name="fid"> <xsl:value-of select="../../@fid"/> <xsl:choose> <xsl:when test="not(../../gml:description) = '' "> <xsl:element name="desc"> <xsl:value-of select="../../gml:description"/> <xsl:otherwise> <xsl:for-each select="parent::*/parent::*/child::*"> <xsl:if test="contains(name(),'descript')"> <xsl:element name="desc_fid"> <xsl:value-of select="." /> <xsl:if test="contains(name(),'name')"> <xsl:element name="name_fid"> <xsl:value-of select="." /> <xsl:for-each select="."> <xsl:choose> <xsl:when test="contains(.//gml:coordinates,',-')"> <xsl:variable name="polygon_rep1"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="',-'"/> <xsl:with-param name="replace-string" select="'XXX'"/> <xsl:variable name="polygon_rep2"> <xsl:call-template name="search-and-replace">
56
<xsl:with-param name="input" select="$polygon_rep1"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="',-'"/> <xsl:variable name="polygon_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$polygon_rep2"/> <xsl:with-param name="search-string" select="'XXX'"/> <xsl:with-param name="replace-string" select="','"/> <path style="stroke:black; stroke-width:.001cm;" d="M{$polygon_rep}"/> <xsl:otherwise> <xsl:variable name="polygon_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="',-'"/> <path style="stroke:black; stroke-width:.001cm;" d="M{$polygon_rep}"/> <xsl:template match="gml:LineString">
57
<xsl:variable name="Ran_id"> <xsl:value-of select="generate-id(.)"/> <xsl:if test="not(../../@fid) = '' "> <xsl:element name="fid"> <xsl:value-of select="../../@fid"/> <xsl:choose> <xsl:when test="not(../../gml:description) = '' "> <xsl:element name="desc"> <xsl:value-of select="../../gml:description"/> <xsl:otherwise> <xsl:for-each select="parent::*/parent::*/child::*"> <xsl:if test="contains(name(),'descript')"> <xsl:element name="desc_fid"> <xsl:value-of select="." /> <xsl:if test="contains(name(),'name')"> <xsl:element name="name_fid"> <xsl:value-of select="." /> <xsl:for-each select="."> <xsl:choose> <xsl:when test="(gml:coord/gml:Y < 0) or (gml:coord/gml:Y > 0)"> <xsl:variable name="testen"> <xsl:call-template name="line_coord"/> <polyline style="fill:none; stroke:black; strokewidth:{$linestring_stroke}cm;" points="{$testen}"/> <xsl:when test="contains(.//gml:coordinates,',-')"> <xsl:variable name="linestring_rep1"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="',-'"/> <xsl:with-param name="replace-string" select="$all_X"/> <xsl:variable name="linestring_rep2"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$linestring_rep1"/> <xsl:with-param name="search-string" select="' '"/> <xsl:with-param name="replace-string" select="$komma_space"/> <xsl:variable name="linestring_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$linestring_rep2"/>
58
<xsl:with-param name="search-string" select="'XXX'"/> <xsl:with-param name="replace-string" select="$just_space"/> <polyline style="fill:none; stroke:black; strokewidth:{$linestring_stroke}cm;" points="{$linestring_rep}"/> <xsl:otherwise> <xsl:variable name="linestring_rep1"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="$X_min"/> <xsl:variable name="linestring_rep2"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$linestring_rep1"/> <xsl:with-param name="search-string" select="' '"/> <xsl:with-param name="replace-string" select="$komma_space"/> <xsl:variable name="linestring_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$linestring_rep2"/> <xsl:with-param name="search-string" select="'XXX'"/> <xsl:with-param name="replace-string" select="$just_space"/> <polyline style="fill:none; stroke:black; strokewidth:{$linestring_stroke}cm;" points="{$linestring_rep}"/> <xsl:template name="line_coord"> <xsl:for-each select="gml:coord"> <xsl:choose> <xsl:when test="gml:Y < 0"> <xsl:variable name="linestring_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="gml:Y"/> <xsl:with-param name="search-string" select="'-'"/> <xsl:with-param name="replace-string" select="''"/>
59
<xsl:value-of select="./gml:X"/><xsl:text disable-output-escaping = "no"> <xsl:value-of select="$linestring_rep"/>,<xsl:text disable-outputescaping = "no"> <xsl:otherwise> <xsl:variable name="linestring_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="gml:Y"/> <xsl:with-param name="search-string" select="gml:Y"/> <xsl:with-param name="replace-string" select="0 - gml:Y"/> <xsl:value-of select="./gml:X"/><xsl:text disable-output-escaping = "no"> <xsl:value-of select="$linestring_rep"/>,<xsl:text disable-outputescaping = "no"> <xsl:template match="gml:Point"> <xsl:variable name="Ran_id"> <xsl:value-of select="generate-id(.)"/> <xsl:if test="not(../../@fid) = '' "> <xsl:element name="fid"> <xsl:value-of select="../../@fid"/> <xsl:choose> <xsl:when test="not(../../gml:description) = '' "> <xsl:element name="desc"> <xsl:value-of select="../../gml:description"/> <xsl:otherwise> <xsl:for-each select="parent::*/parent::*/child::*"> <xsl:if test="contains(name(),'descript')"> <xsl:element name="desc_fid"> <xsl:value-of select="." />
60
<xsl:if test="contains(name(),'name')"> <xsl:element name="name_fid"> <xsl:value-of select="." /> <xsl:for-each select="."> <xsl:choose> <xsl:when test="gml:coord/gml:Y < 0"> <xsl:variable name="point_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="gml:coord/gml:Y"/> <xsl:with-param name="search-string" select="'-'"/> <xsl:with-param name="replace-string" select="''"/> <xsl:variable name="point_X"> <xsl:value-of select="gml:coord/gml:X"/> <xsl:variable name="point_Y"> <xsl:value-of select="$point_rep"/> <xsl:when test="gml:coord/gml:Y > 0"> <xsl:variable name="point_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="gml:coord/gml:Y"/> <xsl:with-param name="search-string" select="gml:coord/gml:Y"/> <xsl:with-param name="replace-string" select="0 - gml:coord/gml:Y"/> <xsl:variable name="point_X"> <xsl:value-of select="gml:coord/gml:X"/> <xsl:variable name="point_Y"> <xsl:value-of select="$point_rep"/> <xsl:when test="contains(.//gml:coordinates,',-')"> <xsl:variable name="point_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="',-'"/> <xsl:with-param name="replace-string" select="','"/> <xsl:variable name="point_X" select="substringbefore(gml:coordinates,',')"/> <xsl:variable name="point_Y" select="substring-after($point_rep,',')"/>
61
<xsl:otherwise> <xsl:variable name="point_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="',-'"/> <xsl:variable name="point_X" select="substringbefore(gml:coordinates,',')"/> <xsl:variable name="point_Y" select="substring-after($point_rep,',')"/> <xsl:template match="gml:Box"> <xsl:variable name="Ran_id"> <xsl:value-of select="generate-id(.)"/> <xsl:if test="not(../../@fid) = '' "> <xsl:element name="fid"> <xsl:value-of select="../../@fid"/> <xsl:choose> <xsl:when test="not(../../gml:description) = '' "> <xsl:element name="desc"> <xsl:value-of select="../../gml:description"/>
62
<xsl:otherwise> <xsl:for-each select="parent::*/parent::*/child::*"> <xsl:if test="contains(name(),'descript')"> <xsl:element name="desc_fid"> <xsl:value-of select="." /> <xsl:if test="contains(name(),'name')"> <xsl:element name="name_fid"> <xsl:value-of select="." /> <xsl:for-each select="."> <xsl:choose> <xsl:when test="(gml:coord[1]/gml:Y < 0) and (gml:coord[2]/gml:Y < 0)"> <xsl:variable name="box_Y1"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="gml:coord[1]/gml:Y"/> <xsl:with-param name="search-string" select="'-'"/> <xsl:with-param name="replace-string" select="''"/> <xsl:variable name="box_Y2"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="gml:coord[2]/gml:Y"/> <xsl:with-param name="search-string" select="'-'"/> <xsl:with-param name="replace-string" select="''"/> <xsl:variable name="box_X1"> <xsl:value-of select="gml:coord[1]/gml:X"/> <xsl:variable name="box_X2"> <xsl:value-of select="gml:coord[2]/gml:X"/> <xsl:variable name="box_width1"> <xsl:value-of select="$box_X2 - $box_X1"/> <xsl:variable name="box_height1"> <xsl:value-of select="$box_Y2 - $box_Y1"/> <xsl:when test="(gml:coord/gml:Y > 0) or (gml:coord/gml:Y = 0)"> <xsl:variable name="box_Y2"> <xsl:value-of select="gml:coord[2]/gml:Y"/> <xsl:variable name="box_Y1"> <xsl:value-of select="(gml:coord[1]/gml:Y) - $box_Y2"/>
63
<xsl:variable name="box_X1"> <xsl:value-of select="gml:coord[1]/gml:X"/> <xsl:variable name="box_X2"> <xsl:value-of select="gml:coord[2]/gml:X"/> <xsl:variable name="box_width1"> <xsl:value-of select="$box_X2 - $box_X1"/> <xsl:variable name="box_height1"> <xsl:value-of select="(gml:coord[2]/gml:Y) - (gml:coord[1]/gml:Y)"/> <xsl:when test="contains(.//gml:coordinates,',-')"> <xsl:variable name="box_rep1"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="',-'"/> <xsl:with-param name="replace-string" select="'XXX'"/> <xsl:variable name="box_rep2"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$box_rep1"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="',-'"/> <xsl:variable name="box_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="$box_rep2"/> <xsl:with-param name="search-string" select="'XXX'"/> <xsl:with-param name="replace-string" select="','"/> <xsl:variable name="box_verdeel1" select="substring-before($box_rep,' ')"/> <xsl:variable name="box_verdeel2" select="substring-after($box_rep,' ')"/> <xsl:variable name="box_X1" select="substring-before($box_verdeel1,',')"/> <xsl:variable name="box_X2" select="substring-before($box_verdeel2,',')"/> <xsl:variable name="box_Y1" select="substring-after($box_verdeel1,',')"/> <xsl:variable name="box_Y2" select="substring-after($box_verdeel2,',')"/> <xsl:variable name="box_width1"> <xsl:value-of select="$box_X2 - $box_X1"/> <xsl:variable name="box_height1"> <xsl:value-of select="$box_Y2 - $box_Y1"/>
64
<xsl:otherwise> <xsl:variable name="box_rep"> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select=".//gml:coordinates"/> <xsl:with-param name="search-string" select="','"/> <xsl:with-param name="replace-string" select="',-'"/> <xsl:variable name="box_verdeel1" select="substring-before($box_rep,' ')"/> <xsl:variable name="box_verdeel2" select="substring-after($box_rep,' ')"/> <xsl:variable name="box_X1" select="substring-before($box_verdeel1,',')"/> <xsl:variable name="box_X2" select="substring-before($box_verdeel2,',')"/> <xsl:variable name="box_Y1" select="substring-after($box_verdeel1,',')"/> <xsl:variable name="box_Y2" select="substring-after($box_verdeel2,',')"/> <xsl:variable name="box_width1"> <xsl:value-of select="$box_X2 - $box_X1"/> <xsl:variable name="box_height1"> <xsl:value-of select="$box_Y2 - $box_Y1"/> <xsl:template name="search-and-replace"> <xsl:param name="input"/> <xsl:param name="search-string"/> <xsl:param name="replace-string"/> <xsl:choose> <xsl:when test="$search-string and contains($input, $search-string)"> <xsl:value-of select="substring-before($input,$search-string)"/> <xsl:value-of select="$replace-string"/> <xsl:call-template name="search-and-replace"> <xsl:with-param name="input" select="substring-after($input,$searchstring)"/> <xsl:with-param name="search-string" select="$search-string"/> <xsl:with-param name="replace-string" select="$replace-string"/>
65
<xsl:otherwise> <xsl:value-of select="$input"/>
66
SVG2.XSLT <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:gml='http://www.opengis.net/gml' xmlns:svg="http://www.w3.org/2000/svg" version="1.0"> <xsl:output method="xml" /> <xsl:variable name="ViewDoc" select="document('viewbox.xml')"/> <script type="text/ecmascript"> var highChoice = 'Rommel'; function highlite(n) { obj = svgDocument.getElementById(highChoice); obj.setAttribute("fill","#FFFFCD"); obj.setAttribute("opacity",".5"); highChoice = n; obj = svgDocument.getElementById(highChoice); obj.setAttribute("fill","#fc3"); obj.setAttribute("opacity",".5"); } // // jaar geeft aan om welke provincie het gaat. <xsl:variable name="bla"> <xsl:value-of select="$ViewDoc/root/viewbox_size"/>
<script type="text/ecmascript"> <xsl:value-of select="$viewb_getal3"/>,<xsl:value-of select="$viewb_getal4zoom"/>
68
,0.6,0,"",true,"coordX","coordY",dynamicLayers,digiLayers,""); //slider properties: x1,y1,value1,x2,y2,value2,startValue,group in which to build the slider,color of slider //width of slider of sliderbar,width of invisible slider bar,width of visible slider myZoomSlider = new slider(710,70,myMainMap.minWidth,710,170,myMainMap.maxWidth, myMainMap.maxWidth,"mapZoomSlider","dimgray",2,10,"sliderSym bol","myRefMapDragger.resizeDragger",true); //set constraints to draggable rect in reference map myRefMapDragger = new dragObj("dragRectForRefMap","referenceMap","myDragCross", ]]> <xsl:value-of select="$little_cross"/>
DOCUMENT_NODE
var directTarget = evt.target; if( directTarget.getNodeType() != 9 ) // if not svgDoc = directTarget.ownerDocument; else svgDoc = directTarget; svgObjInfo = svgDoc.getElementById("infoText"); svgObjFid = svgDoc.getElementById("fidText"); svgObjInfo = svgObjInfo.firstChild; svgObjFid = svgObjFid.firstChild;
} function loadProjectSpecific() { //adopt width and height of map extent document.getElementById("myScaleTextW").firstChild.nodeValue = formatNumberString(myMainMap.curWidth.toFixed(myMainMap.nrDe cimals)) + myMainMap.units; document.getElementById("myScaleTextH").firstChild.nodeValue = formatNumberString(myMainMap.curHeight.toFixed(myMainMap.nrD ecimals)) + myMainMap.units; //adopt line width of park boundary document.getElementById("all_polygon").setAttributeNS(null," stroke-width",myMainMap.curWidth*0.005); } ]]> <defs> <style type="text/css">
69
.normalText {font-size:15;} .smallText {font-size:12;} .boldText {font-weight:bold;} .centerText {text-anchor:middle;} .dragRect {fill:#999999;stroke:none;opacity:0.2;} .dragSymbol {stroke:darkblue;} .normalLinestyle {fill:none;stroke:dimgray;} .background {fill:#B9C8C9;stroke:none;} .darkRectstyle {fill:dimgray;stroke:none;} .nofill {fill:none;} .whitefill {fill:white;} .normalfillcol {fill:dimgray;} .normallinecol {stroke:dimgray;} .nostroke {stroke:none;} .verythinline {stroke-width:1;} .thinline {stroke-width:1.5;} .normalline {stroke-width:2;} .mediumThickLine {stroke-width:5;} ]]> <symbol id="checkBoxRect" overflow="visible"> <symbol id="checkBoxCross" overflow="visible" class="normallinecol nofill verythinline" pointerevents="none"> <symbol id="magnifyer" overflow="visible" class="whitefill normalline normallinecol"> <symbol id="magnifyerZoomOut" overflow="visible" class="whitefill normalline normallinecol"> <use xlink:href="#magnifyer"/> <symbol id="magnifyerZoomIn" overflow="visible"> <use xlink:href="#magnifyer"/> <symbol id="magnifyerFull" overflow="visible"> <use xlink:href="#magnifyer"/> F
70
<symbol id="magnifyerManual" overflow="visible"> <symbol id="magnifyerZoomInWo" overflow="visible" class="whitefill normalline normallinecol"> <symbol id="magnifyerZoomOutWo" overflow="visible" class="whitefill normalline normallinecol"> <symbol id="symbPan" overflow="visible"> <path class="normallinecol verythinline nofill" d="M-2 6 C 2.2 2.5 -8.0 -0 -5.7 -1.9 C -4.3 -2.5 -3.3 -0.5 -2.5 0.7 C -3.2 -2.1 -5.5 -5.2 -3.6 -5.8 C -2.1 -6.3 -1.6 -3.6 -1.1 -1.9 C -0.9 -4.2 -1.6 -6.4 -0.2 -6.6 C 1.4 -6.8 0.9 -3 1.1 -1.9 C 1.5 -3.5 1.2 -6.1 2.5 -6.1 C 3.9 -6.1 3.5 -3.2 3.6 -1.6 C 4 -2.9 4.1 -4.3 5.3 -4.4 C 7.3 -3.5 4 2.2 3 6z"/> <symbol id="symbArrow" overflow="visible" class="nofill verythinline normallinecol" pointer-events="none"> <polyline points="-3,-5 3,-5 3,1 5,1 0,5 -5,1 -3,1 -3,-5"/> <symbol id="symbRecenter" overflow="visible"> <symbol id="sliderSymbol" overflow="visible" class="nofill mediumThickLine normallinecol" pointer-events="none"> <symbol id="myDragCrossSymbol" overflow="visible" strokewidth="{$little_cross_stroke}" class="nofill dragSymbol" pointerevents="none">
71
<marker id="myStartArrow" overflow="visible" orient="auto"> <polyline class="nostroke normalfillcol" points="-0.5,0 8,-2 8,2"/> <marker id="myEndArrow" overflow="visible" orient="auto"> <polyline class="nostroke normalfillcol" points="0.5,0 -8,-2 -8,2"/>
<svg id="mainMap" x="0" y="15" viewBox="{$ViewDoc/root/laagste_x} {$ViewDoc/root/laagste_y} {$ViewDoc/root/viewbox_size} {$viewb_getal4}" width="553" height="700"> <xsl:apply-templates select="//box_object/g"/> <xsl:apply-templates select="//poly_object/g"/> <xsl:apply-templates select="//line_object/g"/> <xsl:apply-templates select="//point_object/g"/> <path d="M0,0 0,0.1 0.1,0.1 0.1,0 0,0"/>
72
<xsl:apply-templates select="//objecten/box_object"/> <xsl:apply-templates select="//objecten/poly_object"/> <xsl:apply-templates select="//objecten/point_object"/> <xsl:apply-templates select="//objecten/line_object"/> GML - SVG converter 1.0 X: Y: Aan- en uitschakelen layers
73
<use id="checkBoxall_polygon" xlink:href="#checkBoxRect" onclick="checkBoxScript(evt,'all_polygon');checkBoxScr ipt(evt,'mouse_polygon')"/> <use id="checkCrossall_polygon" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkCrossmouse_polygon" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkBoxall_linestrings" xlink:href="#checkBoxRect" onclick="checkBoxScript(evt,'all_linestrings');checkBo xScript(evt,'mouse_line')"/> <use id="checkCrossall_linestrings" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkCrossmouse_line" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkBoxall_linestrings" xlink:href="#checkBoxRect" onclick="checkBoxScript(evt,'all_points');checkBoxScri pt(evt,'mouse_point')"/> <use id="checkCrossall_points" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkCrossmouse_point" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkBoxall_linestrings" xlink:href="#checkBoxRect" onclick="checkBoxScript(evt,'all_boxes');checkBoxScrip t(evt,'mouse_box')"/> <use id="checkCrossall_boxes" xlink:href="#checkBoxCross" visibility="visible"/> <use id="checkCrossmouse_box" xlink:href="#checkBoxCross" visibility="visible"/> Polygonen Lijnen Punten Rechthoeken Fid: Informatie:
74
Statusbar: Your Status Text R.M. van den Berg, The Netherlands, 2005 Terug naar het invoerscherm Download de bestanden <svg id="referenceMap" x="580" y="45" viewBox="{$ViewDoc/root/laagste_x} {$ViewDoc/root/laagste_y} {$ViewDoc/root/viewbox_size} {$viewb_getal4}" width="118.52" height="150" onmousedown="myRefMapDragger.drag(evt)" onmousemove="myRefMapDragger.drag(evt)" onmouseup="myRefMapDragger.drag(evt)" onmouseout="myRefMapDragger.drag(evt)"> <use xlink:href="#all_objects" /> <use id="myDragCross" x="{$ViewDoc/root/laagste_x}" y="{$ViewDoc/root/laagste_y}" xlink:href="#myDragCrossSymbol" visibility="hidden" /> Map Navigator
75
<use x="710" y="55" xlink:href="#magnifyerZoomInWo" onclick="zoomIt('in');" onmouseover="magnify(evt,1.2,'in');" onmouseout="magnify(evt,1,'in');"/> <use x="710" y="185" xlink:href="#magnifyerZoomOutWo" onclick="zoomIt('out');" onmouseover="magnify(evt,1.2,'out');" onmouseout="magnify(evt,1,'out');"/> <use x="740" y="85" xlink:href="#magnifyerFull" onclick="zoomIt('full');" onmouseover="magnify(evt,1.2,'full');" onmouseout="magnify(evt,1,'full');"/> <use x="770" y="85" xlink:href="#magnifyerManual" onclick="myMainMap.zoomManual()" onmouseover="magnify(evt,1.2,'manual');" onmouseout="magnify(evt,1,'manual');"/> <use x="800" y="85" xlink:href="#symbPan" onclick="myMainMap.panManual()" onmouseover="magnify(evt,1.2,'panmanual');" onmouseout="magnify(evt,1,'panmanual');"/> <use xlink:href="#symbRecenter" x="830" y="85" onmouseover="magnify(evt,1.2,'recenter')" onmouseout="magnify(evt,1,'recenter')" onclick="myMainMap.recenter()"/> <xsl:template match="objecten/box_object"> <xsl:for-each select="g"> <xsl:variable name="var_desc"> <xsl:choose> <xsl:when test="not(desc) = '' "> <xsl:value-of select="desc"/> <xsl:when test="not(desc_fid) = '' "> <xsl:value-of select="desc_fid"/> <xsl:otherwise> <xsl:value-of select="name_fid"/> <xsl:element name="use"> <xsl:attribute name="id"><xsl:value-of select="@id"/> <xsl:attribute name="xlink:href">#<xsl:value-of select="@id"/> <xsl:attribute name="onmouseover">highlite('<xsl:value-of select="@id"/>');showInfo("<xsl:value-of select='$var_desc'/>");showFid('<xsl:value-of select="fid"/>') <xsl:attribute name="onmouseout">emptyInfo();emptyFid()
76
<xsl:template match="objecten/poly_object"> <xsl:for-each select="g"> <xsl:variable name="var_desc"> <xsl:choose> <xsl:when test="not(desc) = '' "> <xsl:value-of select="desc"/> <xsl:when test="not(desc_fid) = '' "> <xsl:value-of select="desc_fid"/> <xsl:otherwise> <xsl:value-of select="name_fid"/> <xsl:element name="use"> <xsl:attribute name="id"><xsl:value-of select="@id"/> <xsl:attribute name="xlink:href">#<xsl:value-of select="@id"/> <xsl:attribute name="onmouseover">highlite('<xsl:value-of select="@id"/>');showInfo("<xsl:value-of select='$var_desc'/>");showFid('<xsl:value-of select="fid"/>') <xsl:attribute name="onmouseout">emptyInfo();emptyFid() <xsl:template match="objecten/point_object"> <xsl:for-each select="g"> <xsl:variable name="var_desc"> <xsl:choose> <xsl:when test="not(desc) = '' "> <xsl:value-of select="desc"/> <xsl:when test="not(desc_fid) = '' "> <xsl:value-of select="desc_fid"/> <xsl:otherwise> <xsl:value-of select="name_fid"/> <xsl:element name="use"> <xsl:attribute name="id"><xsl:value-of select="@id"/> <xsl:attribute name="xlink:href">#<xsl:value-of select="@id"/> <xsl:attribute name="onmouseover">highlite('<xsl:value-of select="@id"/>');showInfo("<xsl:value-of select='$var_desc'/>");showFid('<xsl:value-of select="fid"/>') <xsl:attribute name="onmouseout">emptyInfo();emptyFid() <xsl:template match="objecten/line_object"> <xsl:for-each select="g">
77
<xsl:variable name="var_desc"> <xsl:choose> <xsl:when test="not(desc) = '' "> <xsl:value-of select="desc"/> <xsl:when test="not(desc_fid) = '' "> <xsl:value-of select="desc_fid"/> <xsl:otherwise> <xsl:value-of select="name_fid"/> <xsl:element name="use"> <xsl:attribute name="id"><xsl:value-of select="@id"/> <xsl:attribute name="xlink:href">#<xsl:value-of select="@id"/> <xsl:attribute name="onmouseover">highlite('<xsl:value-of select="@id"/>');showInfo("<xsl:value-of select='$var_desc'/>");showFid('<xsl:value-of select="fid"/>') <xsl:attribute name="onmouseout">emptyInfo();emptyFid() <xsl:template match="poly_object/g"> <xsl:for-each select="."> <xsl:element name="g"> <xsl:attribute name="id"> <xsl:value-of select="@id"/> <xsl:attribute name="fill"> <xsl:value-of select="@fill"/> <xsl:attribute name="opacity"> <xsl:value-of select="@opacity"/> <xsl:element name="path"> <xsl:attribute name="style"> <xsl:value-of select="path/@style"/> <xsl:attribute name="d"> <xsl:value-of select="path/@d"/> <xsl:template match="line_object/g"> <xsl:for-each select="."> <xsl:element name="g"> <xsl:attribute name="id"> <xsl:value-of select="@id"/> <xsl:attribute name="fill">
78
<xsl:value-of select="@fill"/> <xsl:element name="polyline"> <xsl:attribute name="style"> <xsl:value-of select="polyline/@style"/> <xsl:attribute name="points"> <xsl:value-of select="polyline/@points"/> <xsl:template match="point_object/g"> <xsl:for-each select="."> <xsl:element name="g"> <xsl:attribute name="id"> <xsl:value-of select="@id"/> <xsl:attribute name="fill"> <xsl:value-of select="@fill"/> <xsl:element name="circle"> <xsl:attribute name="cx"> <xsl:value-of select="circle/@cx"/> <xsl:attribute name="cy"> <xsl:value-of select="circle/@cy"/> <xsl:attribute name="r"> <xsl:value-of select="$circle_radius"/> <xsl:attribute name="style"> <xsl:value-of select="circle/@style"/> <xsl:template match="box_object/g"> <xsl:for-each select="."> <xsl:element name="g"> <xsl:attribute name="id"> <xsl:value-of select="@id"/> <xsl:attribute name="fill"> <xsl:value-of select="@fill"/> <xsl:element name="rect"> <xsl:attribute name="x"> <xsl:value-of select="rect/@x"/> <xsl:attribute name="y"> <xsl:value-of select="rect/@y"/>
79
<xsl:attribute name="width"> <xsl:value-of select="rect/@width"/> <xsl:attribute name="height"> <xsl:value-of select="rect/@height"/> <xsl:attribute name="rx"> <xsl:value-of select="rect/@rx"/> <xsl:attribute name="ry"> <xsl:value-of select="rect/@ry"/> <xsl:attribute name="style"> <xsl:value-of select="rect/@style"/>
80