kaktus40 / Cesium-GeoserverTerrainProvider

plug in to use geoserver as terrain provider
Other
361 stars 142 forks source link

DDS/BIL plugin script for sub-meter elevation #9

Closed Akimh closed 9 years ago

Akimh commented 9 years ago

Hello kaktus40, I was wondering how you can alter your script to use sub-meter elevation ranges. I assume, your using the int 16 bit value range. It's working great with data of elevation ranges in meters using the dds/bil plugin and your GeoserverTerrainProvider plugin. Now, I'm trying to include data of sub-meter elevation ranges (e.g. 0.3m). I created floating 32 bit tiles and altered your script to set and get float32 values of your dds/bil plugin script. Also, I set the byte order in GeoServer to "Big Endian" which causes the error(see picture).

capture

Do you have any ideas?

Thank you!

kaktus40 commented 9 years ago

Hello can I have a sample of your data? I'll work with it and make an update of the plug in.

Akimh commented 9 years ago

Hello, and thanks for your support. I share it with you in Google Drive. You should see a notification in your Gmail.

kaktus40 commented 9 years ago

Hello, I worked with your sample. My stages:

gdalwarp -t_srs "EPSG:4326" -ot Byte -co "TILED=YES" -co "COMPRESS=DEFLATE" -r cubicspline ex2_transparent_mosaic_group1.tif converted
gdalwarp -t_srs "EPSG:4326" -ot Float32 -co "TILED=YES" -co "COMPRESS=DEFLATE" -r cubicspline ex2_dsm.tif converted2
gdal_retile.py -v -r cubicspline -ot Float32   -levels 6 -ps 2048 2048 -co "TILED=YES" -co "COMPRESS=DEFLATE" -co "ZLEVEL=5" -targetDir pyramid2/ converted2
gdal_retile.py -v -r cubicspline -ot Byte   -levels 6 -ps 2048 2048 -co "TILED=YES" -co "COMPRESS=DEFLATE" -co "ZLEVEL=5" -targetDir pyramid/ converted
terrainProvider = new Cesium.GeoserverTerrainProvider({
                url : 'http://localhost:8090/geoserver/ows',
                 layerName: 'elevation:evaluation',
                 maxLevel: 20,
                 service: "WMS",
                 formatArray: {
                            format: "image/bil",
                            postProcessArray: function(bufferIn, size, highest, lowest, offset) {
                                var resultat;
                                var viewerIn = new DataView(bufferIn);
                                var littleEndianBuffer = new ArrayBuffer(size.height * size.width * 4);
                                var viewerOut = new DataView(littleEndianBuffer);
                                if (littleEndianBuffer.byteLength === bufferIn.byteLength) {
                                    var temp, goodCell = 0,
                                        somme = 0;
                                    for (var i = 0; i < littleEndianBuffer.byteLength; i += 4) {
                                        temp = viewerIn.getFloat32(i, false) - offset;
                                        if (temp > lowest && temp < highest) {
// needed for big Endian 
                                            viewerOut.setFloat32(i, temp, true);
//for little Endian, there is no need to switch byte so the code should be  viewerOut.setFloat32(i, temp, false);
                                            somme += temp;
                                            goodCell++;
                                        } else {
                                            var val = (goodCell == 0 ? 1 : somme / goodCell);
// needed for big Endian
                                            viewerOut.setFloat32(i, val, true);
//for little Endian, there is no need to switch byte so the code should be  viewerOut.setFloat32(i, val, false);
                                        }
                                    }
                                    resultat = new Float32Array(littleEndianBuffer);
                                }
                                return resultat;
                            }
                        }
            });

//place camera to the correct position
 var target = Cesium.Cartesian3.fromDegrees(6.68093, 46.55159, 1000);
    var offset = new Cesium.HeadingPitchRange(0, -Math.PI/2, 300);
    viewer.camera.lookAt(target, offset);
    viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

The results are in the attached images.

Comments: Initially I was worried that the warping of the data creates some artefact but by using bing imagery, it seems correct. The artefacts seems to be the pick of trees!!

Initial position with your imagery captureinitiale

an other position classical

with bing withbing

with bing withbing2

with bing withbing3

Akimh commented 9 years ago

You're amazing. Thank you very much. Here is my result: uav

When I move around I experience a couple of artifacts. uav1

uav2

When I include the Bing base layer (with or without the UAV imagery layer), I observed this behavior. bing_bad

Is there a workaround, since your examples look like fine?

Also, when I'm zoomed in, I can barely move around (very slow). I assume, this is a performance issue (data size, etc.).

Again, thank you for your great support.

kaktus40 commented 9 years ago

well a workaround should be to merge the elevation data in order to have a bigger area. The artefacts comes from a rupture in elevation data: the area from sample have an elevation of 800m and the rest of the world is at 0 m...

Akimh commented 9 years ago

That make sense. When I have only a small sample area, how do I merge with other terrain data to provide a bigger elevation area? Ty

kaktus40 commented 9 years ago

you should see gdalbuildvrt to make a virtual file. After you can use the vrt file as a tif with gdal_retile

Akimh commented 9 years ago

Just two final questions:

I'm just wondering how you draped the elevation over the globe. Based on the sample screenshot above (especially the first one) , the rest of the globe is flat (outside the sample area) and is floating nicely into that area. It doesn't look like that you extended the area of the elevation data?.

I see also that you can successfully include the Bing layer and the custom image layer together. I can only see my custom layer when I try to include both.

Thanks again for your great support and of course the time your spending.

kaktus40 commented 9 years ago

Hello, for the first question it's the good assertion, I just put a pyramid data elevation based on your sample. When I saw the data via open layer embedded in geoserver, the area around your sample is completed with no data value. I don't see your second question.

Akimh commented 9 years ago

Hi, the no data value of my sample is -1000 meter in the GeoServer OpenLayer viewer. I'm sorry, but I cannot follow your steps to create a nice transition between the elevation data and the rest of the globe. I altered the no data value to e.g. 780 meters and 0, but that seems to be not working. What do I miss?

My second question was, that you included successfully the Bing layer and the custom image layer together, which looks nice. I can only see my custom layer when I try to include both. (see following screenshot, no Bing imagery visible )

76440866-2557-11e5-941c-ae21744593bb

Thank you for your time.

Akimh commented 9 years ago

Hello, I solved question two by leaving out the BingMapsImageryProvider in the Cesium.Viewer constructor.

kaktus40 commented 9 years ago

All my scripts are above. I didn't change the nodata value of your sample.

Akimh commented 9 years ago

Thanks kaktus. I got it.

Since I try different methods to integrate elevation data into Cesium, I saw that you also forked the gdal2cesium python script from giohappy. Did you get it to work in a windows system?

kaktus40 commented 9 years ago

for now I didn't work on it

Akimh commented 9 years ago

Thanks for all of your support.