Usage of offline terrain contents in Android App based on Cesiumjs & Cordova

316 views
Skip to first unread message

pascal poulain

unread,
Jul 16, 2018, 10:13:47 AM7/16/18
to cesium-dev
Good Afternoon,

I'am trying to investigate the use of offline contents inside an Android App based on Cesiumjs and Cordova.
For Imagery and 3D Tiles, the first tests are not so bad, but for the terrain tiles, I am facing issue at the ArrayBuffer fetch level of a content (value exceeded Int limit ) 
If I use the same contents from a terrain tile server, this is working.
I presume that is related to the way a terrain tile is downloaded from the server ("Content-Encoding  gzip;Content-Disposition attachment;") which is not applicable as-is on local file reading.

Is there a way to serve local terrain tiles using file:// using existing Cesiumjs API or some new solution has to defined. ?

Thanks;

Best regards;
Pascal




Gabby Getz

unread,
Jul 18, 2018, 10:57:02 AM7/18/18
to cesium-dev
Hi Pascal,

Serving terrain requires a special configuration designed to handle terrain requests. 

Though not offline, we do have a service, Cesium ion, which can process, host, and serve your terrain data.

If you need an totally offline solution there are some available. Contact Tim for more information.

Thanks,
Gabby 

pascal poulain

unread,
Jul 19, 2018, 9:55:42 AM7/19/18
to cesium-dev
Hi Gaby;

Thanks for the feedback, my concern is about real offline mode where some tiles, terrain and images are on the device to allow to work without internet connexion (or with low bandwith).
Cloud distributed data offer by Cesium ion or on premise  solution as also you can propose require a network access which is not so bad in bandwith, but it is not always the case in real life for some scenario.
To support a minimised set of use cases, it can be useful to have onboard some data to optimize available 4G bandwith if any ( will be an another story with 5G).

In between, I have succeed to manage offline some of my terrain dataset by doing a small code update to apply a gunzip on the read contents for url starting with file:// ( in http, this is done on the fly by the web client).

After some tests, I will potentially share it as pull request it there is an interest for others.

Best regards;
Pascal



Gabby Getz

unread,
Jul 20, 2018, 2:24:16 PM7/20/18
to cesium-dev
Hi Pascal,

Just be careful- Some imagery does not provide the rights to use in an offline context. Natural Earth II is the one we include in Cesium that is allowed.

Additionally, while streaming may be slow initially, after once loaded, requests will be cached on the device so repeated requests will be faster.

The on-prem solution still requires a server, correct. You may be able to configure a custom solution for loading terrain tiles locally, but that behavior is not part of Cesium. If you have an example, please feel free to post it once it's ready!

Thanks!
Gabby

Xavier Tassin

unread,
Apr 3, 2020, 9:54:08 AM4/3/20
to cesium-dev
Hi Pascal,

I am looking for a solution to the exact same problem: would you mind sharing your experience with this?

Thanks,

Xavier

pascal poulain

unread,
Apr 3, 2020, 10:37:50 AM4/3/20
to cesium-dev
Hi Xavier,

I have done a change into CesiumTerrainProvider.prototype.requestTileGeometry to test uri based on file:// and do ungzip of the contents on the client side.
2 year ago, it was working with my own terrain based on CTB but I didn't retest it with last releases of Cesium, as I didn't take time to rework my cordova project to increase the performance on tablet  with large data.
Hereafter the code i have used to test.Perhaps there is a more efficient way to do the uncompression.
     
   return promise.then(function (rawBuffer) {
            var localFile = false;
            var buffer;
            if (typeof url === 'string') {
                localFile = (url.indexOf('file://') === 0) ;
            }
            if (localFile) {
                var tmpArray = new Uint8Array(rawBuffer);
                var uncompressbuffer = pako.ungzip(tmpArray);
                buffer = new ArrayBuffer(uncompressbuffer.length);
                var view = new DataView(buffer);
                uncompressbuffer.map(function(value, i){view.setUint8(i, value);});
            } else {
                buffer = rawBuffer;
            }


Best regards;
Pascal

Xavier Tassin

unread,
Apr 3, 2020, 11:34:37 AM4/3/20
to cesium-dev
Hi Pascal,

Thank you very much for sharing.

Meanwhile I had arrived to about the same result by overriding the Ressource.fetch method as in:

Cesium.Resource.prototype.fetch = function(options) {
options = defaultClone(options, {});
options.method = 'GET';

var promise = this._makeRequest(options);
if (promise && promise.then && this._url.endsWith('.terrain')) {
return promise.then((data)=>{
var inflated = pako.inflate(data);
return inflated.buffer;
});
}

return promise;
};

Thank you, none the less, for the inspiration!

Xavier

pascal poulain

unread,
Apr 3, 2020, 12:32:15 PM4/3/20
to cesium-dev
Hi Xavier,
You are welcome.
Forking Resource is an another way to do it.
I don't remind why i didn't use the direct output of inflate.
Simpliest is better in any case.
Thanks for your feedback.
Pascal

Omar Shehata

unread,
May 4, 2020, 2:39:11 PM5/4/20
to cesium-dev
Heads up that the forum has transitioned over to Discourse and this Google Group will be put into read-only mode today. Details about the transition here.

Reply all
Reply to author
Forward
0 new messages