1 Kaartdigitalisatie De ontwikkeling van dxf->svg converter Mutatis en kaartgeneralisatie. Afstudeerscriptie van S.J.Helmantel Faculteit der Letteren,...
Adobe Illustrator Bitmap Common Gateway Interface Cascading Style Sheet dynamic Hypertext Markup Language Dynamic Link Library Document Type Definitons Autodesk Drawing eXchange Format European Computer Manufacturer's Assocation Grootschalige Basiskaart (Nederland) Graphics Interchange File Groningen Architectuur en Stedenbouw Joint Photographics Experts Group Mathematical Markup Language Portable Network Graphics Ruimtelijke Ordening & Economische Zaken Rijks Universiteit Groningen Standard Generalized Markup Language Synchronized Multimedia Integration Language Scalable Vector Graphics Tagged Image File Format World Wide Web Consortium eXtensible Markup Language eXtensible Stylesheet Language eXtensible Stylesheet Language Transformation
Inleiding
1
Inleiding
Al eeuwenlang worden geografische kaarten gemaakt en gebruikt, zo is een kaart van klei met daarop het noorden van Mesopotamië gevonden, die gemaakt is rond 3800 voor Christus. De oudste gevonden wereldkaart, uit de zesde of vijfde eeuw voor Christus, is van Babylonische afkomst. Geografische kaarten zijn op vele verschillende manieren gemaakt van perkament of papier tot houtsnijwerk of kopergravure of als decoratie op bijvoorbeeld tafels. In 1453 liet de Turkse sultan Mohammed II zelfs een kaart overzetten op tapijt om deze te vereeuwigen. Naast het gebruik als decoratie werden kaarten ook gebruikt als oriëntatiemiddel en als studiemateriaal.[1] Dankzij de hedendaagse elektronische media zijn de mogelijkheden wat betreft kaartgebruik toegenomen, te denken valt bijvoorbeeld aan het gebruik van kaarten in autonavigatiesystemen. Daarnaast kunnen kaarten via internet aan een breed publiek getoond worden, deze moeten dan eerst wel gedigitaliseerd worden en dat kan gebeuren door een cartograaf, maar ook door leken door middel van een converter. Aangezien ik tijdens mijn stage bij Platform GRAS (Groningen Architectuur en Stedenbouw) het maken van een digitale kaart ter ondersteuning van een digitale architectuurgids als opdracht had, heb ik besloten hier verder onderzoek naar te doen. Hieruit is een programma ontstaan, Mutatis, die naast het converteren ook verschillende mogelijkheden biedt om kaarten te generaliseren, waardoor de bestandsgrootte beperkt kan worden. Deze scriptie heeft de volgende opbouw. Naast een uitgebreidere inleiding op het onderwerp komt in hoofdstuk 1 het verschil tussen raster- en vectorbeelden aan de orde, als ook een toelichting op de vectorformaten Autocad DXF en SVG, met enkele toepassingsvoorbeelden van laatstgenoemde. Aangezien SVG een op XML gebaseerde taal is, wordt ook deze metataal kort geïntroduceerd. Vervolgens begint hoofdstuk 2 met een uitleg over de Grootschalige Basis Kaart Nederland, de standaard waarop de in dit onderzoek gebruikte DXF-bestanden zijn gebaseerd, om daarna voorbeelden van raster naar vector en vector naar vector converters te bespreken en af te sluiten met de eigen converter, Mutatis. Hoofdstuk 3 en 4 tonen de tijdens het onderzoek naar voren gekomen problemen, respectievelijk de bestandsgrootte en de kleurvlakken, en de mogelijke oplossingen. Als dit alles besproken is wordt er afgesloten met de conclusie en een aanbeveling voor vervolgonderzoek die te vinden zijn in hoofdstuk 5.
H1 - Kaartdigitalisatie
2
Hoofdstuk 1
Kaartdigitalisatie
1.1 Intro Al enkele jaren worden er gedrukte architectuurgidsen uitgebracht, waarin informatie te vinden is over de verschillende vormen van architectuur binnen een bepaald gebied. Doordat architectuur een dynamisch proces is, waarin dagelijks veranderingen kunnen voorkomen, is het mogelijk dat het drukwerk in korte tijd alweer verouderd is. Het zou dan ook het handigste zijn om een architectuurgids te hebben waarin veranderingen snel kunnen worden aangegeven. Doordat dit in gedrukte versie nauwelijks mogelijk is, is een digitale architectuurgids een uitkomst. Platform GRAS, het platform voor Groningen Architectuur en Stedenbouw, heeft zich sinds zijn oprichting op 5 oktober 1999 als doel gesteld om het debat over de gebouwde omgeving te stimuleren en aan te wakkeren. Aangezien een digitale architectuurgids een mogelijkheid biedt om deze doelstelling te bereiken is Platform GRAS in Groningen begonnen met het maken hiervan.
1.2 Digitale Architectuurgids De voor Gras gemaakte architectuurgids is een database gevuld met tabellen met allerhande informatie, waaronder coördinaatgegevens, over de architectuur binnen de stad Groningen. Deze informatie is via het internet1 te bereiken met de aan dit medium verbonden voordelen, zoals (uitgebreide) zoekfuncties en interactiviteit. Deze interactiviteit wordt vooral gecreëerd door een ingebouwde mogelijkheid om eigen keuzes binnen de architectuurgids, door middel van de coördinaatgegevens, op een digitale kaart als punten geprojecteerd te krijgen. Nadat de structuur van de database was aangelegd, werd in oktober 2002 een begin gemaakt met de opdracht om deze digitale kaarten te maken. Na onderzoek vanuit de Rijks Universiteit Groningen werd besloten dat de kaarten gemaakt zouden moeten worden in het SVG-formaat. Een formaat waarmee vectorbeelden getoond kunnen worden.
1
http://www.architectuurgids.org (30-7-2003 nog niet online)
H1 - Kaartdigitalisatie
3
1.2.1 SVG keuze Om te kijken welk formaat het meest geschikt is voor deze interactieve digitale kaart, werd in het RUG-onderzoek geëxperimenteerd met twee verschillende formaten. De eerste is een rasterbeeld in GIF-formaat en de tweede een vectorbeeld in SVGformaat, beide beeldsoorten worden in hoofdstuk 1.3 besproken. Het grootste probleem van het GIF-formaat in dit onderzoek is de wachttijd voor de gebruiker bij het opbouwen van het beeld. Hoe groter de bestandsgrootte des te langer de wachttijd, waardoor de gebruikerswaardering voor de pagina negatief beïnvloed zal worden. Om de wachttijd te beperken werden drie oplossingen aangedragen. De eerste oplossing is dHTML (dynamic Hypertext Markup Language), deze taal biedt meerdere opties om een internetpagina dynamischer te maken. Met een van deze opties is het mogelijk om een afbeelding in het geheugen op te slaan voor hergebruik op andere plaatsen. Op deze manier is het mogelijk om een kaart eenmaal te laden en vervolgens telkens opnieuw de gevonden coördinaatpunten als nieuwe laag hierover heen te leggen. Qua snelheid heeft deze manier de voorkeur, hij valt echter af doordat niet alle browsers dHTML ondersteunen, waardoor het niet mogelijk is het systeem browser en/of platform onafhankelijk aan te bieden. De tweede oplossing is het maken van een tijdelijke afbeelding, door middel van een script-taal als CGI of met behulp van Java, met daarop de kaart en coördinaatpunten. Deze afbeelding zal vervolgens telkens opnieuw naar de client applicatie verstuurd worden. Het creëren van deze tijdelijk afbeelding kost niet alleen tijd, maar ook de grootte hiervan is nog afhankelijk van de keuze binnen de architectuurgids. Wanneer coördinaatpunten gekozen worden die ver van elkaar afliggen, zal een groter bestand moeten worden overgeheveld naar de ‘client’ applicatie, waardoor de tijdswinst minimaal is. De derde oplossing is SVG wat als voordelen heeft dat het na het downloaden van een plug-in op vrijwel alle browsers of platformen draait, de kaart interactief gemaakt kan worden door middel van ECMA-script of Java-script en de bewerkingen uitgevoerd worden op de computer van de gebruiker, waardoor de verbinding en de server niet belast worden. Het gebruik van vectoren zorgt er ten slotte ten eerste voor dat er met de resolutie geen rekening gehouden hoeft te worden, aangezien het raster bij inzooming niet in beeld komt en ten tweede wordt het bestand verstuurd als losse coördinaten, waardoor de bestandsgrootte beperkt kan blijven. Deze kan echter nog vergroten, indien er voor een hoog detailniveau wordt gekozen. Doordat de digitale kaarten via het internet geraadpleegd zullen worden, is vooral de platform en/of browser onafhankelijkheid en de laadtijd van de kaarten van belang. Daarom krijgt het gebruik van een met behulp van SVG gemaakte vectorkaart de voorkeur boven een rasterkaart.
H1 - Kaartdigitalisatie
4
1.3 Raster- en vectorbeelden Rasterbeelden of bitmapbeelden zijn opgebouwd uit matrices met pixels met elk een eigen kleurwaarde (zie fig 1.1), doordat een beeldscherm ook uit pixels is opgebouwd wordt er weinig tijd gemoeid met het tonen van een rasterbeeld. De meest bekende formaten van deze beelden zijn BMP, GIF, JPEG en TIFF. Een nadeel van rasterbeelden ontstaat wanneer een kwalitatief goede kaart gewenst is met een beperkte bestandsgrootte, bitmapbeelden worden namelijk groter naarmate de kwaliteit verhoogd wordt. Bij inzooming op een rasterbeeld ontstaat een tweede nadeel, namelijk een zogenaamd ‘fuzzy’ gebied rond de gekleurde pixels (zie fig 1.2). Deze beeldsoort is dus vooral te gebruiken indien de kwaliteit en dus de bestandsgrootte niet de hoogste prioriteit heeft.
1 1 1 1 1 1 1 1 1
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 0 0 1
1 1 1 1 1 1 0 0 1
1 1 1 1 1 1 0 0 1
0 0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 0 1
1 1 1 1 1 1 1 1 1
Figuur 1.1 Voorbeeld Rasterbeeld teruggebracht tot matrix (9bij9 pixels) Vectorbeelden worden opgebouwd door middel van objecten, zoals lijnen en bogen, die omschreven zijn als een reeks (‘path’) coördinaten. Een speciaal programma is echter nodig om het beeld om te zetten naar het beeldscherm en dat kost tijd. Vectorbeelden worden vooral gebruikt wanneer nauwkeurige metingen verricht moeten worden of als een gedetailleerd beeld gewenst is. Een DXF bestand is een voorbeeld van een vectorbestand die gebruikt wordt om beelden in CAD programma’s te tonen, een voorbeeld van een taal die gebruik maakt van vectoren is SVG, een op XML gebaseerde taal.
Figuur 1.2 ingezoomd rasterbeeld
Figuur 1.3 ingezoomd vectorbeeld
H1 - Kaartdigitalisatie
5
1.4 Data eXchange Format Het DXF formaat is een door Autodesk ontwikkeld formaat om geometrische informatie in CAD programma’s te tonen. In eerste instantie was DXF alleen ontwikkeld voor Autocad maar tegenwoordig is het een in- en uitvoerstandaard voor CAD programma’s geworden. DXF bestanden worden als ASCII bestand opgeslagen en zijn als verschillende autocadversies weg te schrijven. Voor dit onderzoek zijn vooral de versies 12 en 14 van belang, de structuur van beide versies wordt dan ook in de volgende paragraaf nader bekeken en vergeleken.
1.4.1 Verschil opbouw DXF-12 en DXF-14 Een DXF bestand is opgedeeld in verschillende ‘sections’, zo heeft het DXF-12 formaat 4 secties, namelijk header, tables, blocks en entities. Met de komst van DXF-14 waren de secties verder uitgebreid met een classes en objects sectie. De secties bestaan uit meerdere groepen van twee regels, waarvan de eerste een ‘group code’ (GC) aangeeft en de tweede een ‘tag’ (T). Met deze GC wordt door middel van een getal aangegeven waarvoor de groep gebruikt zal worden en wat voor soort datatype de T is. In DXF-12 werden tien verschillende datatypen gedefinieerd, in DXF-14 waren dit er negentien. In tabel 1.4 zijn de verschillende GC’s aangegeven met de daarbij behorende datatypen. Group Codes Datatype 0-9 String 10 - 59 Floating-point (Double precision 3D point) 60 - 79 Integer (16-bit) 90 - 99 Integer (32-bit) 100 String 102 String 105 String (hexadecimal handle value) 140 - 147 Floating-point (Double precision scalar) 170 - 175 Integer (16-bit) 210 - 239 Floating-point2 280 - 289 Integer (8-bit) 300 - 309 Arbitrary text string 310 - 319 String (hex value of binary chunk) 320 - 329 String (hex handle value) 330 - 369 String (hex object Ids) 999 Comment (string) 1000 - 1009 String 1010 - 1059 Floating-point 1060 - 1070 Integer (16 bit) 1071 Integer (32-bit) Tabel 1.4 Group codes DXF-12 met DXF-14 uitbreiding in rood 2
Datatype i.c.m. GC komt niet voor in DXF-14
H1 - Kaartdigitalisatie
6
De voor dit onderzoek belangrijke GC’s en T’s bevinden zich in de header, tables, entities en block secties. In de header sectie staat de algemene informatie over het bestand, zoals de autocad versie en de minimale en maximale x en y waarden (zie tabel 1.5). De verschillende lagen zijn in de tables sectie te vinden en de objecten (cirkels, lijnen, etc.) en block-objecten bevinden zich respectievelijk in de entities en blocks sectie.
Group Code + Tag Uitleg 0 Een nieuwe sectie, SECTION 2 genaamd HEADER, HEADER 9 gemaakt in Autocad versie: $ACADVER 1 14 AC1014 (12 -> AC1009). ... 9 Met de minimum coördinaten: $EXTMIN X= 10 113.3446403642215 ... ... Met de maximum coördinaten: 9 ... $EXTMAX ... 0 Einde van deze sectie. ENDSEC 0 Nieuwe sectie, SECTION etc. 2 Tabel 1.5 Voorbeeld header sectie, met uitleg
H1 - Kaartdigitalisatie
7
1.5 eXtensible Markup Language In de begin jaren tachtig ontstond een internationale documentatie standaard, genaamd SGML. Aangezien deze standaard als ‘te omvangrijk beschouwd werd voor het internet’ ([7] p.1), werd vanuit het World Wide Web Consortium (W3C) begonnen met het ontwikkelen van een versimpelde vorm, waarna in 1998 de eerste geaccepteerde specificatie3 van XML het licht zag.
Dit is een voorbeeld! <eigen>Met eigen notatie! Fragment 1.6 Voorbeeld simpel XML bestand
Met deze taal is het mogelijk om een eigen notatie te creëren, waarmee nieuwe talen gecreëerd kunnen worden, vandaar dat XML ook wel bekend staat als een meta-taal. Het is wel noodzakelijk om de eigen notatie te definiëren aan de hand van een Document Type Definiton (DTD). Door middel van een stylesheet, zoals een Cascading Style Sheet (CSS) of XSL (eXtensible Stylesheet Language), is het mogelijk om de stijl van verschillende elementen te bepalen, waardoor het XML bestand correct zal worden weergegeven onafhankelijk van browsers en/of platformen.
Fragment 1.7 Voorbeeld aanroep stylesheet in XML bestand
Met XSLT is een taal ontwikkeld waarmee het tegenwoordig zelfs mogelijk is om XML om te zetten naar andere formaten, zoals HTML of SVG. Voorbeelden van talen die gebaseerd zijn op de meta-taal XML zijn MathML, SMIL en SVG.
1.6 Scalable Vector Graphics SVG is begin 2000 ontstaan doordat binnen het W3C de wens ontstaan was om een op XML gebaseerde taal te ontwikkelen, waarmee twee dimensionale vectorbeelden getoond kunnen worden. Aangezien XML als basis fungeert is SVG te combineren met andere op deze meta-taal gebaseerde talen, waardoor meer mogelijkheden ontstaan om informatie te presenteren op het internet. Doordat de informatie opgeslagen wordt als ‘kale’ tekst is het mogelijk om een svg bestand aan de hand van een tekstverwerker gemakkelijk en snel aan te passen (toegankelijkheid) en zal een tekst-object in het vectorbeeld ook als zodanig herkend worden, waardoor het svg bestand goed te doorzoeken is.
1.6.1 opbouw SVG-bestanden Een svg-bestand begint met een standaard verwijzing naar de gebruikte XMLsyntax, vervolgens wordt door middel van de ‘doctype’ aangegeven welke structuur het svg-bestand heeft. Daarna kan de daadwerkelijke beschrijving van het svg bestand beginnen, waarin onder andere de breedte, de lengte en de verschillende objecten aangegeven worden.
<svg width=”xx” height=”yy”> tekst --> Fragment 1.8 Standaard voorbeeld van een svg-bestand. Het tekstobject is een van de vele soorten van objecten die in SVG voor komen, al deze objecten worden omschreven als een reeks van coördinaten voorafgegaan door een vormdefinitie, enkele voor dit onderzoek relevante voorbeelden zijn te zien in tabel 1.9.
H1 - Kaartdigitalisatie
9
Object en voorbeeld Polyline: <polyline points=”x,y x,y ... x,y”/>
Uitleg Een polylijn is een lijn die opgebouwd is uit meer dan twee x- en y-coördinaten.
Een path die een lijn beschrijft geeft ten eerste aan bij welk punt begonnen moet worden (M = move to), vervolgens wordt een lijn (L) getrokken naar de daaropvolgende punten (minimaal 1).
Path (boog/arc-beschrijving): <path d=”M x,y A rx ry xflag4 lflag sflag5 x,y“/>
Ook een path die een boog/arc beschrijft geeft ten eerste aan bij welk punt begonnen moet worden (M = move to). Daarna wordt een arc (A) getekend aan de hand van de te gebruiken x- en y-straal (rx, ry), wordt de mogelijke rotatie ten opzichte van de x-as bepaald (xflag) en de largearc-flag (lflag) en sweep-flag (sflag) worden gebruikt om de richting te bepalen.
Text: ...tekst tekst...
Tekst wordt geplaatst op een coördinaatpunt (x,y) en heeft een stijl, vervolgens komt de daadwerkelijke tekst en wordt het tekst element afgesloten.
Line:
Een lijn is opgebouwd uit een begin x- en ycoördinaat (x1,y1) en een eind x- en y-coördinaat (x2,y2).
Tabel 1.9 Voorbeelden van SVG-objecten met uitleg.
Het is mogelijk om binnen een svg bestand verschillende groepen aan te geven door gebruik te maken van een ‘group’ element () en optioneel een unieke naam (id). Hierdoor kunnen objecten van een bepaalde laag in een groep worden gezet, waardoor een laagstructuur ontstaat of in stand gehouden wordt. Het ‘group’ element kan nog uitgebreid worden, zodat een stijl of actie gebruikt kan worden voor alle objecten binnen de groep. Zo is het mogelijk de stijl te veranderen door een kleurvulling (fill), een kleurwaarde (stroke), een dikte (stroke-width) of een kleurdoorzichtigheid (strokeopacity)7 van een object mee te geven. Ook is het mogelijk om de objecten te roteren (rotate) of te verplaatsen (translate) door middel van een te transformeer actie (transform). 4
X-axis-rotation heeft een waarde tussen 0 en 360 (graden) (voorbeeld zie fig. 3.8) Large-arc-flag en sweep-flag hebben een boolean-waarde (voorbeeld zie fig. 3.8) 6 Stijl-mogelijkheden: stroke (kleur), stroke-width (dikte), fill (vulling), font-family (lettertype), font-size (lettergrootte) 7 Waarden tussen 0 (doorzichtig) en 1 (ondoorzichtig) 5
H1 - Kaartdigitalisatie
10
... OBJECTEN... Fragment 1.10 Voorbeeld element
SVG kan naast interactief ook dynamisch zijn, door middel van het gebruik van een scripttaal (bijv. Javascript of Ecmascript) of animaties. Acties die uitgevoerd kunnen worden door een scripttaal variëren van het aan- en uitzetten van objecten of lagen tot het activeren van en communiceren met een achterliggende database. De animaties zorgen ervoor dat objecten langs een bepaalde route bewegen, waarbij vele extra’s aan te geven zijn, zoals tijdsduur, kleur, rotatie en schaal. Een plugin of viewer is nodig om SVG op het internet getoond te krijgen, deze zijn gemakkelijk en gratis via het internet te verkrijgen.
1.6.2 SVG plug-ins De adobe svg viewer is de meest aangehaalde plug-in en is gratis te downloaden van http://www.adobe.com/svg, een site waarop veel extra informatie en documentatie te vinden is. Deze viewer is te gebruiken voor Windows, Macintosh, Linux en Solaris computers en ondersteund Netscape 4.5 tot 4.77, Microsoft Internet Explorer 4 en hoger, Realplayer 8 en hoger en Opera 5.x. Een browser die in bovenstaande lijst niet voorkomt is Mozilla, om svg hierin te kunnen tonen zijn ‘libraries’ nodig die ontwikkeld worden in het SVG in Mozilla project. Ook voor het Java2 platform zijn viewers ontwikkeld, waaronder de Ionic SVG renderer en Jackaroo van Koala. Beide zijn ‘open source’, wat inhoudt dat de broncode openbaar is, waardoor het voor geïnteresseerden mogelijk is om de broncode aan te passen.
8
waarde tussen 0 en 360 (graden)
H1 - Kaartdigitalisatie
11
1.6.3 Toepassingsvoorbeelden Op het internet zijn op verschillende plaatsen meerdere toepassingsmogelijkheden van svg te vinden. Een internetpagina waarop naast vele artikelen ook vele voorbeelden, variërend van simpel tot uitgebreid met scripts, te vinden zijn is www.carto.net. Enkele van deze uitgebreide voorbeelden worden hier beschreven, aangezien deze een beeld geven van de mogelijkheden van svg en ook goed als basis kunnen fungeren voor de te maken digitale kaart. De attributen die de hieronder beschreven kaarten als basis hebben, zijn een zoomfunctie, waarmee het mogelijk is om de kaart waar gewenst te vergroten of te verkleinen, een laagkeuzefunctie, die het mogelijk maakt om een gedeelte (laag) van de kaart (on)zichtbaar te maken, een kaartoverzicht, waarop te zien is waar men zich bevindt op de hoofdkaart t.o.v. de gehele kaart en scripts, waarmee alle andere attributen aangestuurd worden om de kaart interactief te maken.
Vienna9 Deze kaart gemaakt door A.Neumann geeft de maatschappelijke patronen en structuren weer binnen Wenen. De kaart bezit naast de basisattributen ook nog een histogram, legenda en kleurvlakken. Aan de hand van de legenda en het histogram kan snel een duidelijk beeld verkregen worden van de maatschappelijke patronen en structuren binnen een Weense regio. Daarnaast worden de regio’s ook nog eens ingekleurd, waardoor kleurvlakken ontstaan, wat de duidelijkheid extra ten goede komt.
Campus TU-Dresden10 A.Berger maakte een kaart van de Dresdener campus die te gebruiken is als plattegrond. Naast de basisattributen biedt de kaart nog een informatiewinst per zoom, doordat meer informatie getoond wordt per zoom, bijvoorbeeld straatnamen. Ook heeft het kleurvlakken voor gebouwen en gebied, waardoor de gebruiker snel duidelijkheid krijgt over het gebied. Dit gebruik van kleurvlakken zou mogelijk ook gebruikt kunnen worden voor de digitale architectuurgids kaarten, aangezien deze ook een gebied tonen en als referentiemiddel gebruikt kunnen worden. Tot slot bezit de kaart een schaalindicatie, waardoor afstand af te lezen valt, en een legenda.
Gruben glacier11 Een voorbeeld van svg met animatie is de kaart van Y.Isakowski. De kaart toont de ontwikkeling van de Gruben gletsjer van 1970 t/m 1995. Naast de basisattributen en animatie, bezit de kaart een legenda, een diagram en een topografische kaart waarop de svg geprojecteerd wordt. De beslissing om een topografische rasterkaart als basis te gebruiken kan genomen worden indien er niet ingezoomd hoeft te worden of wanneer het niet mogelijk is om een svg beeld van de rasterkaart correct in te kleuren.
Tuerlersee12 Een andere kaart van A.Neumann biedt een interactieve topografische beeld van Tuerlersee. De basisattributen worden aangevuld met een uitgebreide schuifmogelijkheid, die vooral voordelig werkt indien door een uitgebreide inzooming de kaartprojectie op de gehele kaart (rechtsboven) dusdanig klein is geworden dat het lastig wordt om deze kaart nog te slepen. Extra topografische informatie over rivieren en hoogteverschil wordt ook geboden, als ook de mogelijkheid om een plaats te zoeken en ook bij deze kaart wordt een topografische rasterkaart als basis gebruikt. Een belangrijk extraatje biedt de kaart met de coördinaatindicator voor zowel x, y en z coördinaten. Dit attribuut zal zeker terug moeten komen in de digitale architectuurgids kaart, omdat de architectuur die op deze kaart getoond moet worden veranderlijk is en dus haar eigen coördinaten bezit (zie hst. 1.2).
2.1 Grootschalige Basis Kaart Nederland De bronbestanden die gebruikt zijn om de svg-bestanden van te maken zijn dxfbestanden van de grootschalige basiskaart Nederland(GBKN). Deze vectorbestanden zijn geleverd door de dienst ROEZ van de gemeente Groningen, tonen alle percelen van Groningen-stad en bestaan uit meerdere lagen (zie tab 2.1). Laag Omschrijving 03 hoofdgebouw - steunpilaar gebouw 04 bijgebouw - overige opstal 05 steunpilaar viaduct - kunstwerk 06 tussenmuur 08 bordes/stoep 09 overbouw 14 kant verharding 15 kant open verharding 16 kant gesloten verharding 17 wegmarkering - kant onverhard 18 wegvakgrens 21 insteek sloot 22 waterlijn - walbescherming 24 kademuur 27 muur 28 hek – terreinafscheiding 29 taludlijn - cultuurscheiding 30 hoogspannings leiding 33 open verharding 2 - 4 – 6 34 gesloten verharding 2 - 4 - 6 35 water 36 talud 37 hoogspannings mast 40 boom geschat - boom gemeten 41 rioolput 44 huisnr 46 straatnaam 47 naam water 48 overige tekst - functieaanduiding 49 remmingswerk – steiger – abri - vlakafsluiter Tabel 2.1 Laagindeling vectorbestand (GBKN)
H2- DXF -> SVG Conversie
15
In 1992 werd de Stichting GBKN opgericht met als doel landelijk de GBKN te promoten en de productie hiervan aan te moedigen om zodoende binnen tien jaar een landsdekkend bestand te krijgen. Het gevolg is dat ruim 50 gemeenten ondertussen13 in kaart zijn gebracht volgens de strikte kaartvoorwaarden van de GBKN.Op 16 januari 2003 is de stichting onderdeel geworden van een landelijk samenwerkingsverband (LSV), de Stichting LSV GBKN. Deze stichting bepaald tegenwoordig het beleid van GBKN en dient als informatiepunt voor geïnteresseerden. De GBKN is een sterk gedetailleerde kaart, met harde (bijv. gebouwen) en zachte (bijv. heggen) topografie en semantische informatie (bijv. straatnamen) en een schaal van 1:500 of 1:1000 in bebouwde gebieden en 1:2000 in landelijke gebieden. De kaart is in twee verschillende soorten verschenen, een zogenaamde norm-GBKN en een nutsGBKN. Een norm-GBKN is fotogrammetrisch samengesteld door middel van compleet naverkende metingen uit luchtfoto’s en de precisie van punten ten opzichte van elkaar is op deze kaarten in bebouwd gebied beter dan 28 centimeter en het dubbele in landelijk gebied. De voor dit onderzoek gebruikte kaarten zijn nuts-GBKN, deze zijn ‘in het veld’ vervaardigd, hebben geen informatie buiten een strook van 30 meter vanaf de weg en bezitten een precisie van punten ten opzichte van elkaar van beter dan 10 centimeter. De GBKN bevat een coördinaatstelsel van de Rijksdriehoeksmeting, dit stelsel is gemaakt door gebruik te maken van een stereografische projectie. Hierin wordt de ‘Onze Lieve Vrouwetoren’ in Amersfoort als centraal punt gebruikt, waarna dit punt rekenkundig in zuidwestelijke richting is verschoven, waardoor alle coördinaatpunten in Nederland positief zijn.
Figuur 2.2 Voorbeeld GBKN - Binnenstad Zuid Groningen 13
30-7-2003
H2- DXF -> SVG Conversie
16
2.2 Converters Om de DXF bestanden van de GBK naar SVG om te zetten is een converter nodig, meerdere van deze programma’s zijn op het internet te vinden of te bestellen. In dit onderzoek worden in het kort alleen de converters besproken welke te vinden zijn op de w3c internetpagina en alleen de relevante, dit houdt in dat ze met dxf (of verwante) bestanden als invoer moeten kunnen werken.
2.2.1 Raster -> SVG In principe is het mogelijk om DXF bestanden te exporteren naar rasterbestanden, zoals binnen Autocad de mogelijkheid bestaat om te exporteren naar het BMP formaat. Vervolgens kunnen deze rasterbestanden met behulp van een converter weer terug worden gezet naar een vectorformaat, zoals SVG. Voorbeelden van raster naar SVG converters zijn Vector Eye14 gebaseerd op CR2V van Celinea en KVEC15 van KKSoftware. Aan deze methode, vector naar raster naar vector, kleven echter meerdere nadelen. Om een raster bestand te converteren naar vector formaat wordt gebruik gemaakt van een methode genaamd ‘tracing’. Hiermee wordt het rasterbestand simpel gezegd overgetrokken, zodat vlakken met gevulde pixels als een vector gebied kan worden weggeschreven. Deze methode kan een nadelig resultaat opleveren indien een rasterbestand een complexe structuur heeft met bijvoorbeeld veel kruisende lijnen. Het is in dat geval lastig te bepalen welke lijnen bij elkaar horen. Wordt er gebruik gemaakt van een raster bestand met meerdere kleuren dan kan het probleem ontstaan dat objecten in elkaar over gaan lopen. Stel dat een rode polylijn langs een oranje polylijn loopt in het rasterbestand, zoals in figuur 2.3. Door het kleurverschil zou het duidelijk moeten zijn hoe de polylijnen lopen, maar er is geen kleurverschil meer te zien en er is een zogenaamd ‘fuzzy’ of vaag gebied ontstaan, waarin een mengelmoes aan kleuren is te zien.
Figuur 2.3 Raster bestand met ‘fuzzy’ gebied 14 15
een op Windows draaiend programma dat BMP, TIFF, PNG, JPEG en GIF omzet een command-line convertor voor Windows, Macintosh, Linux, Unix, OS/2 en BeOS platformen
H2- DXF -> SVG Conversie
17
Een ander nadeel ontstaat bij het exporteren naar BMP formaat binnen Autocad, waardoor de wereldcoördinaten, zoals die gebruikt worden in het dxf-bestand, niet worden overgezet, terwijl deze van essentieel belang zijn voor het bepalen van de plaats van de gekozen architectuur binnen de architectuurgids. Het is wel mogelijk om later een berekening toe te voegen om zodoende de coördinaten weer terug te krijgen, alleen betekend dit tijdverlies en handmatig zoekwerk in de bronbestanden. Tot slot bestaat er de mogelijkheid om vector naar vector te converteren, waardoor het niet nodig is om een vectorbestand in een rasterjasje te persen om vervolgens deze weer terug te brengen naar een vectorbestand.
2.2.2 DXF -> SVG Binnen Adobe Illustrator bestaat de mogelijkheid om DXF bestanden om te zetten naar een ander vectorformaat, AI. Hierdoor wordt het aantal te gebruiken converters vergroot, waarmee vectorbestanden omzet kunnen worden naar het SVG formaat. Voorbeelden hiervan zijn de converter van Gardos Software en van Meister, beide te gebruiken met Windows, FME16 van Safe Software, Cad2svg17 (een stand-alone onderdeel van de Dataslinger server) van Savage Software, Cadstd Pro18 van John Apperson en tot slot Mayura Draw19 van Mayura. In principe is het mogelijk om met al de voorgaande vector naar vector converters aan de hand van de grootschalige basiskaarten een correcte svg-kaart te maken. Als er vervolgens naar de beschikbaarheid van de produkten wordt gekeken valt op dat alle converters gekocht moeten worden met prijzen variërend tussen de $25 en $249, op de Gardos converter na.
16
waarmee meer dan 100 bestandsformaten omgezet kunnen worden (waaronder dxf). Te gebruiken op meerdere platformen, waaronder Windows, Solaris, Unix, IBM RS/6000 AIX 4 en Linux. 17 met de mogelijkheid om meerdere databronnen samen te voegen, voor Unix en Windows 18 geschreven in de taal Delphi voor Windows 19 AI naar SVG conversie programma
H2- DXF -> SVG Conversie
18
2.3 Gardos Gardos Software is een onderdeel van het in Athene gestationeerde Civil Tech, een bedrijf dat zich sinds 1989 bezig houdt met het ontwikkelen van technische software. De door Gardos Software ontwikkelde dxf->svg converter is een ActiveX dll bestand, geschreven in Microsoft Visual Basic. De interface van het programma bestaat uit een scherm waarop het te gebruiken dxf-bestand kan worden ingevuld als invoer en het gewenste svg-bestand als uitvoer (zie fig 2.4). Als vervolgens de conversie voltooid is, wordt het svg bestand in dit zelfde scherm getoond, zodat snel duidelijk is of de conversie gelukt is. Simpel en snel, althans als dit alles goed werkt. En dat was dus niet het geval, de gecreëerde svg kaarten waren incompleet en hadden een onacceptabele bestandsgrootte. Aangezien er verder geen documentatie bij het programma zat of op de internetpagina te vinden was, was de reden van het informatieverlies niet makkelijk te achterhalen. Uiteindelijk bleek Gardos niet het gewenste resultaat te bieden als het invoerbestand een Autocad versie 14 DXF bestand was en dus een andere structuur bezat. Een beter resultaat is met Gardos alleen te verwachten als een Autocad versie12 DXF bestand wordt gebuikt, zoals te zien is in figuur 2.6.
Figuur 2.4 Gardos Interface, na conversie.
H2- DXF -> SVG Conversie
19
2.4 Mutatis Aangezien Gardos meerdere nadelen heeft, waaronder DXF incompatibiliteit en een onacceptabele bestandsgrootte, is besloten om een eigen converter te maken. Deze zou naast het oplossen van deze problemen ook nieuwe mogelijkheden moeten bevatten, waarbij in eerste instantie te denken valt aan een mogelijkheid voor de gebruiker om bestaande lagen uit het DXF bestand te (de)selecteren.
Figuur 2.5 Openingsscherm Mutatis (versie GRAS) Mutatis maakt gebruik van een Common Gateway Interface (CGI), waarmee het mogelijk is om externe dynamische applicaties, zoals Mutatis, in een server te plaatsen, zoals HTTP. De HTTP server die gebruikt is tijdens het testen is Apache20 op WindowsXP. Het is met Apache mogelijk om PHP en MySQL scripts te gebruiken, waardoor de communicatie tussen de door Mutatis gefabriceerde SVG bestanden en de Architectuurgids door middel van PHP aanwezig is en de mogelijkheid bestaat om de database te doorlopen aan de hand van MySQL. Meerdere talen kunnen gebruikt worden in combinatie met CGI, waaronder C/C++ en Perl. Aangezien C een programmeertaal is zou Mutatis eerst gecompileerd moeten worden, omdat er in dat geval gebruik gemaakt wordt van een broncode. Met de scripttaal Perl is dit niet nodig, vandaar dat Mutatis in Perl21 is geschreven. Daarnaast is een CGI-script, wat het door het gebruik van Perl is geworden, makkelijker te onderhouden en uit te breiden dan een CGI-programma door het ontbreken van de compilatiestap. 20 21
versie 1.3.20 versie 5.6.1
H2- DXF -> SVG Conversie
20
2.4.1 DXF incompatibiliteit Een van de eerste problemen die aangepakt moesten worden was de incompatibiliteit met de bronbestanden. Deze waren opgeslagen als Autocadversie 14 bestanden, wat er toe leidde dat de met Gardos gegenereerde svg-bestanden informatieverlies vertoonden. De oplossing voor Gardos zat in het opslaan van elk bronbestand als Autocad versie 12, wat echter tot gevolg heeft dat de bronbestandsgrootte vergroot. Voor Mutatis moest de opbouw van dxf14 bestanden gebruikt worden (zie 1.4).
Figuur 2.6 SVG van DXF14-bestand (links) en DXF12-bestand (rechts) m.b.v. Gardos
2.4.2 Laagkeuzemogelijkheid Nadat de GBKN bestanden waren omgezet naar Autocadversie 12, leverde Gardos op het eerste oog correcte svg-bestanden. Deze bestanden bezaten echter alle informatie uit de dxf-bestanden, waaronder bijvoorbeeld putdeksels, en aangezien de svgkaarten gebruikt gingen worden als referentiemiddel was het niet nodig dat alle informatie ook gebruikt ging worden. Nadat het bronbestand al eerder zou moeten worden omgezet, zou het nu andermaal in Autocad aangepast moeten worden en wel zo dat alle irrelevante informatie geselecteerd en handmatig verwijdert moest worden. Een keuzemogelijkheid binnen de converter zou natuurlijk makkelijker en sneller werken. Een dxf-bestand geeft elke vorm/object een laagnummer mee waardoor snel te bepalen is of iets omgezet moet worden naar het svg-formaat of niet. De converter zette op dit moment nog niks daadwerkelijk om naar het svg-formaat, maar schreef het dxfbestand weg als 6 losse tekstbestanden, gesplitst op de secties. Om te bepalen welke lagen er zijn werd gekeken naar het tekstbestand met daarin de tables sectie, hierdoor hoeft niet het gehele bestand telkens door te worden gelopen, maar is het mogelijk om binnen een sectie te zoeken (zie tabel 2.8 en fragment 2.9).
H2- DXF -> SVG Conversie
21
open HEADER, ">header.txt"; while () { # Lees 2 regels van DXF bestand chomp; $f1 = $_; $_ = ; chomp; $f2 = $_; # Schrijf de HEADERsectie weg naar het tekstbestand (header.txt) if (($f1 =~ /2/) && ($f2 =~ "HEADER")){ while ($f2 =! /ENDSEC/){ $_ = ;chomp;$f1 = $_; print HEADER $_ . "\n"; $_ = ;chomp;($f2) = split(' ', $_, 1); print HEADER $_ . "\n";} } }
Fragment 2.7 Voorbeeld Mutatis Code – Splitsen DXF bestand per sectie (vb. Header)
Code Uitleg 100 Subclass marker AcDbLayerTableRecord Naam van de subclass marker 2 Laagnaam 62 Kleur Tabel 2.8 Voorbeeldcode van DXF-bestand met laagaanduiding.
# Haal de laaginfo uit het tekstbestand (met daarin de TABLES sectie) open TABLES, ") { chomp; $f1 = $_; $_ = ; chomp; $f2 = $_; # nieuwe laag if (($f1 =~ "100") && ($f2 =~ "AcDbLayerTableRecord")) { $spin = 1; while ($spin) { $_ = ; chomp; $f1 = $_; $_ = ; chomp; ($f2) = split(' ', $_, 1); # voeg de laagnaam toe aan de lijst if ($f1 =~ / 2/) {@layerlist=(@layerlist,$f2);} if ($f1 =~ / 0$/) {$spin = 0;} } } }
Fragment 2.9 Voorbeeld Mutatis Code – wegschrijven DXF lagen.
H2- DXF -> SVG Conversie
22
2.4.3 Viewbox bepalen Inmiddels was de basis voor Mutatis gelegd en werd het tijd om de informatie over te zetten. De eerste kaart die omgezet werd was een overzichtskaart van Groningen, waarop alleen de (wijk)grenzen stonden aangegeven. Om te bepalen hoe groot het kijkvenster (viewbox) moest worden waarin het svg-bestand kwam te hangen, moest eerst in de header sectie de nodige informatie worden gevonden, namelijk de minimale en maximale x en y waarden. Open HEADER, ") { chomp; $f1 = $_; $_ = ; chomp; $f2 = $_; # Minimale x en y waarden if ($f2 =~ /^\D?EXTMIN/){ $spin = 1; while ($spin) { chomp; $f1 = $_; $_ = ; chomp; ($f2) = split(' ', $_, 1); if ($f1 =~ / 10/) {$xmin = $f2; } if ($f1 =~ / 20/) {$ymin = $f2; $spin = 0;} }} # Breedte en hoogte bepalen aan de hand van maximale waarden if ($f2 =~ /^\D?EXTMAX/){ $spin = 1; while ($spin) { chomp; $f1 = $_; $_ = ; chomp; ($f2) = split(' ', $_, 1); if ($f1 =~ / 10/) {$width = sprintf("%.2f",($f2-$xmin)); } if ($f1 =~ / 20/) {$height = sprintf("%.2f",($f2-$ymin)); $spin=0;} } } }
Fragment 2.10 Voorbeeld Mutatis Code – Bepalen viewbox Na de viewbox bepaald te hebben was het mogelijk om in de entities sectie alle (wijk)grenzen terug te vinden, welke aangegeven stonden als (poly)lijnen (zie 3.4.4). Het resultaat was enigszins verrassend aangezien het plaatje horizontaal gespiegeld te voorschijn kwam. In tekenprogramma’s, zoals Autocad, ligt het nulpunt linksonder, maar doordat svg gebruik maakt van het cartesiaanse coördinaatsysteem ligt in dit formaat het nulpunt linksboven. De x-waarden komen dus correct over en de y-waarden worden gespiegeld ten opzichte van de centrale y-waarde. Om een correcte kaart te krijgen is elke y-waarde omgezet met behulp van de eerder gevonden minimale en maximale y-waarden en de centrale y-waarde van de overzichtskaart. Dit is van belang omdat de architectuur op de kaart zijn eigen coördinaten heeft en de architectuur moet zowel op de wijkkaart als op de buurtkaart op de juiste positie komen. Zou de y-waarde niet gespiegeld worden ten opzichte van de centrale y-waarde van de hoofdkaart dan komt de architectuur niet op de juiste positie (zie tab. 2.11).
H2- DXF -> SVG Conversie
Kaart: Overzichtskaart
Detailkaart
23
Gegevens: Resultaat: Ymid=5.5 Ymin=3, Ymax=8 Architectuurpunt (3,5) Xmin=0, Xmax=4 Architectuurpunt (3,6) I. Met Ymid (=6.5) van detailkaart: Ymin=5, Ymax=8 Architectuurpunt (3,6) Xmin=1, Xmax=4 Architectuurpunt (3,6) II. Met Ymid van overzichtskaart: Architectuurpunt (3,5) Tabel 2.11 Berekening gespiegeld architectuurpunt
De gebruikte formule om de centrale y-waarde te krijgen luid dan als volgt: ymid=ymin+((ymax-ymin)/2) Met de centrale y-waarde (ymid) kan vervolgens de nieuwe y-waarde worden bepaald: y=ymid-(y-ymid) Nadat de overzichtskaart correct werd getoond, konden ook de andere kaarten worden geconverteerd. Dat betekende dat naast (poly)lijnen ook andere objecten omgezet dienden te worden, zoals bogen(arc), tekst en blockobjecten (verwijzingen naar voorgedefinieerde vormen).
2.4.4 Omzetten van grafische objecten (Poly)lijnen kunnen worden omgezet als polyline (indien deze bestaat uit meer dan 2 punten (tabel 3.5(I))) of als line (in het geval van 2 punten (tabel 3.5(II))), ook is het mogelijk om beide om te zetten als path (tabel 3.5(III)). In eerste instantie is er voor gekozen om alle lijnen en polylijnen weg te schrijven als polyline. DXF-code22 0 LWPOLYLINE … 8 0 … 10 x-waarde 20 y-waarde 10 ...
22
Uitleg Het is een polylijn,
Resulta(a)t(en) I: <polyline points=”x,y x,y etc. “/>
behorend bij laag 0,
II (in het geval van een lijn, waarbij de 2de x en y waarden respectievelijk een gc=11 en gc=21 hebben)
met een x-waarde, en een y-waarde,
III <path d=”M x,y L x,y etc /”>
etc. Tabel 2.12 Voorbeeld van het omzetten van een (poly)lijn
groupcode op de volgende regel gevolgd door tag
H2- DXF -> SVG Conversie
24
Tekst heeft veel extra eigenschappen, zoals verplaatsing en verdraaiing. Deze eigenschappen zorgen ervoor dat in eerste instantie elk tekstelement een eigen groep mee krijgt waarin de extra eigenschappen worden aangegeven. De tekst kan langs een object worden neergezet en het lettertype wordt vooraf bepaald, dit kan elk voor het besturingssysteem bekende lettertype zijn. DXF-code19 0 TEXT … 10 ... 40 31.999998 1 ruischerbrug 50 20.625
Uitleg Het is tekst,
Resulta(a)t(en)
ruischerbrug een naam (de tekst), met een x-waarde (en y en z), de tekstgrootte,
en een rotatie. Tabel 2.13 Voorbeeld van het omzetten van tekst.
Voordat een Arc of Boog is omgezet komt het nodige rekenwerk om de hoek kijken. In de DXF-bestanden staat aangegeven wat de centrale x en y waarden zijn, wat de straal is en wat de start- en eindhoek is van de boog. In SVG-formaat heeft een boog echter de begin x en y en de eind x en y coördinaten nodig. Om deze waarden te krijgen is de volgende formule gebruikt: sh1 = starthoek* pi / 180.0; eh1 = eindhoek * pi / 180.0; x0= cx + (rx * cos(sh1)); xn= cx + (rx * cos(eh1)); y0= cy + (ry * sin(sh1)); yn= cy + (ry * sin(eh1));
*(0 0 1, met deze waarden wordt de loop van de boog beschreven (zie fig. 3.8))
eindhoek Tabel 2.14 Voorbeeld van het omzetten van een arc.
Figuur 2.15 Voorbeelden van boogstijlen (uit [6] p80)
Het block-object een voorgedefinieerd blok, waarin meerdere objecten kunnen voorkomen, zoals tekst,polylijn,etc. Aangezien een block-object vaker terug kan komen is het in SVG mogelijk om deze aan het begin van het svg-bestand als <defs> aan te geven. Dit houdt in dat in de rest van de file een verwijzing (bijv. <use xlink:href = "#blocknaam" />) genoeg is om het block-object te gebruiken, waardoor niet constant een zelfde objectbeschrijving voorkomt.
24
groupcode op de volgende regel gevolgd door tag
H2- DXF -> SVG Conversie
26
2.5 Mutatis vs. Gardos Het niet meer vooraf hoeven aanpassen van de bronbestanden is het grote voordeel van Mutatis t.o.v. Gardos. Met Mutatis is het mogelijk om de aangeleverde dxf bestanden te gebruiken en daarnaast een laaggerelateerde keuze te maken, om te bepalen welke informatie wordt omgezet naar svg. Naast dit voordeel kwam een andere positieve verandering aan het licht betreffende de geometrie van de kaart. Doordat Gardos bogen omzet als een polylijn krijgen deze een hoekiger uiterlijk, dit is niet het geval met Mutatis omdat een boog hierin ook daadwerkelijk als een boog wordt weggeschreven (zie fig. 3.9).
Gardos Bogen zijn duidelijk niet compleet en vertonen leegtes, waardoor deze ook niet goed aansluiten op de andere objecten.
Mutatis Bogen (rood) sluiten correct aan op de andere lijnen.
Figuur 2.16 Verschil tussen Gardos en Mutatis wat betreft Bogen(Arc).
De bestandsgrootte is het laatste voordeel, aangezien deze een dusdanige grootte moest hebben zodat internetgebruikers met een modem de architectuurgids op een acceptabele manier konden bezichtigen en gebruiken. Gardos leverde bestanden op die vanaf de allerkleinste buurtbestanden onacceptabel waren, deze bestanden varieerden in grootte tussen de 2,8 en 20,4 mb. Mutatis leverde aanzienlijk kleinere bestanden op tussen de 0,15 en 2,15 mb, zonder informatieverlies en met laagindeling. De grootste bestanden waren echter nog steeds onacceptabel qua grootte dus moest daar nog een andere oplossing voor worden gevonden.
H2- DXF -> SVG Conversie
25000
Grootte (kb)
20000 SVG - Gardos DXF - Acad14 SVG - Mutatis
15000 10000 5000 0 68
13
54
4
81
96
Bestandsnaam Figuur 2.17 Verschil SVG bestandsgrootte tussen Mutatis en Gardos t.o.v. origineel DXF
27
H3 - Bestandsgrootte
28
Hoofdstuk 3
Bestandsgrootte
3.1 Inleiding De digitale architectuurgids en aanverwante SVG-kaart moet voor een breed publiek beschikbaar zijn en heeft dus als voorwaarde dat de inlaadtijd van de bestanden beperkt blijft. Om dit te bereiken is het nodig dat de bestandsgrootte beperkt blijft, waarbij gedacht wordt aan een ideale grootte van 300kb met een uiterste waarde rond de 600kb. Het gebruik van Mutatis levert een grote winst op (zie fig. 2.17 en tabe. 3.1), de bestanden worden hierdoor namelijk teruggebracht tot een grootte tussen de 5 en 15 procent t.o.v. de Gardos svg-bestanden. Maar zoals eerder vermeld zit de grootte van enkele bestanden nog rond de 2mb, daarom is het nodig om de bestanden te generaliseren.
In de literatuur [2][3][4] wordt een onderscheid gemaakt tussen twee vormen van generalisatie, semantische en geometrische. Semantische generalisatie richt zich vooral op de inhoudelijke kant, waarbij de hiërarchie van objecten binnen een kaart onder de loep wordt genomen. Het doel van deze vorm van generalisatie is het verminderen van detail binnen een kaart door middel van reductie van objecten die laag in de hiërarchie staan. Geometrische generalisatie richt zich op het ‘uiterlijk’ van de kaart en zal deze waar nodig aanpassen door bijvoorbeeld vormen aan te passen door middel van samenvoeging, vergroting, verkleining of zelfs verwijdering. Aangezien niet alle informatie van de kaart van belang is voor de gebruiker, zal in eerste instantie met behulp van semantische generalisatie de bestandsgrootte worden teruggebracht. De lagen die van belang zijn voor de gebruiker zijn aangegeven in tabel 3.2, waarin ook een onderverdeling per groep te vinden is. De straatnamen bevinden zich in een aparte laag en kunnen als oriëntatiepunt gebruikt worden, vandaar dat deze wel worden overgezet.
H3 - Bestandsgrootte
29
Laagnaam Groeps-omschrijving 3, 4 Bebouwing 14, 15, 16, 17 Wegen 21, 22, 24 Water 46 Straatnamen Tabel 3.2 Gebruikte lagen voor SVG bestand
2500
Grootte (kb)
2000 1500
conversie laagkeuze
1000 500 0 68
13
54
4
81
96
Bestandsnaam Figuur 3.3 Grootte Mutatis svg bestanden na laagkeuze t.o.v. Mutatis svg bestanden na conversie
Doordat de bestandsgrootte nog niet op het gewenste niveau zit (zie fig. 3.3), zal er naar andere methoden gezocht moeten worden. Aangezien de Grootschalige Basiskaart een gedetailleerd beeld biedt, leek in eerste instantie op dit punt van het onderzoek meer winst te verwachten door gebruik te maken van geometrische i.p.v. semantische generalisatie. De meest efficiënte methode hiervoor leek reductie [4] ook wel simplificatie [5] genoemd. Deze methode heeft tot doel om een kaart te ontdoen van detail met als gevolg rechtere lijnen, die met minder punten (coördinaten) te beschrijven zijn, waardoor de bestandsgrootte vermindert.
H3 - Bestandsgrootte
30
3.2 Detailvermindering Reductie is op verschillende manieren toe te passen, waarbij vijf technieken zijn te onderscheidden [4]. De methode die hier toegepast is, is ‘local tolerance band processing’. Deze techniek legt een denkbeeldig gebied, met een vooraf bepaalde tolerantiegrens, rond de punten die samen een lijn vormen (fig. 3.4(a)). Het gebied heeft de richting van de lijngedeelte tussen het eerste en tweede punt. Vervolgens wordt gekeken of het derde punt binnen het gebied ligt, als dit het geval is dan wordt het tweede punt verwijdert en wordt het volgende punt bekeken (fig. 3.4(b)). Zolang er geen punten buiten het gebied vallen, zal het gebied de richting aanhouden van de eerste twee punten, zodra echter een punt buiten het gebied valt dan zal een nieuw gebied worden opgetrokken met de richting van het ‘buiten het gebied vallende’ punt en het daaraan voorafgaande punt. Het resultaat is een lijn die een benadering, afhankelijk van de gekozen marge, is van de originele lijn en met minder coördinaatpunten te omschrijven is (fig. 3.4(c))
Figuur 3.4 ‘Local tolerance band processing’ methode (uit [2] p. 276)
3.2.1 Resultaat Een sterk verminderde bestandsgrootte bleek echter niet het resultaat, de reden hiervoor lag in de omschrijving van de objecten binnen de dxf bronbestanden. Een gesloten vierkant kan omschreven worden als een polylijn (0,0 0,1 1,1 1,0 0,0) of polygon (0,0 0,1 1,1 1,0). In het dxf bestand kwam het voor dat een vierkant omschreven was als vier losse lijnen ((0,0 0,1) (0,1 1,1)(1,1 1,0)(1,0 0,0)). Nu is het in het geval van dit vierkant ook niet nodig om punten te verwijderen, dit zou immers tot een totaal andere vorm leidden. Echter bovenstaande methode wordt ook toegepast op andere vormen, waaronder complexe lijnen, zodat een lange kronkelige lijn opgedeeld is in een veelvoud aan kleine lijngedeeltes.
H3 - Bestandsgrootte
31
Na onderzoek van 5000 willekeurige lijnen in een dxf-bestand (buurtbestand 96), bleek 90,8% van de lijnen te bestaan uit vier coördinaten of minder. Onderstaand fragment laat de eerste 10 lijnen zien uit het omgezette svg-bestand, waarbij overeenkomstige begin- en eindpunten gekleurd zijn en ‘pp’ voor polyline points staat.
Fragment 3.5 Eerste 10 polylijnen uit svg-bestand
Opvallend aan fragment 3.5 is de hoeveelheid aan dubbele punten in een klein fragment en de lengte van de lijnen. De kracht van reductie zit in de verlaging van detail, blijkt echter dat 90,8% van de lijnen niet of nauwelijks detail bevat dan is het wel duidelijk dat reductie weinig resultaat zal hebben. Zouden de lijnen binnen het bestand namelijk teruggebracht worden naar lijnen met het minimum van twee punten, dan zou de bestandsgrootte verminderen van 380kb naar 290kb. Er wordt dan gebruik gemaakt van een grootte tolerantiewaarde en het svg-bestand zou een ‘Picasso’-achtige uitstraling krijgen, waardoor deze niet meer te gebruiken is als referentiemiddel. Aangezien de lijnen een te geringe lengte hebben, zou een oplossing gevonden moeten worden die het mogelijk maakt om deze lijndelen samen te voegen om zodoende een lijn te krijgen.
H3 - Bestandsgrootte
32
3.3 Lijn samenvoeging Hoe moeten lijnen samengevoegd worden? In dit onderzoek is gekozen om lijnen aan elkaar te ‘knopen’ door middel van overeenkomstige begin- en eindpunten, aangezien dit al eerder een opvallende eigenschap was van het fragment in fragment 3.5. Het beginpunt van de eerste regel werd vergeleken met alle volgende begin- en eindpunten, vervolgens werd het eindpunt vergeleken, waarna de volgende regel werd gepakt, dit alles bleef zich herhalen totdat de laatste regel werd bereikt. Op deze manier zouden de tien polylijnen uit fragment 3.5 terug te brengen moeten zijn tot vier polylijnen (zie frag. 3.6).
Fragment 3.6 Tien polylijnen uit fragment 3.5 teruggebracht tot vier polylijnen De resultaten uit de eerste test waren bemoedigend wat betreft de vermindering in bestandsgrootte, daarentegen was de tijdsduur een grote tegenvaller. De bestandsgrootte verminderde met 30 tot 35 procent, waarbij het percentage opliep naarmate het bestand groter werd. Dit was echter niet het enige wat mee omhoog liep, de tijdsduur25 om de lijnen samen te voegen liep exponentieel omhoog. Een bestand van 500 regels nam ongeveer 12,3 seconden in beslag, bij een vertienvoudiging van het aantal regels ging de tijd naar ongeveer 1230 seconden toe. Met andere woorden de tijd verhield zich als volgt: (Aantal Regels / 500)² * 12,3 Het grootste bestand had ongeveer 36000 regels en het zou daardoor plusminus 17 uur en 42 minuten duren voordat de lijnen binnen dit bestand zouden zijn samengevoegd. Om deze tijd terug te dringen werd besloten om het bestand op te delen in losse stukken van 500 regels waarin gezocht werd naar overeenkomstige punten, hierdoor werd het tijdsverloop in de tweede test lineair en als volgt te berekenen: (Aantal Regels / 500) *12,3 De tijd die het grootste bestand in dit geval nodig had om de lijnen te knopen werd teruggebracht naar ongeveer een kwartier. Dit alles zou echter alleen mogelijk zijn als de bestanden een zelfde bestandsgrootte verandering zouden ondergaan. 25
In figuur 3.7 is duidelijk te zien dat de bestandsgrootte nauwelijks verandert, wat echter opvalt is dat de bestandsgrootte in het geval van 2000 regels verder verkleind is van 104 naar 103 kilobyte. Dit duidt erop dat de methode nog niet goed werkt, aangezien je bij een vermindering van de zoekmogelijkheden verwacht dat het aantal combinaties zal dalen en de bestandsgrootte (licht) zal toenemen. Ook viel op dat de lijnen een piramide-achtige vorm vertoonden, gaandeweg het bestand werden de lijnen langer. Dit kwam doordat de vergelijkingsmethode niet per laag zocht, hierdoor was het mogelijk dat lijnen die niet gecombineerd hoefden te worden toch samen werden gevoegd. Daarnaast werd een punt altijd gekoppeld indien een overeenkomstig punt werd gevonden. Dit laatste kan echter inhouden dat een punt dat gekruist wordt door meerdere lijnen ervoor zorgt dat al deze lijnen worden gecombineerd, waardoor een bepaald lijntraject meerdere malen terugkomt binnen het bestand of zelfs binnen een lijn.
H3 - Bestandsgrootte
Originele Lijnen26 1,0 a 3,0 3,0 b 2,4 1,0 c 2,4 2,4 d 0,10 2,4 e 1,8 2,4 f 3,8 2,4 g 4,10 1,8 h 3,8 0,10 i 4,10
34
Gewenste uitkomst
Werkelijke uitkomst
3 lijnen: I: 1,0 a 3,0 b 2,4 c 1,0
2 lijnen: I: 0,10 d 2,4 b 3,0 a 1,0 a 3,0 b 2,4 c 1,0 a 3,0 a 1,0 c 2,4 b 3,0 a 1,0 a 3,0 b 2,4 e 1,8 h 3,8 f 2,4 b 3,0 a 1,0 a 3,0 b 2,4 c 1,0 a 3,0 a 1,0 c 2,4 b 3,0 a 1,0 a 3,0 b 2,4 d 0,10 d 2,4 b 3,0 a 1,0 a 3,0 b 2,4 c 1,0 a 3,0 a 1,0 c 2,4 b 3,0 a 1,0 a 3,0 b 2,4 e 1,8
II : 2,4 d 0,10 i 4,10 g 2,4
II: III: met 21 punten meer dan I 2,4 e 1,8 h 3,8 f 2,4 Tabel 3.8 Uitkomst na lijncombinatie
Stap Verrichting 1 Lijn a wordt geknoopt aan b (a->b) + a->c 2 b->c + b->d + b->e + b->f + b->g 3 c->d + c->e + c->f + c->g 4 d->e + d->f + d->g + d->i 5 e->f + e->g + e->h 6 f->g + f->h 7 g->i Tabel 3.9 Uitwerking Werkelijke Uitkomst tabel 3.8 Om te voorkomen dat de uitkomst wordt zoals in tabel 3.8 zijn er extra uitzonderingen toegevoegd aan de combinatiemethode. Coördinaatpunten worden alleen nog maar gekoppeld aan punten binnen dezelfde laag en alleen die lijnen met punten, die maar één overeenkomstig ander punt hebben, worden samengevoegd. Op deze manier worden lijnen die elkaar kruisen niet gekoppeld, zodat er geen puntenbrij ontstaat. Natuurlijk houdt dit wel in dat minder punten (en dus lijnen) samengevoegd worden, maar het probleem van het aantal herhalende punten of lijndelen zal verdwijnen. Daarnaast is de mogelijkheid toegevoegd om lijnen met bogen te combineren, hierdoor is het mogelijk objecten af te sluiten die naast lijnen ook bestaan uit bogen. Om dit mogelijk te maken was het noodzakelijk om lijnen niet langer weg te schrijven als polyline, maar als een path aangezien bogen ook als path omschreven worden. Zodra een overeenkomstig punt gevonden wordt in een boog kan de boog simpelweg toegevoegd worden aan de lijn of boog. Als een beginpunt overeenkomt met een eindpunt dan kan het nodig zijn om een boog te draaien dit houdt in dat het beginpunt het eindpunt wordt en andersom en dat de booleanwaarde van de ‘sweepflag’ verandert (zie tab 3.10).
26
De lijnen hebben ter verduidelijking een letter meegekregen, dit zal normaal niet het geval zijn, het is echter wel mogelijk om nul of meerdere coördinaten in de plaats van de letter in te vullen. Aangezien de begin- en eindpunten alleen van belang zijn is er voor gekozen om geen extra (tussen)coördinaten mee te geven.
H3 - Bestandsgrootte
35
Originele objecten Gecombineerd object <path d=”M 0,0 L 3,4 5,2”/> <path d=”M 5,2 A 23 23 0 0 1 6,8”/> <path d=”M 7,0 L27 1,8 2,3 A 45 45 0 0 1 6,9 <path d=”M 0,0 L 3,2”/> L 6,8 A 23 23 0 0 0 5,2 L28 3,4 0,0 L 3,2”/> <path d=”M 2,3 L 1,8 7,0”/> <path d=”M 2,3 A 45 45 0 0 1 6,9”/> <path d=”M 6,9 L 6,8”/> <path d=”M 3,2 L 7,0”/> Tabel 3.10 Voorbeeld van het combineren van (poly)lijnen met bogen (arc)
# Als het een Arc is ... if (@test[$k] eq 'A'){ # met een vervolg, en het vervolg is niet een Line of Arc ... if ((@test[$k+7])&&(@test[$k+7] ne 'L')&& (@test[$k+7] ne 'A')){ # plaats dan een L voor het vervolg @test[$k+7]="L @test[$k+7]"; } }
Fragment 3.11 Mutatis code voor boogcontrole
Het combineren van lijnen levert andermaal een aanzienlijke verkleining van de bestandsgrootte op, deze zijn echter in sommige gevallen nog steeds te groot (zie fig 3.12). Een ander voordeel, waarop in hoofdstuk 4 verder op in gegaan zal worden, is dat veel van de objecten dezelfde begin- en eindcoördinaatpunten hebben gekregen en daardoor gesloten zijn. De hoeveelheid succesvol gesloten objecten is afhankelijk van de complexiteit van de kaart, als er namelijk veel kruisingen zijn dan zullen deze immers niet worden gebruikt om te combineren. Overigens is er bij de nieuwe combinatiemethode gekozen voor resultaat in plaats van snelheid, aangezien het resultaat van meer belang is.29 De generalisatie tot dit punt is acceptabel, ten eerste is de bestandsgrootte ver terug gebracht en ten tweede is het uiterlijk van de kaart niet ‘aangetast’. De, tot dit punt, toegepaste generalisatie is semantisch van aard, aangezien de losse lijndelen/vormen samen worden gebracht naar een hoofdvorm (classificatie[2]). Hierdoor zal in eerste instantie ook voor de verdere generalisatie eerst gezocht worden naar een semantische oplossing.
27
Indien na een ‘M’ (move to) twee of meer coördinaatstellen volgen, zal een ‘L’ (line to) tussen beide worden geplaatst. 28 Indien twee of meer coördinaatstellen na een ‘A’ (arc/boog) volgen, wordt er na het eerste coördinaatstel een ‘L’ (line to) geplaatst. 29 Daarnaast bleek de tijdsduur op een 1,3ghz pc met 896mb geheugen te verwaarlozen. Tests van meer dan een uur, waren in dit geval binnen 3 minuten afgerond.
H3 - Bestandsgrootte
36
2500
Grootte (kb)
2000 conversie laagkeuze combineren
1500 1000 500 0 68
13
54
4
81
96
Bestandsnaam Figuur 3.12 Grootte Mutatis svg bestanden na lijncombineren t.o.v. Mutatis svg bestanden na conversie en laagkeuze
3.4 Notatie Een in een eerder stadium al toegepaste verandering in de notatie binnen een svg bestand zette ‘line’ om in ‘polyline’ en vervolgens naar ‘path’. Binnen de vormbeschrijving is verder niet veel meer te veranderen, maar binnen de coördinaatnotatie is nog wel het een en ander te veranderen. Een eerste opvallend punt is dat de bronbestanden opgemaakt zijn met wereldcoördinaatnotatie, wat in het geval van Groningen leidt tot x-waarden tussen 226868,9 en 240507,67 en y-waarden tussen 577499,6 en 587115,975. Dit houdt in dat elke coördinaat binnen het svg-bestand een honderdduizendtal is, terwijl het binnen svg mogelijk is om een nieuw nulpunt in te stellen en vervolgens een omrekenfactor toe te passen. Viewbox met wereldcoordinaten Viewbox met nieuw nulpunt 30 <svg id="overzichtskaart" viewBox= <svg id="overzichtskaart" viewBox= "226868.9 577499.6 13638.77 9616.375"> "0 0 13638.77 9616.375"> Hello World! Hello World! <path d=”M 227008,578010.4 L ... “/> <path d=”M 139.1,510.8 L ... “/> Tabel 3.13 Viewbox - overzichtskaart Groningen 30
Voor eventueel later gebruik wordt de oude viewbox als commentaar weggeschreven
H3 - Bestandsgrootte
37
Een tweede opvallend punt in de coördinaatnotatie is het aantal decimalen dat gebruikt wordt. Voor de duidelijkheid van de kaart is het onnodig om meer dan 1 decimaal te gebruiken, terwijl dat nu nog twee of (in de meeste gevallen) meer. Het eerder terug brengen van het aantal decimalen is af te raden, omdat dit bij het combineren van objecten er toe kan leidden dat punten foutief gecombineerd zullen worden Originele coördinaten (0.34,5.89) (0.34,5.89) (0.26,5.94)
NEE, doordat het punt vaker dan twee keer voorkomt, terwijl er juist wel sprake is van een combinatiemogelijkheid met de originele coördinaten, namelijk het punt 0.34,5.89. JA, het punt 0.3,5.9 komt twee keer voor en is dus te (0.3,5.9) (0.34,5.89) combineren. Deze situatie is echter ontstaan door het terug (0.4,5.9) (0.35,5.89) brengen tot 1 decimaal, in eerste instantie is geen (0.3,5.9) (0.26,5.94) combinatie mogelijk. Tabel 3.14 Twee voorbeelden van foutieve coördinaatcombinatie Hoewel gezocht werd naar een semantische oplossing is er met de notatieverandering een oplossing gevonden die eigenlijk tussen een semantische en een geometrische oplossing in zit. Semantisch wordt immers de informatie veranderd die getoond wordt, terwijl geometrisch de objecten op een kaart gemanipuleerd worden. Met notatieverandering wordt de informatie veranderd van de objecten op een kaart.
3.4.1 Honderdduizendtal De minimale x en y waarden van de overzichtskaart (buurtind.dxf) worden gebruikt om een nieuw nulpunt te berekenen, hierdoor is het namelijk mogelijk om punten uit de wijk- of buurtkaarten op de juiste positie weer te geven op de overzichtskaart. Elke kaart krijgt een nieuw nulpunt, deze wordt berekend door de bestaande minimale x en y waarden af te trekken met de minimale x en y waarden van de overzichtskaart.
3.4.2 Decimalen Een belangrijk punt waarop gelet moet worden, tijdens het omzetten naar coördinaten met een decimaal, is dat er geen gelijke coördinaatpunten achter elkaar komen te staan en dan vooral niet in bogen. Als dit namelijk wel het geval zou zijn dan is het mogelijk dat een lange lijn over de kaart wordt getrokken, daarom worden de coördinaten van een boog niet tot een decimaal teruggebracht maar in de originele staat gehouden. Dit laatste leidt ook tot problemen indien er na notatieverandering als nog voor het combineren van objecten wordt gekozen. Een punt met 3 decimalen zal alleen te combineren zijn met een punt met 1 decimaal, als de tweede en derde decimaal gelijk zijn aan nul.
H3 - Bestandsgrootte
38
2500
Grootte (kb)
2000
1500
1000
500
0 68
13
54
4
81
96
Bestandsnaam conversie
laagkeuze
combineren
honderdduizendtal
1 decimaal
Figuur 3.15 Grootte Mutatis svg bestanden na notatieverandering t.o.v. Mutatis svg bestanden na conversie, laagkeuze en combinatie.
De kaart van de grootste buurt (buurt 96) heeft na alle semantische generalisatie nog een grote van 767 kilobyte, met andere woorden het bestand is maar liefst 20204 kb in omvang afgenomen oftewel nog maar 3,66% van de originele Gardos SVG bestandsgrootte. Van de 67 buurtkaarten die getoond moeten worden was in eerste instantie geen enkele van een acceptabele grootte, nu zijn er nog vijf die enigszins te groot zijn, daarom is er voor gekozen om bij deze bestanden een waarschuwing mee te geven over de eventuele laadtijd.
H4 - Kleurvlakken
39
Hoofdstuk 4
Kleurvlakken
4.1 Intuïtie Intuïtief -> Door ingeving, onmiddellijk vattend Fragment 4.1 definitie van intuïtief Een tweede vereiste, van de te maken svg-kaart voor de digitale architectuurgids, was gericht op het verhogen van het gebruiksgemak van de kaart door in te spelen op de intuïtie van de gebruiker. Zoals te zien is bij het eerder in hoofdstuk 1.6.3 besproken voorbeeld van de Dresdener campus van A.Berger, maakt deze kaart gebruik van kleuren ter verduidelijking op een manier die ook voor de kaart van de architectuurgids interessant is. Voor de kaart van de architectuurgids werd gekozen voor vier hoofdgroepen met bijbehorende kleuren, namelijk rood voor gebouwen, grijs voor wegen, blauw voor water en groen voor natuur. Svg biedt de mogelijkheid om objecten te vullen, het zou dus mogelijk moeten zijn om per laag een kleur mee te geven en zodoende alle objecten een kleur te geven.
Fig. 4.2 Verkeerd gevuld object
Fig. 4.3 Goed gevuld object
Zoals in figuur 4.2 te zien is, brengt het vullen van het ‘rode kruis’ niet het gewenste resultaat. Een zelfde resultaat was te zien bij het vullen van de buurtkaarten, waarbij alle objecten, op een enkeling na, niet of verkeerd gevuld werden. De reden hiervoor is dat de objectomschrijving van de originele DXF bestanden niet geschikt is om een object binnen SVG te vullen. Een object levert het gewenste vulresultaat wanneer deze in zijn geheel beschreven is, waardoor er geen vulsel kan ‘lekken’. Een object in de GBKN is echter in de meeste gevallen beschreven als een verzameling van meerdere objectendelen, zodat niet duidelijk is welke delen bij een object horen en wat er precies gevuld moet worden.
H4 - Kleurvlakken
40
Doordat de objectomschrijving al eerder problemen opleverde bij het reduceren van lijnen (zie hst 3.2.1) is het wellicht mogelijk om de eerdere techniek van het lijncombineren ook hier toe te passen. Het idee hier achter is dan dat de losse objectfragmenten gecombineerd worden tot het gehele object. Wat echter al eerder gebleken is, is dat niet alles even gemakkelijk te combineren is, vooral de beperking waardoor kruispunten niet worden geknoopt zorgt hiervoor. In figuur 4.5 is te zien dat het daadwerkelijke percentage van ‘afgesloten’ objecten gemiddeld erg laag is, er kan dus wel gevuld worden, maar het resultaat zal ‘rode kruis’-achtige kenmerken hebben, wat het intuïtieve gedeelte eerder negatief verandert dan positief. Figuur 4.4 toont dat vooral de lagen met losstaande objecten (laag 3 en 4) een hoog “afsluitings”-percentage hebben, dit geldt echter niet voor alle bestanden (buurt 4), daarom is het vullen andermaal niet aan te bevelen. Verder valt op dat de lagen 17 (wegmarkering) en 24 (kademuur) blijkbaar niet samen te voegen zijn op een uitzondering na. De reden hiervoor is dat deze lagen bestaan uit ‘tussen’-objecten, die worden gebruikt om objecten uit andere lagen door te laten lopen.
Bestandsnaam Figuur 4.5 Gemiddelde aantal gelijke begin- en eindpunten per bestand (voor alle lagen).
Zou er gekozen worden om bijvoorbeeld de bebouwing op de kaarten te vullen, dan is de kans aanwezig dat vooral in buurtbestand 4, waarin slecht 55.6 en 62.2 procent van de objecten in de bebouwingslagen gesloten zijn, verwarrende situaties zullen ontstaan. Duidelijk is wel dat de wegen niet gevuld kunnen worden en dat in het geval van water dit ook niet aan te raden is. De vierde categorie, natuur, zal ook niet gevuld kunnen worden aangezien deze op de kaarten niet aangegeven staat. Om de kaarten toch makkelijker leesbaar te maken zullen andere oplossingen gezocht moeten worden.
H4 - Kleurvlakken
42
4.2 Oplossingen De eerste oplossing die gebruikt kan worden is gebruik te maken van een rasterbeeld als achtergrond, zoals ook te zien was in de voorbeelden in hoofdstuk 1.6.3 van de ‘Gruben glacier’ van Y.Isakowski en de ‘Tuerlersee’ van A. Neumann. Maar zoals al in hoofdstuk 1.3 is aangegeven heeft een rasterbeeld zijn nadelen, waaronder de bestandsgrootte, en was het gebruik hiervan niet aan te bevelen. Als het echter mogelijk is om een rasterbeeld te maken met alleen kleurvlakken, dan is het wellicht mogelijk om zelfs na enig inzoomen toch nog een goed beeld te krijgen (fig. 4.6). Het probleem ontstaat bij de grenzen van de kleurvlakken, maar aangezien de svg-kaart over het rasterbeeld valt worden de grenzen gedeeltelijk afgedekt door het vectorbeeld (fig 4.7).
Figuur 4.6 zoom (4X) buurt68 svg-kaart
Figuur 4.7 volledige zoom buurt68 svg-kaart
De grootte van het rasterbeeld is afhankelijk van de gewenste kwaliteit en deze is weer afhankelijk van de grootte van het SVG bestand. Hoe groter het svg bestand is des te lager de kwaliteit van het rasterbestand wordt en om deze nog enigszins in stand te houden is een groot bestand gewenst en dat is niet de bedoeling.
H4 - Kleurvlakken
43
De tweede oplossing levert geen kleurvlakken, maar kleurlijnen op en heeft geen merkbare invloed op de bestandsgrootte (zie frag. 4.8). Deze methode is automatisch te realiseren door een kleine toevoeging per laag mee te geven, waardoor alle objecten binnen een laag een bepaalde kleur krijgen. Aangezien er geen sprake is van kleurvlakken zou de intuïtieve prikkel minder kunnen zijn (fig 4.9).
<svg> ... Fragment 4.8 Aangeven kleurcode per in SVG
Figuur 4.9 detail van buurt68 svg kaart met kleurlijnen per laag
H4 - Kleurvlakken
44
Het voordeel van het gebruik van kleurlijnen is de omzeiling van het door Josef Albers omschreven ‘1+1=3 of meer’31 effect. Dit effect zorgt ervoor dat nieuwe objecten ontstaan, door insluiting van twee andere objecten (zie fig 4.10), die meestal lawaaierig, rommelig en niet informatief zijn ([9], p.61). Het gebruik van dunne lijnen zorgt voor rustige vibratieloze randen, met toevoeging van kleuren is het vervolgens mogelijk om duidelijke verschillen tussen aparte lagen te scheppen. Kortom het gebruik van kleurlijnen boven kleurvlakken is visueel gezien aan te bevelen.
Figuur 4.10 Voorbeelden ‘1+1=3 of meer’-effect [9]32
31
Josef Albers, “One Plus One Equals Three or More: Factual Facts and Actual Facts,” in Albers, Search Versus Re-Search (hartford 1969), pp. 17-18. 32 (A) en (B) p.61 , (C) p.62
H5 – Conclusie en Aanbeveling Vervolgonderzoek
45
Hoofdstuk 5
Conclusie en Aanbeveling Vervolgonderzoek
In dit onderzoek is een programma ontwikkeld waarmee in eerste instantie DXF bestanden, gemaakt in Autocad versie 14, omgezet kunnen worden naar SVG. Het programma, Mutatis, werd vervolgens uitgebreid met andere functies, die er op gericht zijn om de grootte van de gegenereerde SVG bestanden te verkleinen. Deze was door het gebruik van Mutatis al afgenomen tot vijf tot vijftien procent van de originele omvang van de door Gardos gecreëerde bestanden. De eerste functie geeft de mogelijkheid om bepaalde lagen uit het DXF bestand wel of niet om te zetten, hierdoor werden de bestanden verder teruggebracht tot vier tot elf procent van het Gardos-origineel. Vervolgens werd geprobeerd met lijngeneralisatie de grootte verder terug te brengen, in theorie een goede manier, maar in de praktijk niet haalbaar door de objectomschrijving binnen de GBKN DXF bestanden. De tweede functie was een gevolg van het falen van de lijngeneralisatie-methode en moest ervoor zorgen dat objectfragmenten samengevoegd werden, zodat minder regels nodig waren om een svg bestand te beschrijven. Deze methode bracht de grootte op vier tot zes procent. De in dit onderzoek toegepaste combinatiemethode, zal in een vervolgonderzoek verder uitgewerkt kunnen worden. Doordat de methode niets doet met overeenkomstige punten die vaker dan twee keer voorkomen, kan het gebeuren dat bepaalde punten niet gecombineerd worden (waar dit wel mogelijk is). Om dit op te lossen kan er voor gekozen worden om een combinatiemethode te maken die enkele stappen vooruit ‘kijkt’. Deze methode zal alle overeenkomstige punten tijdelijk combineren, waardoor meerdere lijnen ontstaan. Deze methode zal door moeten gaan totdat er geen combinatiemogelijkheden meer zijn, waarna de originele coördinatenreeks wordt weggeschreven, of totdat een coördinatenreeks ontstaat met een overeenkomstig begin- en eindpunt, waarna deze (nieuwe) reeks zal worden weggeschreven. De derde en vierde functie hebben betrekking op de notatie van coördinaten binnen het svg-bestand, deze werden teruggebracht van honderdduizendtallen tot tienduizendtallen of lager en weggeschreven met een decimaal. Een probleem ontstond doordat in sommige gevallen een boog een zelfde begin- en eindpunt kreeg, daarom is er voor gekozen om in het geval van een boog het originele aantal van drie decimalen aan te houden. Na deze laatste twee functies was het bestand nog maar twee en een half tot vijf procent van de oorspronkelijke grootte (zie fig. 3.15).
H5 - Conclusie
46
Het intuïtiever maken van de svg kaart zou moeten gebeuren door de vlakken van de verschillende objecten op de kaart in te kleuren. Dit is niet haalbaar doordat de objecten niet als zodanig beschreven zijn en functie twee, zoals hierboven beschreven, niet uitgebreid genoeg is om dit op te lossen. Het gebruik van een rasterkaart is af te raden in verband met de bestandsgrootte en daarnaast levert het bij inzooming een onacceptabel beeld op. Kleurlijnen voelen minder intuïtief aan, maar deze oplossing zorgt wel voor een duidelijk en rustig beeld, een onveranderde bestandsgrootte, een compleet door vectoren opgebouwd bestand en een visueel aantrekkelijke kaart. Duidelijk is wel dat in dit onderzoek een basis is gelegd met het programma Mutatis, waarmee de eerste stappen richting een geslaagde conversie gemaakt kunnen worden. Enkele uitbreidingen aan het programma, zoals verbetering van de compatibiliteit met andere dxf versies of uitbreiding van het mogelijke aantal om te zetten objecten, zullen ervoor moeten zorgen dat dit programma een grotere gebruiksgroep aanspreekt. Voor dit onderzoek en voor de in dit onderzoek gebruikte bestanden biedt Mutatis echter precies datgene wat gevraagd wordt.
Literatuurlijst
47
Literatuurlijst
[1]
L.Bagrow – R.A.Skelton, History of Cartography, C.A.Watts & Co.Ltd., Londen, 1964
[2]
Christopher B. Jones, Geographical Information Systems and Computer Cartography, Addison Wesley Longman Limited pp 271-289, 1997
[3]
Sébastien Mustière – Jean Daniel Zucker – Lorenza Saitta, Cartographic Generalization as a Combination of Representing and Abstracting Knowledge, ACM, 1999
[4]
Martin Galanda, Optimization Techniques for Polygon Generalization, ICA Workshop on Progress in Automated Map Generalization (Beijing), 2001
[5]
AGENT Report D2, Selection of Basic Algorithms, http://agent.ign.fr/deliverable/DD2.html, 1999
Openingsscherm (Stap1.cgi) print "Content-type: text/html\r\n\r\n"; #----------------------------------------------------------------------# DXF_KEUZE MENU MAKEN #----------------------------------------------------------------------print "
DXF KEUZEMENU
"; # stukje info print "versie: "; print "
"; print "
"; print "
"; print "
" ; print""; print "
";
Laagkeuzescherm (Stap2.cgi) print "Content-type: text/html\r\n\r\n"; #----------------------------------------------------------------------# MEEGEGEVEN WAARDEN INLEZEN #----------------------------------------------------------------------binmode(STDIN); # pak de meegegeven waarde uit de url read(STDIN, $ret, $ENV{'CONTENT_LENGTH'}); # splits op de eerste =. ($ret, $val) = split(/=/,$ret,2); # check of er uberhaupt iets is ingevuld if (!$val) { print(" Geen bestandsnaam ingevuld "),exit; } # zet hex om in alfanumeriek $val =~ s/%(..)/pack("c",hex($1))/ge; # zet de plussen om in spaties $val =~ s/\+/ /g;
Appendix A - Broncode Mutatis
49
# check de geldigheid van de bestandsnaam en open deze evt. open (INPUT, $val) or print(" Error: Unable to open file $val: $! "),exit; #----------------------------------------------------------------------# HET DXF BESTAND OPDELEN IN 6 SECTIE TEKSTBESTANDEN #----------------------------------------------------------------------# open de tekstbestanden om de zes 'DXF_sections' naar toe te schrijven. open HEADER, ">sections/header.txt" ; open CLASSES, ">sections/classes.txt" ; open TABLES, ">sections/tables.txt" ; open BLOCKS, ">sections/blocks.txt" ; open ENTITIES, ">sections/entities.txt"; open OBJECTS, ">sections/objects.txt" ;
#----------------------------------------------------------------------# LAAGKEUZE MOGELIJK MAKEN + INFOGEDEELTE #----------------------------------------------------------------------print "
LAAGKEUZEMENU
"; print "DXF Bestand is: $val"; # Haal de laaginfo uit de TABLES 'section' open TABLES, "<sections/tables.txt" or print "
ERROR: Can't open 'TABLES'file" and exit; while () { chomp; $f1 = $_; $_ = ; chomp; $f2 = $_; # nieuwe laag if (($f1 =~ "100") && ($f2 =~ "AcDbLayerTableRecord")) { $spin = 1; while ($spin) { $_ = ;chomp; $f1 = $_; $_ = ;chomp; ($f2) = split( ' ', $_, 1); # voeg de laagnaam toe aan de lijst if ($f1 =~ / 2/) {@layerlist=(@layerlist,$f2);} if ($f1 =~ / 0$/) {$spin = 0;} } } } close TABLES; # Geen lagen gevonden? -> stoppen if (!@layerlist){ print " Bestand is geen autocad14 dxf bestand of bezit geen laagstructuur!"; exit; }
Appendix A - Broncode Mutatis
51
print "
"; #----------------------------------------------------------------------# LAAGMENU MAKEN #----------------------------------------------------------------------print "
Geef de naam van het aan te maken svg-bestand "; print "
"; print "
Vink aan voor
Appendix A - Broncode Mutatis
52
SVG inclusief tekst
" ; print "
"; print ""; print "
";
Conversie- en Generalisatiescherm (Stap3.cgi) print "Content-type: text/html\r\n\r\n"; #----------------------------------------------------------------------# MEEGEGEVEN WAARDEN INLEZEN #----------------------------------------------------------------------binmode(STDIN); # pak de meegegeven waarde uit de url read(STDIN, $ret, $ENV{'CONTENT_LENGTH'}); # splits op &. (@key) = split(/&/, $ret); print "
GENERALISATIEMENU
" ; #----------------------------------------------------------------------# BOUW INFOGEDEELTE #----------------------------------------------------------------------print "U heeft de volgende lagen geselecteerd: " ; foreach $key (sort{ $a <=> $b }(@key)) { if ($key =~ /^svgfile/){ ($tmp,$svg)= split(/=/,$key); if (!$svg){ print "U heeft geen bestandsnaam ingevoerd! " ; exit; } } elsif ($key =~ /^Text/){ ($tmp2,$txt)= split(/=/,$key); } else { $key =~ s/\=on//g; # schrap =on. print " + $key"; push (@gekozenlagen,$key); } }
#haal vreemdsoortige dingen weg en gooi er een svg extensie achter. $svg =~ s/\W.*//g; $svg="$svg.svg";
#----------------------------------------------------------------------# LEES HEADER IN OM SVG-VIEWBOX TE BEPALEN #-----------------------------------------------------------------------
Appendix A - Broncode Mutatis
53
$arcs=0; open OUTPUT, ">svg/$svg"; open HEADER, "<sections/header.txt" or print "
ERROR: Can't open 'HEADER'file" and exit; while () { chomp; $f1 = $_; $_ = ; chomp; $f2 = $_; # Minimale x en y waarden if ($f2 =~ /^\D?EXTMIN/){ $spin = 1; while ($spin) { chomp; $f1 = $_; $_ = ; chomp; ($f2) = split( ' ', $_, 1); if ($f1 =~ / 10/) {$xmin = $f2; } if ($f1 =~ / 20/) {$ymin = $f2; $spin = 0;} } } # Breedte en hoogte bepalen aan de hand van maximale waarden if ($f2 =~ /^\D?EXTMAX/){ $spin = 1; while ($spin) { chomp; $f1 = $_; $_ = ; chomp; ($f2) = split( ' ', $_, 1); if ($f1 =~ / 10/) { $width = sprintf( "%.2f",($f2-$xmin)); } if ($f1 =~ / 20/) { $height = sprintf( "%.2f",($f2-$ymin)); $spin = 0; } } } } $ymid=582307.76; # de ymid van de overzichtskaart $ymin=$ymid-(($ymin+$height)-$ymid); # SVG viewbox opslaan print OUTPUT "<svg width=\"10cm\" height=\"10cm\" viewBox=\"$xmin $ymin $width $height\">\n"; close HEADER;
#----------------------------------------------------------------------# LEES ENTITIES IN OM SVG-OBJECTEN TE BEPALEN #----------------------------------------------------------------------$rotatie = $spin = 0; $flag="X_"; open (ENTITIES, "<sections/entities.txt") or print "
ERROR: Can't open 'ENTITIES'file" and exit;
Appendix A - Broncode Mutatis
54
while (<ENTITIES>){ chomp; $f1 = $_; $_ = <ENTITIES>; chomp; ($f2) = split( ' ', $_, 1); # ZOEK NAAR (POLY)LINE (Polyline en line worden samengepakt) KEEPON: if (($f1 =~ / 0$/) && ($f2 =~ /LINE$/)) { $spin = 1; while ($spin) { $_ = <ENTITIES>;chomp;$f1 = $_; $_ = <ENTITIES>;chomp;($f2) = split( ' ', $_, 1); # Kijk of object onderdeel is van gekozen laag, if ($f1 =~ / 8/){ for ($i=0; $i<@gekozenlagen; $i++){ if ($f2 == $gekozenlagen[$i]){ $laagnaam = "P$f2"; # ja? ga dan verder met object goto LINEON; } } # nee? ga dan verder met de rest v/d file goto KEEPON; } LINEON: # x-waarde (=10) en x2_waarde bij line (=11) if (($f1 =~ / 10/) || ($f1 =~ / 11/)){ push(@$laagnaam,$f2); } # x-waarde (=20) en x2_waarde bij line (=21) if (($f1 =~ / 20/) || ($f1 =~ / 21/)){ $f2=$ymid-($f2-$ymid); push(@$laagnaam,$f2); } # in geval van polyline om aan te geven dat deze polyline wel of niet gesloten is if ($f1 =~ / 70$/){ $flag="X_$f2"; } # einde (poly)line if ($f1 =~ / 0$/){ push(@$laagnaam,$flag);$spin = 0; } } goto KEEPON; } # ZOEK NAAR ARC if (($f1 =~ / 0$/) && ($f2 =~ "ARC")) { $spin = 1; while ($spin) { $_ = <ENTITIES>;chomp;$f1 = $_; $_ = <ENTITIES>;chomp;($f2) = split( ' ', $_, 1); # Kijk of object onderdeel is van gekozen laag, if ($f1 =~ / 8/){ for ($i=0; $i<@gekozenlagen; $i++){ if ($f2 == $gekozenlagen[$i]){
Appendix A - Broncode Mutatis
55
$laagnaam = "A$f2"; # ja? ga dan verder met object goto ARCON; } } # nee? ga dan verder met de rest v/d file goto KEEPON; } ARCON:
# x-startwaarde (=10) if ($f1 =~ / 10/) {push(@$laagnaam,$f2);} # y-startwaarde (=20) if ($f1 =~ / 20/) {push(@$laagnaam,$f2);} # straal (=40) if ($f1 =~ / 40/) {push(@$laagnaam,$f2);} # starthoek (=50) if ($f1 =~ / 50/) {push(@$laagnaam,$f2);} # eindhoek(=51) if ($f1 =~ / 51/) {push(@$laagnaam,$f2);} # einde arc if ($f1 =~ / 0$/) {push(@$laagnaam,qw(X)); $spin = 0; }
} goto KEEPON; } # ZOEK NAAR TEXT (als dit de wens is van gebruiker ($txt=on) if ((($f1 =~ / 0$/) && ($f2 =~ "TEXT")) && $txt =~ "on"){ $spin = 1; while ($spin) { $_ = <ENTITIES>;chomp;$f1 = $_; $_ = <ENTITIES>;chomp;($f2) = split( ' ', $_, 1); # Kijk of object onderdeel is van gekozen laag, if ($f1 =~ / 8/){ for ($i=0; $i<@gekozenlagen; $i++){ if ($f2 == $gekozenlagen[$i]){ $laagnaam = "T$f2"; # ja? ga dan verder met object goto TEXTON; } } # nee? ga dan verder met de rest v/d file goto KEEPON; } TEXTON: # align begin x-waarde (=10) if ($f1 =~ / 10/) {push(@$laagnaam,$f2);} # align begin y-waarde (=20) if ($f1 =~ / 20/) { $f2=$ymid-($f2-$ymid); push(@$laagnaam,$f2); } # teksthoogte (=40) if ($f1 =~ / 40/) {push(@$laagnaam,$f2);} # tekst (=1)
Appendix A - Broncode Mutatis
56
if ($f1 =~ / 1$/) {push(@$laagnaam,$f2);} # tekstrotatie (=50) if ($f1 =~ / 50/) {push(@$laagnaam,$f2);} # plaats v. tekst tov begin en eindwaarden (=72) if ($f1 =~ / 72/) {push(@$laagnaam,$f2);} # align eind x-waarde (=11) if ($f1 =~ / 11/) {push(@$laagnaam,$f2);} # align eind y-waarde (=21) if ($f1 =~ / 21/) { $f2=$ymid-($f2-$ymid); push(@$laagnaam,$f2); } # einde text if ($f1 =~ / 0$/) {push(@$laagnaam,qw(X)); $spin = 0; } } goto KEEPON; } # ZOEK NAAR BLOCK-OBJECTS if (($f1 =~ / 0$/) && ($f2 =~ /INSERT/)) { $spin = 1; while ($spin) { $_ = <ENTITIES>;chomp;$f1 = $_; $_ = <ENTITIES>;chomp;($f2) = split( ' ', $_, 1); # Kijk of object onderdeel is van gekozen laag, if ($f1 =~ / 8/){ for ($i=0; $i<@gekozenlagen; $i++){ if ($f2 == $gekozenlagen[$i]){ $laagnaam = "B$f2"; # ja? ga dan verder met object goto INSRTON; } } # nee? ga dan verder met de rest v/d file goto KEEPON; } INSRTON:# block naam (=2) if ($f1 =~ / 2$/) { push(@$laagnaam,$f2); push(@blockies,$f2); } # insert x-waarde (=10) if ($f1 =~ / 10/) {push(@$laagnaam,$f2);} # insert y-waarde (=20) if ($f1 =~ / 20/) { $f2=$ymid-($f2-$ymid); push(@$laagnaam,$f2); } # rotatiewaarde (=50) if ($f1 =~ / 50/) { $rotatie=1;push(@$laagnaam,$f2); } # einde block object
Appendix A - Broncode Mutatis
57
if ($f1 =~ / 0$/) { if($rotatie==0){ # rotatie is nul of heeft geen waarde (nu dus wel) push(@$laagnaam, 0); } push(@$laagnaam,qw(X)); $spin=$rotatie= 0; } } goto KEEPON; } } close (ENTITIES);
#----------------------------------------------------------------------# LEES BLOCKS IN OM OBJECTEN BINNEN BLOCK_OBJECTS TE BEPALEN #----------------------------------------------------------------------open (BLOCKS, "<sections/blocks.txt") or print "
ERROR: Can't open 'BLOCKS'file" and exit; $Bspline=$spin=$Bvertex=$Bpolies=$Barcs=$Btext=$allign=$TxtR= 0; $polylijn=""; while (){ chomp; $f1 = $_; $_ = ; chomp; ($f2) = split( ' ', $_, 1); # Ga voor elk relevante block-object na hoe deze is opgebouwd foreach $block(@blockies){ if (($f1 =~ / 2$/) && ($f2 eq $block)) { $spin = 1; while ($spin) { $_ = ; chomp; $f1 = $_; $_ = ; chomp; ($f2) = split( ' ', $_, 1); BLKON: # ZIJN ER (POLY)LINES IN HET BLOCK_OBJECT? if (($f1 =~ / 0$/) && (($f2 =~ /LWPOLYLINE/) || ($f2 =~ /LINE/))){ $Bpolies++; $spin2 = 1; $nr = 0; while ($spin2) { $_=;chomp;$f1=$_; $_=;chomp;($f2)=split( ' ',$_,1); if (($f1 =~ / 10/) || ($f1 =~ / 11/)) { if ($nr==1){ $polylijn=$polylijn . "L $f2,"; $nr=0; } else{ $nr++; $polylijn="$polylijn$f2,"; }
if ($f1 =~ / 20/) { $f2=$ymid-($f2-$ymid);$y1=$f2; } if ($f1 =~ / 40/) {$h=$f2;} if ($f1 =~ / 1$/) {$t=$f2;} if ($f1 =~ / 50/) { $TxtR=1;$r=sprintf("%.1f",$f2); } if ($f1 =~ / 72/) { if($f2==0){$allign=1;$p="start";} elsif($f2==1){$allign=1;$p="middle";} elsif($f2==2){$allign=1;$p="end";} } if ($f1 =~ / 11/) {$x2=$f2;} if ($f1 =~ / 21/) { $f2=$ymid-($f2-$ymid);$y2=$f2; } if ($f1 =~ / 0$/) { if (TxtR==0){$r=0;} if ($allign==1){ $x=($x1+$x2)/ 2; $y=($y1+$y2)/ 2; push(@block, "\n$t\n \n"); } else{ push(@block, "\n$t\n\n" ); } $TxtR=$allign=$spin2= 0; } } goto BLKON; } # Block-object omschrijving is klaar if (($f1 =~ / 0$/) && ($f2 =~ /ENDBLK/)) { if ($Bpolies ne 0 || $Barcs ne 0 || $Btext ne 0){ # Andere objecten? Wacht op uitbreiding v. prog J $Hblck{$block}=[@block]; } @block=(); $Bpolies=$spin=$Barcs=$Btext= 0; } } } } } close (BLOCKS);
Appendix A - Broncode Mutatis
60
#----------------------------------------------------------------------# BLOCK_OBJECTS ALS DEFS IN SVG BESTAND OPSLAAN #----------------------------------------------------------------------print OUTPUT "<defs>\n"; foreach $attr (keys %Hblck){ print OUTPUT ""; print OUTPUT "@{$Hblck{$attr}}\n"; print OUTPUT "\n"; } print OUTPUT "";
#----------------------------------------------------------------------# OBJECTEN PER LAAG OPSLAAN IN SVG BESTAND #----------------------------------------------------------------------$i=0; foreach $laag(@gekozenlagen){ # Laag opslaan als print OUTPUT "\n\n"; $temp=$laag; # is er ook Text in deze laag? $laag="T$temp"; if (@$laag){ print OUTPUT "\n\n"; foreach $waarde(@$laag){ $i++; if ($waarde=~/^X$/){ if ($i==5){ #In het geval van een default waarde $r=0; $i++; } if ($i==6){ print OUTPUT "\n"; print OUTPUT "" .$t.""; } if ($i==8){ #In het geval van een default waarde $y2=$x2; $x2=$p; $p="middle"; $r=0; $i++; } if ($i==9){ $x=($x1+$x2)/2; $y=($y1+$y2)/2;
} print OUTPUT ""; } # zijn er ook (Poly)lijnen in deze laag? $laag="P$temp"; if (@$laag){ print OUTPUT "\n\n" ; $nr=1; foreach $waarde(@$laag){ $i++; if ($nr==1){ print OUTPUT "<path d=\"M ";$nr=2; } if ($waarde =~ /^X/){ ($end,$polylineflag) = split(/_/,$waarde); if ($polylineflag eq "1" && (($eersteX != $laatsteX) && ($eersteY != $laatsteY))){ # Deze polylijn zou gesloten moeten zijn, maar is dat niet! print OUTPUT "$eersteX,$eersteY\"/>\n"; } else{ print OUTPUT "\"/>\n"; } $nr=1; $i=0; } elsif ($i&1){ # oneven dan x-waarde if($i==1){ # de eerste X (is het M punt)
Appendix A - Broncode Mutatis
62
$eersteX=$waarde; print OUTPUT "$waarde,"; } elsif($i==3){ #de tweede X (is het L punt) print OUTPUT "L $waarde,"; } else{ # de andere X-en kunnen weggeschreven $laatsteX=$waarde; print OUTPUT "$waarde,"; } } else{ # oneven dan y-waarde (gewoon noteren) if($i==2){ # de eerste Y voor later gebruik wegschrijven $eersteY=$waarde; } $laatsteY=$waarde; print OUTPUT "$waarde "; } } print OUTPUT "\n"; } # zijn er ook Arc's in deze laag? $laag="A$temp"; if (@$laag){ print OUTPUT "\n"; foreach $waarde(@$laag){ $i++; if ($waarde=~/^X$/){ print OUTPUT "\n<path d=\"M $x0,$y0 A $rx $ry 0 $large_arc_flag $sweep_flag $xn,$yn\"/>" ; $i=0; } elsif ($i==1){$cx=$waarde;} #CENTER X POSITIE elsif ($i==2){$cy=$waarde;} #CENTER Y POSITIE elsif ($i==3){$rx=$ry=$waarde;} #RADIUS elsif ($i==4){$delta=$waarde;} #STARTANGLE elsif ($i==5){$theta=$waarde; #ENDANGLE $pi = atan2(1,1) * 4; $theta1 = $theta * $pi / 180.0; $delta1 = $delta * $pi / 180.0; $large_arc_flag = ($delta > 180) ? 0:0; $sweep_flag = ($theta > 0) ? 1:0; $x0 = sprintf("%.3f", ($cx + ($rx * cos($theta1)))); $xn = sprintf("%.3f", ($cx + ($rx * cos($delta1)))); $y0 = $cy + ($ry * sin($theta1)); $yn = $cy + ($ry * sin($delta1)); $y0 = sprintf("%.3f",($ymid - ($y0 - $ymid))); $yn = sprintf("%.3f",($ymid - ($yn - $ymid))); } }
Appendix A - Broncode Mutatis
63
print OUTPUT "\n"; } # zijn er ook Block_Objecten in deze laag? $laag="B$temp"; if (@$laag){ foreach $waarde(@$laag){ $i++; if ($i==1){$blckname=$waarde;} elsif ($i==2){$xnul=$waarde;} elsif ($i==3){$ynul=$waarde;} elsif ($i==4){$rota=0-$waarde;} else{ $i=0; #ga naar de juiste block foreach $attr (keys %Hblck){ if ($attr eq $blckname){ print OUTPUT "\n" ; print OUTPUT "\n<use xlink:href =\"\#$attr\"/>" ; print OUTPUT "\n"; } } } } } print OUTPUT "\n"; } print OUTPUT "\n"; close (OUTPUT); print "
#----------------------------------------------------------------------# GEEF GENERALISATIE-MOGELIJKHEDEN AAN #-----------------------------------------------------------------------
"; # Coordinaten vanuit verschillende objectdelen samenvoegen, om zodoende # een 'in 1 path beschreven' object te krijgen. print "
";
Appendix A - Broncode Mutatis
64
# Waarden herschrijven door viewbox tot 0,0 terug te brengen # (in dit geval (agids) worden de waarden van overzichtskaart gebruikt) print "
"; # Aantal decimalen terugbrengen tot 1 print "
"; # Niet generaliseren maar gelijk in raamwerk (=internetformaat) print "
";
Appendix B - Broncode Generalisatie
65
Appendix B
Broncode Generalisatie
Combineermethode (crdknopen.cgi) print "Content-type: text/html\r\n\r\n"; use Benchmark; # tijd testje $t0= new Benchmark;
#----------------------------------------------------------------------# MEEGEGEVEN WAARDEN INLEZEN #----------------------------------------------------------------------binmode(STDIN); # pak de meegegeven waarde uit de url read(STDIN, $ret, $ENV{'CONTENT_LENGTH'}); # splits op &. ($svg,$niks) = split(/=/, $ret); $newsvg="knoop$svg"; print "
COORDINAAT-'KNOPEN'
" ; open IN, "<svg/$svg" or print "
ERROR: Can't open file: $svg" and exit; open OUT, ">svg/$newsvg"; open OUT2, ">svg/no.txt"; print "change bestand $svg -> $newsvg "; print "!!Alleen lijnen en arcs worden omgezet (text moet nog handmatig)!! "; print "Voor een correct eindresultaat moet u dit NU doen. " ; $teller=0; $viewbox="<svg>"; #----------------------------------------------------------------------# SVG INLEZEN OM BEGIN- EN EINDPUNTEN PER 'PATH' TE BEPALEN #----------------------------------------------------------------------while (){ chomp; $regel = $_; if ($regel =~ /svg /){ $viewbox = "$regel"; } # Laagnaam oppakken elsif ($regel =~ /g id/){ $regel =~ s/\s*//g; $laagnaam =$regel;
Appendix B - Broncode Generalisatie
66
} # Lijnen en bogen wegschrijven om het aantal dubbele coordinaatpunten te bepalen per laag elsif (($regel =~ / L /) or ($regel =~ / A /)){ #regel aanpassen $regel =~ s/\s*<path d=\"M //g; $regel =~ s/\"\/>//g; @xenycoord = split (' ', $regel); if ($regel =~ / A /){ $regel="@xenycoord[0..1]_@xenycoord[2]_@xenycoord[3]_ @xenycoord[4]_@xenycoord[5]_@xenycoord[6] @xenycoord[7]"; } #begincoordinaten wegschrijven $hoh{$laagnaam}{$xenycoord[0]}++; #eindcoordinaten wegschrijven $hoh{$laagnaam}{$xenycoord[-1]}++; #hele regel wegschrijven $alleobj{$laagnaam}{$teller++}=$regel; } } @xenycoord=(); close IN; $begin=$eind=$skip=$used=0; print OUT "$viewbox\n"; print OUT "\n\n" ;
#----------------------------------------------------------------------# BEGIN- EN EINDPUNTEN COMBINEREN #----------------------------------------------------------------------while (($laag,$objecten) = each %alleobj){ while (($laag2,$coords) = each %hoh){ if ($laag==$laag2){ while (($coord,$aantal) = each %$coords){ push (@meerdan2,$coord) if($aantal>2); } } } while (($teller,$object) = each %$objecten){ push (@alleobj,$object); } print OUT "\n"; print OUT2 "\n"; for ($i=0; $i<@alleobj;$i++){ @koppels = split (' ', @alleobj[$i]); foreach $skipkopp(@meerdan2){ if (@koppels[0] eq $skipkopp){$begin=1;} if (@koppels[-1] eq $skipkopp){$eind=1;} if ($begin==1 && $eind==1){ $toprint=""; @alleobj[$i] =~ s/\s{2,}/ /g; @alleobj[$i] =~ s/^\s//g; @alleobj[$i] =~ s/_/ /g;
Appendix B - Broncode Generalisatie
67
@testkoppels = split (' ', @alleobj[$i]); # test om te kijken of er geen problemen ontstaan zijn bij het koppelen van arc's aan lijnen # als er 2 coordinaten na een arc-definitie komen dan moet er een L tussen beide komen. $toprint= "$toprint<path d=\"M"; for ($k=0; $k<@testkoppels; $k++){ if (@testkoppels[$k] eq 'A'){ if ((@testkoppels[$k+7])&&(@testkoppels[$k+7] ne 'L') && (@testkoppels[$k+7] ne 'A')){ print "@testkoppels[$k] ... @testkoppels[$k+6] @testkoppels[$k+7] -> @testkoppels[$k] ... @testkoppels[$k+6] L @testkoppels[$k+7] " ; @testkoppels[$k+7]="L @testkoppels[$k+7]"; } } $toprint= "$toprint @testkoppels[$k]"; } $toprint= "$toprint\"/>"; if (@koppels[0] eq @koppels[-1]){ print OUT "$toprint\n"; } else{ print OUT2 "$toprint\n"; #coord wel ff meegeven print OUT "$toprint\n"; } $skip=1; last; } } if ($skip==0){ for ($j=$i+1; $j<@alleobj; $j++){ @restkoppels = split (' ', @alleobj[$j]); @tempkoppels=@koppels; @temprestkoppels=@restkoppels; if ((@koppels[0] eq @restkoppels[0]) && $begin!=1){ $used=1; splice(@temprestkoppels, 0,1); @temp=reverse(@temprestkoppels); $temp=""; foreach $waarde(@temp){ if($waarde=~/A/){ @attr = split /_/, $waarde; @attr[5]=(1-@attr[5]); $temp="$temp @attr[0]_@attr[1]_@attr[2]_ @attr[3]_@attr[4]_@attr[5]" ; } else{ $temp="$temp $waarde"; } }
Appendix B - Broncode Generalisatie
68
@temprestkoppels=$temp; $alleobj[$j] = "@temprestkoppels @tempkoppels"; last; } elsif ((@koppels[0] eq @restkoppels[-1]) && $begin!=1){ $used=1; splice(@tempkoppels,0,1); $alleobj[$j] = "@temprestkoppels @tempkoppels"; last; } elsif ((@koppels[-1] eq @restkoppels[0]) && $eind!=1){ $used=1; splice(@temprestkoppels, 0,1); $alleobj[$j] = "@tempkoppels @temprestkoppels"; last; } elsif ((@koppels[-1] eq @restkoppels[-1]) && $eind!=1){ $used=1; @temp=reverse(@temprestkoppels); splice(@temp,0,1); $temp=""; foreach $waarde(@temp){ if($waarde=~/A/){ @attr = split /_/, $waarde; @attr[5]=(1-@attr[5]); $temp="$temp @attr[0]_@attr[1]_@attr[2]_ @attr[3]_@attr[4]_@attr[5]" ; } else{ $temp="$temp $waarde"; } } @temprestkoppels=$temp; $alleobj[$j] = "@tempkoppels @temprestkoppels"; last; } } } if ($used==0 && $skip!=1){ @alleobj[$i] =~ s/\s{2,}/ /g; @alleobj[$i] =~ s/^\s//g; @alleobj[$i] =~ s/_/ /g; @testkoppels = split (' ', @alleobj[$i]); # test om te kijken of er geen problemen ontstaan zijn bij het koppelen van arc's aan lijnen # als er 2 coordinaten na een arc-definitie komen dan moet er een L tussen beide komen. print OUT "<path d=\"M"; for ($k=0; $k<@testkoppels; $k++){ if (@testkoppels[$k] eq 'A'){ if ((@testkoppels[$k+7])&&(@testkoppels[$k+7]ne'L') && (@testkoppels[$k+7] ne 'A')){ print "@testkoppels[$k] ... @testkoppels[$k+6]
Appendix B - Broncode Generalisatie
69
@testkoppels[$k+7] -> @testkoppels[$k] ... @testkoppels[$k+6] L @testkoppels[$k+7] " ; @testkoppels[$k+7]="L @testkoppels[$k+7]"; } } print OUT " @testkoppels[$k]"; } print OUT "\"/>\n"; #print OUT "<path d=\"M " . @alleobj[$i] . "\"/>\n"; } @restkoppels=@koppels=(); $used=$skip=$begin=$eind=0; } @meerdan2=@alleobj=(); print OUT "\n"; } print OUT "\n"; close OUT; close OUT2; $t1=new Benchmark; $td=timediff($t1, $t0); print "Uitvoeren van script duurde: " . timestr($td) . " "; print "
"; #einde infogedeelte #----------------------------------------------------------------------# GEEF GENERALISATIE-MOGELIJKHEDEN AAN #-----------------------------------------------------------------------
print "
"; print "
Generalisatiemogelijkheden
" ;
# Waarden herschrijven door viewbox tot 0,0 terug te brengen # (in dit geval (agids) worden de waarden van overzichtskaart gebruikt) print "
#----------------------------------------------------------------------# MEEGEGEVEN WAARDEN INLEZEN #----------------------------------------------------------------------binmode(STDIN); # pak de meegegeven waarde uit de url read(STDIN, $ret, $ENV{'CONTENT_LENGTH'}); # splits op &. ($svg,$niks) = split(/=/, $ret); $newsvg="korter$svg"; print "
COORDINAAT-VERKORTING
" ; open IN, "<svg/$svg" or print "
ERROR: Can't open file: $svg" and exit; open OUT, ">svg/$newsvg"; print "change bestand $svg -> $newsvg ";
$i=0; $minx = 226868.9; $miny = 577499.6; while (){ chomp; $regel = $_; # Haal de nodige informatie uit de viewbox if ($regel =~ /viewBox/){ @opbouw = split ('"', $regel); print "viewbox -> @opbouw[5] "; @xy = split (' ', @opbouw[5]); $Mapminx = @xy[0]; $Mapminy = sprintf("%.3f",@xy[1]); $newminx = sprintf("%.3f",($Mapminx-$minx)); $newminy = sprintf("%.3f",($Mapminy-$miny)); print "MAINMAP minX=226868.9 minY=577499.6 "; print OUT "@opbouw[0]\"@opbouw[1]\"@opbouw[2]\"@opbouw[3] \"@opbouw[4]\"$newminx $newminy @xy[2] @xy[3]\"@opbouw[6]\n"; print OUT "\n" ; } # Verkort de 'path'coordinaten elsif ($regel =~ /path/){ $regel =~ s/\s*<path d=\"M //g; $regel =~ s/\"\/>//g; @coords = split (' ', $regel); print OUT "<path d=\"M "; foreach $coord (@coords){ if ($coord =~ /,/){ # dan is’t daadwerkelijk een coord. ($x,$y) = split (',', $coord);
Appendix B - Broncode Generalisatie
71
$newxcoord=sprintf("%.3f",($x-$minx)); $newycoord=sprintf("%.3f",($y-$miny)); print OUT "$newxcoord,$newycoord "; } else{ print OUT "$coord "; } } print OUT "\"/>\n";$i=0; } # Verkort de 'text'coordinaten elsif ($regel =~ /translate/){ $regel =~ s/\s*//g; ($coord,$rot) = split (' ', $regel); ($transx,$transy) = split (',', $coord); $newx=sprintf("%.3f",($transx-$minx)); $newy=sprintf("%.3f",($transy-$miny)); print OUT "\n" ; } else{ print OUT "$regel\n"; } @coords=(); } close (IN); close (OUT); print "
"; #einde infogedeelte print "
"; print "
Generalisatie-mogelijkheden
"; # Aantal decimalen terugbrengen tot 1 print "
";
1 Decimaal (1dec.cgi) print "Content-type: text/html\r\n\r\n"; #----------------------------------------------------------------------# MEEGEGEVEN WAARDEN INLEZEN #----------------------------------------------------------------------binmode(STDIN); # pak de meegegeven waarde uit de url read(STDIN, $ret, $ENV{'CONTENT_LENGTH'}); # splits op &. ($svg,$niks) = split(/=/, $ret);
Appendix B - Broncode Generalisatie
72
$newsvg="dec$svg"; print "
COORDINAAT-'KNOPEN'
" ; open IN, "<svg/$svg" or print "
ERROR: Can't open file: $svg" and exit; open OUT, ">svg/$newsvg"; print "change bestand $svg -> $newsvg ";
#----------------------------------------------------------------------# TERUGBRENGEN TOT 1 DECIMAAL (BEHALVE ARC'S) #----------------------------------------------------------------------while (){ chomp; $regel = $_; if ($regel =~ /path/){ $regel =~ s/\s*<path d=\"M //g; $regel =~ s/\"\/>//g; @coords = split (' ', $regel); print OUT "<path d=\"M "; foreach $coord (@coords){ if ($coord =~ /,/){ # dan is’t daadwerkelijk een coord. ($x,$y) = split (',', $coord); if ($vorige eq "A"){ print OUT $x . "," . $y ." "; } else{ print OUT sprintf("%.1f",$x) . "," . sprintf("%.1f",$y) ." "; } } else{ if($coord eq "A" || $coord eq "L"){ $vorige=$coord; } print OUT "$coord "; } } print OUT "\"/>\n"; } elsif ($regel =~ /translate/){ $regel =~ s/\s*//g; ($coord,$rot) = split (' ', $regel); ($transx,$transy) = split (',', $coord); $newx=sprintf("%.1f",($transx)); $newy=sprintf("%.1f",($transy)); print OUT "\n" ; } else{
Appendix B - Broncode Generalisatie
print OUT "$regel\n"; if ($regel =~ / viewBox=/){ $regel =~ s/<svg width=\"10cm\" height=\"10cm\" viewBox=\"//g; $regel =~ s/\">//g; ($xmin,$ymin,$width,$height) = split ( ' ', $regel); } } } close (IN); close (OUT); print "
"; print "
Generalisatie-mogelijkheden
"; # Niet generaliseren maar gelijk in raamwerk (=internetformaat) print "