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.
<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.
<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.
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.
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
|
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 aGraphicFill
orGraphicStroke
in aFill
or in aStroke
. It is not clear from the standard how this should be interpreted, but an interpretation can be implemented in anILcdSLDGraphicsProvider
. -
The contrast enhancement feature
Histogram
inRasterSymbolizer
. -
OverlapBehavior
inRasterSymbolizer
. -
The
uom
attribute on aTextSymbolizer
, which can be used to define world-sized text. Support forOverlapBehavior
would require a new implementation ofILcdGXYLayer
, since all objects inTLcdGXYLayer
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.