LuciadLightspeed includes a plots package that allows you to display a large number of points as plots. You can use it to plot hundreds of thousands of aircraft positions on a map, for instance.
The com.luciad.view.lightspeed.layer.plots
package applies many of the visualization concepts explained here. In combination with the styling options of TLspPlotStyle
in the com.luciad.view.lightspeed.style
package, it offers:
-
A Lightspeed layer that is targeted specifically at large static datasets containing points, such as plot data.
-
Extensive configuration options for the styling of plots
-
Plot styling through expressions, which are rapidly evaluated by your computer’s graphics hardware
The Lightspeed plot layer makes use of graphics hardware to expand its visualization capabilities up to millions of points. It also allows you to filter the data and change the style applied to the filtered data instantly, without re-processing the data.
This layer can handle any ILcdModel
that contains point data. However, the data should not change
once it is loaded. In the case of model change events in particular, all the data is re-processed for visualization.
Configuring a plot layer
To create a Lightspeed plot layer, use TLspPlotLayerBuilder
, as shown in Program: Creating a layer for plot objects using TLspPlotLayerBuilder
.
TLspPlotLayerBuilder
ILspLayer layer = TLspPlotLayerBuilder.newBuilder().model(myModel).build();
The TLspPlotLayerBuilder
has a few optional configuration methods, similar to the options of other layer builders such as TLspShapeLayerBuilder
:
-
label
andicon
: to set the label and icon to use in a layer tree GUI. -
bodyStyles
andbodyStyler
: to configure styling options. For more details on styling, see Styling and filtering your plot domain objects. -
bodyMapScaleRange
: to configure at what scale range the data should be displayed. For more details on performance, see Optimizing the performance of a plot layer. -
labelStyles
,labelStyler
andlabelMapScaleRange
: to configure labels for plot layers. For more details on labels, see Adding labels to your plot domain objects.
lightspeed.plots
shows plots using a TLspPlotLayerBuilder
.
Styling and filtering your plot domain objects
By default, the plots are visualized as white dots, but you can fully customize the styling of the plots.
Applying style to a plot layer is similar to styling in other layers: you can use an ILspStyler
or set a fixed style. For more information about using a styler to apply styles, see Linking objects to styles with ILspStyler
.
Instead of calculating the style for each object individually in your styler, though,
you must use one shared style for all objects, TLspPlotStyle
, as shown in Program: Using ILspStyler
for plot layers that uses a single shared TLspPlotStyle
.
ILspStyler
for plot layers that uses a single shared TLspPlotStyle
public class MyStyler extends ALspStyler {
public void style(Collection<?> aObjects, ALspStyleCollector aStyleCollector, TLspContext aContext) {
TLspPlotStyle style = TLspPlotStyle.newBuilder().build();
aStyleCollector.objects(aObjects).style(style).submit();
}
}
You can configure the custom plot style with expressions that calculate the styling options. The layer will use graphics hardware to evaluate these expressions efficiently. See the following sections for examples. See Introduction to data-driven styling for more details about using expressions.
Creating a plot style
You can create a TLspPlotStyle
using its Builder
, which works in a similar way as the style builder for TLspIconStyle
. You can assign an expression to each style aspect of the icons in your plot:
-
icon
-
opacity
-
modulationColor
-
scale
-
visibility
The style itself is immutable. To change the used style, fire a style change event through ALspStyler.fireStyleChangeEvent
. The new style will be
applied instantly. For performance details, see Optimizing the performance of a plot layer.
The creation of expressions is explained in more detail in Introduction to data-driven styling. The rest of this section focuses on the various styling options, and already shows a few examples of expressions.
Choosing an icon for your plot objects
The icon
aspect of your TLspPlotStyle
lets you control what icon is displayed. There is no performance penalty for the use of many different icons, even if there
are several thousands.
For example, Program: Using an expression to choose icons shows a style that assigns a different icon depending on an attribute of the domain objects.
TLspPlotStyle.newBuilder().icon(ifThenElse(eq(inFlightAttribute, constant(43)), constant(inFlightIcon), constant(onGroundIcon)).build();
To learn more about the use of icons with domain objects other than plots, see Painting point symbology with TLspIconStyle
.
Applying transparency to your plot icons
The opacity
aspect of your TLspPlotStyle
allows you to make the plot icons more transparent. You can use this to fade out less important objects, for instance.
Program: Using an expression to apply transparency to icons shows a style that fades out objects based on a time interval.
TLspPlotStyle.newBuilder().opacity(fraction(timeAttribute, minTimeParameter, maxTimeParameter)).build();
Applying a modulation color to your plot icons
With the modulationColor
aspect, you can adapt the color of the icons. You can use this to vary icon color based on an attribute, for example.
The color is mixed with the icon. This usually works best if the icons themselves are in grayscale.
For example, Program: Using an expression to apply a modulation color to icons shows a style that changes the color from red to green based on a time interval.
TLspPlotStyle.newBuilder().modulationColor(mix(Color.red, Color.green, fraction(timeAttribute, minTimeParameter, maxTimeParameter))).build();
Scaling your plot icons
With the scale
aspect, you can adapt the size of the icons. Use this to make less important objects smaller, for example.
Program: Using an expression to scale icons shows a style that shrinks objects based on a time interval.
TLspPlotStyle.newBuilder().scale(fraction(timeAttribute, minTimeParameter, maxTimeParameter)).build();
TLspPlotStyle
also offers an automatic scaling mode. In this mode, the objects are scaled based on
their distance to the camera. This means that when you have zoomed out the map, the icons will be smaller. You will also
have more objects on the screen. This has two benefits:
-
An uncluttered view: if the icons remained large, the view would be cluttered with many large icons.
-
Performance: the visualization performance improves. See Optimizing the performance of a plot layer for more details on performance.
See the Javadoc on automaticScaling
for more information.
Filtering your plot objects
The visibility
aspect lets you filter out specific objects. You can use this to show only relevant objects, for instance, based on the
value of an object attribute.
Program: Using an expression to filter icons shows a style that hides objects of a certain type, namely those with attribute value 43.
TLspPlotStyle.newBuilder().visibility(neq(typeAttribute, constant(43)).build();
Note that object filtering has a positive impact on visualization performance. See Optimizing the performance of a plot layer for more details on performance.
Using oriented plot icons
You can activate icon orientation with the useOrientation
flag. As a result, the icons will be rotated towards their orientations.
For icon orientation to work, your domain objects must implement ILcdOriented
. You can also use an ALspStyleTargetProvider
, about which you can find more information in Extracting geometry from your plot objects.
Adding labels to your plot domain objects
You can enable labels in the same way as you would enable them with a regular TLspShapeLayerBuilder
. Use TLspPlotLayerBuilder.labelStyles
to configure
labels.
You can use all the label styling and decluttering options available in LuciadLightspeed. See Labeling domain objects in a Lightspeed view for more information about labeling in Lightspeed views, or the API reference documentation for TLspLabelStyler
.
Painting plot labels is more CPU-intensive than painting the plots themselves. Therefore, we recommend using a scale range so that labels are only displayed for a subset of the data. See Optimizing the performance of a plot layer for more performance tips. |
Visualizing plot densities
You can visualize plot densities with the density
flag. If you want to enable density, you must make sure that icon
is not set. Activating density will also override any modifications to modulationColor
. Figure 7, “An example of plots visualized as densities. Blue symbolizes low plot density, red symbolizes high plot density.” shows an example of what a density plot looks like.
You can modify the parameters of the density calculation with the density
method:
-
IndexColorMap: A map that translates densities to colors. By default, low densities are blue and high densities are red.
-
Hardness: A double between the values of 0 and 1 that indicates how hard the density plots should be. A value of 0 indicates a soft, smooth plot density sampling, while a value of 1 indicates a sharp, hard density sampling. The default for this value is 0.5.
You cannot combine a density plot with the eye-dome lighting technique mentioned in Enhancing depth perception with eye-dome lighting (EDL). |
Enhancing depth perception with eye-dome lighting (EDL)
For information about improving depth perception by accentuating shape outlines, see eye-dome lighting.
You cannot combine the EDL technique with a density plot. See Visualizing plot densities for more information about density plots. |
Extracting geometry from your plot objects
By default, the plot layer works with domain objects that are ILcdPoint
objects, and optionally ILcdOriented
objects.
If you want to work with domain objects that are not ILcdPoint
objects themselves, you can use an ALspStyleTargetProvider
to extract the geometry from your domain objects.
For oriented icons, the returned geometry must also implement ILcdOriented
. Program: Using an ALspStyleTargetProvider
to extract geometry from domain objects shows you how to use an ALspStyleTargetProvider
.
ALspStyleTargetProvider
to extract geometry from domain objects
public void style(Collection<?> aObjects, ALspStyleCollector aStyleCollector, TLspContext aContext) {
aStyleCollector.objects(aObjects).geometry(fStyleTargetProvider).style(fStyle).submit();
}
See Deriving geometry from objects for more information about ALspStyleTargetProvider
.
Optimizing the performance of a plot layer
In the majority of cases, the plot layer will perform well with the default configuration and most of the styling techniques.
This section provides some insight into ways to get the best performance for your particular case.
Choosing an appropriate model implementation
TLspPlotLayerBuilder
works with any ILcdModel
implementation, including implementations with lazy-loaded data.
However, there is an important distinction between models, depending on the model type:
-
If the model implements
ILcd2DBoundsIndexedModel
, the data is processed incrementally, based on what is visible. It is still cached and processed in bulk for optimal performance, though. -
If the model does not implement
ILcd2DBoundsIndexedModel
, all data is processed once, up front, and never discarded.
Pre-loading attributes
Attributes are processed when they are used by any of the expressions in your TLspPlotStyle
.
If you switch to a different style that uses different attributes, these new attributes have to be processed at the time of
the switch.
This will cause a noticeable performance hit.
To prevent such a pause in performance, you can set all necessary attributes up front with TLspPlotLayerBuilder.mandatoryAttributes
.
Similarly, if you switch between styles that have orientation on or off, you can force the load of orientation information
with TLspPlotLayerBuilder.mandatoryOrientation
.
Optimizing visualization by filtering
By setting a visibility rule that filters out elements on TLspPlotStyle
, you can significantly improve performance.
You could also create such a filter based on the view scale, to provide a level-of-detail.
Despite these filtering measures, it may still be necessary to set a hard scale range on the layer. Outside this scale range, the data will not displayed at all, and does not even have to be loaded.
Optimizing visualization by reducing icon size
Icon size is an important factor in visualization performance, particularly when many objects are visible, and are therefore more likely to overlap on the screen.
Hence, it is recommended to reduce the size of the icons based on scale or distance to camera, as explained in Scaling your plot icons.
Optimizing visualization by setting a scale range for plots or labels
Some very large datasets simply cannot be visualized because they do not fit in memory. In such a case, use a scale range so that only a subset that fits in memory is visualized.
The display of labels is more demanding than the display of plots. Use a scale range so that only a few thousands of objects are labeled.