Stay Connected with the Boundless Blog

Chaining and Rendering Transformations GeoServer Geospatial Software

We’ve mentioned in previous posts how Rendering Transformations in GeoServer can produce rich visualization effects such as contour maps and interpolated surfaces, all generated dynamically.

Rendering transformations are implemented as standard GeoServer WPS processes. As processes can be chained together—that is, the output of one process can be the input of another—rendering transformations can be made even more complex and powerful.

One example of a chained rendering transformation is dynamic visualization of temperature contours (also known as isotherms), given a data set consisting of scattered temperature observations from around the globe.

Temperature Observations
Temperature Observations

A refresher on rendering transformations

Recall that rendering transformations are defined in SLD styles by using the <Transformation> element within a <FeatureTypeStyle>. The process is indicated by a <Function> whose name attribute is the name of the underlying WPS process. The parameters to the process are provided by the arguments to this function, and are themselves wrapped in calls to the special parameter function. This function takes as arguments a <Literal> containing the name of the process parameter being specified, followed by other (optional) <Literal>s containing the argument values.

<Transformation>
  <ogc:Function name="gs:someProcess">
    <ogc:Function name="data">
      <ogc:Literal>someParameter</ogc:Literal>
      <ogc:Literal>someValue</ogc:Literal>    </ogc:Function>
    <ogc:Function name="parameter">
      ...   
    </ogc:Function>
  ...

To be able to be used as a rendering transformation, a process must include one parameter that accepts the data to be transformed (which in this case is the layer being styled). As with other process parameters, this is expressed using the parameter function. The name of the process parameter is determined by the particular process being used. In the simple non-chained case, no arguments are supplied with this parameter; the data is provided implicitly by the SLD rendering engine.

In order to chain transformations, an upstream (inner) process is called as the argument to a downstream (outer) process’s data parameter. The upstream process must also include its own data parameter, which will not have an explicit value (if this is the first/innermost process in the chain). During rendering, the upstream process is executed on the original layer data, and the downstream process is executed on the result of the upstream process. The symbology defined in the SLD must be appropriate for the output format of the final process in the chain, regardless of the original or intermediate formats.

Making isotherms

Getting back to our example, the rendering transformation for isotherms consists of the Barnes Surface process chained to the Contour process. When applied to the temperature data this generates a contour map of estimated average temperatures, as shown in the image below.

Barnes_Contours
Barnes Surface and Contours

The image above is actually displaying three different layers:

  1. base map showing world countries
  2. layer showing the estimated temperature surface, computed using the Barnes Surface rendering transformation
  3. layer showing the isotherm lines generated by contouring the Barnes Surface

Here are the parameters used for this chain:

Barnes Surface:

  • data: [the layer itself]
  • valueAttr: MxTmp
  • dataLimit: 500
  • scale: 15.0
  • convergence: 0.2
  • passes: 3
  • minObservations: 2
  • maxObservations: 15
  • pixelsPerCell: 8
  • queryBuffer: 40

Contour:

  • data: [output of Barnes Surface processes]
  • levels: [-10, -5, 0, 5, 10, 15, 20, 25, 30, 35, 40]
  • simplify: true

Download the SLD for the Barnes Surface/Contour style

The relevant snippet for the <Transformation> element expressing the chained rendering transformation is shown below. Note how the downstream gs:Contour process has the upstream gs:BarnesSurface process nested inside the data parameter. It’s worth pointing out that the data gets converted from vector to raster and back to vector during this chained process. The symbology in the SLD uses symbolizers appropriate for vector data, as that is the final data format.

One final note: The contour levels are defined explicitly with the Contour process levels parameter. These need to match the range of data values which are computed for the surface.

<Transformation>
  <ogc:Function name="gs:Contour">
    <ogc:Function name="parameter">
      <ogc:Literal>data</ogc:Literal>
      <ogc:Function name="gs:BarnesSurface">
        <ogc:Function name="parameter">
          <ogc:Literal>data</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>valueAttr</ogc:Literal>
          <ogc:Literal>MxTmp</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>dataLimit</ogc:Literal>
          <ogc:Literal>500</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>scale</ogc:Literal>
          <ogc:Literal>15.0</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>convergence</ogc:Literal>
          <ogc:Literal>0.2</ogc:Literal>
        </ogc:Function><ogc:Function name="parameter">
          <ogc:Literal>passes</ogc:Literal>
          <ogc:Literal>3</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>minObservations</ogc:Literal>
          <ogc:Literal>2</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>maxObservationDistance</ogc:Literal>
          <ogc:Literal>15</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>pixelsPerCell</ogc:Literal>
          <ogc:Literal>8</ogc:Literal>
        </ogc:Function>
        <ogc:Function name="parameter">
          <ogc:Literal>outputBBOX</ogc:Literal>
          <ogc:Function name="env">
        <ogc:Literal>wms_bbox</ogc:Literal>
        </ogc:Function>
      </ogc:Function>
      <ogc:Function name="parameter">
        <ogc:Literal>outputWidth</ogc:Literal>
        <ogc:Function name="env">
          <ogc:Literal>wms_width</ogc:Literal>
        </ogc:Function>
      </ogc:Function>
      <ogc:Function name="parameter">
        <ogc:Literal>outputHeight</ogc:Literal>
          <ogc:Function name="env">
            <ogc:Literal>wms_height</ogc:Literal>
          </ogc:Function>
      </ogc:Function>
      <ogc:Function name="parameter">
        <ogc:Literal>queryBuffer</ogc:Literal>
        <ogc:Literal>40</ogc:Literal>
      </ogc:Function>
    </ogc:Function>
  </ogc:Function>
  <ogc:Function name="parameter">
    <ogc:Literal>levels</ogc:Literal>
    <ogc:Literal>-10</ogc:Literal>
    <ogc:Literal>-5</ogc:Literal>
    <ogc:Literal>0</ogc:Literal>
    <ogc:Literal>5</ogc:Literal>
    <ogc:Literal>10</ogc:Literal>
    <ogc:Literal>15</ogc:Literal>
    <ogc:Literal>20</ogc:Literal>
    <ogc:Literal>25</ogc:Literal>
    <ogc:Literal>30</ogc:Literal>
    <ogc:Literal>35</ogc:Literal>
    <ogc:Literal>40</ogc:Literal>
  </ogc:Function>
  <ogc:Function name="parameter">
    <ogc:Literal>simplify</ogc:Literal>
    <ogc:Literal>true</ogc:Literal>
  </ogc:Function>
  </ogc:Function>
</Transformation>

Ideas for new rendering transformations welcome

At the moment there are only a few processes in GeoServer which are suitable for implementing chained rendering transformations. We want to continue expanding our offerings but not in a vacuum. What do you wish you could do with rendering transformations? Leave a comment below to let us know.

Boundless Geo

Boundless has over 14 years of experience in the open GIS technology industry; serving as the leading open mapping software and solutions provider to government and commercial sector clients. As an active member of the open source community, including OSGeo and LocationTech, Boundless contributes to over 140 projects repositories. Boundless resides in the USA and has over 80 employees spread across the globe.