Symbology Encoding (SE) Styling
1. Introduction
If you are interested in Symbology Encoding (SE) you are in good hands right here.
If you want to know how to use Styled Layer Descriptor (SLD) in a WMS GetMap request read HowToUseWMSGetMapRequestsWithSLD.
You should also take a look at the OGC specification for SE:
SE (deegree 3 only)
Users interested in a quick reference of useful filter encoding functions to be used in styling, have a look at the filter functions overview page.
But now, lets get started!
2. Overview
There are three classes of geometry-types.
Points
Lines
Polygons
Each of these geometrys is styled differently.
There are a lot of possibilities to style and visually describe your geospatial data with SLD/SE. Lets start with some basics and then move on to the more complex styling!
2.1. General Layout
The general structure of an SE-Style contains:
<FeatureTypeStyle>
<FeatureTypeName> ==> (which is optional if your data source only has one feature type, such as shape files)
<Rule>
It is constructed like this:
<?xml version="1.0" encoding="UTF-8"?>
<FeatureTypeStyle xmlns="http://www.opengis.net/se" xmlns:ogc="http://www.opengis.net/ogc" xmlns:sed="http://www.deegree.org/se" xmlns:deegreeogc="http://www.deegree.org/ogc" xmlns:plan="http://www.deegree.org/plan" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/se http://schemas.opengis.net/se/1.1.0/FeatureStyle.xsd http://www.deegree.org/se http://schemas.deegree.org/se/1.1.0/Symbolizer-deegree.xsd">
<FeatureTypeName>plan:yourFeatureType</FeatureTypeName>
<Rule>
...
</Rule>
</FeatureTypeStyle>
!!!Before you start, always remember that every style is read top-down. So be aware the second <Rule> will overpaint the first one, the third overpaints the second and so on!!!
3. Basics
3.1. Symbolizers
At first, you have to set <Name> and <Description> of the rule.
Next you have to set a Symbolizer, which determines how the feature is drawn on the map. Possible Symbolizers are:
<PointSymbolizer>
<LineSymbolizer>
<PolygonSymbolizer>
<TextSymbolizer>
Inside the Symbolizer-element you can define the uom-attribute (units of measure), which determines the unit of all values set inside the Symbolizer. You can choose between:
uom="pixel"
uom="meter"
uom="mm"
When the uom aren't definded, the default uom are pixel.
In the next line you can give the Symbolizer a <Geometry>-element to rely on, which determines the geometry-property of the FeatureType. If you won't, the first geometry property of the FeatureType will be used.
Each of the Symbolizer-elements has its Dimensions, which are described in more detail below:
<LineSymbolizer> has only one dimension: the <Stroke>-element (to style the stroke).
<PolygonSymbolizer> has two dimensions: the <Stroke> (to sytle the stroke of the polygon) and the <Fill>-element (to style the inside of the polygon).
<PointSymbolizer> can also contain both dimensions: the <Stroke> (to style the stroke of the point) and the <Fill>-element (to style the inside of the point).
<TextSymbolizer> has three dimensions: the <Label> (to set the property, which is to be styled), the <Font> (to style the font) and the <Fill>-element (to style the inside of the font).
<Rule>
<Name>stroke-example</Name>
<Description>
<Title>This stroke is an example</Title>
</Description>
<LineSymbolizer uom="meter">
<Geometry>
<ogc:PropertyName>layer:position</ogc:PropertyName>
</Geometry>
...
</LineSymbolizer>
</Rule>
3.2. Stroke
To describe a <Stroke>, you can use a number of <SvgParameter>.
name="stroke" ==> The stroke (color) is defined by the hex color code (e.g. black ==> #000000).
name="opacity" ==> Opacity can be set by a percentage number, written as decimal (e.g. 0,25 ==> 25% opacity).
name="with" ==> Wide or thin, set your stroke-width however you want.
name="linecap" ==> For linecap (ending) a stroke you can choose the following types: round, edged, square, butt.
name="linejoin" ==> Also there are different types of linejoin possibilities: round, mitre, bevel.
name="dasharray" ==> The dasharray defines where the stroke is painted and where not (e.g. "1 1" ==> - - - ).
<LineSymbolizer uom="meter">
<Geometry>
<ogc:PropertyName>layer:position</ogc:PropertyName>
</Geometry>
<Stroke>
<SvgParameter name="stroke">#000000</SvgParameter>
<SvgParameter name="stroke-opacity">0.5</SvgParameter>
<SvgParameter name="stroke-width">1</SvgParameter>
<SvgParameter name="stroke-linecap">round</SvgParameter>
<SvgParameter name="stroke-linejoin">round</SvgParameter>
<SvgParameter name="stroke-dasharray">1 1</SvgParameter>
</Stroke>
</LineSymbolizer>
3.3. Fill
If you are styling polygons, points or font you can, additional to styling the <Stroke>, style the inside of the polygons, points or font with a <Fill>-element. You can set the <SvgParameter>:
name="fill" (color)
name="fill-opacity"
These two <SvgParameter> are working like those from <Stroke> (see <Stroke>).
...
<PolygonSymbolizer uom="meter">
<Geometry>
<...>
</Geometry>
<Fill>
<SvgParameter name="fill">#000000</SvgParameter>
<SvgParameter name="fill-opacity">0.5</SvgParameter>
</Fill>
<Stroke>
<...>
</Stroke>
</PolygonSymbolizer>
...
3.4. Font
If you are creating a <TextSymbolizer>, you have to specify certain parameters for the displayed text.
First, it's essential to pick a <Label>! Then you have to set the <Font>-element to style your font. These are the possible <SvgParameter>:
name="font-family" ==> Possible types are: e.g. Arial, Times Roman, Sans-Serif
name="font-weight" ==> Possible types are: normal, bold, bolder, lighter
name="font-size"
At last you have to assign the <Fill>-element where you can pick color and opacity of the font. This method is used to show text which is stored in your database.
<TextSymbolizer uom="meter">
<Geometry>
<...>
</Geometry>
<Label>
<ogc:PropertyName>layer:displayedProperty</ogc:PropertyName>
</Label>
<Font>
<SvgParameter name="font-family">Arial</SvgParameter>
<SvgParameter name="font-family">Sans-Serif</SvgParameter>
<SvgParameter name="font-weight">bold</SvgParameter>
<SvgParameter name="font-size">3</SvgParameter>
</Font>
<Fill>
<...>
</Fill>
</TextSymbolizer>
There is another way to design <TextSymbolizer> if you want to create your own text, depending on codes or similar.
Example: code 1000 = gasstation, code 2000 = diner
This style displays Gasstation and Diner instead of just the codes 1000 and 2000.
<TextSymbolizer uom="meter">
<Geometry>
...
</Geometry>
<Label>
<Recode fallbackValue="">
<LookupValue>
<ogc:PropertyName>layer:propertyUsageCode</ogc:PropertyName>
</LookupValue>
<MapItem>
<Data>1000</Data>
<Value>Gasstation</Value>
</MapItem>
<MapItem>
<Data>2000</Data>
<Value>Diner</Value>
</MapItem>
</Recode>
</Label>
<Font>
...
</Font>
<Fill>
...
</Fill>
</TextSymbolizer>
4. Filtering
You can use filters (<Filter>) to limit the features that are applied to the <Rule>. More details on all available filter functions can be found on the dedicated wiki page.
4.1. Basic Filtering
To stick with the example, you want to paint "Gasstation" with another color than "Diner".
Therefore you have to create two <Rule>s with different styles and create a <Filter> for every <Rule>.
The one for "Gasstation" would be:
<Rule>
<Name>...</Name>
<Description>
<Title>...</Title>
</Description>
<ogc:Filter>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>layer:propertyUsageCode</ogc:PropertyName>
<ogc:Literal>1000</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:Filter>
<PointSymbolizer uom="meter">
...
</PointSymbolizer>
</Rule>
The filter for "Diner" would be the same with the "Literal=2000".
There are many more filters you can use and combine, the most important are:
<ogc:Not>
<ogc:Or>
<ogc:And>
<ogc:PropertyIsNull>
<ogc:PropertyIsEqualTo>
4.2. Geometry-Type Filtering
If you want to filter for a geometry, for example if the "Gasstation" really is a point, you have to set a <ogc:Function> with the parameter for the point-geometry:
name="IsPoint" ==> for points
name="IsCurve" ==> for lines
name="IsSurface" ==> for polygons
!!!Please note that the filter will also match the multi-variants of the according geometry-type (e.g. multi-polygon)!!!
<ogc:PropertyIsEqualTo>
<ogc:Function name="IsPoint">
<ogc:PropertyName>layer:position</ogc:PropertyName>
</ogc:Function>
<ogc:Literal>true</ogc:Literal>
</ogc:PropertyIsEqualTo>
5. Graphics & Characters
5.1. Mark
You can use a <Mark> to include default geometries (squares, characters etc.) or user-generated content like SVGs.
It is possible to use all of these for <PointSymbolizer>, <LineSymbolizer> and <PolygonSymbolizer>.
The only difference is the way to get to the <Mark>!
For <PointSymbolizer> it works like this:
<PointSymbolizer uom="meter">
<Geometry>
...
</Geometry>
<Graphic>
<Mark>
...
For <LineSymbolizer> and <PolygonSymbolizer> it works like this:
<Geometry>
...
</Geometry>
<Stroke>
<GraphicStroke>
<Graphic>
<Mark>
...
5.1.1. Using default Geometries
There are some default geometries you can use for your styles in a <Mark>. To do so, you have to set the <WellKnownName>-element with one of the following types:
circle
triangle
star
square
x ==> creates a cross
<Mark>
<WellKnownName>triangle</WellKnownName>
<Fill>
...
</Fill>
</Mark>
5.1.2. Embedding SVGs
You can include SVGs in a <Mark> as geometry-distributors.
Follow the steps below.
<Fill> and <Stroke> work as usual.
<Mark>
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink" xlink:type="simple"
xlink:href="/filepath/symbol.svg" />
<Format>svg</Format>
<Fill>
...
</Fill>
<Stroke>
...
</Stroke>
</Mark>
5.1.3. Using Characters from true type fonts (TTF)
If you need to use single characters for your style, perhaps for a <PointSymbolizer>, you first need to select a font-file (*.ttf) of your choice (watch out for copyrights!). Now you have to indetify the indentifier (glyph index) of your choosen character in the selected font-order, to set it in the "<MarkIndex>".
!!!Please note: Font support is only available for deegree 3!!!
<Mark>
<OnlineResource xlink:href="filepath/yousans.ttf" />
<Format>ttf</Format>
<MarkIndex>99</MarkIndex>
<Fill>
<SvgParameter name="fill">#000000</SvgParameter>
...
</Fill>
<Stroke>
<SvgParameter name="stroke-opacity">0</SvgParameter>
...
</Stroke>
</Mark>
5.2. ExternalGraphic
You can use a <ExternalGraphic>-element to embed graphics, taken from a graphic-file (e.g. SVGs or PNGs). The <OnlineResource> sub-element gives the URL of the graphic-file. Make sure you don't forget the MIME-type in the <Format>-sub-element (e.g. "image/svg" or "image/png").
Hint: It is currently not supported to include a picture as a <ExternalGraphic> in a <GraphicStroke>-element (GraphicStroke/Graphic/ExternalGraphic). For this purpose, please use a <Mark> instead (GraphicStroke/Graphic/Mark).
<Graphic>
<ExternalGraphic>
<OnlineResource xmlns:xlink="http://www.w3.org/1999/xlink"
xlink:type="simple" xlink:href="/filepath/symbol.svg" />
<Format>image/svg</Format>
</ExternalGraphic>
<Size>10</Size>
...
</Graphic>
6. Advanced
But there are still more possibilities to develop sophisticated styles. A few are described below.
6.1. Size
Of course everything has its own <Size>.
You have to set it for every graphic, character etc. The size is defined directly after <Mark>.
<Mark>
<WellKnownName>triangle</WellKnownName>
<Fill>
<SvgParameter name="fill">#000000</SvgParameter>
</Fill>
</Mark>
<Size>3</Size>
6.2. Gap
If you want to use a graphic for a <LineSymbolizer> or <PolygonSymbolizer>, but only paint it every 20m, you can use the <Gap>-element like this:
<GraphicStroke>
<Graphic>
<Mark>
...
</Mark>
...
</Graphic>
<Gap>20</Gap>
</GraphicStroke>
6.3. Rotation
You also have the possibility to rotate every graphic around its center with the <Rotation>-element. This goes from zero to 360 degrees. The rotation is clockwise unless it's negative, then it's counter-clockwise.
<Graphic>
<Mark>
...
</Mark>
<Size>3</Size>
<Rotation>180</Rotation>
</Graphic>
6.4. Displacement
The <Displacement>-element allows you to paint a graphic displaced from his given position. Negative and positive values are possible. You have to set the X and Y displacement from the original geometry.
<Graphic>
<Mark>
...
</Mark>
...
<Displacement>
<DisplacementX>5</DisplacementX>
<DisplacementY>5</DisplacementY>
</Displacement>
</Graphic>
6.5. Perpendicular Offset
The <sed:PerpendicularOffset>-element is used for <LineSymbolizer> and <PolygonSymbolizer>.
So you can draw a line parallel to the original line-position of the feature.
Negative values will create an adjustment to the right and positive to the left side of the line string. For polygons, negative values mean, that the adjustment will be created to the inner of the polygon and positive values one to the outer of the polygon There are three types of Offsets:
type="Standard"
type="Round"
type="Edged"
Additional you can subjoin: substraction="NegativeOffset" which provides overlapping of Offsets.
But be cautious with that command, it's really slowing down your system!
<LineSymbolizer uom="meter">
<Geometry>
<ogc:PropertyName>xplan:position</ogc:PropertyName>
</Geometry>
<Stroke>
...
</Stroke>
<sed:PerpendicularOffset type="Edged" substraction="NegativeOffset">-0.5</sed:PerpendicularOffset>
</LineSymbolizer>
6.6. Halo
A nice possibility to highlight your font, is the <Halo>-element.
The <Radius>-sub-element defines the size of the border.
<TextSymbolizer uom="meter">
<Geometry>
<ogc:PropertyName>xplan:position</ogc:PropertyName>
</Geometry>
<Label>
...
</Label>
<Font>
...
</Font>
<LabelPlacement>
...
</LabelPlacement>
<Halo>
<Radius>1.0</Radius>
<Fill>
...
</Fill>
</Halo>
...
</TextSymbolizer>
7. Detailed Example
This style creates a stroke with following characteristics:
- color=black
- opacity=1.0
- width=2.0 m
- linecap=round
- linejoin=round
- offset=-1.5
- triangles:
- color=grey
- opacity=1.0
- size=3 m
- gap=5 m
- rotation=180° clockwise
<?xml version="1.0" encoding="UTF-8"?>
<FeatureTypeStyle
xmlns="http://www.opengis.net/se"
xmlns:ogc="http://www.opengis.net/ogc"
xmlns:sed="http://www.deegree.org/se"
xmlns:deegreeogc="http://www.deegree.org/ogc"
xmlns:plan="http://www.deegree.org/plan"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.opengis.net/se http://schemas.opengis.net/se/1.1.0/FeatureStyle.xsd http://www.deegree.org/se http://schemas.deegree.org/se/1.1.0/Symbolizer-deegree.xsd">
<FeatureTypeName>plan:Example</FeatureTypeName>
<Rule>
<Name>example</Name>
<Description>
<Title>This is an example</Title>
</Description>
<ogc:Filter>
<ogc:And>
<ogc:PropertyIsEqualTo>
<ogc:Function name="IsSurface">
<ogc:PropertyName>layer:position</ogc:PropertyName>
</ogc:Function>
<ogc:Literal>true</ogc:Literal>
</ogc:PropertyIsEqualTo>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>layer:surfaceUsageCode</ogc:PropertyName>
<ogc:Literal>15000</ogc:Literal>
</ogc:PropertyIsEqualTo>
</ogc:And>
</ogc:Filter>
<PolygonSymbolizer uom="meter">
<Geometry>
<ogc:PropertyName>plan:position</ogc:PropertyName>
</Geometry>
<Stroke>
<GraphicStroke>
<Graphic>
<Mark>
<WellKnownName>triangle</WellKnownName>
<Fill>
<SvgParameter name="fill">#808080</SvgParameter>
<SvgParameter name="fill-opacity">1.0</SvgParameter>
</Fill>
</Mark>
<Size>3</Size>
<Rotation>180</Rotation>
</Graphic>
<Gap>5</Gap>
</GraphicStroke>
</Stroke>
</PolygonSymbolizer>
<PolygonSymbolizer uom="meter">
<Geometry>
<ogc:PropertyName>plan:position</ogc:PropertyName>
</Geometry>
<Stroke>
<SvgParameter name="stroke">#000000</SvgParameter>
<SvgParameter name="stroke-opacity">1.0</SvgParameter>
<SvgParameter name="stroke-width">2.0</SvgParameter>
<SvgParameter name="stroke-linecap">round</SvgParameter>
<SvgParameter name="stroke-linejoin">round</SvgParameter>
</Stroke>
<sed:PerpendicularOffset type="Standard" substraction="NegativeOffset">-1.5</sed:PerpendicularOffset>
</PolygonSymbolizer>
</Rule>
</FeatureTypeStyle>