Sunday 16 March 2014

Using web map services with three.js

In my previous three.js experiments (1, 2, 3, 4, 5) I've only used static files to load terrains and textures. Jarle Pedersen at the Norwegian Mapping Authority has been experimenting with web map services to create 3D terrains.

Jarle is using a modified Web Coverage Service (WCS) to transfer elevation data and a Web Map Service (WMS) for the texture. As WCS don't support a raster format easily parsed with JavaScript, he extended the service to deliver data in a gridded XYZ format (easting, northing and elevation). I've used this service to get elevation data for my map of Jotunheimen:

http://openwms.statkart.no/skwms1/wcs.dtm?SERVICE=WCS&VERSION=1.0.0&REQUEST=GetCoverage&COVERAGE=land_utm33_10m&FORMAT=XYZ&CRS=EPSG:32632&bbox=432000,6790000,492000,6850000&WIDTH=200&HEIGHT=200

The service returns data as text:

432150 6849850 1394.54736328125
432450 6849850 1448.778076171875
432750 6849850 1493.23046875
433050 6849850 1517.87548828125
...

The coordinates are in UTM 32 (meters). It's clearly not the most compact format. As long as we operate on a regular grid or triangle mesh we only need the altitude values. The altitude values could also be transferred in a binary format with less precision as shown in my previous blog post.

I've created a WCS terrain loader which sends the request and returns the altitude values from the response in a callback function.

var terrainLoader = new THREE.TerrainLoaderWCS();
terrainLoader.load(wcsUrl, function(data) {
  ...
});

Remember that you can only use this loader with a Web Coverage Service which returns data in the same XYZ format.

Getting texture data from a Web Map Service (WMS) works out of the box:

http://openwms.statkart.no/skwms1/wms.topo2?SERVICE=WMS&VERSION=1.3.0&REQUEST=GetMap&CRS=EPSG:32632&BBOX=432000,6790000,492000,6850000&WIDTH=2048&HEIGHT=2048&LAYERS=...&FORMAT=image/png

var material = new THREE.MeshPhongMaterial({
  map: THREE.ImageUtils.loadTexture(wmsUrl)
});

The map of Jotunheimen looks like this using these services (click to see in WebGL):



By using web maps services we can just change the geographic bounds and get map data for our area of interest:

http://turban.github.io/webgl-terrain/wxs/?epsg=32633&bbox=-11000,6675000,49000,6735000

Hardanger

http://turban.github.io/webgl-terrain/wxs/?epsg=32633&bbox=405000,7520000,465000,7580000

Lofoten Islands

For code simplicity I'm only operating on rectangular areas. See Jarle Pedersen's repository on GitHub if you want more choice.

See http://kartverket.no/Kart/Kartverksted/Lisens/ for the license terms and http://kartverket.no/Kart/Kartverksted/ for details on the web services.