GeoServer 实现一个渲染变换(Rendering Transformation)
实现一个渲染变换(Rendering Transformation)
简介
渲染转换是一种特殊的WPS过程,它运行在Geoserver WMS渲染管道中,对数据进行转换,以提供更有效的可视化。本节介绍如何在Java中实现呈现转换过程
呈现转换非常通用,可以转换输入数据的内容和格式。内容转换通常涉及复杂的地理空间处理,需要访问整个数据集(与几何转换不同,几何学转换一次只对单个空间特征进行操作)。格式转换从矢量转换到栅格,反之亦然,以产生适合于所需可视化的输出格式(例如,用于显示连续曲面的瓦片,或用于显示离散对象的矢量数据)。
有关Geoserver中渲染转换功能的更多信息,请参阅Geoserver用户指南的渲染转换部分。
渲染转换的生命周期
要实现渲染转换,首先就要了解它在GeoServer中的生命周期以及执行的操作。一个渲染转换是在SLD中通过在
下面是实现gs:Heatmap转换在SLD中声明的代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41<FeatureTypeStyle>
<Transformation>
<ogc:Function name="gs:Heatmap">
<ogc:Function name="parameter">
<ogc:Literal>data</ogc:Literal>
</ogc:Function>
<ogc:Function name="parameter">
<ogc:Literal>weightAttr</ogc:Literal>
<ogc:Literal>pop2000</ogc:Literal>
</ogc:Function>
<ogc:Function name="parameter">
<ogc:Literal>radiusPixels</ogc:Literal>
<ogc:Function name="env">
<ogc:Literal>radius</ogc:Literal>
<ogc:Literal>100</ogc:Literal>
</ogc:Function>
</ogc:Function>
<ogc:Function name="parameter">
<ogc:Literal>pixelsPerCell</ogc:Literal>
<ogc:Literal>10</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>
</Transformation>
在WMS请求中我们使用SLD来指定变换,所有的参数都是在SLD文档中指定的参数。一些参数值必须由SLD变量指定。参考上图。
在执行转换过程之前,可以通过可选的反向查询(invertQuery)或invertGridGeometry方法,将查询Geoserver所做的查询重写到源数据存储。这允许转换扩大查询范围,因为某些类型的转换可能需要包含位于原始查询窗口之外的数据。渲染变换是可以扩大查询范围的,因为某些类型的转换可能需要包含位于原始查询数据之外的数据。
然后对源数据存储执行查询,并对结果数据集执行转换过程。转换返回的数据集要么格式相同要么格式不同。如果坐标系和需求不一样还会被自动转换。最后,输出数据集通过渲染管道传递,由SLD的
转换过程类 (Transformation process class)
和其它WPS过程类似,渲染转换的实现也是通过Java类的。一个服务过程(process)需要实现GSProcess marker接口。并且需要通过applicationContext.xml文件来注册到GeoServer中。另外如果需要了解更多关于如果构建以及如何注册等信息请参阅WPS服务构建章节(上一篇哦)。
WPS服务必须提供关于这个服务的元数据以及参数。最简单的方法是使用GeoTools annotation-based Process API,它使用了Java注解来指定元数据。例如,下面的代码展示了渲染变换(gs:Heatmap)元数据指定的过程。
1 | @DescribeProcess(title = "Heatmap", |
GeoServer对于每个渲染变换实现单个实例。这意味着呈现转换类必须是无状态的,使得我们可以通过调用他们来处理不同的请求。这是通过避免在类中声明任何实例变量来确保的。对于复杂的转换,可能需要实现一个辅助类,以允许使用实例变量。
译者注:这里面的意思应该是每个WPS服务实现都是有一个类不会,那么在多线程情况下,如果里面有变量可能会是线程不安全的,所以变量建议通过别的类来存储,这样避免变量串了。
执行方法(execute method)
像所有的服务过程类(process classes)一样,一个渲染转换类必须实现一个执行方法,来教会GeoServer如何执行转换。执行方法的签名(DescribeResult、DescribeParameter)指定输入参数的类型和过程结果。
一个Heatmap变换的执行结果如下:
1 | @DescribeResult(name = "result", description = "The heat map surface as a raster") |
输入参数(Input parameters)
一个受支持的输入参数是通过execute方法的参数传入的。元数据则是通过@DescribeParameter注解获取的。
要接受要转换的输入数据,过程必须定义一个输入参数,类型为SimpleFeatureCollection或GridCoverage2D。在GeoServer支持数据作为参数传入,来执行过程,但是需要指定上面所说的参数。可以定义任意数量的其他参数。参数可以是强制性的,也可以是可选的(如果不存在,可选参数的值为NULL)。可以通过定义数组值参数来接受值列表.
有些转换需要有关请求地图的范围和坐标系统的信息,并要求图像的宽度和高度。这些需要的情况包括:
1、转换操作依赖请求分辨率;
2、转换操作计算的是一个栅格结果,需要目标坐标系来达到一个最佳效果;
这些值可以从SLD预定义变量中获得,并通过ReferencedEncrype和Integer类型的参数传入。(有关所有可用预定义变量的详细信息,请参阅“用户指南”中的SLD部分中的变量替换。)
在Heatmap变换的情况下,请求分辨率会被用于整个数据范围内的像素半径参数,另外输出栅格也会在需要的坐标系下进行计算避免不被期望的投影。
为了支持这个变换需要定义outputBBOX、outputWidth以及outputHeight参数。这些是由预定义的SLD变量提供的,如上面SLD片段。
变换输出(Transformation output)
变换的输出是一个新的( SimpleFeatureCollection 或者 GridCoverage2D类型的)数据集,返回类型需要在execute的返回类型中指定。名称以及元数据由execute方法的@DescribeResult注解负责提供。
如果输出数据集数据的坐标系与地图输出的坐标系不符,GeoServer将会自己动调整坐标。另外我们可以通过设置请求坐标系来解决避免自动转换(一定要明确坐标系)。
查询重写(Query rewriting)
如果需要,渲染转换有能力改变对源数据集的查询。允许扩展要读取的数据的范围,对于某些类型的转换(特别是通过计算围绕输入的空间窗口来确定结果的那些)是必要的。这也允许控制查询优化(例如,确保几何抽取不阻止点特征被读取)。
译者注:我的理解就是读取的范围可以扩大或者精炼。
查询重写是通过提供InvertQuery或invertGridGeometry方法来实现的。这些方法的一般签名是:1
2
X invertX( [inputParam,]* Query targetQuery, GridGeometry targetGridGeometry)
targetQuery参数是请求的查询构造体。
targetGridGeometry是被请求的输出地图的地理参考范围。他不会被用在数据查询汇总,但可能需要与转换参数一起使
用,以确定如何重写查询。例如,如果在输出单元中指定了参数,那么输出范围信息将该值转换为与输入CRS相适应的值。
自己实现?
此外,这些方法可以接受为执行方法定义的任意数量的输入参数。如果定义了这些参数,他们也必须通过@DescribeParameter参数在execute中进行注解。
invertQuery方法
这个方法会在渲染变换处理矢量数据是调用(输入数据的类型是SimpleFeatureCollection)。
这个方法会返回一个新的查询值,包含了范围或查询优化所需的任何更改。它被用于查询资源数据集。
热力图渲染过程实现了invertQuery来增大查询范围。这个查询范围则是通过与radiusPixels参数相关的ground size决定的。
The Heatmap process implements the invertQuery method in order to enlarge the query extent by the ground size corresponding to the radiusPixels parameter.
这句ground size是啥?
为了允许将像素尺寸转换为ground distance,还需要提供输出地图范围的输入参数。所实现的方法的签名是:
1 | public Query invertQuery( |
invertGridGeometry 方法
这个方法会在渲染栅格数据时(输入格式是GridCoverage2D)时被调用。该方法返回一个新的GridGeometry值,用作对源栅格数据集的查询范围。
在总结
总结一下 ,渲染变换的重点是:
1、再输入的时候必须有个输入参数是FeatureCollection或者GridCoverage2D。
2、在输入参数中包含地图范围和图像尺寸是很有用的。
3、输出是必须有单一一个输出结果是FeatureCollection类型或者GridCoverage2D类型。
4、invertQuery和invertGridGeometry方法为可选项,可以被提供来重写数据查询。
5、注意渲染变换代码的无状态问题。