Publishing digital elevation in Cesium
Posted by: Admire Nyakudya | in GeoServer | 2 months, 2 weeks ago | Comments

Digital elevation data is now readily available from multiple sources. There are several tools that can help to visualise elevation data, Cesium being one. Recently I have been researching how to visualise terrain data in cesium and I could not see a  complete example that I could replicate on my own. This post will highlight the steps I took to visualise elevation data in cesium.

  1.  Download elevation data. You can download the data from or using the SRTM Downloader plugin in QGIS. In this example, I am using a GeoTIFF from
  2. Modify your downloaded images to create a seamless layer. You can use gdalbuildvrt or merge the individual tiles to a single image using
  3. Spin up an instance of GeoServer. In this case, we will use the kartoza/geoserver docker image. To render the terrain data, we also need to install a GeoServer BIL extension. We run the following command to spin up GeoServer with the correct extension.
    docker run -d -p 8080:8080 --name geoserver -v `pwd`/data:/data -e COMMUNITY_EXTENSIONS=dds-plugin kartoza/geoserver:2.17.2
  4. Open your GeoServer instance and publish your DEM. 
    NB: Remember to define the BIL format settings for your raster layer when publishing the layer.
  5. Navigate to layer preview and test if you can preview your raster layer.
  6. Proceed to download the cesium terrain workshop material
    NB: The cesium workshop shows a lot of information which is not necessary for our example. We need to modify index.html and Source/App.js to be minimalistic for our example.
  7. Delete some lines from the index.html by running:
    sed -i.bak '24,54d;' cesium-workshop/index.html
  8.  Add a minimalistic App.js to replace the current one in the folder cesium-workshop/Source.
    (function () {
        "use strict";
        var west = 7.1;
        var south = -11.2;
        var east = 72.9;
        var north = 41.2;

        var rectangle = Cesium.Rectangle.fromDegrees(west, south, east, north);

        Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;

        Cesium.Camera.DEFAULT_VIEW_RECTANGLE = rectangle;
        var viewer = new Cesium.Viewer('cesiumContainer', {
            scene3DOnly: true,
            selectionIndicator: false,
            baseLayerPicker: false


        // Remove default base layer
        viewer.imageryLayers.addImageryProvider(new Cesium.IonImageryProvider({assetId: 3954}));
        var terrainProvider = new Cesium.GeoserverTerrainProvider({
            url: "http://localhost:8080/geoserver/wms",
            layerName: "kartoza:E020N40",
            //styleName: "tradecraft:graytocolor",
            waterMask: true
        viewer.terrainProvider = terrainProvider;
  9. Add a declaration for using Cesium-GeoserverTerrainProvider.
    sed -i '/App.js/i <script src="Source/GeoserverTerrainProvider.js"></script>' cesium-workshop/index.html
  10. Use a web server to render your HTML file. For my use case, I am using Nginx in docker.
    version: '3.4'

        image: nginx
          - ./cesium-workshop:/web
          - ./sites-enabled:/etc/nginx/conf.d:ro
          driver: json-file
            max-size: 200m
            max-file: '10'
          - 8091:80
    Where my nginx conf located in sites-enabled looks like
    server {

        listen      80;
        # the domain name it will serve for
        server_name localhost;

        # max upload size, adjust to taste
        client_max_body_size 15M;

        location / {
            add_header "Access-Control-Allow-Origin" "*";
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
            add_header 'Access-Control-Allow-Headers' 'X-Requested-With,Accept,Content-Type, Origin';
            root /web/;
            index index.html index.htm;

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
            root /usr/share/nginx/html;

  11. Navigate to http://localhost:8091
  12. Rotate your map and you should be able to visualise the terrain as depicted below.
  13. In the production environment remember to replace the cesium default ion access token with your own
Currently unrated


Have any questions? Contact us.
We would love to hear from you!
Subscribe to our Mailing list (spam-free, industry-relevant occasional emails)

Subscribe to our mailing list

* indicates required