You can add support for custom data formats to Lucy, so that it is possible to read and display the data in Lucy. To add basic support for a format, so that you can read and visualize the data, you must provide Lucy with at least two things:
- To read data
Add classes to Lucy that can convert a file to an
ILcdModelis a logical representation of the file data. The conversion is handled by an
ILcdModelDecoder. For example, an
ILcdModelDecodercould convert the information in a POL file to an
ILcdModelcontaining polygons, lines, and so on.
- To visualize data
For more information on
ILcdLayer instances and their relationship, see LuciadLightspeed core concepts and Model reading and writing. The best practices sample of Lucy contains a sample implementation of an
ILcdModelDecoder that demonstrates the responsibilities of an
Lucy comes with all necessary add-ons to add the formats supported by LuciadLightspeed to Lucy. The
TLcyDefaultDecodersAddOn adds the formats that are supported by LuciadLightspeed, while the formats that depend on a LuciadLightspeed component, ECW
for instance, each have their own add-on. If you want to add support for a custom data format to Lucy, you can register an
ILcdModelDecoder that can decode this format with Lucy.
ILcyLucyEnv provides these methods for the accounting of
ILcdModelDecoder instances, inherited from
getModelDecoderCountreturns the number of added
getModelDecoder( int )retrieves the
ILcdModelDecoderat the given index.
getDecoderFileTypeDescriptor( int )retrieves the
ALcyFileTypeDescriptorat the given index.
When you register an
ILcdModelDecoder, you can specify an
ALcyFileTypeDescriptor. This is a descriptor that provides the user with a high-level description of the file types that can be decoded with the
ILcdModelDecoder. When your decoder is not file-based, but reads data from a database for instance, you can specify
null as the file type descriptor. You can make your own implementation of
ALcyFileTypeDescriptor, or you can use
TLcyFileTypeDescriptor and just provide it with a display name and a list of extensions.
The file type descriptors are intended to be used to provide quick filtering of a directory listing for instance. Such a list
could contain thousands of files. Therefore, when you implement the
If you want to decode a certain source to a
ILcdModel in your add-on, you can use the composite model decoder of Lucy. This decoder, which you can retrieve with the
getCompositeModelDecoder method of
ILcyLucyEnv, will decode the given source name with the first registered
ILcdModelDecoder that reports it can decode this source name. Lucy also contains a composite data source handler for the registered
Note that you can override the
ILcdInputStreamFactory used to load the data by registering your own in Lucy. You can do this either directly on the Lucy environment, or through
the composite factory
TLcyCompositeInputStreamFactory. Most built-in formats will use the composite factory to create an
InputStream. Notable exceptions are
dimap. If you want to write your own
ILcdModelDecoder, it is advised to use
TLcyCompositeInputStreamFactory as well.
Lucy also reads files that do not result in an
ILcdModel. As such, you cannot use a
ILcdModelDecoder to read these files. A workspace file is one example of this case. To read those kinds of files, Lucy works with
ALcyDataSourceHandler objects. An
ALcyDataSourceHandler is similar to an
ILcdModelDecoder, but instead of decoding the source to a model, a
ALcyDataSourceHandler can handle the source any way it wants in the method
handleDataSource( String aSourceName, Object aTarget ).
addDataSourceHandler( ALcyDataSourceHandler, ALcyFileTypeDescriptor )adds the
ALcyDataSourceHandlerand the corresponding
ALcyFileTypeDescriptor. This file type descriptor serves the same purpose as for an
getDataSourceHandlerCountreturns the number of added
getDataSourceHandler( int )retrieves the
ALcyDataSourceHandlerat the given index.
getFileTypeDescriptor( int )retrieves the
ALcyFileTypeDescriptorat the given index.
If you want to write model data to the new file format, you need to add an
ILcdModelEncoder to Lucy. For this purpose,
ILcyLucyEnv is an extension of
ILcyModelEncoderContainer. The addition of
ILcdModelEncoder instances is similar to the addition of
ILcdModelDecoder instances. Lucy uses these encoders when you click the Save as…​ menu item, for instance. Lucy will ask all registered encoders if they can encode the model of the selected layer using the
canEncode( ILcdModel, String ). All the encoders that can encode the model will be presented as a choice in the File type combo box of the file chooser. The user can then select in which format the file should be saved, or in other words, which
ILcdModelEncoder should be used. Finally, the model is saved with the selected
ILcdModelEncoder to the specified destination name.
Note that you can override the
ILcdOutputStreamFactory used to save the data by registering your own in Lucy. You can do this either directly in the Lucy environment, or through
the composite factory
TLcyCompositeOutputStreamFactory. Most built-in formats will use the composite factory to create an
OutputStream. If you want to write your own
ILcdModelEncoder, it is advised to use
TLcyCompositeOutputStreamFactory as well.
When Lucy users open a file with the File→ Open menu item, the file type filter mechanism gives them the possibility to choose which files they want to see. The corresponding
drop-down box contains a list of group filters, followed by a sorted list of single-typed filters. The single-typed filters
ALcyFileTypeDescriptor instances registered together with the
ILcdModelDecoder instances and
ALcyDataSourceHandler instances. For a discussion about how these are registered, see Model data files and Handling arbitrary non-model data files. The group filters will combine a number of single-file-type filters. Lucy always contains the "All Known Files" filter,
which represents all registered single-file-type filters. Some add-ons, such as the
TLcyDefaultDecodersAddOn, will register the group filter "All Vector Files" or "All Raster Files", representing all vector or all raster files. You
can add other groups using
getCompositeFileTypeDescriptorGroup() on the
ILcyLucyEnv. The best practices sample of Lucy shows how you can do that.
TLcyDataFormatManager class contains two methods called
handleDataSources, which are used when a file is opened in Lucy:
handleDataSourcesis invoked without
ALcyDataSourceHandlerarrays, it goes over all registered
ILcdModelDecoderinstances and asks each of them if they can decode a source with a particular name, using the method
canDecodeSource( String ). Lucy also uses the method
canHandleDataSource( String aSourceName, Object aTarget )on all registered
ALcyDataSourceHandlerinstances to ask them if they can handle the file. If multiple decoders/handlers report that they can decode/handle the source name, Lucy lets the user select the decoder or handler. The selected
ALcyDataSourceHandlerthen decodes or handles the specified source name.
ILcdModelDecoderhas been selected, a layer is created and added to the map so that the data is visualized.
If certain files fail to open on the map component specified in the call of
TLcyDataFormatManager.ALcyMapComponentChooser will be used to choose another map
component to open the files on.
If a user opens multiple files, error messages should pop up once for each handled group of files. The model reference chooser
has an OK for All button to allow the user to choose a model reference once for a group of files. To accomplish this,
ILcyDataSourceListener instances are registered to
ILcyLucyEnv.getDataFormatManager(). Currently they can listen to two events:
As intended, listeners can collect error messages between the two events, for example, and can show a combined message when the HANDLING_ENDED event is received. If no HANDLING_STARTED event is fired, the listeners should display a pop-up error message for each problem.
If a format contains height data, you must register an
ILcdModelHeightProviderFactory with the
ILcyLucyEnv. You can do this through the method
ILcyLucyEnv.addService(). Lucy then uses these registered height provider factories to retrieve height values. When you are implementing new functionality
in Lucy that uses height data, you should use these registered factories. This is demonstrated in the following code:
ILcdModelHeightProviderFactoryinstances is used to create a height provider.
//Create a composite factory based on all ILcdModelHeightProviderFactory instances //registered on the Lucy backend TLcyCompositeModelHeightProviderFactory compositeFactory = new TLcyCompositeModelHeightProviderFactory(lucyEnv); // Create a set of required and optional properties. Map<String, Object> requiredProperties = new HashMap<>(); requiredProperties.put(ALcdModelHeightProviderFactory.KEY_GEO_REFERENCE, reference); Map<String, Object> optionalProperties = new HashMap<>(); // Create a height provider using the composite height provider factory. ILcdHeightProvider heightProvider = compositeFactory.createHeightProvider(model, requiredProperties, optionalProperties);
A useful class for registering and using
ILcdModelHeightProviderFactory instances is
TLcyCompositeModelHeightProviderFactory. Create an instance of this class using an
ILcyLucyEnv, and register height provider factories by adding them with
TLcyCompositeModelHeightProviderFactory.addModelHeightProviderFactory(). It then serves as a composite height provider factory that uses all registered
ILcdModelHeightProviderFactory instances registered in the
To retrieve height data from a view, use the class
TLcyViewHeightProvider. That class uses the registered height provider factories in the
ILcyLucyEnv to create a composite height provider from all models in the view that provide height data. It uses an instance of
TLcyCompositeModelHeightProviderFactory internally to do this.
Lightspeed views have a built-in height provider, which you can retrieve from the terrain support functionality of such a
view , through
ILspView.getTerrainSupport. See Visualizing terrain elevation in a Lightspeed view for more information.