implement-rendertrans.rst 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. .. _wps_services_implement_rendertrans:
  2. Implementing a Rendering Transformation
  3. =======================================
  4. **Rendering Transformations** are a special kind of WPS process
  5. which run within the GeoServer WMS rendering pipeline
  6. to transform data in order to provide more effective visualization.
  7. This section describes how to implement a rendering transformation process in Java.
  8. Rendering transformations are very general, and can transform both the content
  9. and the format of input data.
  10. Content transformation typically involves complex geospatial processing
  11. which requires access to the entire dataset
  12. (in contrast to *geometry transformations*, which operate on a single spatial feature at a time).
  13. Format transformation converts from vector to raster
  14. or vice-versa in order to produce an output
  15. format appropriate to the desired visualization
  16. (for instance, a raster for displaying continuous surfaces, or vector data for displaying discrete objects).
  17. For more information about the function and use of rendering transformations within GeoServer, refer to the
  18. *Rendering Transformations* section of the *GeoServer User Guide*.
  19. Lifecycle of a Rendering Transformation
  20. ---------------------------------------
  21. To implement a rendering transformation it is useful to understand
  22. their lifecycle and operation within GeoServer.
  23. A rendering transformation is invoked in an SLD by providing a ``<Transformation>`` element inside a ``<FeatureTypeStyle>``.
  24. This element specifies the name of the transformation process and the names and values of
  25. the process parameters. As an example, the following is a portion of an SLD which uses
  26. the ``gs:Heatmap`` transformation:
  27. .. code-block:: xml
  28. :linenos:
  29. <FeatureTypeStyle>
  30. <Transformation>
  31. <ogc:Function name="gs:Heatmap">
  32. <ogc:Function name="parameter">
  33. <ogc:Literal>data</ogc:Literal>
  34. </ogc:Function>
  35. <ogc:Function name="parameter">
  36. <ogc:Literal>weightAttr</ogc:Literal>
  37. <ogc:Literal>pop2000</ogc:Literal>
  38. </ogc:Function>
  39. <ogc:Function name="parameter">
  40. <ogc:Literal>radiusPixels</ogc:Literal>
  41. <ogc:Function name="env">
  42. <ogc:Literal>radius</ogc:Literal>
  43. <ogc:Literal>100</ogc:Literal>
  44. </ogc:Function>
  45. </ogc:Function>
  46. <ogc:Function name="parameter">
  47. <ogc:Literal>pixelsPerCell</ogc:Literal>
  48. <ogc:Literal>10</ogc:Literal>
  49. </ogc:Function>
  50. <ogc:Function name="parameter">
  51. <ogc:Literal>outputBBOX</ogc:Literal>
  52. <ogc:Function name="env">
  53. <ogc:Literal>wms_bbox</ogc:Literal>
  54. </ogc:Function>
  55. </ogc:Function>
  56. <ogc:Function name="parameter">
  57. <ogc:Literal>outputWidth</ogc:Literal>
  58. <ogc:Function name="env">
  59. <ogc:Literal>wms_width</ogc:Literal>
  60. </ogc:Function>
  61. </ogc:Function>
  62. <ogc:Function name="parameter">
  63. <ogc:Literal>outputHeight</ogc:Literal>
  64. <ogc:Function name="env">
  65. <ogc:Literal>wms_height</ogc:Literal>
  66. </ogc:Function>
  67. </ogc:Function>
  68. </ogc:Function>
  69. </Transformation>
  70. ...
  71. During WMS requests which uses an SLD specifying a transformation,
  72. the arguments passed to the transformation process
  73. are assembled from the parameters and values specified in the SLD.
  74. Some argument values may be determined dynamically from SLD variables
  75. (as shown above in **lines 22-40**).
  76. Before the transformation process is executed, it is given an opportunity to rewrite
  77. the query GeoServer makes to the source datastore, via
  78. the optional ``invertQuery`` or ``invertGridGeometry`` methods.
  79. This allows a transformation to enlarge the query extent,
  80. since some kinds of transformations may need to include data which
  81. lies outside the original query window.
  82. The query is then performed against the source datastore,
  83. and the transformation process is executed against the resulting dataset.
  84. The transformation returns a computed output dataset
  85. of the same or different format.
  86. If the output has a different coordinate system (CRS) than
  87. the requested map it is reprojected automatically.
  88. Finally, the output dataset is passed on through the rendering pipeline
  89. to be styled by the symbolizers defined in the SLD ``<FeatureTypeStyle>``.
  90. Transformation process class
  91. ----------------------------
  92. Like other WPS processes, rendering transformations are implememented as Java classes.
  93. A process class implements the ``GSProcess`` marker interface,
  94. and is registered with GeoServer via an ``applicationContext.xml`` file.
  95. For further information about the basic steps for creating, building and deploying a GeoServer WPS process in Java
  96. refer to the :ref:`wps_services_implementing` section.
  97. WPS processes must provide metadata about themselves and their parameters.
  98. The easiest way to do this is to use the GeoTools annotation-based Process API,
  99. which uses Java annotations to specify metadata.
  100. For example, the code below shows the process metadata specified for the ``gs:Heatmap`` rendering transformation:
  101. .. code-block:: java
  102. @DescribeProcess(title = "Heatmap",
  103. description = "Computes a heatmap surface over a set of irregular data points as a GridCoverage.")
  104. public class HeatmapProcess implements GeoServerProcess {
  105. GeoServer instantiates a **single instance** of each rendering transformation class.
  106. This means that rendering transformation classes must be **stateless**,
  107. since they may be called concurrently to service different requests.
  108. This is ensured by avoiding declaring any instance variables within the class.
  109. For complex transformations it may be desirable to implement an auxiliary class
  110. to allow the use of instance variables.
  111. execute method
  112. --------------
  113. Like all process classes, a rendering transformation class must declare an ``execute`` method,
  114. which is called by GeoServer to perform the transformation.
  115. The signature of the ``execute`` method specifies the types of the input parameters
  116. and the process result.
  117. The declaration of the ``execute`` method for the Heatmap transformation is:
  118. .. code-block:: java
  119. @DescribeResult(name = "result", description = "The heat map surface as a raster")
  120. public GridCoverage2D execute(
  121. // tranformation input data
  122. @DescribeParameter(name = "data", description = "Features containing the data points")
  123. SimpleFeatureCollection obsFeatures,
  124. // process parameters
  125. @DescribeParameter(name = "radiusPixels",
  126. description = "Radius to use for the kernel, in pixels")
  127. Integer argRadiusPixels,
  128. @DescribeParameter(name = "weightAttr",
  129. description = "Featuretype attribute containing the point weight value",
  130. min = 0, max = 1)
  131. String valueAttr,
  132. @DescribeParameter(name = "pixelsPerCell",
  133. description = "Number of pixels per grid cell (default = 1)",
  134. min = 0, max = 1)
  135. Integer argPixelsPerCell,
  136. // output map parameters
  137. @DescribeParameter(name = "outputBBOX",
  138. description = "Georeferenced bounding box of the output")
  139. ReferencedEnvelope argOutputEnv,
  140. @DescribeParameter(name = "outputWidth", description = "Width of the output raster")
  141. Integer argOutputWidth,
  142. @DescribeParameter(name = "outputHeight", description = "Height of the output raster")
  143. Integer argOutputHeight,
  144. ) throws ProcessException {
  145. ...
  146. Input parameters
  147. ^^^^^^^^^^^^^^^^
  148. The supported process input parameters are defined as parameters to the ``execute`` method.
  149. The metadata for them is supplied via ``@DescribeParameter`` annotations.
  150. To accept the input data to be transformed, the process must define one input parameter of type ``SimpleFeatureCollection`` or ``GridCoverage2D``.
  151. In the invoking SLD only the name of this parameter is specified,
  152. since GeoServer provides the dataset to be transformed as the parameter value.
  153. Any number of other parameters can be defined.
  154. Parameters can be mandatory or optional (optional parameters have a value of ``null`` if not present).
  155. Lists of values can be accepted by defining an array-valued parameter.
  156. Some transformations require information about the request map extent and coordinate system, and request image width and height.
  157. Situations where these are required include:
  158. * the transformation operation depends on the request resolution
  159. * the transformation computes a raster result in the request coordinate system
  160. to ensure optimal visual quality
  161. These values can be obtained from SLD **predefined variables** and passed in via parameters of types
  162. ``ReferencedEnvelope`` and ``Integer``.
  163. (See the *Variable Substitution in SLD* section in the *User Guide* for details of all predefined variables available.)
  164. In the case of the Heatmap transformation, the request resolution is used to determine the ground size of the
  165. ``radiusPixels`` parameter, and the output raster is computed in the request coordinate system
  166. to avoid undesired reprojection.
  167. To support this the transformation defines the required ``outputBBOX``, ``outputWidth`` and ``outputHeight`` parameters.
  168. These are supplied by predefined SLD variables as shown in **lines 22-40** of the SLD snippet above.
  169. Transformation output
  170. ^^^^^^^^^^^^^^^^^^^^^
  171. The output of a transformation is a new dataset of type ``SimpleFeatureCollection`` or ``GridCoverage2D``.
  172. This is specified as the return type of the ``execute`` method.
  173. Name and description metadata is provided by the ``@DescribeResult`` annotation on the ``execute`` method.
  174. If the output dataset is not in the coordinate system requested for map output, GeoServer
  175. reprojects it automatically.
  176. As noted in the previous section, there may be situations where it is desirable to avoid this.
  177. In this case the transformation must ensure that the output has the appropriate CRS.
  178. Query rewriting
  179. ---------------
  180. If required, the rendering transformation has the ability to alter the query made against the source dataset.
  181. This allows expanding the extent of the data to be read, which is necessary for some kinds of
  182. transformations (in particular, ones whose result is determined by computing
  183. over a spatial window around the input). This also allows controlling query optimizations
  184. (for instance, ensuring that geometry decimation does not
  185. prevent point features from being read).
  186. Query rewriting is performed by providing one of the methods ``invertQuery`` or ``invertGridGeometry``.
  187. These methods have the general signature of::
  188. X invertX( [inputParam,]* Query targetQuery, GridGeometry targetGridGeometry)
  189. The ``targetQuery`` parameter is the query constructed from the original request.
  190. The ``targetGridGeometry`` parameter is the georeferenced extent of the requested output map.
  191. It is not used in the dataset query, but may be needed for use in conjunction with
  192. the transformation parameters to determine how to rewrite the query.
  193. For instance, if a parameter is specified in output units,
  194. the output extent information is required to transform the value into units
  195. applicable in the input CRS.
  196. In addition, these methods can accept any number of the input parameters
  197. defined for the ``execute`` method.
  198. If defined these parameters must be annotated with
  199. ``@DescribeParameter`` in the same way as in the ``execute`` method.
  200. invertQuery method
  201. ^^^^^^^^^^^^^^^^^^
  202. This method is called when the rendering tranformation applies to vector data
  203. (the data input is of type ``SimpleFeatureCollection``).
  204. The method returns a new ``Query`` value, which contains any required alterations of extent or query optimizations.
  205. This is used to query the source dataset.
  206. The Heatmap process implements the ``invertQuery`` method in order to enlarge the query extent
  207. by the ground size corresponding to the ``radiusPixels`` parameter.
  208. To allow converting the pixel size into a ground distance the input parameters providing the output map extents are also required.
  209. The signature of the implemented method is:
  210. .. code-block:: java
  211. public Query invertQuery(
  212. @DescribeParameter(name = "radiusPixels",
  213. description = "Radius to use for the kernel", min = 0, max = 1)
  214. Integer argRadiusPixels,
  215. // output image parameters
  216. @DescribeParameter(name = "outputBBOX",
  217. description = "Georeferenced bounding box of the output")
  218. ReferencedEnvelope argOutputEnv,
  219. @DescribeParameter(name = "outputWidth",
  220. description = "Width of the output raster")
  221. Integer argOutputWidth,
  222. @DescribeParameter(name = "outputHeight",
  223. description = "Height of the output raster")
  224. Integer argOutputHeight,
  225. Query targetQuery, GridGeometry targetGridGeometry
  226. ) throws ProcessException {
  227. ...
  228. invertGridGeometry method
  229. ^^^^^^^^^^^^^^^^^^^^^^^^^
  230. This method is called when the rendering tranformation applies to raster data
  231. (the data input is of type ``GridCoverage2D``).
  232. The method returns a new ``GridGeometry`` value,
  233. which is used as the query extent against the source raster dataset.
  234. Summary
  235. -------
  236. In summary, the key features of a rendering transformation process class are:
  237. * There must be an input parameter which is a ``FeatureCollection`` or a ``GridCoverage2D``
  238. * It may be useful to have input parameters which provide the request map extent and image dimensions
  239. * There must be a single result of type ``FeatureCollection`` or ``GridCoverage2D``
  240. * The optional ``invertQuery`` or ``invertGridGeometry`` methods may be supplied to rewrite the initial data query
  241. * The transformation process class must be **stateless**