LuciadLightspeed allows you to structure styling information according to OpenGIS standards:

  • OGC 05-077r4, the OpenGIS Symbology Encoding Implementation Specification version 1.1.0 (SE 1.1.0)

  • OGC 05-078r4, the OpenGIS Styled Layer Descriptor Profile of the Web Map Service Implementation Specification, versions 1.0.0 and 1.1.0

This article discusses how you can apply such structured styling information to an ILcdModel to create an ILspLayer or an ILcdGXYLayer.

Originally, styling was included in the OGC Styled Layer Descriptor (OGC SLD) Implementation Specification. Later on, the styling part was split off from OGC SLD, and renamed to Symbology Encoding (SE). The most recent version of the OGC SLD basically only describes how Symbology Encoding styles can be used in the context of a Web Map Service (WMS).

In the LuciadLightspeed product and its documentation, we will continue to refer to Symbology Encoding with the acronym SLD, as this is the original prefix used for all classes that now provide the Symbology Encoding support.

Using SLD styling and symbology encoding in LuciadLightspeed

The OpenGIS standard SLD, from here on referred to as the standard, allows you to define uniform styling information for geospatial data through symbology encoding. The standard provides a uniform way to store a comprehensive model for styling information in an XML format.

Although the standard was originally conceived to convey styling information to a Web Map Server, the styling model can also be applied to data in standalone applications. This article does not cover the whole SLD implementation. Applying SLD in a Web Map Server context is discussed in the OGC Web Server Suite developers' guide that comes with the server product LuciadFusion. See that guide to learn more about assigning style to a layer in a Web Map Server.

Symbology encoding is based on the paradigm that style and content should be separated. As LuciadLightspeed adheres to the same paradigm, it is particularly well-suited to implement SLD: it provides the ILcdModel interface as a container for content. You can use the ILspStyler, ILcdGXYPainter and ILcdGXYLabelPainter interfaces to apply style. The styling information is modeled in the package ogc.sld.model discussed in The SLD styling model.

Although the styling model may be constructed programmatically, it is usually decoded from XML files. The package ogc.sld.xml contains classes to decode and encode styling models from and to XML files, see Decoding and encoding SLD styling models.

Once the styling model has been constructed, you can apply it to an ILcdModel. See

for examples.

SLD styling limitations lists the limitations of the styler and painter implementation for the styling model and how these limitations may be overcome.

It is recommended to keep a copy of the standard specification document close by while you are reading this.

The SLD styling model

Why provide a model implementation?

Although the styling aspects in SLD are numerous, the standard is far from comprehensive. Different fields of application require different representations, and these cannot all be mapped to the styling elements provided by the standard. The package ogc.sld.model contains the Java equivalent of the Schema files that comprise the SLD styling model. An extension of the SLD styling model would result in an equivalent extension of the Java model. An ILcdGXYPainter can then be created on top of the extended Java model, taking into account the new styling elements.

Having a model implementation also provides a way to customize styles at runtime. Applications can provide a GUI to customize the model implementation, so that you can avoid tedious editing of an XML file. Applying the new style to an ILcdModel in a GXY view then only requires creating a GXY painter based on the new styling model.

Model structure

As the styling model is completely described in the standard, this section only gives an overview of the elements and explains how they are converted to classes in LuciadLightspeed.

The SLD styling model contains three levels: feature type style, rule and symbolizer, each of which has its own function. The first two levels enable selection of the objects to which the style should be applied, while the third contains the actual style information.

The feature type style enables initial filtering on the object. For example, you would want to apply a 'blue' feature type style only to objects that represent hydrographic data.

The feature type style contains a number of rules. The rule level enables filtering at a more finely grained level, using filters as defined in the Filter Encoding Implementation Specification[1].

For details on the filters, refer to the standard and OGC Filters in a LuciadLightspeed application, which discusses the LuciadLightspeed implementation of this standard. Use of filters enables selection of objects on:

  • Properties of the object

  • The result of computations on properties of objects

  • Location of the object

  • And so on

Rules are only applied within a certain scale range, allowing you to switch styles when zooming in on a view. An example is a set of rules for a city where:

  • On a very small scale, the city is rendered as a point.

  • On a small scale, the city is rendered as a point combined with a label.

  • On a large scale, the city is portrayed as a polygon which depicts the built-up area of the city.

  • On a very large scale, satellite imagery shows the details of the buildings of the city.

The standard also introduces an else filter. If an object is not accepted by the filters in all other rules, the style defined in the rule containing the else filter is applied to it.

Every rule contains a number of symbolizers, which contain the actual styling information. Five types of symbolizers are defined in the standard, each containing specific styling aspects:

  • A point symbolizer

  • A line symbolizer

  • A polygon symbolizer

  • A text symbolizer

  • A raster symbolizer

Symbolizers can select the geometry they should be applied to, since an object may be represented by different geometries as demonstrated in the example above. If the selected geometry does not fit the symbolizer type a conversion should be applied to it.

The first three symbolizers should be considered as symbolizers for spatial dimensions. The polygon symbolizer is not restricted to defining styles for polygons, rather it defines styles for any object that covers an area. For LuciadLightspeed this includes objects which should be rendered as filled circles, arcbands, buffers, and so on. Analogously, when an object should be rendered as a circle which should not be filled, a line symbolizer style may be applied to it.

For details on the styling aspects of the symbolizers, refer to the standard and the API documentation.

Using the content

The strength of the styling model is that it enables the use of the content to customize the style, through the use of parameter values. A parameter value is a mix of plain text and expressions as defined in the Filter specification. Program: Using parameter value for channel selection shows an example: the value of the fill color for a polygon symbolizer is composed from the RGB values, extracting the value for the green channel from the object, while the red and blue channel are set to 0. Using this parameter value assumes that the object has the property GreenValue and that the property is stored as a hexadecimal value.

Program: Using parameter value for channel selection
<PolygonSymbolizer>
  <Fill>
    <CssParameter name="fill">#00<ogc:PropertyName>GreenValue</ogc:PropertyName>00</CssParameter>
  </Fill>
</PolygonSymbolizer>

Program: Computing the stroke width using parameter value demonstrates how the width of a stroke is computed when rendering a highway. It takes into account the number of lanes, the width of a lane and a fixed scaling factor.

Program: Computing the stroke width using parameter value
<LineSymbolizer>
  <Geometry>
    <ogc:PropertyName>CenterLine</ogc:PropertyName>
  </Geometry>
  <Stroke>
    <CssParameter name="stroke-width">
      <ogc:Multiply>
        <ogc:PropertyName>NUMBER_LANES</ogc:PropertyName>
        <ogc:Div>
          <ogc:PropertyName>LANE_WIDTH_METERS</ogc:PropertyName>
          <ogc:Literal>3</ogc:Literal>
        </ogc:Div>
      </ogc:Multiply>
    </CssParameter>
  </Stroke>
</LineSymbolizer>

Model implementation

The standard comprises Schema files describing the styling model and how it should be stored in XML files. ogc.sld.model provides a Java translation of the Schema. As rule of thumb, a type in the Schema corresponds to one class. Exceptions to this rule are rare and due to one of these reasons:

  • An attempt to take into account future changes or extensions to the SLD specification, or

  • The fact that no Java class corresponded well to the semantics intended by the type

This relation facilitates the creation of the Java equivalent model for the styling information contained in XML. Program: Constructing a style programmatically demonstrates this for the XML example in Program: Computing the stroke width using parameter value: it sets which property of the object should be interpreted as the geometry of the object to be rendered, builds the stroke containing the expression to compute the width and constructs a line symbolizer containing both.

Program: Constructing a style programmatically
ALcdSLDSymbolizer createLineSymbolizer() {
  // indicate which property of the object should be interpreted as the geometry to render
  TLcdOGCPropertyName geometryProperty = property("CenterLine");
  TLcdSLDGeometry geometry = new TLcdSLDGeometry(geometryProperty);

  // build the expression that computes the stroke width, based on the object.
  ILcdOGCExpression strokeWidthExpression = buildStrokeWidthExpression();
  // embed the expression in the parameter value.
  TLcdSLDParameterValue strokeWidthParameter = new TLcdSLDParameterValue(strokeWidthExpression);

  // create the stroke and set the stroke width parameter.
  TLcdSLDStroke stroke = new TLcdSLDStroke();
  stroke.setCssParameter(TLcdSLDStroke.CSS_PARAMETER_STROKE_WIDTH, strokeWidthParameter);

  // create the symbolizer and assign the stroke and the geometry to it.
  return new TLcdSLDLineSymbolizer(geometry, stroke);
}

Program: Computing the stroke width using parameter value programmatically shows the Java equivalent of the expression to compute the stroke width. The expression is built from the inside out: first the arguments of the division are defined and a division expression is created, then the argument for the multiplication is defined and the multiplication expression is returned.

Program: Computing the stroke width using parameter value programmatically
private ILcdOGCExpression buildStrokeWidthExpression() {

  // indicate which property should be interpreted as the first argument of the division
  TLcdOGCPropertyName laneWidthProperty = property("LANE_WIDTH_METERS");
  // the second argument to the division is a constant. It should not be interpreted.
  TLcdOGCLiteral scaleFactor = literal(3);

  // construct the disivion expression
  ILcdOGCExpression divisionExpression = div(laneWidthProperty, scaleFactor);

  // indicate which property should be interpreted as the first argument of the multiplication
  TLcdOGCPropertyName numberOfLanesProperty = property("NUMBER_LANES");

  // return the multiplication expression
  return mul(divisionExpression, numberOfLanesProperty);
}

The snippets use a static import of the TLcdOGCFilterFactory class:

import static com.luciad.ogc.filter.model.TLcdOGCFilterFactory.*;

Decoding and encoding SLD styling models

While providing an implementation of the SLD model in Java is useful, SLD styles are typically created from XML files. The package com.luciad.ogc.sld.xml contains classes to assist with the decoding of styling models from XML files and the encoding of styling models to XML files: The package contains a decoder, TLcdSLDFeatureTypeStyleDecoder, which decodes XML files with FeatureTypeStyle as the top element to a TLcdSLDFeatureTypeStyle object. Analogously, the TLcdSLDFeatureTypeStyleEncoder encodes a TLcdSLDFeatureTypeStyle object to an XML file.

SLD styling limitations

You need to take into account a number of limitations when you use SLD styling in LuciadLightspeed .

Unsupported SLD elements

The classes in ogc.sld.model support the complete styling model. The TLcdSLDFeatureTypeStyleDecoder decodes all XML elements and attributes in a FeaturedTypeStyle element. The implementation of the conversion to painters in ogc.sld.view.gxy however does not encompass the complete styling model. The following items are not supported:

  • A combination of CssParameter and a GraphicFill or GraphicStroke in a Fill or in a Stroke. It is not clear from the standard how this should be interpreted, but an interpretation can be implemented in an ILcdSLDGraphicsProvider.

  • The contrast enhancement feature Histogram in RasterSymbolizer.

  • OverlapBehavior in RasterSymbolizer.

  • The uom attribute on a TextSymbolizer, which can be used to define world-sized text. Support for OverlapBehavior would require a new implementation of ILcdGXYLayer, since all objects in TLcdGXYLayer are painted one after another, not taking into account relations between the objects.

  • SE 1.1 specifies a color replacement feature for external graphics. This element will be ignored in LuciadLightspeed . In most cases, it is better to use a mark graphic with a stroke and fill. In addition, it is unclear whether this feature will still be available in the next version of the standard.

  • SE 1.1 also allows rules to be retrieved through a link to an external resource. These links will not be resolved automatically, but users can support them by replacing the links with the actual resolved rules after decoding the style.

There are also some minor limitations for the TLspSLDStyler specifically:

  • Lines painted with a perpendicular offset only support pixels as unit of measure, both for the offset and the line width.

Limitations on external graphics

The default ILcdObjectIconProvider only supports the retrieval of an ExternalGraphic if its OnlineResource locates a file encoded in the SVG format, or a file with a format that can be decoded with java.awt.Toolkit (JPEG, GIF, PNG). It suffices to replace the default ILcdObjectIconProvider with another implementation to add support for other formats.

Other SLD styling limitations

  • LuciadLightspeed selection and snapping do not take into account styling information. This is of interest for styles containing line displacements: in that case, the representation of the object is not at the actual location of the object.

  • The implementation TLcdSLDFeatureTypeStylePainter does not apply feature type filtering.


1. OGC 04-095,OpenGIS Filter Encoding Implementation Specification