This example shows how to create your own datasource with following features:
Decoding and processing in a web-worker
Usage of the styling engine in a custom datasource
Creation of three.js objects in a web-worker
Creating data that appears above and below ground level
To achieve all this we have to implement a custom decoder:
A decoder is a class that encapsulates all the work that should be done in
a web-worker (i.e. decoding and processing).
In this example we derive from ThemedTileDecoder b/c we also want to use
the styling capabilities of harp.gl. If styling is not needed one could also
derive from ITileDecoder directly.
The main entry point for the decoder is the ThemedTileDecoder.decodeThemedTile
method (or ITileDecoder.decodeTile if no styling is needed). All CPU intensive
work, like decoding and processing, should go here, because this method is executed
in a web-worker. The input to this method (data) is coming from the main-thread
and is the result of the DataProvider.getTile method.
The DataProvider is the component that is telling harp.gl where to get the data from.
The main method that has to be implemented is the DataProvider.getTile method.
This method is executed in the main thread and should not do any CPU intense work.
Normally you would just do a fetch here. The result is passed to a web-worker and gets
processed further. In this example we don't fetch any data, but just create some data on the
fly.
Finally we can create our CustomDataSource:
As you can see there is no functionality added but everything is used from TileDataSource.
It is not mandatory to create a derived class but most likely it is needed at some point to
add custom logic.
The more interesting part is the instantiation of our CustomDataSource:
There are two ways to tell the DataSource about our decoder. Either by setting a
decoder instance or by specifying a
concurrentDecoderServiceName.
The first approach would result in decoding the data in the main thread. That might
be useful for debugging or simple data sources, but we want to show the decoding in
a web-worker here, so we use
concurrentDecoderServiceName.
To understand the
concurrentDecoderServiceName
parameter we have to first understand the decoder bundle. All web-workers that are
created by harp.gl are loading the decoder bundle that
was specified in MapViewOptions.decoderUrl when creating the MapView:
By default the url of the decoder bundle is "decoder.bundle.js" and is generated out of
decoder.ts
(Assuming you created your app with the
Yeoman generator).
To properly geometry that is considerable higher or lower than the ground level, the bounding
boxes of the Tiles have to be enlarged to contain that geometry. If that is not done, the
tile may not be rendered at all, or the geometry may be clipped in some circumstances.
In this example, the line is rendered at an altitude of -100m, making the line appear on
ground level when zoomed out, but increasingly far below ground level when zoomed in.
This example shows how to create your own datasource with following features:
To achieve all this we have to implement a custom decoder:
A decoder is a class that encapsulates all the work that should be done in a web-worker (i.e. decoding and processing).
In this example we derive from ThemedTileDecoder b/c we also want to use the styling capabilities of harp.gl. If styling is not needed one could also derive from ITileDecoder directly.
The main entry point for the decoder is the ThemedTileDecoder.decodeThemedTile method (or ITileDecoder.decodeTile if no styling is needed). All CPU intensive work, like decoding and processing, should go here, because this method is executed in a web-worker. The input to this method (
data
) is coming from the main-thread and is the result of the DataProvider.getTile method.The DataProvider is the component that is telling harp.gl where to get the data from. The main method that has to be implemented is the DataProvider.getTile method. This method is executed in the main thread and should not do any CPU intense work. Normally you would just do a fetch here. The result is passed to a web-worker and gets processed further. In this example we don't fetch any data, but just create some data on the fly.
Finally we can create our
CustomDataSource
:As you can see there is no functionality added but everything is used from TileDataSource. It is not mandatory to create a derived class but most likely it is needed at some point to add custom logic.
The more interesting part is the instantiation of our
CustomDataSource
:There are two ways to tell the DataSource about our decoder. Either by setting a decoder instance or by specifying a concurrentDecoderServiceName. The first approach would result in decoding the data in the main thread. That might be useful for debugging or simple data sources, but we want to show the decoding in a web-worker here, so we use concurrentDecoderServiceName.
To understand the concurrentDecoderServiceName parameter we have to first understand the decoder bundle. All web-workers that are created by harp.gl are loading the decoder bundle that was specified in MapViewOptions.decoderUrl when creating the MapView:
By default the url of the decoder bundle is "decoder.bundle.js" and is generated out of decoder.ts (Assuming you created your app with the Yeoman generator).
The CustomDecoder has to be registered in the WorkerServiceManager during the initialization of the decoder bundle. This is done in CustomDecoderService.start
We call CustomDecoderService.start in the previously mentioned decoder.ts.
To properly geometry that is considerable higher or lower than the ground level, the bounding boxes of the Tiles have to be enlarged to contain that geometry. If that is not done, the tile may not be rendered at all, or the geometry may be clipped in some circumstances.
In this example, the line is rendered at an altitude of -100m, making the line appear on ground level when zoomed out, but increasingly far below ground level when zoomed in.