- GeoServer Cookbook
- Stefano Iacovella
- 757字
- 2021-08-05 17:09:56
Filtering data with CQL spatial operators
ECQL does not only let you create readable and powerful filters on feature attributes; obviously, it also lets you filter out geometric properties.
There are a few spatial operators that you can use in a CQL filter: EQUALS
, DISJOINT
, INTERSECTS
, TOUCHES
, CROSSES
, WITHIN
, CONTAINS
, OVERLAPS
, RELATE
, DWITHIN
, and BEYOND
. With all these operators at your fingertips, you can really build complex filters.
In this recipe, we will use the BEYOND
operator that is the inverse of DWITHIN
, which we used in the recipe Using WFS spatial filters. With the filter, we will select the populated places located at least 1,000 km away from Rome, Italy. The result is shown in the following screenshot:

Tip
You can find the full source code for this recipe in the ch01_wmsCQLSpatialFilter.html
file.
How to do it…
- Create a projected table with populated places in PostGIS:
gisdata=> CREATE TABLE populatedplaceswm AS SELECT name, ST_Transform(geom,3857) AS geom FROM populatedplaces; gisdata=> CREATE INDEX populatedplaceswm_0_geom_gist ON populatedplaceswm USING gist(geom);
- Have a look at the latitude and longitude values for Rome using the following lines of code:
gisdata=> select ST_AsText(geom) from populatedplaces where name = 'Rome'; ----------------------------------------- POINT(12.481312562874 41.8979014850989)
- Copy
wmsCQLFilter.html
towmsCQLSpatialFilter.html
and edit the JavaScript code. Changesld
toPointSymbolizer
with a red fill for points outside the buffer:sld+= '<PointSymbolizer>'; sld+= '<Graphic>'; sld+= '<Mark>'; sld+= '<WellKnownName>circle</WellKnownName>'; sld+= '<Fill>'; sld+= '<CssParameter name="fill">#FF0000</CssParameter>'; sld+= '</Fill>'; sld+= '</Mark>'; sld+= '<Size>3</Size>'; sld+= '</Graphic>'; sld+= '</PointSymbolizer>';
- Add an
sld2
variable that holds drawing rules for points contained in the buffer area. You can reuse the code for thesld
variable, changing the fill color to green:sld2+= '<PointSymbolizer>'; sld2+= '<Graphic>'; sld2+= '<Mark>'; sld2+= '<WellKnownName>circle</WellKnownName>'; sld2+= '<Fill>'; sld2+= '<CssParameter name="fill">#00FF00</CssParameter>'; sld2+= '</Fill>'; sld2+= '</Mark>'; sld2+= '<Size>3</Size>'; sld2+= '</Graphic>'; sld2+= '</PointSymbolizer>';
- Set the SRS for the map to
EPSG:3857
:map = new OpenLayers.Map({ div: "myMap", allOverlays: true, projection: "EPSG:3857", maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34), maxResolution: 156543.0339, units: 'm',
- Add a layer with a
cql
filter for points located outside a 1,000-kilometre circular buffer from Rome:new OpenLayers.Layer.WMS("Far away places", "http://localhost/geoserver/wms",{ layers: "NaturalEarth:populatedplaceswm", format: "image/png", transparent: true, cql_filter: "BEYOND(geom,POINT(1389413 5145697),1000000,meters)", sld_body: sld,
- Add a layer with a
cql
filter for points located inside a 1,000-kilometre circular buffer from Rome:new OpenLayers.Layer.WMS("Near places", "http://localhost/geoserver/wms",{ layers: "NaturalEarth:populatedplaceswm", format: "image/png", transparent: true, cql_filter: "DWITHIN(geom,POINT(1389413 5145697),1000000,meters)", sld_body: sld2,
- Save the file and point your browser to it. Your map will show a set of green points around Rome. As shown in the previous image, Rome is surrounded by red points.
How it works…
Using spatial operators in cql_filter
is not really different than filtering other attributes. We used a map in a planar coordinate, in this case, the Web Mercator projection, because of an issue within GeoServer. Although you can define units that will be used to calculate distance in the BEYOND
and DWITHIN
operators, the interpretation depends on the data store (see http://jira.codehaus.org/browse/GEOS-937 for a detailed discussion). In PostGIS, the distance is evaluated according to the default units for the native spatial reference system of the data.
Tip
A spatial reference system (SRS) is a coordinate-based local, regional, or global system used to locate geographical entities. SRS defines a specific map projection as well as transformations between different SRS.
We need to create a new table with points projected in a planar coordinate. Then, we create an OpenLayers
map object and set it to EPSG:3857
. When using a projected SRS, we also need to set the map extent, resolution, and units:
projection: "EPSG:3857", maxExtent: new OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508.34), maxResolution: 156543.0339, units: 'm',
We then add two layers pointing to the same feature type, populatedplaceswm
, and using two different spatial filters. The first one uses the BEYOND
operator, passing it the coordinates of Rome expressed in meters, a 1000-kilometer distance, and the units:
cql_filter: "BEYOND(geom,POINT(1389413 5145697),1000000,meters)",
Note
Although the units are not evaluated when filtering features, the parameter is mandatory. Hence, you have to insert it, but you need to be aware of the native SRS of the data and calculate a proper value for the distance
To override the default rendering of features, we set sld_body
for the request to the SLD created in the JavaScript code:
sld_body: sld,
To represent features inside the buffer, we create a similar layer, filtering features with the DWITHIN
operator. The syntax is pretty similar to BEYOND
; please ensure that you set the same point and distance to build the buffer area:
cql_filter: "DWITHIN(geom,POINT(1389413 5145697),1000000,meters)",
Then, we set a different sld_body
value to represent features with a different symbol:
sld_body: sld2,
- Django+Vue.js商城項(xiàng)目實(shí)戰(zhàn)
- Python 3.7網(wǎng)絡(luò)爬蟲(chóng)快速入門(mén)
- C和C++安全編碼(原書(shū)第2版)
- 人臉識(shí)別原理及算法:動(dòng)態(tài)人臉識(shí)別系統(tǒng)研究
- Instant QlikView 11 Application Development
- PLC編程及應(yīng)用實(shí)戰(zhàn)
- Nginx Essentials
- HTML5+CSS3網(wǎng)站設(shè)計(jì)基礎(chǔ)教程
- Kotlin從基礎(chǔ)到實(shí)戰(zhàn)
- Node.js從入門(mén)到精通
- 大學(xué)計(jì)算機(jī)應(yīng)用基礎(chǔ)(Windows 7+Office 2010)(IC3)
- 從零開(kāi)始學(xué)UI:概念解析、實(shí)戰(zhàn)提高、突破規(guī)則
- Java從入門(mén)到精通(視頻實(shí)戰(zhàn)版)
- Java EE實(shí)用教程
- 讓Python遇上Office:從編程入門(mén)到自動(dòng)化辦公實(shí)踐