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

Program: Creating a layer for plot objects using 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:

plot sample
Figure 1. The sample 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.

Program: Using 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.

Program: Using an expression to choose icons
TLspPlotStyle.newBuilder().icon(ifThenElse(eq(inFlightAttribute, constant(43)), constant(inFlightIcon), constant(onGroundIcon)).build();
plot icons
Figure 2. Using an expression to choose different icons for domain objects.

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.

Program: Using an expression to apply transparency to icons
TLspPlotStyle.newBuilder().opacity(fraction(timeAttribute, minTimeParameter, maxTimeParameter)).build();
plot opacity
Figure 3. Using an expression to apply transparency.

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.

Program: Using an expression to apply a modulation color to icons
TLspPlotStyle.newBuilder().modulationColor(mix(Color.red, Color.green, fraction(timeAttribute, minTimeParameter, maxTimeParameter))).build();
plot color
Figure 4. Using an expression to apply modulation color.

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.

Program: Using an expression to scale icons
TLspPlotStyle.newBuilder().scale(fraction(timeAttribute, minTimeParameter, maxTimeParameter)).build();
plot scale
Figure 5. Using an expression to scale icons.

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.

Program: Using an expression to filter icons
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.

plot oriented
Figure 6. Using oriented icons.

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.

plot densities 1
Figure 7. An example of plots visualized as densities. Blue symbolizes low plot density, red symbolizes high plot density.

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.

Program: Using an ALspStyleTargetProvider to extract geometry from domain objects
  public void style(Collection<?> aObjects, ALspStyleCollector aStyleCollector, TLspContext aContext) {
    aStyleCollector.objects(aObjects).geometry(fStyleTargetProvider).style(fStyle).submit();
  }

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.