GeoServer and Cesium for Terrain Rendering

Hello in my repository I try to manage no data value by changing altitude with previous cell altitude. What do you think?

Hello, I don't know if you use my plugin but I finally improve it to decrease some identified glitches of bil/DDS plug in (sometimes datas provided by bil/DDS plugin aren't consistent).

Unfortunately I'm still unable to get the geometry back using your plugin. It seems to always fail on line 536:

if (littleEndianBuffer.byteLength === bufferIn.byteLength)

Also, maybe you should use

throw new Cesium.DeveloperError('no good size');

at line 366

Hello,
the core problem is in bil/DDS plugin that doesn't always send good datas. In these cases array size is different than expected size. Also
"if (littleEndianBuffer.byteLength === bufferIn.byteLength)" is a mandatory to filter good datas returned by bil/DDS plugin. ( problem seems to be known http://forum.worldwindcentral.com/showthread.php?18819-DDS-Plugin-for-geoserver/page4 ).
Hence, for me, it's not a developerError but just indication to throw when data size mismatches. In the when.js framework (https://github.com/cujojs/when) used in Cesium, a throw command can be catched by otherwise whatever the object type thrown.

In my plugin, I defined a Styled Layer Description (SLD see http://docs.geoserver.org/stable/en/user/webadmin/data/styles.html) in geoserver to convert a 16 bit grayscale color map into a more classical 8 bit red/green/blue scale map which is useable by internet navigator and so by Cesium. For that, you need to insert mySLD.xml (https://github.com/kaktus40/Cesium-GeoserverTerrainProvider/blob/master/mySLD.xml) into geoserver and to remember the name of inserted style, for the exemple it's "grayToColor".
After that, you could use geoserverTerrain provider like this:
var terrainProvider = new Cesium.GeoserverTerrainProvider({
        url : "http://localhost:8080/geoserver/elevation/wms",
        layerName: "SRTM90",
        heightmapWidth:64,
        styleName:"grayToColor"// name of inserted SLD
    });

After that, the plugin will use BIL format in priority and when the datas provided by geoserver in BIL format is wrong, the geoserverTerrainProvider will require a map with the style defined in parameter styleName to make a terrain.

For information I made some captures of an area where BIL/DDS plugin seems to have problems with SRTM 90 meters (lat= 29.39355398979329°; long=85.60289665359001°):
- capture with your WebMapServiceTerrainProvider: http://postimg.org/image/h65mjb47p/
- capture with GeoserverTerrainProvider without SLD: http://postimg.org/image/hueh292xh/
- capture with GeoserverTerrainProvider and with SLD: http://postimg.org/image/6grxr1set/

Hi,

I'm trying to add a geotiff DEM to the Cesium globe using GeoserverTerrainProvider. The terrain data looks fine in Cesium, but I am having problems with the new terrain being displayed incorrectly at a much lower elevation than the rest of the globe. See here: http://s7.postimg.org/ahyakuhij/geoserver_qld3.jpg

I have tiled the data using GDAL and imported it into geoserver using ImagePyramid and with BIL plugin installed, and the SLD stylesheet mapping -32768 to #000000 and 15000 to #00BA98. The code I'm using is below. I have tried the example specified on the plugin page, however I cannot get the data to show at all without the postProcessArray function below:

var terrainProvider = new Cesium.GeoserverTerrainProvider({
        url : "http://localhost:8081/geoserver/cubeglobe/wms",
        layerName: "pyramid",
        heightmapWidth:65,
        styleName:"grayToColor",
        formatImage: "image/png",
        tagAltitudeProperty:"GRAY_INDEX",
        waterMask: false,
        formatArray: {
            format : "application/bil16",
            postProcessArray : function(bufferIn)
            {
                // bil is 16 bits big endian cell
                var viewerIn = new DataView(bufferIn);
                var littleEndianBuffer = new ArrayBuffer(bufferIn.byteLength);
                if (littleEndianBuffer.byteLength === bufferIn.byteLength)
                {
                    var viewerOut = new DataView(littleEndianBuffer);
                    //time to switch bytes!!
                    for (var i = 0; i < bufferIn.byteLength; i += 2)
                    {
                        viewerOut.setUInt16(i, viewerIn.getUInt16(i, false), true);
                    }
                  
                    return new UInt16Array(viewerOut.buffer);
                }
                
                return undefined;
            }
    }
    });

I have been modifying the plugin source around lines 427 to 442 and have gotten various results, and I have tried to determine if the SLD values need to be changed for my data (elevation range is -5625m to 2848m), but I am still not understanding things correctly. I am now resorting to trial and error with no success.

Changing line 427 to:
var valeur = (dataPixels[i + 1] << 8 | dataPixels[2] - 32768);
I get this image.. http://s7.postimg.org/m8c828aaz/geoserver_qld1.jpg
Which looks correct elevation outside the land surface (bathymetry) but still incorrect inside the land surface.

Does anyone have any idea what I am doing wrong here?

Some advice would be greatly appreciated thanks!

Allan

Hello,

thank to you I corrected a little issue in line 427: dataPixels[2] should be dataPixels[i+2].

When I wrote GeoserverTerrainProvider, I presume that elevation range is -500m to 12000m (see the default formatArray line 577).

To sum up the plug in behavior, for each tile, it requests a data array from geoserver (format=bil) and parse this array. Sometimes, the size of bill array is inconsistent, also the plug in request from geoserver the image of the tile styled with SLD. The images requested should be blue (range of color between #000000 for -32768 and #00BA98 for 15000 in Red Green Blue format).

The elevation range of your data seems to be -5625m to 2848m. I suggest to get the update of GeoserverTerrainProvider, change line 577 in compliance with the elevation range of your data and combine the use of GeoserverTerrainProvider and ground-push plugin ( https://github.com/NICTA/cesium-groundpush-plugin )

Thanks for your reply Farouk.. and thanks for your work developing this plugin, it will be a great feature for my needs if I can get it working with my data.

I have updated the plugin with the fixed line 427, and modified line 577 to account for my data range, but I still cannot see any improvement.

As you suggested, the use of the groundpush plugin has allowed me to push the DEM up (32768m) to the correct height but it is now difficult matching the groundpush bounds and the DEM bounds, which results in either a 32768m ditch or wall around the data. I have exaggerated this in the image here for demonstration: http://s30.postimg.org/t63lmqe1d/geoserver_groundpush.png

Without groundpush, the DEM data is showing correctly, except it is 32768 below the surface.. again when I modify line 427 to:
var valeur = (dataPixels[i + 1] << 8 | dataPixels[i+2] + 32768);
I get the result in this image (with heightScale=5):
http://s14.postimg.org/lg2sz75m9/geoserver_bathymetry.png
Where the bathymetry is correct, but the land surface is still at -32768. Is there a change I can make that will align both land and bathymetry? I presume the waterMask is the key (I have set waterMask:false). I am searching for a way to increase only the land elevation values by 32768 - do you have any advice to do this?

I am also getting a large number of WebGL errors (which may be related to the inconsistent BIL array sizes)

WebGL: INVALID_OPERATION: texImage2D: ArrayBufferView not big enough for request with UNPACK_ALIGNMENT > 1

Your help is really appreciated, thanks again!

Allan

I guess that "the earth surface under ocean" has no-data elevation or an elevation of 0 meter...
You can check this via geoserver layer preview. In this page you choose openlayer as a common format. With a double click in the map, geoserver return the data which was double clicked (elevation in meter or grey tone or color).

I guess that "the earth surface under ocean" has no-data elevation or an elevation of 0 meter...
You can check this via geoserver layer preview. In this page you choose openlayer as a common format. With a double click in the map, geoserver return the data which was double clicked (elevation in meter or grey tone or color).

Unfortunately I still cannot get my data to show correctly.

I have confirmed the preview in Geoserver and my bathymetry data looks as expected. See image here, showing almost the entire dataset:
http://s27.postimg.org/w1b80rx03/bathymetry_preview.png

The value of 140.0 displayed is from a point towards the bottom-left corner of the data (which is the land surface of Queensland, lighter green). The top-right side of the image is the bathymetry under the water (all negative values).

As mentioned previously, the terrain surface relief looks correct, except my data is showing far beneath the rest of the global terrain. I have tried various modifications to the source with mixed results, all incorrect. I can get the bathymetry surface only to display at the correct position by changing line 427, as in my previous post, but the land remains underneath the rest of the terrain.

It would be great if you could help me understand the format of the dataPixels array. Or if there is a way I can isolate just the land values only?

thanks again

Allan

Hi Allan,

You may want to give STK World Terrain Server a try. The STK World Terrain Server can convert any raw height data readable by GDAL into the open format quantized-mesh, that can be easily rendered in Cesium via the CesiumTerrainProvider. The STK World Terrain Server is a commercial product and there may be a licensing options available that fits your needs. I can put you in touch with someone at Analytical Graphics if you’d like to find out more.

Alex

Unfortunately I still cannot get my data to show correctly.

I have confirmed the preview in Geoserver and my bathymetry data looks as expected. See image here, showing almost the entire dataset:

http://s27.postimg.org/w1b80rx03/bathymetry_preview.png

The value of 140.0 displayed is from a point towards the bottom-left corner of the data (which is the land surface of Queensland, lighter green). The top-right side of the image is the bathymetry under the water (all negative values).

As mentioned previously, the terrain surface relief looks correct, except my data is showing far beneath the rest of the global terrain. I have tried various modifications to the source with mixed results, all incorrect. I can get the bathymetry surface only to display at the correct position by changing line 427, as in my previous post, but the land remains underneath the rest of the terrain.

It would be great if you could help me understand the format of the dataPixels array. Or if there is a way I can isolate just the land values only?

thanks again

Allan

Hello,
I follow the Alexander’s recommendation. You should try with
quantized-mesh. I suspect that Cesium globe uses a limitation of
terrain when it’s below a certain depth (maybe 0 meter?). When I use
any Terrain provider, during construction, I can’t go below this
limitation with camera…

2014년 1월 29일 수요일 오전 3시 16분 7초 UTC+8, bobactor 님의 말:

>
>
> >
>
> > > Hello!
>
> >
>
> > >
>
> >
>
> > > I'm trying to build a terrain visualization stack on my local machine using Cesius and GeoServer (using other proprietary servers is not an option). Unfortunately, I didn't have much luck.
>
> >
>
> > >
>
> >
>
> > > 1 - Why was WebMapServiceTerrainProvider removed from the master branch? In an older discussion here in cesium-dev there was a patch to make it work on latest Cesium. Is there any other problem with it?
>
> >
>
> > >
>
> >
>
> > > 2 - What's the point of using BIL format on GeoServer instead of plain PNG or other format? I seem to understand it has something to do with terrain data resolution, but I'm not quite sure.
>
> >
>
> > >
>
> >
>
> > > I'm sorry for the naive questions, but I would like to understand :slight_smile:
>
> >
>
> > >
>
> >
>
> > > Alessio
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
> >
>
>
> >
>
> > > Hello!
>
> >
>
> > >
>
> >
>
> > > I'm trying to build a terrain visualization stack on my local machine using Cesius and GeoServer (using other proprietary servers is not an option). Unfortunately, I didn't have much luck.
>
> >
>
> > >
>
> >
>
> > > 1 - Why was WebMapServiceTerrainProvider removed from the master branch? In an older discussion here in cesium-dev there was a patch to make it work on latest Cesium. Is there any other problem with it?
>
> >
>
> > >
>
> >
>
> > > 2 - What's the point of using BIL format on GeoServer instead of plain PNG or other format? I seem to understand it has something to do with terrain data resolution, but I'm not quite sure.
>
> >
>
> > >
>
> >
>
> > > I'm sorry for the naive questions, but I would like to understand :slight_smile:
>
> >
>
> > >
>
> >
>
> > > Alessio
>
> >
>
> >
>
> >
>
> > Hello I'm implementing a solution a terrain provider which uses Geoserver.
>
> >
>
> > This solution works with bil,gif,png ang jpeg formats. The bil format is an array directly directly machine readable. The others formats need a little transformation (picture to array).
>
> >
>
> > I'm using SRTM 250 meters in my tests.
>
> >
>
> > Best regards
>
>
>
> Thank you very much for your reply. I just found your repository and compiled Cesium with GeoServerProvider support.
>
>
>
> I know this is a bit OT, but can you point me to a guide or something to understand how to import SRTM data to GeoServer?
>
>
>
> Also would you please post a snippet on how to use your provider in Cesium?
>
>
>
> Thank you very much!

Hello,
1- you can download SRTM data at http://srtm.csi.cgiar.org/
2- you need to install GDAL tools and python to work with SRTM http://trac.osgeo.org/gdal/wiki/DownloadingGdalBinaries
3- you need to install geoserver image pyramid plugin
4- a guide is available at http://docs.geoserver.org/latest/en/user/tutorials/imagepyramid/imagepyramid.html

I didn't make a documentation to my implementation of geoserver terrain provider. I'll write it soon. I saw that you find my github.
Once you defined a layer of SRTM in geoserver, you could use this snippet:

var terrainProvider = new Cesium.GeoserverTerrainProvider({
        url : "http://localhost:8080/geoserver/elevation/wms",
        layerName: "SRTM250",
        maxLevel:4,
        heightmapWidth:65
    });
    centralBody.terrainProvider = terrainProvider;

Hello,

I did an image pyramid from SRTM website and import the data into the geoserver successfully.

and use the following js code to use the elevation to show in Cesium but didn't work , Could you kindly instruct me what's wrong ?

Thanks very much....

below is my test.html with javascript code:

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Use correct character set. -->
  <meta charset="utf-8">
  <!-- Tell IE to use the latest, best version (or Chrome Frame if pre-IE11). -->
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>Hello World!</title>
  <script src="../Build/Cesium/Cesium.js"></script>
  <script src="../Build/Cesium-GeoserverTerrainProvider-master/GeoserverTerrainProvider.js" type="text/javascript"></script>
  <style>
      @import url(../Build/Cesium/Widgets/widgets.css);
      html, body, #cesiumContainer {
          width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
      }
  </style>
</head>
<body>
  <div id="cesiumContainer"></div>
  <script>
    var canvas = new Cesium.Viewer('cesiumContainer');
    var scene = new Cesium.Scene(canvas);
    var primitives = scene.primitives;
    var globe = new Cesium.Globe(Cesium.Ellipsoid.WGS84);
    scene.globe=globe;

    var terrainProvider = new Cesium.GeoserverTerrainProvider({
        url : "http://localhost:8090/geoserver/elevation/wms?",
        layerName: "SRTM90",
        styleName:"grayToColor",
        waterMask:true
    });
    globe.terrainProvider = terrainProvider;
  
    var hand = new Cesium.ScreenSpaceEventHandler(canvas);
    // return altitude with double click in console.log!!
  hand.setInputAction(
            function (movement) {
                if(movement.position != null) {
                    var carDtesian = scene.camera.pickEllipsoid(movement.position, ellipsoid);
                    if (cartesian) {
                        var cartographic = ellipsoid.cartesianToCartographic(cartesian);
                        cartographic.height=globe.getHeight(cartographic);
                        console.log("lat= "+(cartographic.latitude*180/Math.PI)+"°; long="+(cartographic.longitude*180/Math.PI)+"°; altitude="+cartographic.height+" meters")
                    }
                }
            }, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
  </script>
</body>
</html>

Hello could you check that your internet navigator receive the data. Maybe you have a CORS issue? (see http://enable-cors.org/ )

Hello could you check that your internet navigator receive the data. Maybe you have a CORS issue? (see http://enable-cors.org/ )

Yes, I think so, too. here is the JavaScript console shows:

Uncaught TypeError: undefined is not a function
HelloWorld2.html:1 XMLHttpRequest cannot load http://localhost:8090/geoserver/elevation/wms?SERVICE=WMS&REQUEST=GetCapabilities&tiled=true. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.

Is that what you said? If so, please kindly instruct how to solve the CORS issue.

Thanks for your instruction sincerely....

Hello,
in http://enable-cors.org/ you have the instructions to remove the CORS issue. First,geoserver is deployed on Tomcat? glassFish? Jboss...?? Do you use an httpd server like Apache, Nginx...?
Through these questions, you see I can't help you without more informations on your configuration and http://enable-cors.org/ is easy to apprehend.

bobac...@gmail.com於 2015年1月8日星期四UTC+8下午2時04分03秒寫道:

ccye...@gmail.com於 2015年1月8日星期四UTC+8下午4時21分23秒寫道:

bobac...@gmail.com於 2015年1月8日星期四UTC+8下午2時04分03秒寫道:
> > > Hello could you check that your internet navigator receive the data. Maybe you have a CORS issue? (see http://enable-cors.org/ )
> >
> >
> > Yes, I think so, too. here is the JavaScript console shows:
> >
> > Uncaught TypeError: undefined is not a function
> > HelloWorld2.html:1 XMLHttpRequest cannot load http://localhost:8090/geoserver/elevation/wms?SERVICE=WMS&REQUEST=GetCapabilities&tiled=true. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access.
> >
> > Is that what you said? If so, please kindly instruct how to solve the CORS issue.
> >
> >
> > Thanks for your instruction sincerely....
>
> Hello,
> in http://enable-cors.org/ you have the instructions to remove the CORS issue. First,geoserver is deployed on Tomcat? glassFish? Jboss...?? Do you use an httpd server like Apache, Nginx...?
> Through these questions, you see I can't help you without more informations on your configuration and http://enable-cors.org/ is easy to apprehend.

ok, thanks very much I'll study that web page to get the answer.

actually, I use Node.js to run the httpd server

"D:\Cesium1.5>node server.js
Cesium development server running locally. Connect to http://localhost:8080/ "

the geoserver is 2.5 and run using Java ...
Everything is simple....

Sorry , I read that web CORS page, but it's too difficult to me,

as to I just want to test the efficiency of Cesium, so please kindly instruct me how to do to solve the CORS issue.

the web server is run under Node.js and the geoserver is 2.5 running under JAVA.
my OS is windows 7, the Javascript code that load the elevation data is described below. I just edited it from the HelloWorld.html bundled with Cesium 1.5.

Hope you could give some instruction about the next step. Thanks very much.....

How do you install geoserver?