OBS: En nyere versjon av eksempelet her er tilgjengelig på http://www.atlefren.net/post/2011/02/kartverket-openlayers/. Se gjerne på koden der!
Du har sikkert en GPS, eller en smarttelefon med GPS innebygd? Du liker kanskje også å gå på tur og logge den? Men du synes ikke det er så forbanna kult å legge ut et track fra en tur i den norske villmark over Google Maps (la oss innse det) elendige turkart eller kornete satelittbilder?
Du ønsker kanskje ikke å vise frem noe slik som dette til turvenner? Du skulle heller ønske du kunne lagt inn ruta di over “indrefileten” av norske data? Nemlig kartverkets kart? Du har sikkert fått med deg at disse er tilgjengelige for gratis bruk for privatpersoner?
Du har kanskje til og med kommet så langt at du har fått satt opp OpenLayers med kartverkets WMS på din hjemmeside?
Men der stopper du kanskje? Du skjønner ikke helt hvordan du skal få lagt GPX fila di over kartet? Eller du får kanskje lasta den inn, men den havner helt riv, ruskende, galt avsted? Eller kanskje ser hele Norge helt på trynet ut? Frykt ikke, siden kongeriket Norge har fått meg utdanna som IKT-Geomatiker tenkte jeg jeg skulle prøve å hjelpe deg.
Jeg vet folk lurer på dette. Jeg så tidligere en tweet fra Martin Bekkelund om temaet, og når har også søkefraser som “turkart egne gpx-filer” begynnt å dukke opp i søkeloggene her på bloggen. Derfor tenkte jeg å yte en innsats.
Så, hva tenkte jeg å gå gjennom? Først av alt en liten intro til å sette opp OpenLayers med Kartverkets WMS i Openlayers. Så tenkte jeg å gå gjennom hvordan man får inn GPX-data i OpenLayers, før jeg forklarer magien bak transformasjoner og dermed får alt til å passe sammen.
Kartoppsett
Først må du ha opp et kart, det gjøres ved å gjøre ca følgende:
1. Lag en HTML-side med en div med høyde og bredde 100%. Gi denne diven en id
<html>
<head>
<title>Kart</title>
<!-- sett opp en div til kartet -->
<style type="text/css">
#map { width: 100%; height: 100%;}
</style>
</head>
<body>
<div id="map"></div>
</body>
</html>
2. Så må du legge inn OpenLayers js-biblioteket. Det greieste er å hente den fra serveren deres direkte.
Dette gjør du ved å legge til en <script>-tag i headeren:
<!-- last inn OpenLayers js -->
<script src="http://openlayers.org/api/OpenLayers.js"></script>
3. Så må vi skrive litt JavaScript selv. Vi ønsker å ha en metode som startes når siden listes, og vi velger å legge all javascript-koden direkte inn i en script-blokk i headeren: Da får vi følgende skjelett:
<html>
<head>
<title>Kart</title>
<!-- sett opp en div til kartet -->
<style type="text/css">
#map { width: 100%; height: 100%;}
</style>
<!-- last inn OpenLayers js -->
<script src="http://openlayers.org/api/OpenLayers.js"></script>
<script type="text/javascript">
//her kommer JS-koden vår
function init(){
}
</script>
</head>
<body onload="init()">
<div id="map"></div>
</body>
</html>
4. Da er grunnlaget lagt, vi har importert OpenLayers-biblioteket, og vi har en (foreløpig) tom init-funksjon. Da gjenstår det å lage et Map-objekt, et layer objekt og legge til litt kontroller.
Gjør vi dette blir js-blokka vår seende slik ut (med beskrivende kommentarer):
<script type="text/javascript">
//selve kartet
var map;
//her starter vi ting
function init() {
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3; //reduserer problemet med "rosa" tiles (openlayers viser rosa tiles når den ikke får lastet en tile)
//sett opp kartet (EPSG:32633 er UTM sone 33N)
map = new OpenLayers.Map( 'map', {
projection: new OpenLayers.Projection('EPSG:32633'),
maxExtent: new OpenLayers.Bounds(-2500000.0,3500000.0,3045984.0,9045984.0),
units: "m",
maxResolution: 2708.0, // tilsvarer zoom level 3 (hele er 21664.0)
numZoomLevels: 18 // egentlig 21, men maxResolution tilsvarer zoom level 3 (følgelig er 0-3 skrudd av)
} );
//musenavigering
map.addControl(new OpenLayers.Control.MouseDefaults());
// Definer karttjenesten(e)
var topo2 = new OpenLayers.Layer.WMS(
"Topografisk norgeskart2","http://opencache.statkart.no/gatekeeper/gk/gk.open?",
{layers: 'topo2', format: 'image/png'},{attribution:''}
);
// Legg WMSen fra kartverket til kartet
map.addLayers([topo2]);
//sentrer kartet på besseggen
map.setCenter(new OpenLayers.LonLat(683589,7146336),0); //Besseggen
}
</script>
5. Har du kommet så langt skal du nå ha ett Norgeskart du kan zoome og panorere rundt i, slik som dette.
GPX-innlasting
Godt å vel det, men jeg ser jo fortsatt ikke noe track? Nei, det skal vi ta nå.
Første skritt er å lokalisere en .gpx-fil (min ser slik ut) og ligger i samme mappe som kartet mitt på webserveren.
En ting kan vi like godt notere oss først som sist: GPX filer er i et koordinatsystem kjent som WGS 84 Lat/Lon, mens kartet vårt er i WGS84 UTM Sone 33N. Derfor må vi transformere, men det kommer vi til. Først skal vi få lasta inn GPX-fila i JS-koden.
1. Innlasting. OpenLayers har støtte for GPX-formatet og støtte for å laste filer. I tilegg må vi ha et vector-layer å legge tracket vårt i.
Ved å legge inn dette får vi noe slikt som:
//openLayers GPX-leser
var format = new OpenLayers.Format.GPX();
//layeren vi hiver featurene fra GPX i
var featureLayer = null;
//selve kartet
var map;
//her starter vi ting
function init() {
//sett opp featurelayeren som en vector-layer
featureLayer = new OpenLayers.Layer.Vector("GPX");
//url til gpx-fila (må ligge på samme server)
var url = "track.gpx";
//OpenLayers har støtte for å lese inn filer
OpenLayers.loadURL(url, null, null, loadSuccess, loadFailure);
//sett opp kartet (EPSG:32633 er UTM sone 33N)
map = new OpenLayers.Map( 'map', {
projection: new OpenLayers.Projection('EPSG:32633'),
maxExtent: new OpenLayers.Bounds(-2500000.0,3500000.0,3045984.0,9045984.0),
units: "m",
maxResolution: 2708.0, // tilsvarer zoom level 3 (hele er 21664.0)
numZoomLevels: 18 // egentlig 21, men maxResolution tilsvarer zoom level 3 (følgelig er 0-3 skrudd av)
} );
//musenavigering
map.addControl(new OpenLayers.Control.MouseDefaults());
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3; //reduserer problemet med "rosa" tiles (openlayers viser rosa tiles når den ikke får lastet en tile)
// Definer karttjenesten(e)
var topo2 = new OpenLayers.Layer.WMS(
"Topografisk norgeskart2","http://opencache.statkart.no/gatekeeper/gk/gk.open?",
{layers: 'topo2', format: 'image/png'},{attribution:''}
);
// Legg WMSen fra kartverket og featureLayeren vår til kartet
map.addLayers([topo2,featureLayer]);
//sentrer kartet på besseggen
map.setCenter(new OpenLayers.LonLat(683589,7146336),0); //Besseggen
}
//denne kalles når GPX-fila er lastet
function loadSuccess(request) {
//les responsen her som GPX
var features = format.read(request.responseText);
}
//denne kalles hvis/når noe går galt ved lesing av fila
function loadFailure(request) {
alert("Kunne ikke lese GPX-fila...");
}
Vi ser vi har gjort endel nye ting:
- Vi har definert et format og en featureLayer
- Vi kjører et kall til OpenLayers.loadURL
- Vi legger til et layer til til kartet
- Vi har en funksjon loadSuccess som laster GPX-fila over i et feature-array
Men vi kommer forsatt ikke så veldig langt.
Neste, logiske skritt, ville være å legge til featurene i featureLayeret og zoome inn på disse. Dvs å legge til litt i loadSuccess:
function loadSuccess(request) {
//les responsen her som GPX
var features = format.read(request.responseText);
//vi får da en samling features, legg disse til vector-layeret
featureLayer.addFeatures(features);
//zoom kartet, denne gangen til område de lastede featurene dekker
map.zoomToExtent(featureLayer.getDataExtent());
}
Men dette vil ikke fungere, det ser vi her. Problemet er, som nevnt før, at vi har to forskjellige koordinatsystem. Hadde kartet vært i WGS84 Lon/Lat hadde det fungert (men det vil vi ikke, da ser ikke kartet bra ut), hadde GPX-fila vært i WGS84 UTM Sone 33N ville det fungert (men det er aldri GPX-filer).
Dermed må vi transformere. Her kommer OpenLayers til kort, men den kan støtte seg på Proj4js. Du må laste ned kildekoden, og legge “lib/proj4js-compressed.js” et sted der javascriptet ditt når den, samt inkludere den på samme måte som med OpenLayers.js. Hvis du legger den i samme mappe legger du til:
<script src="proj4js-compressed.js"></script>
i headeren.
I tillegg må du definere for Proj4Js hvilke parametere som gjelder for WGS84 UTM Sone 33N, da den ikke kjenner det. Dette gjør du ved å legge inn følgende i begynnelsen av JavaScriptet:
//Proj4js definisjon for WGS84 UTM Sone 33N
Proj4js.defs["EPSG:32633"] = "+proj=utm +zone=33 +ellps=WGS84 +datum=WGS84 +units=m +no_defs";
(Denne definisjonen finner du under “Proj4js” på http://spatialreference.org/ref/epsg/32633/.)
Da er vi nesten i mål, nå gjenstår bare selve transformasjonen. Det vi må gjøre i loadSuccess er å loope gjennom alle featurene og transformere geometriene fra WGS84 LatLon (som har kode EPSG:4326) til WGS84 UTM Sone 33N (som har kode EPSG:32633). Dette gjør vi med transform-metoden til geometri-objektet, og funskjonen vår blir slik:
function loadSuccess(request) {
//les responsen her som GPX
var features = format.read(request.responseText);
//loop gjennom alle features og transformer fra WGS84 Lat/Lon (EPSG4326) til WGS84 UTM Sone 33N (EPSG:32633)
for(var i = 0; i
}
//vi får da en samling features, legg disse til vector-layeret
featureLayer.addFeatures(features);
//zoom kartet, denne gangen til område de lastede featurene dekker
map.zoomToExtent(featureLayer.getDataExtent());
}
Nå ser vi et spor slynge seg oppover Skogshorn, men det er litt blasst. Vi må endre hvordan det tegnes!
Flikking og pussing
Vi har nå ting på plass, men det ser kanskje litt sært ut? Vi kan mens vi er i gang fikse litt på utseendet på lina vår, via et StyleMap på vektor-layeret. Dette gjør vi ganske enkelt slik (og tegner linja med 2px grønn strek):
//angi styling av features
var styleMap = new OpenLayers.StyleMap(OpenLayers.Util.applyDefaults({
strokeColor: "green",
strokeWidth: 2},
OpenLayers.Feature.Vector.style["default"]));
//sett opp featurelayeren som en vector-layer
featureLayer = new OpenLayers.Layer.Vector("GPX", {styleMap: styleMap});
Og får dette. (For mer om styling, se OpenLayers.Feature.Vector).
Eller kanskje du foretrekker å bruke N50-kartet som bakgrunn, og la brukeren få velge? Mulighetene er mange!
Konklusjon
Dette var bare en quick-and-dirty gjennomgang av prinsippene, koden fungerer greit til enkel bruk, men den kan lett kombineres med opplastingsrutiner for å laste opp GPX-filer via f.eks. php, eller du kan utvide ting til å bruke en romlig database for å lagre GPS-tracket? Muligehtene er mange.
Og, skulle du oppdage feil eller mangler, eller har spørsmål er det bare å si fra!

#1 Tweets that mention HC SVNT DRACONES » GPX med Kartverkets bakgrunnskart -- Topsy.com: (27. July 2010, 00:55)
[...] This post was mentioned on Twitter by Erlend Kvinnesland, Atle Frenvik Sveen. Atle Frenvik Sveen said: Blogger: GPX med Kartverkets bakgrunnskart http://bit.ly/9aVuTt #geomatikk (@MartinBekkelund) [...]
#2 Alexander Salveson Nossum: (27. July 2010, 08:38)
Bra med den type tutorials! Vil tro det er veldig nyttig for ganske mange!
Legger til en annen basic-tutorial om kun OpenLayers og Statens Kartverk sine tjenester: http://folk.ntnu.no/alexanno/projects/index.php/OpenLayers_Crash_Course
#3 Atle: (27. July 2010, 09:25)
Takk for kommentar, godt etter å ha brukt litt tid på slikt.
Glemte helt å nevne at du, og andre, også har laget tutorials som dreier seg rundt kartverkets tjenester, det får eventuelt bli en ny samlepost!
#4 Martin Bekkelund: (10. August 2010, 13:16)
Kjenner at jeg har litt lyst til å gi deg en klem.
Dette har jeg, som du så riktig har merket deg, lurt på lenge. Dessverre kokte det bort i kålen før ferien, så da var det ekstra hyggelig å se denne artikkelen da jeg kom tilbake.
Tusen, tusen takk!
Neste prosjekt blir kanskje å lage et lite PHP-skript som automatiserer opplasting og visning?
#5 Atle: (10. August 2010, 16:48)
Takker, hyggelig med sånne tilbakemeldinger.
Jeg synes jo denne appropachen var en smule mer elegant enn det jeg skisserte før sommeren, så for min del var det artig å få det til. Så håper jeg både du og andre får brukt den til noe fornuftig.
Nå er ikke jeg noen racer på PHP, men jeg vil tro det er en enkel sak å lage et standard upload-script, og det å programmatisk gi js-koden en fil som input er vel heller ikke rocket-science. Men for at jeg skal sette meg ned å gjøre noe sånnt tror jeg jeg må ha bruk for det selv
Dog, du har vel litt PHP-peil selv også, har du ikke? :p
#6 Martin Bekkelund: (11. August 2010, 14:33)
Jeg har allerede brukt dette til noe nyttig. Moro å kunne lage en egen, privat turportal hvor jeg publiserer alle GPX-rutene mine.
Det er jo, som du skriver, ikke vanskelig å lage et slikt PHP-skript som bare genererer en ny HTML-fil med ny GPX-informasjon. Jeg er ingen guru på PHP, men det kunne vært moro å lage. Men det var denne tiden, da.
#7 Garmin Forerunner 305 « Martin Bekkelund: (30. August 2010, 10:35)
[...] er at jeg kan kombinere GPX-filen med kartdata fra Statens kartverk, slik Atle Frenvik Sveen har beskrevet for oss. Resultatet er intet annet en lekkert, i hvert fall for oss [...]
#8 Jan Andreas Knudsen: (24. January 2011, 11:46)
Takk for denne!
Selv med begrenset html-kunnskap var jo dette veldig lett å sette opp (ehm; klippe og lime): http://kart.jaknudsen.com/2011-01-22.html
Moro å se helgens skitur i detalj når man går nye steder
#9 Atle: (24. January 2011, 12:41)
Hyggelig å høre at det kommer folk til nytte, og at det faktisk er mulig å bruke oppskriften for omtrent menigmann
#10 HC SVNT DRACONES » GPX med Kartverkets bakgrunnskart, del 2: (16. February 2011, 21:11)
[...] skrev for en stund siden litt om hvordan man kan kombinere GPX-filer med de åpne WMS-servicene til kartverket. Igrunn bare [...]
#11 marius rohde johannessen: (14. March 2011, 17:09)
Flott post! Dette skal testes. Finnes det måter å legge til bilder fra turer i kartet, f.eks fra panoramio? Hender man har noen fine geotaggede mobilbilder man gjerne vil dele med andre.
#12 Atle: (14. March 2011, 17:19)
Marius; Takk for tilbakemelding, jeg har laget en ny versjon, som du finner her: http://www.atlefren.net/post/2011/02/kartverket-openlayers/ denne har støtte for bilder, men ikke via panoramio eller flicker eller lignende sider. Dog, med litt js-kunnskap skal det ikke være umulig å få til.
#13 HC SVNT DRACONES » Hjelp, jeg vil lære meg OpenSource WebGIS?: (17. May 2011, 12:53)
[...] hvem vil ikke det? Joke aside, som jeg tror jeg har vist flere ganger her på bloggen er det mye man kan gjøre med en eller flere av tre [...]
#14 Geir A Granviken: (28. September 2011, 21:04)
Endelig fant jeg en løsning som faktisk fungerer, nemlig din!! Jeg har ønsket nettopp dette, å kunne vise GPS-spor på Statkarts fantastiske norgeskart, i stedet for på det sørgelige kartet hos Google. (Og det var etter å ha sett de flotte kartene på Ut.no, at jeg skjønte at det kanskje var mulig å gjøre dette mye mye bedre!)
Jeg har kastet bort flere dager på å teste ut løsninger med utgangspunkt i eksemplene på Statkarts utviklersider (som forøvrig er fulle av feil, som tok særdeles lang tid å debugge for en som bare kan vanlig HTML, før jeg i det hele tatt fikk vist et kart på skjermen…), samt eksempel-nettstedene det var linket til. Men ikke pokker om jeg fikk opp noe spor fra gpx-filene på det samme kartet, uansett hva jeg prøvde av anvisninger på hvordan man skulle gjøre det med OpenLayers. Før jeg gav opp gjorde jeg et siste enkelt Google søk, tror det var gpx+statkart, – og vips havnet jeg her!
Jeg tok meg den frihet å kopiere hele kildefilen i det ferdige eksemplet ditt, for å bruke som utgangspunkt, og da fikk jeg jammen meg både kart OG gpx-spor gitt!
Hjertelig takk for dette kompetente stykket arbeide! Du kan se min foreløpige test-side her: http://www.ggranvik.no/tur/tur_snoehetta.htm. Jeg ser du har laget en videreutviklet versjon, som jeg sikkert kommer til å prøve også, men foreløpig er jeg happy bare for det å kunne vise et GPS-spor på Statkarts norgeskart! Forøvrig burde jeg vel legge inn en attribution til din kilde når jeg skal skal publisere en ferdig side?
#15 Atle: (28. September 2011, 21:34)
Så bra du fant noe som endelig fungerte!
Hvis det er slik at Kartverkets eksempler har feil så ville jeg sendt dem en mail, de vil sikkert rette opp i ting hvis de får høre hva som ikke fungerer.
Har du forresten sett http://www.mineturer.org ? Det kan også være en løsning, hvis du kun er interessert i å se turene dine på kart. Dog, jeg skjønner godt at man vil ha ting på egen side.
Når det gjelder attribution er det ikke noe krav i det hele tatt, jeg anser dette eksempelet som “public domain”, men om du på en eller annen måte vil hive inn en link til denne bloggposten er det bare fint, det sørger jo bare for at Google-ranken til denne siden havner høyere, noe som vil glede andre i samme situasjon som deg.
#16 Geir A. Granviken: (2. October 2011, 17:20)
Ja, jeg burde vel maile Statkart om disse eksempel-kodelinjene deres. Jeg prøver gjerne mineturer.org etterhvert. Nå har man vel faktisk muligheten for å gjøre omtent det samme (tror jeg da) på norgeskart.no også. Hvis man oppretter en brukerkonto og logger inn, kan man nemlig laste opp egne GPX-filer, og vise de som egne lag. Veldig sparsomt med dokumentasjon riktignok. Og med funksjonen hvor man kan lage en link for embedding, er det tydeligvis IKKE mulig å få med egne lag (i hvert fall har ikke jeg fått til det). Derfor er koden din fortsatt nødvendig hvis man vil vise en gpx-rute til andre enn seg selv ser det ut til!
Ellers putter jeg inn en attribution til koden din, for som du sier vil jo det bare bidra til å øke rankingen på Google.