Introduction

This guide explains how you can set up your LuciadLightspeed application as a LuciadFusion client. LuciadFusion is Luciad’s server solution for the management, processing and sharing of large spatial data sets in networked environments. As a LuciadFusion client, your application can connect to a LuciadFusion server, retrieve data from it, and visualize it.

About LuciadFusion provides a comprehensive overview of the key concepts and the functional workflow of LuciadFusion, while About the Fusion Client explains the purpose of the Fusion Client. This article concludes with an outline of the purpose, contents and audience of this guide.

About LuciadFusion

The main LuciadFusion components

The main goal of LuciadFusion is to make managing and serving geospatial data easy. End users can easily access and readily visualize the data served by LuciadFusion in 2D and 3D on clients running LuciadLightspeed or other OGC-compatible applications.

The foundation of LuciadFusion is provided by the LuciadFusion Platform, a service application framework. It consists of the LuciadFusion Server and allows you to plug in custom services. It also offers data publication services out of the box, as well as other tools and services that facilitate data management and publication.

FusionComponents
Figure 1. LuciadFusion Platform Components
The LuciadFusion Studio

Data managers can turn to LuciadFusion Studio to manage geospatial data and serve it to client applications. LuciadFusion Studio is a web application that allows data managers to centralize their geospatial data in a catalog, manage and style their data, and publish the resulting products through the services hosted on the LuciadFusion Platform.

Managing data centrally

The LuciadFusion catalog describes the data or data series managed in LuciadFusion Studio. You get your data and data resources in LuciadFusion by uploading it, or by adding the location of the data as a data root, and letting LuciadFusion Studio discover the data by crawling the data root. LuciadFusion supports all data resources, including metadata and style files.

Once you have imported all data, LuciadFusion allows you to manage it centrally, create products from the data, and serve the data to client applications from services.

Publishing products

To serve your client applications an integral geospatial picture, you can combine several thematically related datasets into products, and publish that product through the LuciadFusion services. LuciadFusion products also allow you to style data differently according to client needs, by setting up several products that each combine the same data set with distinct style files.

LuciadFusion Platform Services

The LuciadLightspeed Platform hosts multiple services that allow you to publish your data to any geospatial application through various OGC and custom protocols:

Serve data on-the-fly through OGC WxS services

Direct publication of data through OGC services, without fusing it upfront. Data can be published on a number of services defined by the Open Geospatial Consortium. The supported OGC service protocols are:

  • The OGC Web Map Service lets you publish data with styling applied.

  • The OGC Web Map Tiling Service lets you publish data with styling applied. The styled data is served in a tiled fashion.

  • The OGC Web Feature Service lets you retrieve vector data.

  • The OGC Web Coverage Service lets you retrieve raster data.

Serve fused/pre-tiled data

The process of fusing data consists of converting data into a new data set organized in a hierarchical tile structure, often called a coverage. The OGC 3D Tiles services automatically fuses 3D point cloud and mesh data without any interaction. The Tiling Engine is a service that can fuse vector and raster data on request. You can use the Data Connectivity Manager tool to configure the Tiling Engine.

OGC 3D Tiles Service

The OGC 3D Tiles service lets you publish a large amount of point cloud or mesh data using the 3D Tiles protocol.

Tiling Engine

The LuciadFusion Tiling Engine is a service that fuses source data to organize it in a hierarchical tile structure, a coverage. This optimizes access to the data, for the purpose of querying, visualization, and analysis.

Data Connectivity Manager (DCM)

The DCM is a tool that allows you to connect to local or remote data sources, retrieve the data, fuse the data with the Tiling Engine, and store the fused data as coverages.

Tile Store

A logical structure combining various coverages. You can use it in LuciadFusion V2016.1 and in the DCM, but not in the LuciadFusion Studio.

Luciad Tile Service(LTS)

The Luciad Tile Service allows you to retrieve tiles that have been prepared using the LuciadFusion Tiling Engine.

Serve Symbology through a service

The Symbology Service serves MS2525/APP6 icons. This is an optional service. The extent of your license determines whether you can use this service.

For each service type, multiple instances can be created, each hosting many products. You can set up two WMS services, for instance.

The LuciadFusion Platform is based on the well-known Spring framework for system and application development. Java developers familiar with the Spring framework can quickly familiarize themselves with the LuciadFusion Platform as well. They can also easily customize and extend the platform to suit the needs of their organization.

The LuciadFusion Platform also allows developers to add and remove services, customize services through configuration, and develop and plug in their own services, to perform additional data analysis for example.

About the Fusion Client

The LuciadLightspeed Fusion Client component provides the framework for creating a client that allows users to connect to a Luciad Tile Service. The Fusion client can be integrated with LuciadLightspeed applications so that users can retrieve the LuciadFusion coverage data, and visualize it in a LuciadLightspeed view, or use it as input for other purposes.

The Fusion Client is installed in the same directory as LuciadLightspeed. Go to the start page of LuciadLightspeed by clicking start.jar in the LuciadLightspeed home directory, and then clicking the Documentation button. From here you can access the API reference, code samples, release notes, technical notes, and documentation of LuciadLightspeed Essential and installed components, including the Fusion Client.

About this guide

The articles in this guide provide guidelines on how to:

  • Use the Fusion Client API for creating a client component and connect to a LuciadFusion Data Server, retrieve data from it, and handle the data

  • Integrate the Fusion Client with LuciadLightspeed

  • Customize the connection to a Data Server

This guide is intended for application developers who are familiar with LuciadLightspeed and have a basic knowledge of LuciadFusion. For more information on building a LuciadLightspeed application, refer to the LuciadLightspeed Developer’s Guide.

The functionality discussed in this guide is available in all LuciadLightspeed product tiers.

Conventions

This section describes the typographical conventions that are used in this guide and the naming conventions for the LuciadFusion API components.

Typographical conventions

This guide uses the following typographical conventions:

  • Bold text is used to highlight a term. Note that when a term is used multiple times in a paragraph, only the first occurrence of the term is bold.

  • Italic text is used to quote text or to refer to a document.

  • Reference text is used for internal references to sections, figures, tables, or programs. For example in: Refer to Retrieving resources for more information on(…​).

  • Typewriter text is used API elements such as class and interface names, for input and output messages, code snippets, and for file names and extensions.

Information paragraphs contain important information or useful tips.

For reasons of text alignment and readability, the names of Java packages, Java classes, URLs and directory paths may be split over multiple lines. In these cases, the names, URLs and paths will contain hyphens that are not part of the name or path. You can still open hyphenated hyperlinks successfully by clicking the link, but if you copy and paste URLs and directory paths to the browser’s address bar, the hyphens may come along. If you are copy-pasting, remove the superfluous hyphens in the browser to make the link work.

Naming conventions

The following conventions apply to the naming of LuciadFusion API elements:

  • Names starting with:

    • ILfn are interfaces

    • ALfn are abstract classes

    • TLfn are concrete classes

    • ELfn are enumerations

  • Names related to integration with LuciadLightspeed start with ILsp, ALsp, TLsp, or ELsp.

  • Names outside LuciadFusion (for example, names of sample classes) never start with ILfn, ALfn, TLfn, or ELfn.

  • Names of classes that are part of the Lucy Fusion Client addons start with ILcy, ALcy, TLcy, or ELcy.

  • Names of LuciadFusion Java packages have the following format: com.luciad.fusion.*.

The LuciadLightspeed API follows the same naming conventions but uses sp instead of fn to denote LuciadLightspeed interfaces and classes. The names of all LuciadLightspeed Java packages are listed in the LuciadLightspeed Developer’s Guide.

Connecting to a Data Server

This article describes how to connect to a Data Server using the Fusion Client API. Working with a Data Server explains the basics of a Data Server and describes how data is represented. Creating a client explains how to create a client component and set up a connection to the server. The remaining sections illustrate how to use the client component and work with the data from the Data Server.

Working with a Data Server

ResourceModel Conceptual
Figure 3. Conceptual resource model

The LuciadFusion Data Server represents the data as a set of resources which are stored in a Tile Store. Figure 3, “Conceptual resource model” illustrates the conceptual resource model. There are 3 types of resources: assets, coverages, and themes. An asset represents a set of source data that can be fused. This source data can either be image data (for example a GeoTIFF file), elevation data (for example a DTED file) or vector data (for example an ESRI shape file). An asset can consist of multiple files. Note that all files in one asset must have the same geographic reference. A coverage represents a collection of fused assets. The fused data is stored in a coverage as a hierarchical grid of tiles. This allows fast retrieval of any part of the fused data at any resolution. A theme groups a number of resources. You can use themes to organize multiple resources into a more user-friendly structure.

Each resource has an optional ISO 19115 metadata object, which may contain a wide range of common metadata as defined by the ISO 19115 standard.

ResourceModel Classes
Figure 4. Implementation of the resource model

Figure 4, “Implementation of the resource model” illustrates the implementation of the resource model. Each resource has a unique ID which is used to model the relations with other resources. Note that the server enforces a unique ID for each resource. It does however not enforce any restrictions on the resource IDs of a theme or the asset IDs of a coverage. As a consequence it is for example valid for a theme to refer to a resource that does not exist (yet) or even refer to itself. Refer to Retrieving resources for more information on traversing a resource model. An asset has an asset part for each of its data elements (for example a file). A raster coverage can contain image assets, elevation assets, multi-valued assets, or rasterized vector assets.

To communicate with clients, the Data Server supports two protocols by default:

  • The Luciad Tile Service (LTS) protocol, specifically designed to access, query and manage a LuciadFusion Tile Store from a LuciadLightspeed-based application

  • The OGC Web Map Service (WMS) protocol, to access the data in a standardized way from a LuciadLightspeed or other OGC-compatible application

The Fusion Client uses the LTS protocol, enabling the use of all data querying and data management capabilities offered by the Data Server. To connect to the server using the WMS protocol from a LuciadLightspeed-based application, use a LuciadLightspeed OGC Web Client Suite.

Creating a client

CreateClient
Figure 5. Creating a client

TLfnLTSClient is the central class for connecting to a Data Server. Figure 5, “Creating a client” shows the necessary steps to create an instance of this class. First, you need to create an ALfnEnvironment by calling the static newInstance method on this class. This environment encapsulates all data that can be shared between the client and other environments (for example the server environment). Next, you create an ALfnClientEnvironment by calling its static newInstance method. The client environment encapsulates all data that can be shared between clients.

You typically create the instances of the environment classes once and reuse them afterwards, as they may hold resources for which the allocation or initialization is expensive.

Next, you create a client factory, which is the entry point for creating all client related services. Finally you create the client and connect to a server at a specified URI by calling the factory’s createLTSClient method. Make sure that the URI refers to the LTS service of the Data Server, for example http://myserver:8081/LuciadFusion/lts. The resulting client gives you access to the Tile Store of the Data Server using the method getTileStore. You can retrieve resources from the Tile Store and operate on the data through the ALfnTileStore of the client as explained in the next sections. For more information on the supported server protocols refer to the LuciadFusion Developer’s Guide.

Consistency checking

In order to enable consistency checking of coverages that support it, you need to decorate your ALfnTileStore instance with a TLfnDigestTileStore instance and pass it a handler to be notified of any corruptions. You can also choose to omit corrupt tiles altogether.

Bear in mind that only the coverages which specify a message digest algorithm in their coverage metadata are actually checked for consistency.

Retrieving resources

You can retrieve resources by ID using the getResourceMetadata, getRasterAssetMetadata, getRasterCoverageMetadata, and getThemeMetadata methods on the Tile Store. Alternatively you can retrieve all resources on a server by using the query method with a default TLfnQuery object. For more information on querying data, refer to Querying resources.

You can use the above mentioned methods for retrieving resources also to retrieve the assets of a coverage or the resources in a theme. Because the server does not enforce any restrictions on the referred resources, you need to be careful when retrieving resources. For example, make sure to handle resources that do not exist. You can use the TLfnThemeMetadataTraverser to apply a specific operation to all the resources in a theme, without worrying about special cases as illustrated in Program: Retrieving all coverages in a theme.

Program: Retrieving all coverages in a theme
public List<ALfnCoverageMetadata> getCoverages(TLfnThemeMetadata aTheme, ILfnResourceMetadataResolver aResolver) {
  List<ALfnCoverageMetadata> coverages = new ArrayList<ALfnCoverageMetadata>();
  TLfnThemeMetadataTraverser themeTraverser =
      new TLfnThemeMetadataTraverser(aResolver);
  // Traverse all resources in the theme
  themeTraverser.traverse(aTheme, new ALfnResourceMetadataVisitor() {
    @Override
    public void visit(TLfnThemeMetadata aTheme) {
      // Traverse using this theme traverse
      themeTraverser.traverse(aTheme, this);
    }

    @Override
    public void visit(TLfnRasterCoverageMetadata aCoverage) {
      // Add the coverage
      coverages.add(aCoverage);
    }

  });
  return coverages;
}

Creating and updating resources

As illustrated in Program: Creating a raster asset, you can create new resources by first using their respective builder classes to create a new resource instance and then putting it on the Tile Store. If the put succeeds, the put method returns the resource as it was put on the server (that is, the specified resource with a new update sequence). If the put fails, an exception is thrown.

Program: Creating a raster asset
public void createRasterAsset(
    ALfnTileStore aTileStore,
    String aId, int aUpdateSequence, ELfnDataType aType, String aLocation,
    ILcdBounds aBounds, ILcdGeoReference aGeoReference, TLfnResolution aResolution) throws IOException, TLfnServiceException {

  // Create the raster asset
  TLfnRasterAssetMetadata asset =
      TLfnRasterAssetMetadata.newBuilder().id(aId)
                             .updateSequence(aUpdateSequence)
                             .type(aType)
                             .geoReference(aGeoReference)
                             .addAssetPart().location(aLocation).boundingBox(aBounds).resolutions(aResolution).buildAssetPart()
                             .build();

  // Put it on the Tile Store
  asset = aTileStore.putRasterAssetMetadata(asset);
}

You can update an existing resource in a similar way, as illustrated in Program: Updating a raster asset. The updated version of the resource must have the same update sequence as the current version. If the put succeeds, the put method will return the resource as it was put on the server. If the put fails, an exception is thrown.

Program: Updating a raster asset
public void updateRasterAsset(
    ALfnTileStore aTileStore,
    String aId, String aName, TLcdISO19115Metadata aIso19115Metadata) throws IOException, TLfnServiceException {
  // Get the old raster asset
  TLfnRasterAssetMetadata oldAsset = aTileStore.getRasterAssetMetadata(aId);

  // Create the updated raster asset
  TLfnRasterAssetMetadata.Builder assetBuilder =
      TLfnRasterAssetMetadata.newBuilder(oldAsset);
  assetBuilder.name(aName)
              .iso19115Metadata(aIso19115Metadata);
  TLfnRasterAssetMetadata newAsset = assetBuilder.build();

  // Put it on the Tile Store
  newAsset = aTileStore.putRasterAssetMetadata(newAsset);
}

Querying resources

You can use the TLfnQuery.Builder and create the TLcdOGCFilter directly using the OGC filter API. The XPath expressions that you can use for querying a specific attribute are documented in the API reference of the resource classes. For more information on using OGC filters, see the OGC Filter documentation. You can query the Tile Store with an OGC filter by using its query method. You can also limit the number of resources returned in the result and query only certain types of resources.

You should always use spatial filtering if possible to achieve optimal performance. A common scenario is to use the bounds of the view.

Using coverage user data to store your own metadata

You can associate arbitrary binary data with a coverage using its "user data". Each coverage has a key-blob store that you can use to store your own data.

This user data is stored on the tile store itself, so you can access from anywhere. When the coverage is removed, the user data is also removed.

See the Javadoc of ALfnCoverage.getUserData for details.

Note: this store is not optimized for very frequent access, large blobs or many keys.

Copying the asset sources to the Tile Store

LuciadFusion allows you to copy the original asset sources to the Tile Store, to support OGC WMS GetFeatureInfo requests. You can configure this for any regular coverage metadata object by using assetSourcesInTileStore on the coverage metadata builder . If you enable the setting, the asset sources of all the assets of a coverage will be copied to the Tile Store during the fusion process. As a result, WMS GetFeatureInfo requests are automatically supported for that coverage. This feature is currently supported for S-57 asset sources only.

Using non-tiled coverages

Non-tiled coverages have no tiles, but have the asset sources in the Tile Store instead. Due to the absence of tiles, you can only visualize non-tiled coverages with a WMS client, and not a regular Fusion Client.

Copying tile data

It is possible to copy the tile data of an entire coverage into another, empty coverage. The source and target coverages may be on the same or different Tile Stores. To copy the tile data:

  1. Identify the source coverage on the source Tile Store and get its ALfnCoverage instance from ALfnTileStore.

  2. Make sure an empty coverage exists on the target Tile Store with a coverage structure that matches that of the source coverage. Get its ALfnCoverage instance from ALfnTileStore. Typically, you will create a new coverage by copying its metadata from the source, possibly altering its ID and name but never its structure (bounding box, georeference, …​).

  3. Get the binary content stream by calling exportTo on the source coverage.

  4. Put the binary content stream by calling importFrom on the target coverage.

You can either save the result from the export to a temporary stream and use it later as input for an import, or pipe it directly into the import.

Bear in mind that the abovementioned import/export mechanism only copies the tile content of a coverage, not its metadata nor its asset sources. It is your responsibility to keep the metadata in sync, and to copy the asset metadata as you see fit. The utility class TLfnTileStoreUtil helps you take care of this frequent scenario. There is currently no API to copy the asset sources.

Compatibility considerations

Versions older than 11.1 also support a limited form of import. It was possible to import a coverage from a local Tile Store into another Tile Store. The limitation being that the source coverage had to be on a local Tile Store (no limitation on the target).

Both the import protocol and the binary format of the Tile Store have changed since 11.1, which means that importing new coverages into old Tile Stores will fail. Importing old coverages into new Tile Stores will succeed (even if the client in the middle is an old one).

Caching tile data

Since version 2013.0, it is possible to cache tiles that were retrieved from a given (remote) Tile Store to a local file system-based Tile Store using the TLfnCachingTileStore.

This TLfnCachingTileStore will cache all retrieved tiles from a remote Tile Store into a local Tile Store, while delegating all modifying actions (deleting of resources, putting of resource metadata, etc.) to the remote Tile Store. Once a tile is retrieved and cached, consecutive getTile requests for that specific tile will return the cached version. If the remote Tile Store becomes unavailable at some point in time, the TLfnCachingTileStore continues to serve these cached tiles.

The freshness of tiles can be controlled with the expiration duration. When tiles are updated or deleted on the backend, the tile cache may continue serving outdated cached tiles for as long as the expiration duration allows. After the expiration duration for a tile has expired, an updated tile will be retrieved again from the remote Tile Store. Low expiration durations yield fresher tiles, at the expense of cache efficiency. It should be the goal to set the expiration duration as high as possible while still being acceptable for your use case. Typical values lie in the range of minutes to hours. The expiration duration is ignored when the remote Tile Store is offline, meaning that the cache prefers to serve outdated tiles rather than serving no tiles at all. The rules are as follows:

  1. If a tile is not found in cache and is found on the remote Tile Store, the result is the new tile.

  2. If a tile is not found in cache and is not found on the remote Tile Store, the result is "tile not found".

  3. If a tile is found in cache and not expired, the result is the cached tile.

  4. If a tile is found in cache and expired and found on the remote Tile Store, the result is the new tile. The cached tile is updated and its expiration duration is reset.

  5. If a tile is found in cache and expired and not found on the remote Tile Store, the result is "tile not found". The cached tile is deleted.

  6. If the remote Tile Store is offline and a tile is not found in cache, the result is "tile not found".

  7. If the remote Tile Store is offline and a tile is found in cache, the result is the cached tile, regardless of whether it is expired or not.

  8. Failures meaning "remote Tile Store offline" are never propagated onto the user’s handler.

  9. The user can check if the remote Tile Store is online with the method TLfnCachingTileStore.isOnline().

  10. Failures other than "remote Tile Store offline" are always propagated onto the user’s handler.

The TLfnCachingTileStore can be configured to have a maximum size. This is done by supplying a low and high mark (expressed in bytes) to the constructor of TLfnCachingTileStore. Once the cache reaches the high mark size, an asynchronous sweep operation removes tiles from the cache on a least recently used basis, until the low mark size is reached. Note however that this sweeping is done on a best-effort basis, meaning the cache size can momentarily exceed the high mark or be below the low mark size.

To start caching retrieved tiles:

  1. Identify the URI of the ALfnTileStore from which tiles should be retrieved. This Tile Store can either be available locally or on some remote location.

  2. Identify the ALfnTileStore on which the tiles should be cached. This Tile Store should be available locally and be an instance of TLfnFileSystemTileStore or a wrapper thereof. This Tile Store must not be in use by other clients.

  3. Create a TLfnCachingTileStore with the URI of the remote Tile Store, an instance of the local Tile Store, a ALfnTileStoreProvider for (re)creating the remote Tile Store from its URI and a low and high mark expressed in bytes.

  4. Perform getTile requests on the TLfnCachingTileStore to fetch tiles from the remote Tile Store and cache them in the local Tile Store.

  5. Closing the TLfnCachingTileStore will take care of closing any and all Tile Stores which were created by the instance. When you’ve passed the ALfnTileStore being used as cache as an argument to the constructor of TLfnCachingTileStore, the instance is not created by the TLfnCachingTileStore so you are responsible for closing it yourself.

Should the server running the remote Tile Store go offline, then the TLfnCachingTileStore will automatically try to reconnect at fixed time intervals. In the process, the TLfnCachingTileStore will obtain a new Tile Store instance from the ALfnTileStoreProvider.

Integrating the client with LuciadLightspeed

This article describes how to visualize the retrieved tiles from a LuciadFusion Data Server in a LuciadLightspeed application. It covers the creation of a model and a layer, and discusses some important considerations if you are going to work with vector models.

Creating a model for a coverage in a Tile Store

You can create a model for a data source using TLfnTileStoreModelDecoder, where a data source corresponds to a coverage in a Tile Store.

If you do not know the available data sources upfront, you can discover them first before decoding them, as illustrated in Program: Discover all data sources, then select and decode them:

  1. Discover the list of the data sources given a Tile Store URI.

  2. Select one or more data sources.

  3. Decode a model from each of the selected data sources.

Program: Discover all data sources, then select and decode them
TLfnTileStoreModelDecoder modelDecoder = new TLfnTileStoreModelDecoder();
List<TLfnTileStoreDataSource> dataSources = modelDecoder.discoverDataSources("http://localhost:8080/tileengine/lts");
TLfnTileStoreDataSource selectedDataSource = dataSources.get(0);
ALfnTileStoreModel model = modelDecoder.decodeSource(selectedDataSource);

If you know the coverage ID upfront, you can decode a model from it directly, as illustrated in Program: Creating a model from a known coverage ID:

  1. Decode a Tile Store using TLfnTileStoreModelDecoder.

  2. Decode the model from the Tile Store and known coverage ID.

Program: Creating a model from a known coverage ID
TLfnTileStoreModelDecoder modelDecoder = new TLfnTileStoreModelDecoder();
ALfnTileStore tileStore = modelDecoder.decodeTileStore("http://localhost:8080/tileengine/lts");
String knownCoverageID = "earth_image";
ALfnTileStoreModel model = modelDecoder.decode(tileStore, knownCoverageID);

You can recognize a LuciadFusion Tile Store model by its model descriptor. The model descriptor will be a TLfnTileStoreModelDescriptor object. More specifically, it will be a subclass of TLfnRasterTileStoreModelDescriptor.

Creating a model for LuciadFusion raster coverage data

An alternative and more simplified use is to consume LuciadFusion coverages representing raster-type data. In this case, you can decode coverages that are part of a Tile Store or coverages that have been copied out of a Tile Store and are available on a local file system. You can create a model for such a data source using TLcdCoverageModelDecoder, where a data source corresponds to a coverage.

Program: Decode a fusion coverage from the file system.
TLcdCoverageModelDecoder modelDecoder = new TLcdCoverageModelDecoder();
ILcdModel model = modelDecoder.decode("Data/LuciadFusion/Coverages/earth__image.xml");

The TLcdCoverageModelDecoder supports the decoding of remote LuciadFusion coverages when they are presented as a coverage data source.

Program: Decode a fusion coverage a remote Luciad Tile Server.
TLcdCoverageDataSource coverageDataSource = new TLcdCoverageDataSource("http://sampleservices.luciad.com/lts", "92c09725-a9c5-46fb-bffd-d9e23b4abbf2");
TLcdCoverageModelDecoder modelDecoder = new TLcdCoverageModelDecoder();
ILcdModel model = modelDecoder.decodeSource(coverageDataSource);

When a raster coverage has been decoded in this way, the decoded model has a TLcdCoverageModelDescriptor, which denotes that the element within the model is suitable for use with the imaging API.

Working with with raster coverage models

Raster coverages can be one of three data types: RASTER, IMAGE or ELEVATION. The latter two types can be considered legacy sub-types of the RASTER data type. The data type determines the structure and the additional interfaces implemented by the model descriptor:

  • RASTER can preserve multi-band and multi-dimensional data. The model descriptor implements ILcdImageModelDescriptor. The model element is a domain object following the 'has-an-image' paradigm of the image processing API: it is an ILcdDataObject with a TLcdHasGeometryAnnotation referring to an ALcdImage.

  • IMAGE is the legacy type for RGB(A) imagery, and ELEVATION is the legacy type for elevation data. The model descriptor implements ILcdImageModelDescriptor and usually also ILcdEarthModelDescriptor. The model element is an ALcdImage: it follows the 'is-an-image' paradigm of the image API.

    Coverages decoded with a TLfnTileStoreModelDecoder may also be ILcdEarthTileSet objects, which follow the tile set API. In some circumstances though, elevation coverages follow the image processing API only, and no longer follow the tile set API.

    If you need to get the ALcdImage from the domain object, use ALcdImage.fromDomainObject. It figures out for you if the domain object is-an-image or has-an-image, saving you the trouble.

Working with tiled raster coverages

If the domain object is a tile set, it has an ILcdEarthTileSetCoverage for the specified coverage. The tiles produced by the tile set contain the decoded tile data, as opposed to the encoded tile data that you receive if you use TLfnLTSClient directly. For more information about tile sets, refer to the LuciadFusion User’s Guide or the Working with Earth tilesets article of the LuciadLightspeed developer’s Guide.

By default, the tile data codecs registered with the ALfnEnvironment are used. You can customize the used codecs through the model decoder, however.

Processing tiled coverages with the image processing framework

To integrate with the API of LuciadLightspeed’s image processing framework, you can use a model element as an ALcdImageMosaic, on the following condition: an ILcdEarthTileDataCodec that decodes to java.awt.image.RenderedImage or one of its subclasses must be available. This is the case for all default tile formats. If you have implemented a custom tile format, you need to add the necessary codecs to theALfnEnvironment yourself.

It is especially recommended to use the image processing framework API when you are working with point-sampled data. The tile set API is still supported for backward compatibility. However, because it lacks a point-sampled notion, pixels in point-sampled data will be interpreted incorrectly as area-sampled pixels. This may result in inaccuracies, such as pixels shifted slightly out of place.

For more information about the image processing framework API, see Modeling raster data for image processing.

Working with multi-dimensional models

If the raster coverage has multiple dimensions, as indicated by TLfnRasterCoverageMetadata.getDimension(), the decoded model will also be an ILcdMultiDimensionalModel. For the purpose of dimensional filtering, it will behave as a regular filterable multi-dimensional model. For more information about multi-dimensional models and dimensional filtering, see How to filter measurement data.

Limitations of the coverage model decoder

The TLcdCoverageModelDecoder only decodes raster coverages. The model decoder only supports the decoding of tiled coverages with tile data codecs that are supported out-of-the-box by LuciadFusion. If you have a coverage that is using a custom tile data codec you need to fall back to the TLfnTileStoreModelDecoder.

Creating a layer

Creating a layer from a raster coverage

Program: Creating a Lightspeed layer for a model with raster coverages and Program: Creating a GXY layer for a model with raster coverages illustrate how to create a layer for a raster coverage, for use in a Lightspeed view and a GXY view respectively. In all cases, the model can be treated as a generic Earth model.

  • The Earth Lightspeed painter maintains a single coverage per layer. Therefore, it needs at least two layers to visualize a 3D terrain, one layer with an image coverage and one layer with an elevation coverage. The topologies of these coverages do not need to match: they may have a different bounding box, and a different row and column structure for their tile pyramid.

Program: Creating a Lightspeed layer for a model with raster coverages
//First create the model
//Start by creating a TLcdCoverageDataSource for the coverage
String tileStoreURL = "http://sampleservices.luciad.com/lts";
String coverageID = "92c09725-a9c5-46fb-bffd-d9e23b4abbf2";
TLcdCoverageDataSource dataSource = new TLcdCoverageDataSource(tileStoreURL, coverageID);

//Decode the model by passing the datasource to the model decoder
ILcdModelDecoder decoder =
    new TLcdCompositeModelDecoder(TLcdServiceLoader.getInstance(ILcdModelDecoder.class));
ILcdModel model = decoder.decodeSource(dataSource);

//Create a layer for the model with default styling
ILspLayer layer = TLspRasterLayerBuilder.newBuilder()
                                        .model(model)
                                        .build();

//Add the layer to the Lightspeed view (an ILspView)
view.addLayer(layer);
Program: Creating a GXY layer for a model with raster coverages
//First create the model
//Start by creating a TLcdCoverageDataSource for the coverage
String tileStoreURL = "http://sampleservices.luciad.com/lts";
String coverageID = "92c09725-a9c5-46fb-bffd-d9e23b4abbf2";
TLcdCoverageDataSource dataSource = new TLcdCoverageDataSource(tileStoreURL, coverageID);

//Decode the model by passing the datasource to the model decoder
ILcdModelDecoder decoder =
    new TLcdCompositeModelDecoder(TLcdServiceLoader.getInstance(ILcdModelDecoder.class));
ILcdModel model = decoder.decodeSource(dataSource);

//Create a layer for the model with default styling
ILcdGXYLayer layer = TLcdGXYLayer.create(model);
//Wrap the layer with an async layer wrapper to ensure
//that the view remains responsive while data is being painted
layer = ILcdGXYAsynchronousLayerWrapper.create(layer);

//Add the async layer to the GXY view (an ILcdGXYView)
view.addGXYLayer(layer);

Creating a layer from a raster coverage model

You need to set a TLcdGXYImagePainter on the layer for the GXY case.

For Lightspeed you can make use of the raster layer factory making use of TLspRasterLayerBuilder as for other image data formats.

Working with multi-band data

You can preserve the multi-band semantics of the source data in a raster coverage of the RASTER data type. By default, a coverage will preserve all the band semantics of the source data. You can access the band semantics of the source data on the metadata of the corresponding asset. If you are fusing heterogeneous assets to a raster coverage, it is recommended that all assets have the same band semantics. Otherwise, the result is undetermined. You can customize the band semantics of the coverage metadata using TLfnRasterCoverageMetadata.Builder.bandSemantics().

Working with multi-dimensional data

You can preserve the multi-dimensional information of the source data in coverages of either the RASTER or the IMAGE data type. NetCDF data is an example of multi-dimensional source data.

From multi-dimensional data to a raster coverage

By default, a raster coverage preserves all the multi-dimensional information of the source data. It is possible to reduce dimensional information of the coverage to a subset of the source data dimensions: you can use TLfnRasterCoverageMetadata.Builder.dimensions() to filter dimensions. The tile data will contain multi-page images: each possible combination of dimensions and possible values will correspond to one page of the tile image.

When you decode a model from a multi-dimensional raster coverage, the model is ILcdMultiDimensionalModel. For all practical purposes such as visualization and dimensional filtering, it is indistinguishable from the source model.

Multi-dimensional raster coverages have an overhead: when tiles are being loaded, all the dimensional data is downloaded to the client. Filtering happens on the client. This means that the dimensional filters change smoothly while the data is being visualized. At the same time, there is an overhead if you only use a fraction of the dimensional data. This is why you can configure the coverage to retain only a subset of the dimensional information of the source data.

From multi-dimensional data to an image coverage

If you need only a single dimensional 'view' of the multi-dimensional source data, you can consider using an IMAGE coverage. This means that RGB images will be rendered from a single dimensional filter. By default, the dimensional filter of the coverage will be the first combination of possible values for each dimension. You can override this manually with TLfnRasterCoverageMetadata.Builder.dimensions(), but keep in mind that there should only be a single value for each TLcdDimension. In other words, TLcdDimension.getValues() should have size 1.

Customizing the server connection

This article describes how to customize the connection to a LuciadFusion Data server, using the transport layer of a client.

Customizing a transport

ILcdTransport is the central interface for customizing the connection to a Data Server. It has a single method performRequest that takes a TLcdTransportRequest as argument and returns a TLcdTransportResponse. Perform the following steps to customize the transport used by the client:

  1. Create the default transport using the createTransport method on TLfnClientFactory

  2. Wrap this transport to apply your customizations

  3. Create a client that uses this wrapped transport using the matching createLTSClient method on TLfnClientFactory

You can also create a default transport with a custom configuration by specifying a specific transport type and matching configuration parameter to the createTransport method. The currently supported type is TRANSPORT_TYPE_DEFAULT, which requires an Apache HttpClient 4.1.1 as configuration parameter. A default configuration parameter for a transport type can be created using the createTransportConfiguration method.